import React, { useState, useEffect } from 'react'; import { AuthProvider, AuthGuard, useAuth } from './AdminAuth'; import AdminLayout from './AdminLayout'; interface Collection { id: string; slug: string; name_en: string; name_nl: string; description: string | null; type: 'smart' | 'manual' | 'hybrid'; rules_json: any; sort_by: string; is_active: boolean; is_featured: boolean; max_products: number | null; } const RULE_FIELDS = ['brand', 'category', 'price', 'offer_count', 'is_sneaker', 'name']; const RULE_OPS = ['equals', 'not_equals', 'contains', 'greater_than', 'less_than', 'in']; interface Rule { field: string; operator: string; value: string; } function RuleRow({ rule, onChange, onRemove }: { rule: Rule; onChange: (r: Rule) => void; onRemove: () => void }) { return (
onChange({ ...rule, value: e.target.value })} className="bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5] flex-1" placeholder="Waarde" />
); } function CollectionBuilderContent() { const { token } = useAuth(); const [collections, setCollections] = useState([]); const [loading, setLoading] = useState(true); const [editing, setEditing] = useState(null); const [rules, setRules] = useState([]); const [showForm, setShowForm] = useState(false); const [refreshing, setRefreshing] = useState>(new Set()); const [message, setMessage] = useState(''); const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }; const flash = (msg: string) => { setMessage(msg); setTimeout(() => setMessage(''), 3000); }; const loadCollections = () => { fetch('/api/admin/collections', { headers: { Authorization: `Bearer ${token}` } }) .then(r => r.json()) .then(d => setCollections(d.collections || [])) .catch(() => {}) .finally(() => setLoading(false)); }; useEffect(() => { loadCollections(); }, [token]); const rulesFromJson = (json: any): Rule[] => { if (!json || !json.rules) return []; return (json.rules || []).map((r: any) => ({ field: r.field || 'brand', operator: r.operator || 'equals', value: String(r.value || ''), })); }; const rulesToJson = (rules: Rule[]) => ({ operator: 'AND', rules: rules.map(r => ({ field: r.field, operator: r.operator, value: r.value })), }); const startEdit = (c: Collection) => { setEditing({ ...c }); setRules(rulesFromJson(c.rules_json)); setShowForm(true); }; const startNew = () => { setEditing({ id: '', slug: '', name_en: '', name_nl: '', description: null, type: 'smart', rules_json: null, sort_by: 'relevance', is_active: true, is_featured: false, max_products: 50, }); setRules([{ field: 'brand', operator: 'equals', value: '' }]); setShowForm(true); }; const save = async () => { if (!editing) return; const data = { ...editing, rules_json: rules.length > 0 ? rulesToJson(rules) : null, }; try { if (editing.id) { await fetch('/api/admin/collections', { method: 'PUT', headers, body: JSON.stringify({ id: data.id, name_en: data.name_en, name_nl: data.name_nl, description: data.description, rules_json: data.rules_json, sort_by: data.sort_by, is_active: data.is_active, is_featured: data.is_featured, max_products: data.max_products }), }); } else { await fetch('/api/admin/collections', { method: 'POST', headers, body: JSON.stringify({ slug: data.slug, name_en: data.name_en, name_nl: data.name_nl, description: data.description, type: data.type, rules_json: data.rules_json, sort_by: data.sort_by, is_featured: data.is_featured, max_products: data.max_products }), }); } flash('Opgeslagen ✓'); loadCollections(); setShowForm(false); setEditing(null); } catch { flash('Fout bij opslaan'); } }; const deleteCollection = async (id: string) => { if (!confirm('Collection verwijderen?')) return; await fetch('/api/admin/collections', { method: 'DELETE', headers, body: JSON.stringify({ id }) }); loadCollections(); flash('Verwijderd ✓'); }; const refreshCollection = async (id: string) => { setRefreshing(prev => new Set(prev).add(id)); try { const res = await fetch(`/api/admin/collections/${id}/refresh`, { method: 'POST', headers }); const d = await res.json(); flash(`Vernieuwd: ${d.products || 0} producten`); } catch { flash('Fout bij vernieuwen'); } setRefreshing(prev => { const n = new Set(prev); n.delete(id); return n; }); }; if (loading) return
Laden...
; return ( {message && (
{message}
)}
{showForm && editing && (

{editing.id ? 'Bewerken' : 'Nieuwe'} Collection

setEditing({ ...editing, name_en: e.target.value })} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
setEditing({ ...editing, name_nl: e.target.value })} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5]" />
setEditing({ ...editing, slug: e.target.value })} disabled={!!editing.id} className="w-full bg-[#0A0A0A] border border-[#333] rounded-lg px-3 py-2 text-sm text-[#F5F5F5] disabled:opacity-50" />