import { useState, useRef, useEffect } from 'react'; import { Link, useNavigate, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useAuthStore } from '../../store/useAuthStore'; import { useProjectStore } from '../../store/useProjectStore'; import { ShareModal } from './ShareModal'; import { LanguageSwitcher } from './LanguageSwitcher'; import { useLocalizedHref, useCurrentLocale } from '../../i18n/useLocalizedNavigate'; import { blogUrlFor } from '../../i18n/path'; import { trackVisitGitHub, trackVisitDiscord } from '../../utils/analytics'; import type { AutoSaveState } from '../../hooks/useAutoSaveProject'; import './LanguageSwitcher.css'; const GITHUB_URL = 'https://github.com/davidmonterocrespo24/velxio'; const DISCORD_URL = 'https://discord.gg/3mARjJrh4E'; interface AppHeaderProps { /** Optional auto-save state — when set, renders a save status indicator. */ autoSave?: AutoSaveState; } const SAVE_STATUS_COPY: Record = { idle: { label: 'Saved', color: '#7d8590' }, dirty: { label: 'Unsaved changes', color: '#f0883e' }, saving: { label: 'Saving…', color: '#3fb950' }, saved: { label: 'Saved', color: '#3fb950' }, error: { label: 'Save failed', color: '#f85149' }, }; const AutoSaveIndicator: React.FC<{ state: AutoSaveState }> = ({ state }) => { const meta = SAVE_STATUS_COPY[state.status]; const tip = state.status === 'error' && state.errorMessage ? `Auto-save failed: ${state.errorMessage}` : state.lastSavedAt ? `Last saved ${new Date(state.lastSavedAt).toLocaleTimeString()}` : 'Auto-save ready'; return (
{meta.label}
); }; export const AppHeader: React.FC = ({ autoSave }) => { const user = useAuthStore((s) => s.user); const logout = useAuthStore((s) => s.logout); const navigate = useNavigate(); const location = useLocation(); const currentProject = useProjectStore((s) => s.currentProject); const [dropdownOpen, setDropdownOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false); const [showShareModal, setShowShareModal] = useState(false); const dropdownRef = useRef(null); const { t } = useTranslation(); const localize = useLocalizedHref(); const currentLocale = useCurrentLocale(); useEffect(() => { const handler = (e: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { setDropdownOpen(false); } }; document.addEventListener('mousedown', handler); return () => document.removeEventListener('mousedown', handler); }, []); // Close mobile menu on route change useEffect(() => { setMenuOpen(false); }, [location.pathname]); const handleLogout = async () => { setDropdownOpen(false); await logout(); navigate(localize('/')); }; const isActive = (path: string) => location.pathname === localize(path) ? ' header-nav-link-active' : ''; return (
{/* Brand */}
Velxio
{/* Main nav links (desktop) */}
{/* Right: language + share + auth + mobile hamburger */}
{/* Auto-save status — only when a project is loaded and the editor page mounted the hook */} {autoSave && currentProject && } {/* Share button — visible when a project is loaded */} {currentProject && location.pathname === '/editor' && ( )} {/* Auth UI */} {user ? (
{dropdownOpen && (
setDropdownOpen(false)} style={{ display: 'block', padding: '9px 14px', color: '#ccc', textDecoration: 'none', fontSize: 13, }} > {t('header.auth.myProjects')}
)}
) : (
{t('header.auth.signIn')} {t('header.auth.signUp')}
)} {/* Mobile hamburger */}
{showShareModal && setShowShareModal(false)} />}
); };