Files
gridpilot.gg/apps/website/app/teams/[id]/TeamDetailInteractive.tsx
2026-01-05 19:35:49 +01:00

127 lines
4.5 KiB
TypeScript

'use client';
import { useState, useEffect, useCallback } from 'react';
import { useParams, useRouter } from 'next/navigation';
import TeamDetailTemplate from '@/templates/TeamDetailTemplate';
import { useServices } from '@/lib/services/ServiceProvider';
import { TeamDetailsViewModel } from '@/lib/view-models/TeamDetailsViewModel';
import { TeamMemberViewModel } from '@/lib/view-models/TeamMemberViewModel';
import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
type Tab = 'overview' | 'roster' | 'standings' | 'admin';
export default function TeamDetailInteractive() {
const params = useParams();
const teamId = params.id as string;
const { teamService } = useServices();
const router = useRouter();
const currentDriverId = useEffectiveDriverId();
const [team, setTeam] = useState<TeamDetailsViewModel | null>(null);
const [memberships, setMemberships] = useState<TeamMemberViewModel[]>([]);
const [activeTab, setActiveTab] = useState<Tab>('overview');
const [loading, setLoading] = useState(true);
const [isAdmin, setIsAdmin] = useState(false);
const loadTeamData = useCallback(async () => {
setLoading(true);
try {
const teamDetails = await teamService.getTeamDetails(teamId, currentDriverId);
if (!teamDetails) {
setTeam(null);
setMemberships([]);
setIsAdmin(false);
return;
}
const teamMembers = await teamService.getTeamMembers(teamId, currentDriverId, teamDetails.ownerId);
const adminStatus = teamDetails.isOwner ||
teamMembers.some((m) => m.driverId === currentDriverId && (m.role === 'manager' || m.role === 'owner'));
setTeam(teamDetails);
setMemberships(teamMembers);
setIsAdmin(adminStatus);
} finally {
setLoading(false);
}
}, [teamId, currentDriverId, teamService]);
useEffect(() => {
void loadTeamData();
}, [loadTeamData]);
const handleUpdate = () => {
loadTeamData();
};
const handleRemoveMember = async (driverId: string) => {
if (!confirm('Are you sure you want to remove this member?')) {
return;
}
try {
const performer = await teamService.getMembership(teamId, currentDriverId);
if (!performer || (performer.role !== 'owner' && performer.role !== 'manager')) {
throw new Error('Only owners or admins can remove members');
}
const membership = await teamService.getMembership(teamId, driverId);
if (!membership) {
throw new Error('Member not found');
}
if (membership.role === 'owner') {
throw new Error('Cannot remove the team owner');
}
await teamService.removeMembership(teamId, driverId);
handleUpdate();
} catch (error) {
alert(error instanceof Error ? error.message : 'Failed to remove member');
}
};
const handleChangeRole = async (driverId: string, newRole: 'owner' | 'admin' | 'member') => {
try {
const performer = await teamService.getMembership(teamId, currentDriverId);
if (!performer || (performer.role !== 'owner' && performer.role !== 'manager')) {
throw new Error('Only owners or admins can update roles');
}
const membership = await teamService.getMembership(teamId, driverId);
if (!membership) {
throw new Error('Member not found');
}
if (membership.role === 'owner') {
throw new Error('Cannot change the owner role');
}
// Convert 'admin' to 'manager' for the service
const serviceRole = newRole === 'admin' ? 'manager' : newRole;
await teamService.updateMembership(teamId, driverId, serviceRole);
handleUpdate();
} catch (error) {
alert(error instanceof Error ? error.message : 'Failed to change role');
}
};
const handleGoBack = () => {
window.history.back();
};
return (
<TeamDetailTemplate
team={team}
memberships={memberships}
activeTab={activeTab}
loading={loading}
isAdmin={isAdmin}
onTabChange={setActiveTab}
onUpdate={handleUpdate}
onRemoveMember={handleRemoveMember}
onChangeRole={handleChangeRole}
onGoBack={handleGoBack}
/>
);
}