Refactor composite submission logic

This commit is contained in:
gpt-engineer-app[bot]
2025-11-02 20:29:08 +00:00
parent 6a9df807fa
commit bb951e637f
6 changed files with 290 additions and 23 deletions

View File

@@ -5,7 +5,7 @@ import * as z from 'zod';
import { validateSubmissionHandler } from '@/lib/entityFormValidation';
import { getErrorMessage } from '@/lib/errorHandler';
import type { RideTechnicalSpec, RideCoasterStat, RideNameHistory } from '@/types/database';
import type { TempCompanyData, TempRideModelData } from '@/types/company';
import type { TempCompanyData, TempRideModelData, TempParkData } from '@/types/company';
import { entitySchemas } from '@/lib/entityValidationSchemas';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
@@ -23,13 +23,14 @@ 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 } from 'lucide-react';
import { Plus, Zap, Save, X, Building2 } from 'lucide-react';
import { toDateOnly, parseDateOnly } from '@/lib/dateUtils';
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
import { useManufacturers, useRideModels } from '@/hooks/useAutocompleteData';
import { useUserRole } from '@/hooks/useUserRole';
import { ManufacturerForm } from './ManufacturerForm';
import { RideModelForm } from './RideModelForm';
import { ParkForm } from './ParkForm';
import { TechnicalSpecsEditor, validateTechnicalSpecs } from './editors/TechnicalSpecsEditor';
import { CoasterStatsEditor, validateCoasterStats } from './editors/CoasterStatsEditor';
import { FormerNamesEditor } from './editors/FormerNamesEditor';
@@ -45,12 +46,21 @@ import {
type RideFormData = z.infer<typeof entitySchemas.ride>;
interface RideFormProps {
onSubmit: (data: RideFormData) => Promise<void>;
onSubmit: (data: RideFormData & {
_tempNewPark?: TempParkData;
_tempNewManufacturer?: TempCompanyData;
_tempNewDesigner?: TempCompanyData;
_tempNewRideModel?: TempRideModelData;
}) => Promise<void>;
onCancel?: () => void;
initialData?: Partial<RideFormData & {
id?: string;
banner_image_url?: string;
card_image_url?: string;
_tempNewPark?: TempParkData;
_tempNewManufacturer?: TempCompanyData;
_tempNewDesigner?: TempCompanyData;
_tempNewRideModel?: TempRideModelData;
}>;
isEditing?: boolean;
}
@@ -154,14 +164,18 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
validateSubmissionHandler(onSubmit, 'ride');
}, [onSubmit]);
// Manufacturer and model state
// Temp entity states
const [tempNewPark, setTempNewPark] = useState<TempParkData | null>(initialData?._tempNewPark || null);
const [selectedManufacturerId, setSelectedManufacturerId] = useState<string>(
initialData?.manufacturer_id || ''
);
const [selectedManufacturerName, setSelectedManufacturerName] = useState<string>('');
const [tempNewManufacturer, setTempNewManufacturer] = useState<TempCompanyData | null>(null);
const [tempNewRideModel, setTempNewRideModel] = useState<TempRideModelData | null>(null);
const [tempNewManufacturer, setTempNewManufacturer] = useState<TempCompanyData | null>(initialData?._tempNewManufacturer || null);
const [tempNewDesigner, setTempNewDesigner] = useState<TempCompanyData | null>(initialData?._tempNewDesigner || null);
const [tempNewRideModel, setTempNewRideModel] = useState<TempRideModelData | null>(initialData?._tempNewRideModel || null);
const [isParkModalOpen, setIsParkModalOpen] = useState(false);
const [isManufacturerModalOpen, setIsManufacturerModalOpen] = useState(false);
const [isDesignerModalOpen, setIsDesignerModalOpen] = useState(false);
const [isModelModalOpen, setIsModelModalOpen] = useState(false);
// Advanced editor state - using simplified interface for editors (DB fields added on submit)
@@ -299,7 +313,9 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
_technical_specifications: technicalSpecs,
_coaster_statistics: coasterStats,
_name_history: formerNames,
_tempNewPark: tempNewPark,
_tempNewManufacturer: tempNewManufacturer,
_tempNewDesigner: tempNewDesigner,
_tempNewRideModel: tempNewRideModel
};
@@ -1337,6 +1353,41 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
</div>
</form>
{/* Park Modal - Add before Manufacturer Modal */}
<Dialog open={isParkModalOpen} onOpenChange={setIsParkModalOpen}>
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Create New Park</DialogTitle>
</DialogHeader>
<ParkForm
onSubmit={async (data) => {
setTempNewPark(data as TempParkData);
setIsParkModalOpen(false);
setValue('park_id', undefined);
}}
onCancel={() => setIsParkModalOpen(false)}
/>
</DialogContent>
</Dialog>
{/* Designer Modal */}
<Dialog open={isDesignerModalOpen} onOpenChange={setIsDesignerModalOpen}>
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Create New Designer</DialogTitle>
</DialogHeader>
<ManufacturerForm
initialData={tempNewDesigner}
onSubmit={(data) => {
setTempNewDesigner(data);
setIsDesignerModalOpen(false);
setValue('designer_id', undefined);
}}
onCancel={() => setIsDesignerModalOpen(false)}
/>
</DialogContent>
</Dialog>
{/* Manufacturer Modal */}
<Dialog open={isManufacturerModalOpen} onOpenChange={setIsManufacturerModalOpen}>
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">