di usage in website

This commit is contained in:
2026-01-06 19:36:03 +01:00
parent 589b55a87e
commit e589c30bf8
191 changed files with 6367 additions and 4253 deletions

View File

@@ -4,7 +4,7 @@ import { useState, FormEvent } from 'react';
import { useRouter } from 'next/navigation';
import Input from '../ui/Input';
import Button from '../ui/Button';
import { useServices } from '@/lib/services/ServiceProvider';
import { useCreateDriver } from '@/hooks/driver/useCreateDriver';
interface FormErrors {
name?: string;
@@ -16,8 +16,7 @@ interface FormErrors {
export default function CreateDriverForm() {
const router = useRouter();
const { driverService } = useServices();
const [loading, setLoading] = useState(false);
const createDriverMutation = useCreateDriver();
const [errors, setErrors] = useState<FormErrors>({});
const [formData, setFormData] = useState({
@@ -50,37 +49,37 @@ export default function CreateDriverForm() {
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
if (loading) return;
if (createDriverMutation.isPending) return;
const isValid = await validateForm();
if (!isValid) return;
setLoading(true);
try {
const bio = formData.bio.trim();
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';
const displayName = formData.name.trim();
const parts = displayName.split(' ').filter(Boolean);
const firstName = parts[0] ?? displayName;
const lastName = parts.slice(1).join(' ') || 'Driver';
await driverService.completeDriverOnboarding({
createDriverMutation.mutate(
{
firstName,
lastName,
displayName,
country: formData.country.trim().toUpperCase(),
...(bio ? { bio } : {}),
});
router.push('/profile');
router.refresh();
} catch (error) {
setErrors({
submit: error instanceof Error ? error.message : 'Failed to create profile'
});
setLoading(false);
}
},
{
onSuccess: () => {
router.push('/profile');
router.refresh();
},
onError: (error) => {
setErrors({
submit: error instanceof Error ? error.message : 'Failed to create profile'
});
},
}
);
};
return (
@@ -98,7 +97,7 @@ export default function CreateDriverForm() {
error={!!errors.name}
errorMessage={errors.name}
placeholder="Alex Vermeer"
disabled={loading}
disabled={createDriverMutation.isPending}
/>
</div>
@@ -114,7 +113,7 @@ export default function CreateDriverForm() {
error={!!errors.name}
errorMessage={errors.name}
placeholder="Alex Vermeer"
disabled={loading}
disabled={createDriverMutation.isPending}
/>
</div>
@@ -131,7 +130,7 @@ export default function CreateDriverForm() {
errorMessage={errors.country}
placeholder="NL"
maxLength={3}
disabled={loading}
disabled={createDriverMutation.isPending}
/>
<p className="mt-1 text-xs text-gray-500">Use ISO 3166-1 alpha-2 or alpha-3 code</p>
</div>
@@ -147,7 +146,7 @@ export default function CreateDriverForm() {
placeholder="Tell us about yourself..."
maxLength={500}
rows={4}
disabled={loading}
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">
@@ -167,10 +166,10 @@ export default function CreateDriverForm() {
<Button
type="submit"
variant="primary"
disabled={loading}
disabled={createDriverMutation.isPending}
className="w-full"
>
{loading ? 'Creating Profile...' : 'Create Profile'}
{createDriverMutation.isPending ? 'Creating Profile...' : 'Create Profile'}
</Button>
</form>
</>

View File

@@ -8,8 +8,7 @@ import ProfileStats from './ProfileStats';
import CareerHighlights from './CareerHighlights';
import DriverRankings from './DriverRankings';
import PerformanceMetrics from './PerformanceMetrics';
import { useEffect, useState } from 'react';
import { useServices } from '@/lib/services/ServiceProvider';
import { useDriverProfile } from '@/hooks/driver/useDriverProfile';
interface DriverProfileProps {
driver: DriverViewModel;
@@ -25,42 +24,29 @@ interface DriverTeamViewModel {
}
export default function DriverProfile({ driver, isOwnProfile = false, onEditClick }: DriverProfileProps) {
const { driverService } = useServices();
const [profileData, setProfileData] = useState<DriverProfileStatsViewModel | null>(null);
const [teamData, setTeamData] = useState<DriverTeamViewModel | null>(null);
const { data: profileData, isLoading } = useDriverProfile(driver.id);
useEffect(() => {
const load = async () => {
try {
// Load driver profile
const profile = await driverService.getDriverProfile(driver.id);
// Extract stats from profile
if (profile.stats) {
setProfileData(profile.stats);
}
// Load team data if available
if (profile.teamMemberships && profile.teamMemberships.length > 0) {
const currentTeam = profile.teamMemberships.find(m => m.isCurrent) || profile.teamMemberships[0];
if (currentTeam) {
setTeamData({
team: {
name: currentTeam.teamName,
tag: currentTeam.teamTag ?? ''
}
});
}
}
} catch (error) {
console.error('Failed to load driver profile data:', error);
// Extract team data from profile
const teamData: DriverTeamViewModel | null = (() => {
if (!profileData?.teamMemberships || profileData.teamMemberships.length === 0) {
return null;
}
const currentTeam = profileData.teamMemberships.find(m => m.isCurrent) || profileData.teamMemberships[0];
if (!currentTeam) {
return null;
}
return {
team: {
name: currentTeam.teamName,
tag: currentTeam.teamTag ?? ''
}
};
void load();
}, [driver.id, driverService]);
})();
const driverStats = profileData;
const globalRank = profileData?.overallRank ?? null;
const driverStats = profileData?.stats ?? null;
const globalRank = driverStats?.overallRank ?? null;
const totalDrivers = 1000; // Placeholder
const performanceStats = driverStats ? {

View File

@@ -1,9 +1,9 @@
'use client';
import { useDriverProfile } from '@/hooks/driver';
import { useMemo } from 'react';
import Card from '../ui/Card';
import RankBadge from './RankBadge';
import { useMemo } from 'react';
import { useDriverProfile } from '@/hooks/useDriverService';
interface ProfileStatsProps {
driverId?: string;
@@ -206,35 +206,4 @@ export default function ProfileStats({ driverId, stats }: ProfileStatsProps) {
);
}
function PerformanceRow({ label, races, wins, podiums, avgFinish }: {
label: string;
races: number;
wins: number;
podiums: number;
avgFinish: number;
}) {
const winRate = ((wins / races) * 100).toFixed(0);
return (
<div className="flex items-center justify-between p-3 rounded bg-deep-graphite border border-charcoal-outline">
<div className="flex-1">
<div className="text-white font-medium">{label}</div>
<div className="text-gray-500 text-xs">{races} races</div>
</div>
<div className="flex items-center gap-6 text-xs">
<div>
<div className="text-gray-500">Wins</div>
<div className="text-green-400 font-medium">{wins} ({winRate}%)</div>
</div>
<div>
<div className="text-gray-500">Podiums</div>
<div className="text-warning-amber font-medium">{podiums}</div>
</div>
<div>
<div className="text-gray-500">Avg</div>
<div className="text-white font-medium">{avgFinish.toFixed(1)}</div>
</div>
</div>
</div>
);
}