From bcf4c1f797d94c95ee436ed0d6b57a3077c77336 Mon Sep 17 00:00:00 2001 From: Matt Ciaccio Date: Fri, 24 Apr 2026 15:36:27 +0200 Subject: [PATCH] feat(interests): add yacht-picker to interest form --- src/components/interests/interest-form.tsx | 107 +++++++++++---------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/src/components/interests/interest-form.tsx b/src/components/interests/interest-form.tsx index 256bb4e..69bb9c9 100644 --- a/src/components/interests/interest-form.tsx +++ b/src/components/interests/interest-form.tsx @@ -18,18 +18,8 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select'; -import { - Sheet, - SheetContent, - SheetHeader, - SheetTitle, - SheetFooter, -} from '@/components/ui/sheet'; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from '@/components/ui/popover'; +import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from '@/components/ui/sheet'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Command, CommandEmpty, @@ -41,6 +31,7 @@ import { import { Checkbox } from '@/components/ui/checkbox'; import { Separator } from '@/components/ui/separator'; import { TagPicker } from '@/components/shared/tag-picker'; +import { YachtPicker } from '@/components/yachts/yacht-picker'; import { apiFetch } from '@/lib/api/client'; import { useEntityOptions } from '@/hooks/use-entity-options'; import { createInterestSchema, type CreateInterestInput } from '@/lib/validators/interests'; @@ -71,6 +62,7 @@ interface InterestFormProps { id: string; clientId: string; clientName?: string | null; + yachtId?: string | null; berthId?: string | null; berthMooringNumber?: string | null; pipelineStage: string; @@ -101,6 +93,7 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps resolver: zodResolver(createInterestSchema), defaultValues: { clientId: '', + yachtId: undefined, pipelineStage: 'open', reminderEnabled: false, tagIds: [], @@ -111,26 +104,34 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps const reminderEnabled = watch('reminderEnabled'); const selectedClientId = watch('clientId'); const selectedBerthId = watch('berthId'); + const selectedYachtId = watch('yachtId'); - const { options: clientOptions, isLoading: clientsLoading, setSearch: setClientSearch } = - useEntityOptions({ - endpoint: '/api/v1/clients/options', - labelKey: 'fullName', - }); + const { + options: clientOptions, + isLoading: clientsLoading, + setSearch: setClientSearch, + } = useEntityOptions({ + endpoint: '/api/v1/clients/options', + labelKey: 'fullName', + }); - const { options: berthOptions, isLoading: berthsLoading, setSearch: setBerthSearch } = - useEntityOptions({ - endpoint: '/api/v1/berths/options', - labelKey: 'mooringNumber', - }); + const { + options: berthOptions, + isLoading: berthsLoading, + setSearch: setBerthSearch, + } = useEntityOptions({ + endpoint: '/api/v1/berths/options', + labelKey: 'mooringNumber', + }); useEffect(() => { if (interest && open) { reset({ clientId: interest.clientId, + yachtId: interest.yachtId ?? undefined, berthId: interest.berthId ?? undefined, - pipelineStage: interest.pipelineStage as typeof PIPELINE_STAGES[number], - leadCategory: interest.leadCategory as typeof LEAD_CATEGORIES[number] | undefined, + pipelineStage: interest.pipelineStage as (typeof PIPELINE_STAGES)[number], + leadCategory: interest.leadCategory as (typeof LEAD_CATEGORIES)[number] | undefined, source: interest.source ?? undefined, notes: interest.notes ?? undefined, reminderEnabled: interest.reminderEnabled ?? false, @@ -140,6 +141,7 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps } else if (!interest && open) { reset({ clientId: '', + yachtId: undefined, pipelineStage: 'open', reminderEnabled: false, tagIds: [], @@ -178,10 +180,7 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps {isEdit ? 'Edit Interest' : 'New Interest'} -
mutation.mutate(data))} - className="space-y-6 py-6" - > + mutation.mutate(data))} className="space-y-6 py-6"> {/* Client */}

@@ -202,16 +201,13 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps )} disabled={isEdit} > - {selectedClient?.label ?? (interest?.clientName ?? 'Select client...')} + {selectedClient?.label ?? interest?.clientName ?? 'Select client...'} - + {clientsLoading ? 'Loading...' : 'No clients found.'} @@ -258,16 +254,13 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps !selectedBerthId && 'text-muted-foreground', )} > - {selectedBerth?.label ?? (interest?.berthMooringNumber ?? 'Select berth...')} + {selectedBerth?.label ?? interest?.berthMooringNumber ?? 'Select berth...'} - + {berthsLoading ? 'Loading...' : 'No berths found.'} @@ -312,6 +305,24 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps

+ +
+ + setValue('yachtId', id ?? undefined)} + ownerFilter={ + selectedClientId ? { type: 'client', id: selectedClientId } : undefined + } + disabled={!selectedClientId} + placeholder={selectedClientId ? 'Select yacht...' : 'Select a client first'} + /> +

+ Required before the interest can leave the "Open" stage. +

+ {/* TODO: also include company-owned yachts where client is a member — requires autocomplete owner=any|company filter */} + {/* TODO: add "Add new yacht" inline shortcut (requires YachtForm integration) */} +
@@ -326,7 +337,9 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps - setValue('leadCategory', v ? v as typeof LEAD_CATEGORIES[number] : undefined) + setValue( + 'leadCategory', + v ? (v as (typeof LEAD_CATEGORIES)[number]) : undefined, + ) } > @@ -427,18 +443,11 @@ export function InterestForm({ open, onOpenChange, interest }: InterestFormProps {/* Tags */}
- setValue('tagIds', ids)} - /> + setValue('tagIds', ids)} />
-