di usage in website
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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 ? {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user