Files
gridpilot.gg/apps/website/components/drivers/CreateDriverForm.tsx
2026-01-12 01:01:49 +01:00

178 lines
5.2 KiB
TypeScript

'use client';
import { useState, FormEvent } from 'react';
import { useRouter } from 'next/navigation';
import Input from '../ui/Input';
import Button from '../ui/Button';
import { useCreateDriver } from "@/lib/hooks/driver/useCreateDriver";
interface FormErrors {
name?: string;
iracingId?: string;
country?: string;
bio?: string;
submit?: string;
}
export default function CreateDriverForm() {
const router = useRouter();
const createDriverMutation = useCreateDriver();
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 (createDriverMutation.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';
createDriverMutation.mutate(
{
firstName,
lastName,
displayName,
country: formData.country.trim().toUpperCase(),
...(bio ? { bio } : {}),
},
{
onSuccess: () => {
router.push('/profile');
router.refresh();
},
onError: (error) => {
setErrors({
submit: error instanceof Error ? error.message : 'Failed to create profile'
});
},
}
);
};
return (
<>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-300 mb-2">
Driver Name *
</label>
<Input
id="name"
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
error={!!errors.name}
errorMessage={errors.name}
placeholder="Alex Vermeer"
disabled={createDriverMutation.isPending}
/>
</div>
<div>
<label htmlFor="iracingId" className="block text-sm font-medium text-gray-300 mb-2">
Display Name *
</label>
<Input
id="name"
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
error={!!errors.name}
errorMessage={errors.name}
placeholder="Alex Vermeer"
disabled={createDriverMutation.isPending}
/>
</div>
<div>
<label htmlFor="country" className="block text-sm font-medium text-gray-300 mb-2">
Country Code *
</label>
<Input
id="country"
type="text"
value={formData.country}
onChange={(e) => setFormData({ ...formData, country: e.target.value })}
error={!!errors.country}
errorMessage={errors.country}
placeholder="NL"
maxLength={3}
disabled={createDriverMutation.isPending}
/>
<p className="mt-1 text-xs text-gray-500">Use ISO 3166-1 alpha-2 or alpha-3 code</p>
</div>
<div>
<label htmlFor="bio" className="block text-sm font-medium text-gray-300 mb-2">
Bio (Optional)
</label>
<textarea
id="bio"
value={formData.bio}
onChange={(e) => setFormData({ ...formData, bio: e.target.value })}
placeholder="Tell us about yourself..."
maxLength={500}
rows={4}
disabled={createDriverMutation.isPending}
className="block w-full rounded-md border-0 px-4 py-3 bg-iron-gray text-white shadow-sm ring-1 ring-inset ring-charcoal-outline placeholder:text-gray-500 focus:ring-2 focus:ring-inset focus:ring-primary-blue transition-all duration-150 sm:text-sm sm:leading-6 resize-none"
/>
<p className="mt-1 text-xs text-gray-500 text-right">
{formData.bio.length}/500
</p>
{errors.bio && (
<p className="mt-2 text-sm text-warning-amber">{errors.bio}</p>
)}
</div>
{errors.submit && (
<div className="rounded-md bg-warning-amber/10 p-4 border border-warning-amber/20">
<p className="text-sm text-warning-amber">{errors.submit}</p>
</div>
)}
<Button
type="submit"
variant="primary"
disabled={createDriverMutation.isPending}
className="w-full"
>
{createDriverMutation.isPending ? 'Creating Profile...' : 'Create Profile'}
</Button>
</form>
</>
);
}