139 lines
5.1 KiB
TypeScript
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>
|
|
);
|
|
} |