diff --git a/src/components/admin/RideForm.tsx b/src/components/admin/RideForm.tsx index 7a44171f..a573bfcf 100644 --- a/src/components/admin/RideForm.tsx +++ b/src/components/admin/RideForm.tsx @@ -23,10 +23,10 @@ import { SlugField } from '@/components/ui/slug-field'; import { Checkbox } from '@/components/ui/checkbox'; import { toast } from '@/hooks/use-toast'; import { handleError } from '@/lib/errorHandler'; -import { Plus, Zap, Save, X, Building2 } from 'lucide-react'; +import { Plus, Zap, Save, X, Building2, AlertCircle } from 'lucide-react'; import { toDateOnly, parseDateOnly, toDateWithPrecision } from '@/lib/dateUtils'; import { useUnitPreferences } from '@/hooks/useUnitPreferences'; -import { useManufacturers, useRideModels } from '@/hooks/useAutocompleteData'; +import { useManufacturers, useRideModels, useParks } from '@/hooks/useAutocompleteData'; import { useUserRole } from '@/hooks/useUserRole'; import { ManufacturerForm } from './ManufacturerForm'; import { RideModelForm } from './RideModelForm'; @@ -208,12 +208,14 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }: // Fetch data const { manufacturers, loading: manufacturersLoading } = useManufacturers(); const { rideModels, loading: modelsLoading } = useRideModels(selectedManufacturerId); + const { parks, loading: parksLoading } = useParks(); const { register, handleSubmit, setValue, watch, + trigger, formState: { errors } } = useForm({ resolver: zodResolver(entitySchemas.ride), @@ -256,11 +258,13 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }: ride_model_id: initialData?.ride_model_id || undefined, source_url: initialData?.source_url || '', submission_notes: initialData?.submission_notes || '', - images: { uploaded: [] } + images: { uploaded: [] }, + park_id: initialData?.park_id || undefined } }); const selectedCategory = watch('category'); + const isParkPreselected = !!initialData?.park_id; // Coming from park detail page const handleFormSubmit = async (data: RideFormData) => { @@ -419,6 +423,96 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }: /> + {/* Park Selection */} +
+

Park Information

+ +
+ + + {tempNewPark ? ( + // Show temp park badge +
+ New + {tempNewPark.name} + + +
+ ) : ( + // Show combobox for existing parks + { + setValue('park_id', value); + trigger('park_id'); + }} + placeholder={isParkPreselected ? "Park pre-selected" : "Select a park"} + searchPlaceholder="Search parks..." + emptyText="No parks found" + loading={parksLoading} + disabled={isParkPreselected} + /> + )} + + {/* Validation error display */} + {errors.park_id && ( +

+ + {errors.park_id.message} +

+ )} + + {/* Create New Park Button */} + {!tempNewPark && !isParkPreselected && ( + + )} + + {/* Help text */} + {isParkPreselected ? ( +

+ Park is pre-selected from the park detail page and cannot be changed. +

+ ) : ( +

+ {tempNewPark + ? "New park will be created when submission is approved" + : "Select the park where this ride is located"} +

+ )} +
+
+ {/* Category and Status */}
diff --git a/src/hooks/useAutocompleteData.ts b/src/hooks/useAutocompleteData.ts index 4fce7ee0..1bc41b2b 100644 --- a/src/hooks/useAutocompleteData.ts +++ b/src/hooks/useAutocompleteData.ts @@ -301,4 +301,46 @@ export function usePropertyOwners() { }, []); return { propertyOwners, loading }; +} + +/** + * Hook to fetch all parks for autocomplete + * Returns parks as combobox options + */ +export function useParks() { + const [parks, setParks] = useState([]); + const [loading, setLoading] = useState(false); + + useEffect(() => { + async function fetchParks() { + setLoading(true); + try { + const { data, error } = await supabase + .from('parks') + .select('id, name, slug') + .order('name'); + + if (error) throw error; + + setParks( + (data || []).map(park => ({ + label: park.name, + value: park.id + })) + ); + } catch (error: unknown) { + handleNonCriticalError(error, { action: 'Fetch parks' }); + toast.error('Failed to load parks', { + description: 'Please refresh the page and try again.', + }); + setParks([]); + } finally { + setLoading(false); + } + } + + fetchParks(); + }, []); + + return { parks, loading }; } \ No newline at end of file