From 3ba2077e0ab18597f078578efbf2404a3b3549d2 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 12 Oct 2025 16:28:28 +0000 Subject: [PATCH] Refactor: Restore type safety in forms --- src/components/admin/DesignerForm.tsx | 37 +++++++++++++++----- src/components/admin/ManufacturerForm.tsx | 39 +++++++++++++++++----- src/components/admin/OperatorForm.tsx | 37 +++++++++++++++----- src/components/admin/PropertyOwnerForm.tsx | 24 +++++++++++-- 4 files changed, 109 insertions(+), 28 deletions(-) diff --git a/src/components/admin/DesignerForm.tsx b/src/components/admin/DesignerForm.tsx index 09f71f88..330cb9e2 100644 --- a/src/components/admin/DesignerForm.tsx +++ b/src/components/admin/DesignerForm.tsx @@ -21,6 +21,26 @@ import { useAuth } from '@/hooks/useAuth'; import { toast } from 'sonner'; import { useNavigate } from 'react-router-dom'; +// Raw form input state (before Zod transformation) +interface DesignerFormInput { + name: string; + slug: string; + company_type: 'designer' | 'manufacturer' | 'operator' | 'property_owner'; + description?: string; + person_type: 'company' | 'individual' | 'firm' | 'organization'; + founded_year?: string; + founded_date?: string; + founded_date_precision?: 'day' | 'month' | 'year'; + headquarters_location?: string; + website_url?: string; + images?: { + uploaded: any[]; + banner_assignment?: number | null; + card_assignment?: number | null; + }; +} + +// Zod output type (after transformation) type DesignerFormData = z.infer; interface DesignerFormProps { @@ -51,8 +71,9 @@ export function DesignerForm({ onSubmit, onCancel, initialData }: DesignerFormPr defaultValues: { name: initialData?.name || '', slug: initialData?.slug || '', + company_type: 'designer' as const, description: initialData?.description || '', - person_type: initialData?.person_type || 'company', + person_type: initialData?.person_type || ('company' as const), website_url: initialData?.website_url || '', founded_year: initialData?.founded_year ? String(initialData.founded_year) : '', headquarters_location: initialData?.headquarters_location || '', @@ -78,13 +99,13 @@ export function DesignerForm({ onSubmit, onCancel, initialData }: DesignerFormPr setIsSubmitting(true); try { - if (initialData?.id) { - await submitDesignerUpdate(initialData.id, data as unknown as DesignerFormData, user.id); - toast.success('Designer update submitted for review'); - } else { - await submitDesignerCreation(data as unknown as DesignerFormData, user.id); - toast.success('Designer submitted for review'); - } + if (initialData?.id) { + await submitDesignerUpdate(initialData.id, data, user.id); + toast.success('Designer update submitted for review'); + } else { + await submitDesignerCreation(data, user.id); + toast.success('Designer submitted for review'); + } onCancel(); } catch (error) { console.error('Submission error:', error); diff --git a/src/components/admin/ManufacturerForm.tsx b/src/components/admin/ManufacturerForm.tsx index b6813bcf..2765236d 100644 --- a/src/components/admin/ManufacturerForm.tsx +++ b/src/components/admin/ManufacturerForm.tsx @@ -21,6 +21,26 @@ import { useAuth } from '@/hooks/useAuth'; import { toast } from 'sonner'; import { useNavigate } from 'react-router-dom'; +// Raw form input state (before Zod transformation) +interface ManufacturerFormInput { + name: string; + slug: string; + company_type: 'designer' | 'manufacturer' | 'operator' | 'property_owner'; + description?: string; + person_type: 'company' | 'individual' | 'firm' | 'organization'; + founded_year?: string; + founded_date?: string; + founded_date_precision?: 'day' | 'month' | 'year'; + headquarters_location?: string; + website_url?: string; + images?: { + uploaded: any[]; + banner_assignment?: number | null; + card_assignment?: number | null; + }; +} + +// Zod output type (after transformation) type ManufacturerFormData = z.infer; interface ManufacturerFormProps { @@ -51,12 +71,13 @@ export function ManufacturerForm({ onSubmit, onCancel, initialData }: Manufactur defaultValues: { name: initialData?.name || '', slug: initialData?.slug || '', + company_type: 'manufacturer' as const, description: initialData?.description || '', - person_type: initialData?.person_type || 'company', + person_type: initialData?.person_type || ('company' as const), website_url: initialData?.website_url || '', founded_year: initialData?.founded_year ? String(initialData.founded_year) : '', founded_date: initialData?.founded_date || (initialData?.founded_year ? `${initialData.founded_year}-01-01` : ''), - founded_date_precision: initialData?.founded_date_precision || (initialData?.founded_year ? 'year' : 'day'), + founded_date_precision: initialData?.founded_date_precision || (initialData?.founded_year ? ('year' as const) : ('day' as const)), headquarters_location: initialData?.headquarters_location || '', images: initialData?.images || { uploaded: [] } } @@ -80,13 +101,13 @@ export function ManufacturerForm({ onSubmit, onCancel, initialData }: Manufactur setIsSubmitting(true); try { - if (initialData?.id) { - await submitManufacturerUpdate(initialData.id, data as unknown as ManufacturerFormData, user.id); - toast.success('Manufacturer update submitted for review'); - } else { - await submitManufacturerCreation(data as unknown as ManufacturerFormData, user.id); - toast.success('Manufacturer submitted for review'); - } + if (initialData?.id) { + await submitManufacturerUpdate(initialData.id, data, user.id); + toast.success('Manufacturer update submitted for review'); + } else { + await submitManufacturerCreation(data, user.id); + toast.success('Manufacturer submitted for review'); + } onCancel(); } catch (error) { console.error('Submission error:', error); diff --git a/src/components/admin/OperatorForm.tsx b/src/components/admin/OperatorForm.tsx index 4f83e6b6..b12a8377 100644 --- a/src/components/admin/OperatorForm.tsx +++ b/src/components/admin/OperatorForm.tsx @@ -21,6 +21,26 @@ import { useAuth } from '@/hooks/useAuth'; import { toast } from 'sonner'; import { useNavigate } from 'react-router-dom'; +// Raw form input state (before Zod transformation) +interface OperatorFormInput { + name: string; + slug: string; + company_type: 'designer' | 'manufacturer' | 'operator' | 'property_owner'; + description?: string; + person_type: 'company' | 'individual' | 'firm' | 'organization'; + founded_year?: string; + founded_date?: string; + founded_date_precision?: 'day' | 'month' | 'year'; + headquarters_location?: string; + website_url?: string; + images?: { + uploaded: any[]; + banner_assignment?: number | null; + card_assignment?: number | null; + }; +} + +// Zod output type (after transformation) type OperatorFormData = z.infer; interface OperatorFormProps { @@ -51,8 +71,9 @@ export function OperatorForm({ onSubmit, onCancel, initialData }: OperatorFormPr defaultValues: { name: initialData?.name || '', slug: initialData?.slug || '', + company_type: 'operator' as const, description: initialData?.description || '', - person_type: initialData?.person_type || 'company', + person_type: initialData?.person_type || ('company' as const), website_url: initialData?.website_url || '', founded_year: initialData?.founded_year ? String(initialData.founded_year) : '', headquarters_location: initialData?.headquarters_location || '', @@ -78,13 +99,13 @@ export function OperatorForm({ onSubmit, onCancel, initialData }: OperatorFormPr setIsSubmitting(true); try { - if (initialData?.id) { - await submitOperatorUpdate(initialData.id, data as unknown as OperatorFormData, user.id); - toast.success('Operator update submitted for review'); - } else { - await submitOperatorCreation(data as unknown as OperatorFormData, user.id); - toast.success('Operator submitted for review'); - } + if (initialData?.id) { + await submitOperatorUpdate(initialData.id, data, user.id); + toast.success('Operator update submitted for review'); + } else { + await submitOperatorCreation(data, user.id); + toast.success('Operator submitted for review'); + } onCancel(); } catch (error) { console.error('Submission error:', error); diff --git a/src/components/admin/PropertyOwnerForm.tsx b/src/components/admin/PropertyOwnerForm.tsx index 6218245a..6123e917 100644 --- a/src/components/admin/PropertyOwnerForm.tsx +++ b/src/components/admin/PropertyOwnerForm.tsx @@ -20,6 +20,24 @@ import { useAuth } from '@/hooks/useAuth'; import { toast } from 'sonner'; import { useNavigate } from 'react-router-dom'; +// Raw form input state (before Zod transformation) +interface PropertyOwnerFormInput { + name: string; + slug: string; + description?: string; + person_type: 'company' | 'individual' | 'firm' | 'organization'; + founded_year?: string; + founded_date?: string; + founded_date_precision?: 'day' | 'month' | 'year'; + headquarters_location?: string; + website_url?: string; + images?: { + uploaded: any[]; + banner_assignment?: number | null; + card_assignment?: number | null; + }; +} + const propertyOwnerSchema = z.object({ name: z.string().min(1, 'Name is required'), slug: z.string().min(1, 'Slug is required'), @@ -81,7 +99,7 @@ export function PropertyOwnerForm({ onSubmit, onCancel, initialData }: PropertyO name: initialData?.name || '', slug: initialData?.slug || '', description: initialData?.description || '', - person_type: initialData?.person_type || 'company', + person_type: initialData?.person_type || ('company' as const), website_url: initialData?.website_url || '', founded_year: initialData?.founded_year ? String(initialData.founded_year) : '', headquarters_location: initialData?.headquarters_location || '', @@ -108,10 +126,10 @@ export function PropertyOwnerForm({ onSubmit, onCancel, initialData }: PropertyO setIsSubmitting(true); try { if (initialData?.id) { - await submitPropertyOwnerUpdate(initialData.id, data as unknown as PropertyOwnerFormData, user.id); + await submitPropertyOwnerUpdate(initialData.id, data, user.id); toast.success('Property owner update submitted for review'); } else { - await submitPropertyOwnerCreation(data as unknown as PropertyOwnerFormData, user.id); + await submitPropertyOwnerCreation(data, user.id); toast.success('Property owner submitted for review'); } onCancel();