TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1'use client';23import { useActionState } from 'react';4import { createCollectionAction, updateCollectionAction } from '@/lib/account/actions';5import { idle } from '@/lib/auth/state';6import { Field, FormMessage, Select, SubmitButton, TextArea, TextInput } from '@/components/account/form';78const KINDS = [9 ['collection', 'Collection'],10 ['wishlist', 'Wishlist (with budget)'],11 ['vault', 'Vault / storage'],12 ['sold', 'Sold archive'],13] as const;1415export function CreateCollectionForm() {16 const [state, action] = useActionState(createCollectionAction, idle);17 return <CollectionFields state={state} action={action} submitLabel="Create collection" />;18}1920export function EditCollectionForm({ collection }: { collection: { id: string; name: string; description: string | null; kind: string; budgetUsd: number | null; color: string | null } }) {21 const [state, action] = useActionState(updateCollectionAction, idle);22 return <CollectionFields state={state} action={action} submitLabel="Save changes" initial={collection} />;23}2425function CollectionFields({ state, action, submitLabel, initial }: { state: import('@/lib/auth/state').ActionState; action: (fd: FormData) => void; submitLabel: string; initial?: { id: string; name: string; description: string | null; kind: string; budgetUsd: number | null; color: string | null } }) {26 return (27 <form action={action} className="space-y-4" noValidate>28 {initial ? <input type="hidden" name="collectionId" value={initial.id} /> : null}29 <FormMessage state={state} />30 <div className="grid gap-4 sm:grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,1fr)_80px]">31 <Field label="Name" name="name" error={state.fieldErrors?.name}>32 <TextInput name="name" required maxLength={80} defaultValue={initial?.name ?? ''} placeholder="e.g. Vintage Pokémon, Watch box, 2025 pickups" />33 </Field>34 <Field label="Type" name="kind">35 <Select name="kind" defaultValue={initial?.kind ?? 'collection'}>36 {KINDS.map(([v, l]) => (37 <option key={v} value={v}>38 {l}39 </option>40 ))}41 </Select>42 </Field>43 <Field label="Budget (USD, optional)" name="budgetUsd" error={state.fieldErrors?.budgetUsd}>44 <TextInput name="budgetUsd" type="number" min={0} step="1" defaultValue={initial?.budgetUsd ?? ''} placeholder="wishlists" />45 </Field>46 <Field label="Colour" name="color">47 <input type="color" name="color" defaultValue={initial?.color ?? '#1f3a8a'} className="h-10 w-full cursor-pointer rounded-md border border-border bg-elevated p-1 md:h-9" />48 </Field>49 </div>50 <Field label="Description (optional)" name="description">51 <TextArea name="description" maxLength={500} defaultValue={initial?.description ?? ''} placeholder="What lives here?" className="min-h-[60px]" />52 </Field>53 <SubmitButton pendingText="Saving…">{submitLabel}</SubmitButton>54 </form>55 );56}57