website refactor
This commit is contained in:
105
apps/website/client-wrapper/RosterAdminPage.tsx
Normal file
105
apps/website/client-wrapper/RosterAdminPage.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
'use client';
|
||||
|
||||
import type { MembershipRole } from '@/lib/types/MembershipRole';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
useLeagueJoinRequests,
|
||||
useLeagueRosterAdmin,
|
||||
useApproveJoinRequest,
|
||||
useRejectJoinRequest,
|
||||
useUpdateMemberRole,
|
||||
useRemoveMember,
|
||||
} from "@/hooks/league/useLeagueRosterAdmin";
|
||||
import { RosterAdminTemplate } from '@/templates/RosterAdminTemplate';
|
||||
import type { JoinRequestData, RosterMemberData } from '@/lib/view-data/LeagueRosterAdminViewData';
|
||||
import type { LeagueRosterJoinRequestDTO } from '@/lib/types/generated/LeagueRosterJoinRequestDTO';
|
||||
import type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';
|
||||
|
||||
const ROLE_OPTIONS: MembershipRole[] = ['owner', 'admin', 'steward', 'member'];
|
||||
|
||||
export function RosterAdminPage() {
|
||||
const params = useParams();
|
||||
const leagueId = params.id as string;
|
||||
|
||||
// Fetch data using React-Query + DI
|
||||
const {
|
||||
data: joinRequests = [],
|
||||
isLoading: loadingJoinRequests,
|
||||
refetch: refetchJoinRequests,
|
||||
} = useLeagueJoinRequests(leagueId);
|
||||
|
||||
const {
|
||||
data: members = [],
|
||||
isLoading: loadingMembers,
|
||||
refetch: refetchMembers,
|
||||
} = useLeagueRosterAdmin(leagueId);
|
||||
|
||||
const loading = loadingJoinRequests || loadingMembers;
|
||||
|
||||
// Mutations
|
||||
const approveMutation = useApproveJoinRequest({
|
||||
onSuccess: () => refetchJoinRequests(),
|
||||
});
|
||||
|
||||
const rejectMutation = useRejectJoinRequest({
|
||||
onSuccess: () => refetchJoinRequests(),
|
||||
});
|
||||
|
||||
const updateRoleMutation = useUpdateMemberRole({
|
||||
onError: () => refetchMembers(), // Refetch on error to restore state
|
||||
});
|
||||
|
||||
const removeMemberMutation = useRemoveMember({
|
||||
onSuccess: () => refetchMembers(),
|
||||
});
|
||||
|
||||
const pendingCountLabel = useMemo(() => {
|
||||
return joinRequests.length === 1 ? '1 request' : `${joinRequests.length} requests`;
|
||||
}, [joinRequests.length]);
|
||||
|
||||
const handleApprove = async (requestId: string) => {
|
||||
await approveMutation.mutateAsync({ leagueId, requestId });
|
||||
};
|
||||
|
||||
const handleReject = async (requestId: string) => {
|
||||
await rejectMutation.mutateAsync({ leagueId, requestId });
|
||||
};
|
||||
|
||||
const handleRoleChange = async (driverId: string, newRole: MembershipRole) => {
|
||||
await updateRoleMutation.mutateAsync({ leagueId, driverId, newRole });
|
||||
};
|
||||
|
||||
const handleRemove = async (driverId: string) => {
|
||||
await removeMemberMutation.mutateAsync({ leagueId, driverId });
|
||||
};
|
||||
|
||||
const viewData = useMemo(() => ({
|
||||
leagueId,
|
||||
joinRequests: joinRequests.map((req: LeagueRosterJoinRequestDTO): JoinRequestData => ({
|
||||
id: req.id,
|
||||
driver: req.driver as { id: string; name: string },
|
||||
requestedAt: req.requestedAt,
|
||||
message: req.message || undefined,
|
||||
})),
|
||||
members: members.map((m: LeagueRosterMemberDTO): RosterMemberData => ({
|
||||
driverId: m.driverId,
|
||||
driver: m.driver as { id: string; name: string },
|
||||
role: m.role,
|
||||
joinedAt: m.joinedAt,
|
||||
})),
|
||||
}), [leagueId, joinRequests, members]);
|
||||
|
||||
return (
|
||||
<RosterAdminTemplate
|
||||
viewData={viewData}
|
||||
loading={loading}
|
||||
pendingCountLabel={pendingCountLabel}
|
||||
onApprove={handleApprove}
|
||||
onReject={handleReject}
|
||||
onRoleChange={handleRoleChange}
|
||||
onRemove={handleRemove}
|
||||
roleOptions={ROLE_OPTIONS}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user