import { useCollection, useIdentity } from '@deplixo/sdk'; import { BOX_SIZES, STYLES, STEPS, TREATS } from './components/constants.js'; import { StepBox, StepStyle, StepColors, StepAccent, StepTreats, StepDetails } from './components/Steps.jsx'; import Concept from './components/Concept.jsx'; const EMPTY = { box: null, customQty: 12, style: null, colors: [], accent: null, treats: [], occasion: '', nameNum: '', notes: '', }; function Wizard({ onSaved }) { const [step, setStep] = React.useState(0); const [selection, setSelection] = React.useState(EMPTY); const [savedId, setSavedId] = React.useState(null); const designs = useCollection('designs'); const update = (patch) => setSelection(s => ({ ...s, ...patch })); const box = BOX_SIZES.find(b => b.id === selection.box); const style = STYLES.find(s => s.id === selection.style); const canAdvance = () => { switch (step) { case 0: return !!selection.box; case 1: return !!selection.style; case 2: return style ? selection.colors.length >= style.minColors : false; case 3: return true; // accent optional case 4: return selection.treats.length >= 1; case 5: return true; // details optional default: return true; } }; const restart = () => { setSelection(EMPTY); setStep(0); setSavedId(null); }; const saveConcept = async (concept) => { const record = { selection, concept, savedAt: new Date().toISOString(), }; const created = await designs.add(record); setSavedId(created?.id || 'saved'); if (onSaved) onSaved(); }; return (
{STEPS.map((label, i) => (
{label}
))}
{step === 0 && } {step === 1 && } {step === 2 && } {step === 3 && } {step === 4 && } {step === 5 && } {step === 6 && ( )} {step < 6 && (
)}
); } function SavedDesigns() { const { items, loading, remove } = useCollection('designs'); const { user } = useIdentity(); const mine = (items || []).filter(d => d.author?.id === user?.id); const [viewing, setViewing] = React.useState(null); if (loading) return
Loading saved designs…
; if (!mine.length) return (

Saved designs

You haven't saved any designs yet. Complete the wizard and tap Save this design to keep it here.
); if (viewing) { const d = viewing; const box = BOX_SIZES.find(b => b.id === d.value?.selection?.box); const style = STYLES.find(s => s.id === d.value?.selection?.style); return (

{d.value?.concept?.title || 'Saved design'}

{d.value?.concept?.title}

{d.value?.concept?.tagline}

Box{box?.name}
Style{style?.name}
Colors{(d.value?.selection?.colors || []).join(', ')}
Accent{d.value?.selection?.accent || 'None'}
Treats {(d.value?.selection?.treats || []).map(id => TREATS.find(t => t.id === id)?.name).filter(Boolean).join(', ')}

Overall design

{d.value?.concept?.overallDesign}

{d.value?.concept?.treatPlan && (

Treat-by-treat plan

{d.value.concept.treatPlan.map((p, i) => { const t = TREATS.find(x => x.id === p.treatId); return (
{t?.emoji} {t?.name || p.treatId} ×{p.count}
{p.decoration}
); })}
)}
); } return (

Saved designs

Your previously generated design concepts.

{mine.map(d => { const box = BOX_SIZES.find(b => b.id === d.value?.selection?.box); const style = STYLES.find(s => s.id === d.value?.selection?.style); return (
setViewing(d)}>

{d.value?.concept?.title || 'Untitled concept'}

{box?.name} • {style?.name}
{new Date(d.value?.savedAt || d.createdAt).toLocaleDateString()}
); })}
); } function App() { const [tab, setTab] = React.useState('design'); return (

Sweet Studio

AI-powered design concepts for chocolate-covered treat boxes

{tab === 'design' && setTab('saved')} />} {tab === 'saved' && }
); } ReactDOM.createRoot(document.getElementById('root')).render();