84 lines
2.5 KiB
TypeScript
84 lines
2.5 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { AlertCircle } from 'lucide-react';
|
|
import { useInject } from '@/lib/di/hooks/useInject';
|
|
import { RACE_RESULTS_SERVICE_TOKEN } from '@/lib/di/tokens';
|
|
import { FilePicker } from '@/ui/FilePicker';
|
|
import { Box } from '@/ui/Box';
|
|
import { Text } from '@/ui/Text';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { InfoBox } from '@/ui/InfoBox';
|
|
|
|
interface ImportResultsFormProps {
|
|
raceId: string;
|
|
onSuccess: (results: unknown[]) => void;
|
|
onError: (error: string) => void;
|
|
}
|
|
|
|
export function ImportResultsForm({ raceId, onSuccess, onError }: ImportResultsFormProps) {
|
|
const [uploading, setUploading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const raceResultsService = useInject(RACE_RESULTS_SERVICE_TOKEN);
|
|
|
|
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const file = event.target.files?.[0];
|
|
if (!file) return;
|
|
|
|
setUploading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const content = await file.text();
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const results = (raceResultsService as any).parseAndTransformCSV(content, raceId);
|
|
onSuccess(results);
|
|
} catch (err) {
|
|
const errorMessage =
|
|
err instanceof Error ? err.message : 'Failed to parse CSV file';
|
|
setError(errorMessage);
|
|
onError(errorMessage);
|
|
} finally {
|
|
setUploading(false);
|
|
event.target.value = '';
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Stack gap={4}>
|
|
<FilePicker
|
|
label="Upload Results CSV"
|
|
description="CSV format: driverId, position, fastestLap, incidents, startPosition"
|
|
accept=".csv"
|
|
onChange={handleFileChange}
|
|
disabled={uploading}
|
|
/>
|
|
|
|
{error && (
|
|
<InfoBox
|
|
variant="warning"
|
|
icon={AlertCircle}
|
|
title="Error"
|
|
description={error}
|
|
/>
|
|
)}
|
|
|
|
{uploading && (
|
|
<Text align="center" color="text-gray-400" size="sm">
|
|
Parsing CSV and importing results...
|
|
</Text>
|
|
)}
|
|
|
|
<Box p={4} bg="bg-iron-gray/20" rounded="lg">
|
|
<Text weight="semibold" block mb={2} size="xs" color="text-gray-500">CSV Example:</Text>
|
|
<Box as="pre" color="text-gray-400">
|
|
{`driverId,position,fastestLap,incidents,startPosition
|
|
550e8400-e29b-41d4-a716-446655440001,1,92.456,0,3
|
|
550e8400-e29b-41d4-a716-446655440002,2,92.789,1,1
|
|
550e8400-e29b-41d4-a716-446655440003,3,93.012,2,2`}
|
|
</Box>
|
|
</Box>
|
|
</Stack>
|
|
);
|
|
}
|