diff --git a/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/components/review/review-stage.tsx b/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/components/review/review-stage.tsx index 717a7d9db..831a832c4 100644 --- a/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/components/review/review-stage.tsx +++ b/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/components/review/review-stage.tsx @@ -3,37 +3,54 @@ import { useCallback, useMemo, useState } from 'react'; import { useRouter } from 'next/navigation'; import { useTranslations } from 'next-intl'; -import { Box, Paper, Typography, Grid, Button } from '@mui/material'; +import { Box, Paper, Typography, Grid, Button, CircularProgress } from '@mui/material'; +import { useQuery } from '@apollo/client/react'; import { useFinalDeliberation } from '../../final-deliberation-context'; import { EnrichedTeam } from '../../types'; +import { GET_DIVISION_AWARDS } from '../../graphql'; import { AwardSection } from './award-section'; import { ApprovalModal } from './approval-modal'; export const ReviewStage: React.FC = () => { const router = useRouter(); const t = useTranslations('pages.deliberations.final.review'); - const { awards, deliberation, division, teams } = useFinalDeliberation(); + const { deliberation, division, teams } = useFinalDeliberation(); const [openConfirmDialog, setOpenConfirmDialog] = useState(false); - // Filter out personal awards and group by name + const { data: awardsData, loading: awardsLoading } = useQuery(GET_DIVISION_AWARDS, { + variables: { divisionId: division.id } + }); + const mappedWinners = useMemo(() => { const mapped: Record = {}; - for (const [awardName, value] of Object.entries(awards)) { - let teamIds: string[] = []; - if (awardName === 'champions') { - teamIds = Object.values(deliberation.champions); - } else { - teamIds = value as string[]; + + if (!awardsData?.division?.judging?.awards) { + return mapped; + } + + // Group awards by name, filtering for TEAM awards with winners only + for (const award of awardsData.division.judging.awards) { + if (award.type !== 'TEAM' || !award.winner) { + continue; } - const winners = []; - for (const teamId of teamIds) { - const team = teams.find(t => t.id === teamId); - winners.push(team!); + + if (!mapped[award.name]) { + mapped[award.name] = []; + } + + if ('team' in award.winner) { + const teamWinner = award.winner; + if (teamWinner.team) { + const team = teams.find(t => t.id === teamWinner.team.id); + if (team) { + mapped[award.name].push(team); + } + } } - mapped[awardName] = winners; } + return mapped; - }, [awards, deliberation.champions, teams]); + }, [awardsData, teams]); const handleOpenConfirm = useCallback(() => { setOpenConfirmDialog(true); @@ -57,15 +74,21 @@ export const ReviewStage: React.FC = () => { - - - {Object.entries(mappedWinners).map(([awardName, winners]) => ( - - - - ))} - - + {awardsLoading ? ( + + + + ) : ( + + + {Object.entries(mappedWinners).map(([awardName, winners]) => ( + + + + ))} + + + )} diff --git a/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/query.ts b/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/query.ts index f6e098409..da450575d 100644 --- a/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/query.ts +++ b/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/query.ts @@ -1,6 +1,11 @@ import { gql, TypedDocumentNode } from '@apollo/client'; import { merge } from '@lems/shared/utils'; -import type { FinalDeliberationData, FinalDeliberationVars } from './types'; +import type { + FinalDeliberationData, + FinalDeliberationVars, + DivisionAwardsData, + DivisionAwardsVars +} from './types'; export const GET_FINAL_DELIBERATION: TypedDocumentNode< FinalDeliberationData, @@ -142,6 +147,35 @@ export const GET_FINAL_DELIBERATION: TypedDocumentNode< } `; +export const GET_DIVISION_AWARDS: TypedDocumentNode = gql` + query GetDivisionAwards($divisionId: String!) { + division(id: $divisionId) { + id + judging { + awards { + id + name + type + place + winner { + ... on TeamWinner { + team { + id + number + name + slug + } + } + ... on PersonalWinner { + name + } + } + } + } + } + } +`; + export function parseFinalDeliberationData(data: FinalDeliberationData) { const updates: Record = {}; diff --git a/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/types.ts b/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/types.ts index 2ac741bca..35042fc3f 100644 --- a/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/types.ts +++ b/apps/frontend/src/app/[locale]/lems/(volunteer)/deliberation/final/graphql/types.ts @@ -66,3 +66,22 @@ export interface FinalDeliberationData { export interface FinalDeliberationVars { divisionId: string; } + +export interface DivisionAwardsData { + division: { + id: string; + judging: { + awards: Array<{ + id: string; + name: string; + type: 'PERSONAL' | 'TEAM'; + place: number; + winner?: TeamWinner | PersonalWinner; + }>; + }; + }; +} + +export interface DivisionAwardsVars { + divisionId: string; +}