diff --git a/apps/admin/src/pages/MenuManagerPage.tsx b/apps/admin/src/pages/MenuManagerPage.tsx index 9666022..037e114 100644 --- a/apps/admin/src/pages/MenuManagerPage.tsx +++ b/apps/admin/src/pages/MenuManagerPage.tsx @@ -1,6 +1,6 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef } from 'react' import { API_BASE, type Menu } from '@homaroma/types' -import { Save, Loader2, Plus, Trash2, GripVertical, Copy, Check } from 'lucide-react' +import { Save, Loader2, Plus, Trash2, GripVertical, Copy, Check, Download, Upload } from 'lucide-react' const TreeNodeEditor = ({ node, type, depth, onChange, onRemove }: any) => { const childrenKey = type === 'root' ? 'columns' : 'links'; @@ -99,6 +99,7 @@ export default function MenuManagerPage() { // We'll manage multiple menus, e.g., 'main' and 'footer-explore' const [selectedMenuName, setSelectedMenuName] = useState('main') + const fileInputRef = useRef(null) useEffect(() => { Promise.all([ @@ -139,6 +140,55 @@ export default function MenuManagerPage() { setMenus(menus.map(m => m.name === selectedMenuName ? { ...m, items: newItems } : m)) } + const handleExport = () => { + const dataStr = JSON.stringify(currentMenu, null, 2) + const blob = new Blob([dataStr], { type: 'application/json' }) + const url = URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = `menu-${selectedMenuName}-snapshot-${new Date().toISOString().split('T')[0]}.json` + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + URL.revokeObjectURL(url) + } + + const handleImport = (e: React.ChangeEvent) => { + const file = e.target.files?.[0] + if (!file) return + + const reader = new FileReader() + reader.onload = async (event) => { + try { + const content = event.target?.result as string + const parsed = JSON.parse(content) + + if (!parsed || typeof parsed !== 'object') { + throw new Error('Invalid JSON format') + } + + const newItems = Array.isArray(parsed.items) ? parsed.items : [] + const newPayload = parsed.payload || [] + + setMenus(menus.map(m => m.name === selectedMenuName ? { ...m, items: newItems, payload: newPayload } : m)) + + if (!menus.find(m => m.name === selectedMenuName)) { + setMenus([...menus, { id: Date.now(), name: selectedMenuName, items: newItems, payload: newPayload }]) + } + + alert('Menu loaded from file! Click "Save Menu" to apply changes.') + } catch (err) { + console.error(err) + alert('Failed to parse JSON file') + } finally { + if (fileInputRef.current) { + fileInputRef.current.value = '' + } + } + } + reader.readAsText(file) + } + const handleSave = async (e: React.FormEvent) => { e.preventDefault() setSaving(true) @@ -183,17 +233,42 @@ export default function MenuManagerPage() {
- {['main', 'footer-explore', 'footer-support'].map(name => ( +
+ {['main', 'footer-explore', 'footer-support'].map(name => ( + + ))} +
+
+ - ))} + +
diff --git a/apps/spa/src/components/Footer.tsx b/apps/spa/src/components/Footer.tsx index 4286691..a68fbf4 100644 --- a/apps/spa/src/components/Footer.tsx +++ b/apps/spa/src/components/Footer.tsx @@ -11,7 +11,7 @@ export default function Footer({ categories = [] }: FooterProps) { const [exploreMenu, setExploreMenu] = useState([]) const [supportMenu, setSupportMenu] = useState([]) const [settings, setSettings] = useState(null) - const brandName = settings?.brandName || 'HomAroma' + const brandName = settings?.brandName || '' const translateMenuLabel = (item: MenuItem) => { const lang = localStorage.getItem('homaroma_lang') || 'en' diff --git a/apps/spa/src/components/Navbar.tsx b/apps/spa/src/components/Navbar.tsx index ab1e9fe..f14ed59 100644 --- a/apps/spa/src/components/Navbar.tsx +++ b/apps/spa/src/components/Navbar.tsx @@ -144,7 +144,7 @@ export default function Navbar({ topOffsetClassName = 'top-0' }: NavbarProps) { : (hasAnnouncement ? 'top-[32px] md:top-[40px]' : 'top-0') const finalTopClassName = scrolled ? 'top-0' : computedOffset - const brandName = settings?.brandName || 'HomAroma' + const brandName = settings?.brandName || '' return ( <> diff --git a/apps/website/public/images/hero.png b/apps/website/public/images/hero.png deleted file mode 100644 index 2225541..0000000 Binary files a/apps/website/public/images/hero.png and /dev/null differ diff --git a/apps/website/public/images/oil_ozone.png b/apps/website/public/images/oil_ozone.png deleted file mode 100644 index 2f583a7..0000000 Binary files a/apps/website/public/images/oil_ozone.png and /dev/null differ diff --git a/apps/website/public/images/reed_diffuser.png b/apps/website/public/images/reed_diffuser.png deleted file mode 100644 index b294126..0000000 Binary files a/apps/website/public/images/reed_diffuser.png and /dev/null differ diff --git a/apps/website/src/components/Footer.tsx b/apps/website/src/components/Footer.tsx index 7f789a3..a936367 100644 --- a/apps/website/src/components/Footer.tsx +++ b/apps/website/src/components/Footer.tsx @@ -52,7 +52,7 @@ export default function Footer({ // Social links — use settings if available, fallback to placeholder buttons const hasSocialLinks = settings && (settings.facebookUrl || settings.instagramUrl || settings.tiktokUrl) - const brandName = settings?.brandName || 'HomAroma' + const brandName = settings?.brandName || '' return (