From ed69a4b8408da2f3b56d393d82aefed05241cc34 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 22 Jun 2026 20:09:42 -0400 Subject: [PATCH] x --- apps/admin/src/App.tsx | 2 - apps/admin/src/pages/HeroSettingsPage.tsx | 441 ---------------------- apps/backend/prisma/schema.prisma | 28 -- apps/backend/src/index.ts | 3 +- apps/backend/src/routes/hero.ts | 127 ------- apps/mcp-server/index.ts | 28 +- 6 files changed, 3 insertions(+), 626 deletions(-) delete mode 100644 apps/admin/src/pages/HeroSettingsPage.tsx delete mode 100644 apps/backend/src/routes/hero.ts diff --git a/apps/admin/src/App.tsx b/apps/admin/src/App.tsx index a69202d..787359a 100644 --- a/apps/admin/src/App.tsx +++ b/apps/admin/src/App.tsx @@ -5,7 +5,6 @@ import ProductsPage from './pages/ProductsPage' import ProductEditPage from './pages/ProductEditPage' import CategoriesPage from './pages/CategoriesPage' import CustomersPage from './pages/CustomersPage' -import HeroSettingsPage from './pages/HeroSettingsPage' import PageBuilderPage from './pages/PageBuilderPage' import RawMaterialsPage from './pages/RawMaterialsPage' import LoginPage from './pages/LoginPage' @@ -50,7 +49,6 @@ function App() { } /> } /> } /> - } /> } /> } /> } /> diff --git a/apps/admin/src/pages/HeroSettingsPage.tsx b/apps/admin/src/pages/HeroSettingsPage.tsx deleted file mode 100644 index 9ff9a09..0000000 --- a/apps/admin/src/pages/HeroSettingsPage.tsx +++ /dev/null @@ -1,441 +0,0 @@ -import { useState, useEffect } from 'react' -import { - LayoutDashboard, - Plus, - Trash2, - CheckCircle2, - Circle, - Image as ImageIcon, - UploadCloud, - Loader2, - X, - ExternalLink, - ChevronRight, - Info, - ClipboardPaste -} from 'lucide-react' -import { API_BASE, type Hero } from '@homaroma/types' -import MediaLibraryModal from '../components/MediaLibraryModal' - -export default function HeroSettingsPage() { - const [heroes, setHeroes] = useState([]) - const [loading, setLoading] = useState(true) - const [isModalOpen, setIsModalOpen] = useState(false) - const [isUploading, setIsUploading] = useState(false) - const [editingHero, setEditingHero] = useState | null>(null) - - const [isMediaModalOpen, setIsMediaModalOpen] = useState(false) - const [onSelectMedia, setOnSelectMedia] = useState<((url: string) => void) | null>(null) - - const fetchData = async () => { - setLoading(true) - try { - const res = await fetch(`${API_BASE}/hero/all`) - const data = await res.json() - setHeroes(data) - } catch (err) { - console.error('Fetch error:', err) - } finally { - setLoading(false) - } - } - - useEffect(() => { - fetchData() - }, []) - - const handleSave = async (e: React.FormEvent) => { - e.preventDefault() - if (!editingHero) return - - try { - const res = await fetch(`${API_BASE}/hero`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(editingHero) - }) - if (res.ok) { - setIsModalOpen(false) - fetchData() - } - } catch (err) { - console.error('Save error:', err) - } - } - - const handleActivate = async (id: number) => { - try { - const res = await fetch(`${API_BASE}/hero/${id}/activate`, { - method: 'PATCH' - }) - if (res.ok) { - fetchData() - } - } catch (err) { - console.error('Activate error:', err) - } - } - - const handleDelete = async (id: number) => { - if (!confirm('Are you sure you want to delete this Hero entry?')) return - try { - const res = await fetch(`${API_BASE}/hero/${id}`, { - method: 'DELETE' - }) - if (res.ok) { - fetchData() - } - } catch (err) { - console.error('Delete error:', err) - } - } - - const handleUpload = async (file: File) => { - setIsUploading(true) - const formData = new FormData() - formData.append('file', file) - - try { - const res = await fetch(`${API_BASE}/upload`, { - method: 'POST', - body: formData - }) - const data = await res.json() - if (data.url) { - setEditingHero(prev => ({ ...prev, imageUrl: data.url })) - } - } catch (err) { - console.error('Upload error:', err) - } finally { - setIsUploading(false) - } - } - - const handlePasteFromClipboard = async () => { - try { - const items = await navigator.clipboard.read() - for (const item of items) { - const imageTypes = item.types.filter(t => t.startsWith('image/')) - for (const type of imageTypes) { - const blob = await item.getType(type) - const file = new File([blob], 'pasted-image.png', { type }) - handleUpload(file) - return - } - } - alert('No image found in clipboard') - } catch (err) { - console.error('Clipboard error:', err) - alert('Please allow clipboard access or copy an image first.') - } - } - - const openAddModal = () => { - setEditingHero({ - tagline: 'A New Paradigm of Calm', - title: 'Inhale [Serenity]', - description: 'Crafting premium sensory experiences that transform your space into a sanctuary of peace.', - imageUrl: '/images/hero.png', - buttonText: 'Explore Collection', - buttonLink: '/shop', - isActive: false - }) - setIsModalOpen(true) - } - - const openEditModal = (hero: Hero) => { - setEditingHero(hero) - setIsModalOpen(true) - } - - return ( -
- {!isModalOpen ? ( - <> -
-
-

Hero Management

-

Control the first impression of your sanctuary.

-
- -
- -
- {loading ? ( - Array.from({ length: 3 }).map((_, i) => ( -
- )) - ) : heroes.length === 0 ? ( -
- -

No hero entries found. Create your first one!

-
- ) : ( - heroes.map((hero) => ( -
-
- {/* Preview Image */} -
- Hero Preview - {!hero.isActive && ( -
- Inactive -
- )} -
- - {/* Content */} -
-
-
-
- - {hero.tagline} - - {hero.isActive && ( - - - Live on Site - - )} -
-

ID: HERO-{hero.id.toString().padStart(3, '0')}

-
- -
-

- {hero.title.split('[').map((part, i) => { - if (part.includes(']')) { - const [accent, rest] = part.split(']') - return ( - - {accent} - {rest} - - ) - } - return {part} - })} -

-

- {hero.description} -

-
- -
-
- - {hero.buttonText} -
-
- - {hero.buttonLink} -
-
-
- -
- {!hero.isActive && ( - - )} - - -
-
-
-
- )) - )} -
- - ) : ( - editingHero && ( -
-
-

- - {editingHero.id ? 'Edit Hero Section' : 'Create New Hero'} -

- -
- -
-
- {/* Image Upload Area */} -
-
- - -
-
{ - setOnSelectMedia(() => (url: string) => setEditingHero(prev => ({ ...prev, imageUrl: url }))) - setIsMediaModalOpen(true) - }} - > - {editingHero.imageUrl ? ( - <> - Hero Background -
- -
- - ) : ( -
- -

Select Image

-
- )} - - {isUploading && ( -
- -
- )} -
-
- -

Recommended size: 1920x1080px. High quality but optimized for web.

-
-
- - {/* Content Fields */} -
- - setEditingHero({ ...editingHero, tagline: e.target.value })} - className="admin-input w-full" - placeholder="e.g. A New Paradigm of Calm" - /> -
- -
- - setEditingHero({ ...editingHero, title: e.target.value })} - className="admin-input w-full" - placeholder="e.g. Inhale [Serenity]" - /> -

Use [brackets] for the accent serif font.

-
- -
- -