135 lines
4.6 KiB
Vue
135 lines
4.6 KiB
Vue
<template>
|
|
<nav class="sticky top-0 z-50 w-full glass border-b border-gray-200/50 dark:border-gray-800/50">
|
|
<div class="w-full px-4 sm:px-6 lg:px-8">
|
|
<div class="flex items-center justify-between h-16">
|
|
<!-- Left Side: Logo & Navigation -->
|
|
<div class="flex items-center gap-8">
|
|
<NavbarLogo />
|
|
|
|
<!-- Desktop Navigation -->
|
|
<div class="hidden md:flex items-center">
|
|
<NavbarLinks />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Side: Actions & User -->
|
|
<div class="hidden md:flex items-center gap-5">
|
|
<!-- Auth & Projects -->
|
|
<template v-if="authStore.user">
|
|
<NavbarProjectActions
|
|
@open-save-modal="openSaveModal"
|
|
@open-project-list="isProjectListOpen = true"
|
|
/>
|
|
|
|
<div class="h-4 w-px bg-gray-200 dark:bg-gray-700"></div>
|
|
|
|
<!-- User Dropdown -->
|
|
<NavbarUserMenu @open-auth-modal="isAuthModalOpen = true" />
|
|
</template>
|
|
|
|
<div v-else>
|
|
<button @click="isAuthModalOpen = true" class="btn btn-primary btn-sm shadow-indigo-500/20 shadow-lg">
|
|
Login / Register
|
|
</button>
|
|
</div>
|
|
|
|
<div class="h-4 w-px bg-gray-200 dark:bg-gray-700"></div>
|
|
|
|
<NavbarSocials @open-help="$emit('open-help')" />
|
|
</div>
|
|
|
|
<!-- Mobile Menu Button -->
|
|
<div class="flex md:hidden">
|
|
<DarkModeToggle />
|
|
<button @click="isMobileMenuOpen = !isMobileMenuOpen" class="ml-4 p-2 rounded-md text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors">
|
|
<i :class="isMobileMenuOpen ? 'fas fa-times' : 'fas fa-bars'" class="text-lg"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Menu -->
|
|
<NavbarMobileMenu
|
|
:is-open="isMobileMenuOpen"
|
|
@close="isMobileMenuOpen = false"
|
|
@open-help="$emit('open-help')"
|
|
/>
|
|
</nav>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, toRef } from 'vue';
|
|
import DarkModeToggle from '../utilities/DarkModeToggle.vue';
|
|
import { useAuthStore } from '@/stores/useAuthStore';
|
|
import AuthModal from '@/components/auth/AuthModal.vue';
|
|
import ProjectList from '@/components/project/ProjectList.vue';
|
|
import SaveProjectModal from '@/components/project/SaveProjectModal.vue';
|
|
import { useProjectStore, type Project } from '@/stores/useProjectStore';
|
|
import { useSettingsStore } from '@/stores/useSettingsStore';
|
|
import { useExportLayers } from '@/composables/useExportLayers';
|
|
import { useLayers } from '@/composables/useLayers';
|
|
|
|
// Sub-components
|
|
import NavbarLogo from './navbar/NavbarLogo.vue';
|
|
import NavbarLinks from './navbar/NavbarLinks.vue';
|
|
import NavbarProjectActions from './navbar/NavbarProjectActions.vue';
|
|
import NavbarUserMenu from './navbar/NavbarUserMenu.vue';
|
|
import NavbarSocials from './navbar/NavbarSocials.vue';
|
|
import NavbarMobileMenu from './navbar/NavbarMobileMenu.vue';
|
|
|
|
defineEmits(['open-help']);
|
|
|
|
const isMobileMenuOpen = ref(false);
|
|
const isAuthModalOpen = ref(false);
|
|
const isProjectListOpen = ref(false);
|
|
const isSaveProjectModalOpen = ref(false);
|
|
|
|
const authStore = useAuthStore();
|
|
const projectStore = useProjectStore();
|
|
const settingsStore = useSettingsStore();
|
|
const { layers, columns, activeLayerId } = useLayers();
|
|
|
|
const { generateProjectJSON, loadProjectData } = useExportLayers(
|
|
layers,
|
|
columns,
|
|
toRef(settingsStore, 'negativeSpacingEnabled'),
|
|
activeLayerId,
|
|
toRef(settingsStore, 'backgroundColor'),
|
|
toRef(settingsStore, 'manualCellSizeEnabled'),
|
|
toRef(settingsStore, 'manualCellWidth'),
|
|
toRef(settingsStore, 'manualCellHeight')
|
|
);
|
|
|
|
const handleOpenProject = async (project: Project) => {
|
|
try {
|
|
if (project.data) {
|
|
await loadProjectData(project.data);
|
|
}
|
|
projectStore.currentProject = project;
|
|
} catch (e) {
|
|
console.error("Failed to open project", e);
|
|
alert("Failed to open project data");
|
|
}
|
|
};
|
|
|
|
const openSaveModal = () => {
|
|
isSaveProjectModalOpen.value = true;
|
|
}
|
|
|
|
const handleSaveProject = async (name: string) => {
|
|
try {
|
|
const data = await generateProjectJSON();
|
|
|
|
if (projectStore.currentProject && projectStore.currentProject.name === name) {
|
|
await projectStore.updateProject(projectStore.currentProject.id, data);
|
|
} else {
|
|
await projectStore.createProject(name, data);
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
alert("Failed to save project");
|
|
}
|
|
};
|
|
</script>
|
|
|