Files
gridpilot.gg/apps/website/app/teams/[id]/TeamDetailInteractive.tsx
2026-01-06 19:36:03 +01:00

139 lines
5.1 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import TeamDetailTemplate from '@/templates/TeamDetailTemplate';
import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
// Shared state components
import { StateContainer } from '@/components/shared/state/StateContainer';
import { useTeamDetails } from '@/hooks/team/useTeamDetails';
import { useTeamMembers } from '@/hooks/team/useTeamMembers';
import { useInject } from '@/lib/di/hooks/useInject';
import { TEAM_SERVICE_TOKEN } from '@/lib/di/tokens';
import { Users } from 'lucide-react';
type Tab = 'overview' | 'roster' | 'standings' | 'admin';
export default function TeamDetailInteractive() {
const params = useParams();
const teamId = params.id as string;
const router = useRouter();
const currentDriverId = useEffectiveDriverId();
const teamService = useInject(TEAM_SERVICE_TOKEN);
const [activeTab, setActiveTab] = useState<Tab>('overview');
// Fetch team details using DI + React-Query
const { data: teamDetails, isLoading: teamLoading, error: teamError, retry: teamRetry } = useTeamDetails(teamId, currentDriverId);
// Fetch team members using DI + React-Query
const { data: memberships, isLoading: membersLoading, error: membersError, retry: membersRetry } = useTeamMembers(
teamId,
currentDriverId,
teamDetails?.ownerId || ''
);
const isLoading = teamLoading || membersLoading;
const error = teamError || membersError;
const retry = async () => {
await teamRetry();
await membersRetry();
};
// Determine admin status
const isAdmin = teamDetails?.isOwner ||
(memberships || []).some((m: any) => m.driverId === currentDriverId && (m.role === 'manager' || m.role === 'owner'));
const handleUpdate = () => {
retry();
};
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 (
<StateContainer
data={teamDetails}
isLoading={isLoading}
error={error}
retry={retry}
config={{
loading: { variant: 'skeleton', message: 'Loading team details...' },
error: { variant: 'full-screen' },
empty: {
icon: Users,
title: 'Team not found',
description: 'The team may have been deleted or you may not have access',
action: { label: 'Back to Teams', onClick: () => router.push('/teams') }
}
}}
>
{(teamData) => (
<TeamDetailTemplate
team={teamData!}
memberships={memberships || []}
activeTab={activeTab}
loading={isLoading}
isAdmin={isAdmin}
onTabChange={setActiveTab}
onUpdate={handleUpdate}
onRemoveMember={handleRemoveMember}
onChangeRole={handleChangeRole}
onGoBack={handleGoBack}
/>
)}
</StateContainer>
);
}