Refactor: Implement complete type safety plan

This commit is contained in:
gpt-engineer-app[bot]
2025-10-16 14:39:42 +00:00
parent 88e89e0a65
commit 8d26ac0749
10 changed files with 239 additions and 12 deletions

View File

@@ -20,6 +20,7 @@ import { submitDesignerCreation, submitDesignerUpdate } from '@/lib/entitySubmis
import { useAuth } from '@/hooks/useAuth';
import { toast } from 'sonner';
import { useNavigate } from 'react-router-dom';
import type { UploadedImage } from '@/types/company';
// Raw form input state (before Zod transformation)
interface DesignerFormInput {
@@ -34,7 +35,7 @@ interface DesignerFormInput {
headquarters_location?: string;
website_url?: string;
images?: {
uploaded: any[];
uploaded: UploadedImage[];
banner_assignment?: number | null;
card_assignment?: number | null;
};

View File

@@ -21,6 +21,7 @@ import { useAuth } from '@/hooks/useAuth';
import { toast } from 'sonner';
import { useNavigate } from 'react-router-dom';
import { toDateOnly } from '@/lib/dateUtils';
import type { UploadedImage } from '@/types/company';
// Raw form input state (before Zod transformation)
interface ManufacturerFormInput {
@@ -35,7 +36,7 @@ interface ManufacturerFormInput {
headquarters_location?: string;
website_url?: string;
images?: {
uploaded: any[];
uploaded: UploadedImage[];
banner_assignment?: number | null;
card_assignment?: number | null;
};

View File

@@ -20,6 +20,7 @@ import { submitOperatorCreation, submitOperatorUpdate } from '@/lib/entitySubmis
import { useAuth } from '@/hooks/useAuth';
import { toast } from 'sonner';
import { useNavigate } from 'react-router-dom';
import type { UploadedImage } from '@/types/company';
// Raw form input state (before Zod transformation)
interface OperatorFormInput {
@@ -34,7 +35,7 @@ interface OperatorFormInput {
headquarters_location?: string;
website_url?: string;
images?: {
uploaded: any[];
uploaded: UploadedImage[];
banner_assignment?: number | null;
card_assignment?: number | null;
};

View File

@@ -20,6 +20,7 @@ import { submitPropertyOwnerCreation, submitPropertyOwnerUpdate } from '@/lib/en
import { useAuth } from '@/hooks/useAuth';
import { toast } from 'sonner';
import { useNavigate } from 'react-router-dom';
import type { UploadedImage } from '@/types/company';
// Raw form input state (before Zod transformation)
interface PropertyOwnerFormInput {
@@ -34,7 +35,7 @@ interface PropertyOwnerFormInput {
headquarters_location?: string;
website_url?: string;
images?: {
uploaded: any[];
uploaded: UploadedImage[];
banner_assignment?: number | null;
card_assignment?: number | null;
};

View File

@@ -4,6 +4,7 @@ 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 type { TempCompanyData, TempRideModelData } from '@/types/company';
import { entitySchemas } from '@/lib/entityValidationSchemas';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
@@ -129,8 +130,8 @@ export function RideForm({ onSubmit, onCancel, initialData, isEditing = false }:
initialData?.manufacturer_id || ''
);
const [selectedManufacturerName, setSelectedManufacturerName] = useState<string>('');
const [tempNewManufacturer, setTempNewManufacturer] = useState<any>(null);
const [tempNewRideModel, setTempNewRideModel] = useState<any>(null);
const [tempNewManufacturer, setTempNewManufacturer] = useState<TempCompanyData | null>(null);
const [tempNewRideModel, setTempNewRideModel] = useState<TempRideModelData | null>(null);
const [isManufacturerModalOpen, setIsManufacturerModalOpen] = useState(false);
const [isModelModalOpen, setIsModelModalOpen] = useState(false);

View File

@@ -61,3 +61,16 @@ export const handleInfo = (
duration: 4000
});
};
/**
* Type-safe error message extraction utility
* Use this instead of `error: any` in catch blocks
*/
export const getErrorMessage = (error: unknown): string => {
if (error instanceof Error) return error.message;
if (typeof error === 'string') return error;
if (error && typeof error === 'object' && 'message' in error) {
return String(error.message);
}
return 'An unexpected error occurred';
};

View File

@@ -4,6 +4,14 @@
import { ImageAssignments } from '@/components/upload/EntityMultiImageUploader';
export interface UploadedImage {
url: string;
cloudflare_id?: string;
file?: File;
isLocal?: boolean;
caption?: string;
}
export interface CompanyFormData {
name: string;
slug: string;
@@ -26,3 +34,17 @@ export interface TempCompanyData {
headquarters_location?: string;
website_url?: string;
}
export interface TempRideModelData {
name: string;
slug: string;
category: string;
ride_type: string;
description?: string;
images?: {
uploaded: UploadedImage[];
banner_assignment?: number | null;
card_assignment?: number | null;
};
_technical_specifications?: unknown[];
}

View File

@@ -31,8 +31,8 @@ export interface SubmissionItemData {
id: string;
submission_id: string;
item_type: EntityType | 'photo' | 'ride_model';
item_data: any;
original_data?: any;
item_data: Record<string, unknown>;
original_data?: Record<string, unknown>;
status: 'pending' | 'approved' | 'rejected';
depends_on: string | null;
order_index: number;
@@ -124,3 +124,4 @@ export function createSubmissionContent(
...referenceIds
};
}