156 lines
4.3 KiB
TypeScript
156 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState, FormEvent } from 'react';
|
|
import { Input } from '@/ui/Input';
|
|
import { Button } from '@/ui/Button';
|
|
import { Box } from '@/ui/Box';
|
|
import { Text } from '@/ui/Text';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { TextArea } from '@/ui/TextArea';
|
|
import { InfoBox } from '@/ui/InfoBox';
|
|
import { AlertCircle } from 'lucide-react';
|
|
|
|
interface FormErrors {
|
|
name?: string;
|
|
iracingId?: string;
|
|
country?: string;
|
|
bio?: string;
|
|
submit?: string;
|
|
}
|
|
|
|
interface CreateDriverFormProps {
|
|
onSuccess: () => void;
|
|
isPending: boolean;
|
|
}
|
|
|
|
export function CreateDriverForm({ onSuccess, isPending }: CreateDriverFormProps) {
|
|
const [errors, setErrors] = useState<FormErrors>({});
|
|
|
|
const [formData, setFormData] = useState({
|
|
name: '',
|
|
country: '',
|
|
bio: ''
|
|
});
|
|
|
|
const validateForm = async (): Promise<boolean> => {
|
|
const newErrors: FormErrors = {};
|
|
|
|
if (!formData.name.trim()) {
|
|
newErrors.name = 'Name is required';
|
|
}
|
|
|
|
if (!formData.country.trim()) {
|
|
newErrors.country = 'Country is required';
|
|
} else if (!/^[A-Z]{2,3}$/i.test(formData.country)) {
|
|
newErrors.country = 'Invalid country code (use 2-3 letter ISO code)';
|
|
}
|
|
|
|
if (formData.bio && formData.bio.length > 500) {
|
|
newErrors.bio = 'Bio must be 500 characters or less';
|
|
}
|
|
|
|
setErrors(newErrors);
|
|
return Object.keys(newErrors).length === 0;
|
|
};
|
|
|
|
const handleSubmit = async (e: FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
if (isPending) return;
|
|
|
|
const isValid = await validateForm();
|
|
if (!isValid) return;
|
|
|
|
const bio = formData.bio.trim();
|
|
const displayName = formData.name.trim();
|
|
const parts = displayName.split(' ').filter(Boolean);
|
|
const firstName = parts[0] ?? displayName;
|
|
const lastName = parts.slice(1).join(' ') || 'Driver';
|
|
|
|
// Construct data for parent to handle
|
|
const driverData = {
|
|
firstName,
|
|
lastName,
|
|
displayName,
|
|
country: formData.country.trim().toUpperCase(),
|
|
...(bio ? { bio } : {}),
|
|
};
|
|
|
|
console.log('Driver data to create:', driverData);
|
|
onSuccess();
|
|
};
|
|
|
|
return (
|
|
<Box as="form" onSubmit={handleSubmit}>
|
|
<Stack gap={6}>
|
|
<Input
|
|
label="Driver Name *"
|
|
id="name"
|
|
type="text"
|
|
value={formData.name}
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFormData({ ...formData, name: e.target.value })}
|
|
variant={errors.name ? 'error' : 'default'}
|
|
errorMessage={errors.name}
|
|
placeholder="Alex Vermeer"
|
|
disabled={isPending}
|
|
/>
|
|
|
|
<Box>
|
|
<Input
|
|
label="Country Code *"
|
|
id="country"
|
|
type="text"
|
|
value={formData.country}
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFormData({ ...formData, country: e.target.value })}
|
|
variant={errors.country ? 'error' : 'default'}
|
|
errorMessage={errors.country}
|
|
placeholder="NL"
|
|
maxLength={3}
|
|
disabled={isPending}
|
|
/>
|
|
<Text size="xs" color="text-gray-500" mt={1} block>Use ISO 3166-1 alpha-2 or alpha-3 code</Text>
|
|
</Box>
|
|
|
|
<Box>
|
|
<TextArea
|
|
label="Bio (Optional)"
|
|
id="bio"
|
|
value={formData.bio}
|
|
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setFormData({ ...formData, bio: e.target.value })}
|
|
placeholder="Tell us about yourself..."
|
|
maxLength={500}
|
|
rows={4}
|
|
disabled={isPending}
|
|
/>
|
|
<Box display="flex" justifyContent="between" mt={1}>
|
|
{errors.bio ? (
|
|
<Text size="sm" color="text-warning-amber">{errors.bio}</Text>
|
|
) : <Box />}
|
|
<Text size="xs" color="text-gray-500">
|
|
{formData.bio.length}/500
|
|
</Text>
|
|
</Box>
|
|
</Box>
|
|
|
|
{errors.submit && (
|
|
<InfoBox
|
|
variant="warning"
|
|
icon={AlertCircle}
|
|
title="Error"
|
|
description={errors.submit}
|
|
/>
|
|
)}
|
|
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
disabled={isPending}
|
|
fullWidth
|
|
>
|
|
{isPending ? 'Creating Profile...' : 'Create Profile'}
|
|
</Button>
|
|
</Stack>
|
|
</Box>
|
|
);
|
|
}
|