import React, { useState, useEffect } from 'react'; import { AuthProvider, AuthGuard, useAuth } from './AdminAuth'; import AdminLayout from './AdminLayout'; interface Section { id: string; type: string; title: string; config: Record; sort_order: number; enabled: boolean; } const SECTION_TYPES = [ { value: 'hero', label: 'Hero Banner' }, { value: 'featured_products', label: 'Featured Products' }, { value: 'collection', label: 'Collection' }, { value: 'brand_grid', label: 'Brand Grid' }, { value: 'deals', label: 'Latest Deals' }, { value: 'trending', label: 'Trending' }, { value: 'new_arrivals', label: 'New Arrivals' }, { value: 'custom_html', label: 'Custom HTML' }, ]; const TYPE_ICONS: Record = { hero: '🖼️', featured_products: '⭐', collection: '📁', brand_grid: '🏷️', deals: '🔥', trending: '📈', new_arrivals: '🆕', custom_html: '💻', }; function ConfigEditor({ section, onChange }: { section: Section; onChange: (config: Record) => void }) { const c = section.config || {}; const update = (key: string, value: any) => onChange({ ...c, [key]: value }); switch (section.type) { case 'hero': return (
update('title', e.target.value)} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
update('subtitle', e.target.value)} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
update('cta_text', e.target.value)} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
update('cta_url', e.target.value)} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
update('background_image', e.target.value)} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
); case 'featured_products': return (
update('max_items', parseInt(e.target.value))} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
update('product_ids', e.target.value.split(',').map((s: string) => s.trim()).filter(Boolean))} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
); case 'collection': return (
update('collection_slug', e.target.value)} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
update('limit', parseInt(e.target.value))} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
); case 'brand_grid': return (
update('brands', e.target.value.split(',').map((s: string) => s.trim()).filter(Boolean))} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" placeholder="Nike, Adidas, New Balance, Asics" />
); case 'deals': case 'trending': case 'new_arrivals': return (
update('limit', parseInt(e.target.value))} className="w-32 bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" /> Automatisch gevuld
); default: return null; } } function HomepageEditorContent() { const { token } = useAuth(); const [sections, setSections] = useState([]); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [editingId, setEditingId] = useState(null); const [dragIdx, setDragIdx] = useState(null); const [newType, setNewType] = useState('hero'); const [message, setMessage] = useState(''); const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }; useEffect(() => { fetch('/api/admin/homepage', { headers: { Authorization: `Bearer ${token}` } }) .then(r => r.json()) .then(d => setSections(d.sections || [])) .catch(() => {}) .finally(() => setLoading(false)); }, [token]); const flash = (msg: string) => { setMessage(msg); setTimeout(() => setMessage(''), 3000); }; const moveSection = (from: number, to: number) => { const next = [...sections]; const [item] = next.splice(from, 1); next.splice(to, 0, item); setSections(next.map((s, i) => ({ ...s, sort_order: i }))); }; const saveOrder = async () => { setSaving(true); try { await fetch('/api/admin/homepage', { method: 'PUT', headers, body: JSON.stringify({ reorder: true, ids: sections.map(s => s.id) }), }); flash('Volgorde opgeslagen ✓'); } catch { flash('Fout bij opslaan'); } setSaving(false); }; const toggleEnabled = async (section: Section) => { const updated = { ...section, enabled: !section.enabled }; await fetch('/api/admin/homepage', { method: 'PUT', headers, body: JSON.stringify({ id: section.id, type: section.type, title: section.title, config: section.config, enabled: updated.enabled }), }); setSections(prev => prev.map(s => s.id === section.id ? updated : s)); }; const saveSection = async (section: Section) => { await fetch('/api/admin/homepage', { method: 'PUT', headers, body: JSON.stringify({ id: section.id, type: section.type, title: section.title, config: section.config, enabled: section.enabled }), }); flash('Sectie opgeslagen ✓'); setEditingId(null); }; const addSection = async () => { const label = SECTION_TYPES.find(t => t.value === newType)?.label || newType; try { const res = await fetch('/api/admin/homepage', { method: 'POST', headers, body: JSON.stringify({ type: newType, title: label, config: {}, enabled: true }), }); const created = await res.json(); setSections(prev => [...prev, created]); flash('Sectie toegevoegd ✓'); } catch { flash('Fout bij toevoegen'); } }; const deleteSection = async (id: string) => { if (!confirm('Sectie verwijderen?')) return; await fetch('/api/admin/homepage', { method: 'DELETE', headers, body: JSON.stringify({ id }), }); setSections(prev => prev.filter(s => s.id !== id)); flash('Verwijderd ✓'); }; if (loading) return
Laden...
; return ( {message && (
{message}
)}

Sleep om te herschikken. Klik Edit om secties aan te passen.

{sections.length === 0 ? (
🏠
Nog geen homepage secties
Voeg hierboven een sectie toe om te beginnen
) : (
{sections.map((section, idx) => (
setDragIdx(idx)} onDragOver={e => e.preventDefault()} onDrop={() => { if (dragIdx !== null && dragIdx !== idx) moveSection(dragIdx, idx); setDragIdx(null); }} className={`bg-[#141414] border rounded-xl p-4 transition-all cursor-move ${section.enabled ? 'border-[#333]' : 'border-[#222] opacity-50'} ${dragIdx === idx ? 'border-[#00FF6A] scale-[1.02]' : 'hover:border-[#444]'}`} >
{TYPE_ICONS[section.type] || '📄'}
{section.title}
{SECTION_TYPES.find(t => t.value === section.type)?.label || section.type}
{editingId === section.id && (
setSections(prev => prev.map(s => s.id === section.id ? { ...s, title: e.target.value } : s))} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
setSections(prev => prev.map(s => s.id === section.id ? { ...s, config } : s))} />
)}
))}
)} {sections.length > 0 && (
)}
); } export default function HomepageEditorPage() { return ; }