diff --git a/public/models/robot-doctor.glb b/public/models/robot-doctor.glb new file mode 100644 index 0000000..68772f7 Binary files /dev/null and b/public/models/robot-doctor.glb differ diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 866f54f..3277624 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -35,6 +35,8 @@ export default function AdminPage() { const [rowGlbFiles, setRowGlbFiles] = useState>({}); const [rowGlbUploading, setRowGlbUploading] = useState>({}); const [rowGlbError, setRowGlbError] = useState>({}); + const [syncingGlbs, setSyncingGlbs] = useState(false); + const [syncResult, setSyncResult] = useState(''); useEffect(() => { pricingStore.getState().hydrate(); }, []); @@ -99,6 +101,49 @@ export default function AdminPage() { } }; + /** Reads all .glb files already on the server and links them to matching personas/items */ + const handleSyncGlbs = async () => { + setSyncingGlbs(true); + setSyncResult(''); + try { + const res = await fetch('/api/admin/list-models/'); + const data = await res.json(); + const models: { id: string; modelPath: string; filename: string }[] = data.models ?? []; + let count = 0; + models.forEach(({ id, modelPath }) => { + // Update pricing item if it exists + const item = pricingStore.getState().items.find((i) => i.id === id); + if (item && item.modelPath !== modelPath) { + pricingStore.getState().updateItem(id, { modelPath }); + count++; + } + // Update or create persona + const existing = personaStore.getState().personas.find((p) => p.id === id); + if (existing) { + if (existing.modelPath !== modelPath) { + personaStore.getState().updatePersona(id, { modelPath }); + count++; + } + } else if (item) { + personaStore.getState().addPersona({ + id, + label: item.label, + description: item.label, + colors: { torso: '#3b82f6', legs: '#3b82f6' }, + modelPath, + }); + count++; + } + }); + setSyncResult(count > 0 ? `✓ Synced ${models.length} model(s)` : `✓ Already up to date (${models.length} model(s))`); + setTimeout(() => setSyncResult(''), 3000); + } catch { + setSyncResult('Sync failed'); + } finally { + setSyncingGlbs(false); + } + }; + const handleAddItem = async () => { setAddItemError(''); const id = newItem.id.trim().toLowerCase().replace(/_/g, '-').replace(/\s+/g, '-'); @@ -480,7 +525,11 @@ export default function AdminPage() { {addItemError &&

{addItemError}

} -
+
+ {syncResult && {syncResult}} +