diff --git a/backend/src/routes/dashboard.js b/backend/src/routes/dashboard.js index b2e4078..1ca5f0f 100644 --- a/backend/src/routes/dashboard.js +++ b/backend/src/routes/dashboard.js @@ -49,7 +49,7 @@ router.get('/', authenticate, async (req, res, next) => { // Socket may not be initialized (e.g., during tests) } - // Get user's heats for each event + // Get user's heats and recording suggestions for each event const activeEvents = await Promise.all( eventParticipants.map(async (ep) => { const heats = await prisma.eventUserHeat.findMany({ @@ -75,6 +75,47 @@ router.get('/', authenticate, async (req, res, next) => { }, }); + // Get recording suggestions for this event + const heatIds = heats.map(h => h.id); + + // Suggestions where user is the dancer (someone records them) + const toBeRecorded = await prisma.recordingSuggestion.findMany({ + where: { + eventId: ep.event.id, + heatId: { in: heatIds }, + }, + include: { + heat: { + include: { + division: { select: { abbreviation: true } }, + competitionType: { select: { abbreviation: true } }, + }, + }, + recorder: { + select: { id: true, username: true, avatar: true }, + }, + }, + }); + + // Suggestions where user is the recorder (they record someone) + const toRecord = await prisma.recordingSuggestion.findMany({ + where: { + eventId: ep.event.id, + recorderId: userId, + }, + include: { + heat: { + include: { + division: { select: { abbreviation: true } }, + competitionType: { select: { abbreviation: true } }, + user: { + select: { id: true, username: true, avatar: true }, + }, + }, + }, + }, + }); + return { id: ep.event.id, slug: ep.event.slug, @@ -91,6 +132,28 @@ router.get('/', authenticate, async (req, res, next) => { heatNumber: h.heatNumber, role: h.role, })), + recordingSuggestions: { + toBeRecorded: toBeRecorded.map(s => ({ + id: s.id, + status: s.status, + heat: { + heatNumber: s.heat.heatNumber, + division: s.heat.division?.abbreviation, + competitionType: s.heat.competitionType?.abbreviation, + }, + recorder: s.recorder, + })), + toRecord: toRecord.map(s => ({ + id: s.id, + status: s.status, + heat: { + heatNumber: s.heat.heatNumber, + division: s.heat.division?.abbreviation, + competitionType: s.heat.competitionType?.abbreviation, + }, + dancer: s.heat.user, + })), + }, }; }) ); diff --git a/frontend/src/components/dashboard/index.js b/frontend/src/components/dashboard/index.js index 477f6ef..969a85f 100644 --- a/frontend/src/components/dashboard/index.js +++ b/frontend/src/components/dashboard/index.js @@ -1,3 +1,4 @@ export { default as DashboardEventCard } from './DashboardEventCard'; export { default as DashboardMatchCard } from './DashboardMatchCard'; +export { default as RecordingSummaryCard } from './RecordingSummaryCard'; export { IncomingRequestCard, OutgoingRequestCard } from './MatchRequestCards'; diff --git a/frontend/src/pages/DashboardPage.jsx b/frontend/src/pages/DashboardPage.jsx index 412eb29..7359c94 100644 --- a/frontend/src/pages/DashboardPage.jsx +++ b/frontend/src/pages/DashboardPage.jsx @@ -10,6 +10,7 @@ import EmptyState from '../components/common/EmptyState'; import { DashboardEventCard, DashboardMatchCard, + RecordingSummaryCard, IncomingRequestCard, OutgoingRequestCard, } from '../components/dashboard'; @@ -20,6 +21,7 @@ import { ChevronRight, Inbox, Send, + Video, } from 'lucide-react'; const DashboardPage = () => { @@ -159,6 +161,14 @@ const DashboardPage = () => { const hasIncoming = matchRequests?.incoming?.length > 0; const hasOutgoing = matchRequests?.outgoing?.length > 0; + // Filter events with recording suggestions + const eventsWithRecordings = activeEvents?.filter( + (event) => + event.recordingSuggestions && + (event.recordingSuggestions.toBeRecorded.length > 0 || + event.recordingSuggestions.toRecord.length > 0) + ) || []; + return (
@@ -207,6 +217,24 @@ const DashboardPage = () => { )} + {/* Recording Assignments Section */} + {eventsWithRecordings.length > 0 && ( +
+
+

+

+
+ +
+ {eventsWithRecordings.map((event) => ( + + ))} +
+
+ )} + {/* Active Matches Section */}