diff --git a/src/components/admin/RideForm.tsx b/src/components/admin/RideForm.tsx index 4cd2d677..e62c6364 100644 --- a/src/components/admin/RideForm.tsx +++ b/src/components/admin/RideForm.tsx @@ -3,6 +3,7 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { validateSubmissionHandler } from '@/lib/entityFormValidation'; +import type { RideTechnicalSpec, RideCoasterStat, RideNameHistory } from '@/types/database'; import { entitySchemas } from '@/lib/entityValidationSchemas'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; @@ -133,10 +134,31 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }: const [isManufacturerModalOpen, setIsManufacturerModalOpen] = useState(false); const [isModelModalOpen, setIsModelModalOpen] = useState(false); - // Advanced editor state - const [technicalSpecs, setTechnicalSpecs] = useState([]); - const [coasterStats, setCoasterStats] = useState([]); - const [formerNames, setFormerNames] = useState([]); + // Advanced editor state - using simplified interface for editors (DB fields added on submit) + const [technicalSpecs, setTechnicalSpecs] = useState<{ + spec_name: string; + spec_value: string; + spec_type: 'string' | 'number' | 'boolean' | 'date'; + category?: string; + unit?: string; + display_order: number; + }[]>([]); + const [coasterStats, setCoasterStats] = useState<{ + stat_name: string; + stat_value: number; + unit?: string; + category?: string; + description?: string; + display_order: number; + }[]>([]); + const [formerNames, setFormerNames] = useState<{ + former_name: string; + date_changed?: Date | null; + reason?: string; + from_year?: number; + to_year?: number; + order_index: number; + }[]>([]); // Fetch data const { manufacturers, loading: manufacturersLoading } = useManufacturers(); diff --git a/src/components/admin/RideModelForm.tsx b/src/components/admin/RideModelForm.tsx index 40dbd676..09e7c3f5 100644 --- a/src/components/admin/RideModelForm.tsx +++ b/src/components/admin/RideModelForm.tsx @@ -3,6 +3,7 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; import { Button } from '@/components/ui/button'; +import type { RideModelTechnicalSpec } from '@/types/database'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Label } from '@/components/ui/label'; @@ -65,7 +66,14 @@ export function RideModelForm({ initialData }: RideModelFormProps) { const { isModerator } = useUserRole(); - const [technicalSpecs, setTechnicalSpecs] = useState([]); + const [technicalSpecs, setTechnicalSpecs] = useState<{ + spec_name: string; + spec_value: string; + spec_type: 'string' | 'number' | 'boolean' | 'date'; + category?: string; + unit?: string; + display_order: number; + }[]>([]); const { register, diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index 2cb0e437..9695b451 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -698,29 +698,29 @@ export default function Profile() {

{activity.title || 'Left a review'}

- {activity.moderation_status === 'pending' && ( + {(activity as any).moderation_status === 'pending' && ( Pending )} - {activity.moderation_status === 'flagged' && ( + {(activity as any).moderation_status === 'flagged' && ( Flagged )}
{[...Array(5)].map((_, i) => ( - + ))}
- {activity.park_id && activity.parks ? ( - - {activity.parks.name} + {(activity as any).park_id && activity.parks ? ( + + {activity.parks.name || 'Unknown Park'} - ) : activity.ride_id && activity.rides ? ( + ) : (activity as any).ride_id && activity.rides ? (
- - {activity.rides.name} + + {activity.rides.name || 'Unknown Ride'} {activity.rides.parks && ( - at {activity.rides.parks.name} + at {activity.rides.parks.name || 'Unknown Park'} )}
) : null} @@ -729,55 +729,55 @@ export default function Profile() { <>

- Submitted {activity.submission_type} - {activity.content?.name && `: ${activity.content.name}`} + Submitted {(activity as any).submission_type || 'content'} + {(activity as any).content?.name && `: ${(activity as any).content.name}`}

- {activity.status === 'pending' && ( + {(activity as any).status === 'pending' && ( Pending )} - {activity.status === 'approved' && ( + {(activity as any).status === 'approved' && ( Approved )} - {activity.status === 'rejected' && ( + {(activity as any).status === 'rejected' && ( Rejected )}
- {activity.content?.description && ( + {(activity as any).content?.description && (

- {activity.content.description} + {(activity as any).content.description}

)} ) : activity.type === 'ranking' ? ( <>
-

Created ranking: {activity.title}

+

Created ranking: {(activity as any).title || 'Untitled'}

- {activity.list_type.replace('_', ' ')} + {((activity as any).list_type || '').replace('_', ' ')}
- {activity.description && ( + {(activity as any).description && (

- {activity.description} + {(activity as any).description}

)} ) : ( <>

Added ride credit

- {activity.rides && ( + {(activity as any).rides && (
- - {activity.rides.name} + + {(activity as any).rides.name} - {activity.rides.parks && ( - at {activity.rides.parks.name} + {(activity as any).rides.parks && ( + at {(activity as any).rides.parks.name} )}
)} - {activity.ride_count > 1 && ( + {(activity as any).ride_count > 1 && (

- Ridden {activity.ride_count} times + Ridden {(activity as any).ride_count} times

)} diff --git a/src/types/database.ts b/src/types/database.ts index ca8999c3..61dbc08d 100644 --- a/src/types/database.ts +++ b/src/types/database.ts @@ -281,10 +281,47 @@ export interface AuditLogEntry { created_at: string; } -// Activity entry - flexible structure for mixed activity types -export interface ActivityEntry { +// Activity entry - discriminated union for different activity types +export type ActivityEntry = + | ReviewActivity + | SubmissionActivity + | RankingActivity + | GenericActivity; + +interface ReviewActivity { id: string; - type?: 'review' | 'credit' | 'submission' | 'ranking'; + type: 'review'; created_at: string; - [key: string]: unknown; // Allow any additional properties from different activity types + rating?: number; + parks?: { slug?: string; name?: string } | null; + rides?: { slug?: string; name?: string; parks?: { slug?: string; name?: string } | null } | null; + content?: string; + title?: string; + description?: string; +} + +interface SubmissionActivity { + id: string; + type: 'submission'; + created_at: string; + status?: string; + submission_type?: string; + entity_type?: string; + action?: string; +} + +interface RankingActivity { + id: string; + type: 'ranking'; + created_at: string; + parks?: { slug?: string; name?: string } | null; + name?: string; + position?: number; +} + +interface GenericActivity { + id: string; + type?: string; + created_at: string; + [key: string]: unknown; } \ No newline at end of file