diff --git a/app/api/display/route.ts b/app/api/display/route.ts index afe45465..0deb86d8 100644 --- a/app/api/display/route.ts +++ b/app/api/display/route.ts @@ -12,7 +12,7 @@ import { getDisplayIdFromHeaders, writeDisplayIdToHeaders } from '@lib/auth/Disp import { readSettings } from '@lib/Settings'; import db, { tActivities, tActivitiesLocations, tActivitiesTimeslots, tDisplays, tEvents, tNardo, - tRoles, tSchedule, tShifts, tTeams, tUsers, tUsersEvents } from '@lib/database'; + tRoles, tSchedule, tShifts, tStorage, tTeams, tUsers, tUsersEvents } from '@lib/database'; /** * Interface defining an individual shift that will be shared with the display. @@ -38,6 +38,11 @@ const kDisplayShiftDefinition = z.object({ */ name: z.string(), + /** + * Optional URL to the volunteer's avatar, when available. + */ + avatar: z.string().optional(), + /** * Team that the volunteer is part of. */ @@ -346,6 +351,8 @@ async function display(request: Request, props: ActionProps): Promise .executeSelectMany(); if (shifts.length > 0) { + const storageJoin = tStorage.forUseInLeftJoin(); + const schedule = await dbInstance.selectFrom(tSchedule) .innerJoin(tUsersEvents) .on(tUsersEvents.userId.equals(tSchedule.userId)) @@ -357,6 +364,8 @@ async function display(request: Request, props: ActionProps): Promise .on(tRoles.roleId.equals(tUsersEvents.roleId)) .innerJoin(tUsers) .on(tUsers.userId.equals(tSchedule.userId)) + .leftJoin(storageJoin) + .on(storageJoin.fileId.equals(tUsers.avatarId)) .where(tSchedule.shiftId.in(shifts)) .and(tSchedule.eventId.equals(configuration.eventId)) .and(tSchedule.scheduleDeleted.isNull()) @@ -367,6 +376,7 @@ async function display(request: Request, props: ActionProps): Promise end: tSchedule.scheduleTimeEnd, name: tUsers.displayName.valueWhenNull(tUsers.firstName), + avatar: storageJoin.fileHash, team: tTeams.teamTitle, role: tRoles.roleName, }) @@ -379,6 +389,7 @@ async function display(request: Request, props: ActionProps): Promise ...entry, start: entry.start.epochSeconds, end: entry.end.epochSeconds, + avatar: entry.avatar ? `/blob/${entry.avatar}.png` : undefined, }; if (isBefore(entry.end, currentTime)) diff --git a/app/display/cards/ActiveVolunteersCard.tsx b/app/display/cards/ActiveVolunteersCard.tsx index 5b397165..245f8875 100644 --- a/app/display/cards/ActiveVolunteersCard.tsx +++ b/app/display/cards/ActiveVolunteersCard.tsx @@ -3,7 +3,6 @@ 'use client'; -import Avatar from '@mui/material/Avatar'; import Box from '@mui/material/Box'; import Grid from '@mui/material/Unstable_Grid2'; import Paper from '@mui/material/Paper'; @@ -11,6 +10,7 @@ import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import type { DisplayShiftInfo } from '../DisplayContext'; +import { Avatar } from '@app/components/Avatar'; import { Temporal, formatDate } from '@lib/Temporal'; /** @@ -39,9 +39,7 @@ function ActiveVolunteerCard(props: ActiveVolunteerCardProps) { return ( - - {props.volunteer.name[0]} - + {props.volunteer.name} {props.volunteer.name}