Files
spritesheet-generator/src/components/layout/Navbar.vue

127 lines
5.1 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 @save-project="handleQuickSave" @open-save-modal="openSaveModal" @open-new-project-modal="isNewProjectModalOpen = true" @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')" @save-project="handleQuickSave" @open-save-modal="openSaveModal" @open-new-project-modal="isNewProjectModalOpen = true" @open-project-list="isProjectListOpen = true" />
</nav>
<AuthModal :is-open="isAuthModalOpen" @close="isAuthModalOpen = false" />
<ProjectList :is-open="isProjectListOpen" @close="isProjectListOpen = false" @open-project="handleOpenProject" />
<SaveProjectModal :is-open="isSaveProjectModalOpen" :initial-name="saveModalInitialName" @close="isSaveProjectModalOpen = false" @save="handleSaveProject" />
<NewProjectModal :is-open="isNewProjectModalOpen" @close="isNewProjectModalOpen = false" @create="handleCreateNewProject" />
</template>
<script setup lang="ts">
import { ref, computed } 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 NewProjectModal from '@/components/project/NewProjectModal.vue';
import { useProjectStore, type Project } from '@/stores/useProjectStore';
import { useProjectManager } from '@/composables/useProjectManager';
// 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 isNewProjectModalOpen = ref(false);
const saveMode = ref<'save' | 'save-as'>('save');
const authStore = useAuthStore();
const projectStore = useProjectStore();
const { createProject, openProject, saveProject, saveAsProject } = useProjectManager();
const handleOpenProject = async (project: Project) => {
await openProject(project);
};
const openSaveModal = (mode: 'save' | 'save-as' = 'save') => {
saveMode.value = mode;
isSaveProjectModalOpen.value = true;
};
const saveModalInitialName = computed(() => {
if (saveMode.value === 'save-as') {
return projectStore.currentProject?.name ? projectStore.currentProject.name + ' (copy)' : '';
}
return projectStore.currentProject?.name;
});
const handleQuickSave = async () => {
if (projectStore.currentProject?.name) {
await saveProject(projectStore.currentProject.name);
} else {
openSaveModal('save');
}
};
const handleSaveProject = async (name: string) => {
try {
if (saveMode.value === 'save-as') {
await saveAsProject(name);
} else {
await saveProject(name);
}
} catch {
// Error handled in composable
}
};
const handleCreateNewProject = (config: { width: number; height: number; columns: number; rows: number }) => {
createProject(config);
};
</script>