-
Notifications
You must be signed in to change notification settings - Fork 27
Schedule table component #239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,146 @@ | ||||||
| import { | ||||||
| Table, | ||||||
| TableBody, | ||||||
| TableCell, | ||||||
| TableHeader, | ||||||
| TableRow, | ||||||
| } from "@/components/shadcn/ui/table"; | ||||||
|
|
||||||
| import { type EventType as Event } from "@/lib/types/events"; | ||||||
| import { ReactNode } from "react"; | ||||||
| import { formatInTimeZone } from "date-fns-tz"; | ||||||
| import c from "config"; | ||||||
| import { Badge } from "@/components/shadcn/ui/badge"; | ||||||
| import Link from "next/link"; | ||||||
|
|
||||||
| const userTimeZone = c.hackathonTimezone; | ||||||
|
|
||||||
| function splitByDay(schedule: Event[]) { | ||||||
| const days: Map<string, Event[]> = new Map<string, Event[]>(); | ||||||
| schedule.forEach((event) => { | ||||||
| const day = daysOfWeek[event.startTime.getDay()]; | ||||||
|
|
||||||
| if (days.get(day)) { | ||||||
| days.get(day)?.push(event); | ||||||
| } else { | ||||||
| days.set(day, [event]); | ||||||
| } | ||||||
| }); | ||||||
| return days; | ||||||
| } | ||||||
|
|
||||||
| type ScheduleTableProps = { | ||||||
| schedule: Event[]; | ||||||
|
|
||||||
| }; | ||||||
|
|
||||||
| const daysOfWeek = [ | ||||||
| "Sunday", | ||||||
| "Monday", | ||||||
| "Tuesday", | ||||||
| "Wednesday", | ||||||
| "Thursday", | ||||||
| "Friday", | ||||||
| "Saturday", | ||||||
| ]; | ||||||
| function eventDateString(arr: Event[], timezone: string) { | ||||||
| const date = formatInTimeZone(arr[0].startTime, timezone, "PPPP"); | ||||||
| const retString = date.substring(0, date.length - 6); | ||||||
| return retString; | ||||||
| } | ||||||
|
|
||||||
| export default function ScheduleTable({ | ||||||
| schedule, | ||||||
| }: ScheduleTableProps) { | ||||||
| return ( | ||||||
| <div className="mx-auto mt-5 w-[99vw] lg:w-3/4"> | ||||||
| <Table className="grid gap-6"> | ||||||
| {Array.from(splitByDay(schedule).entries()).map( | ||||||
| ([dateID, arr]): ReactNode => ( | ||||||
| <> | ||||||
| <TableBody key={dateID} className="border"> | ||||||
| <TableHeader className="flex justify-start"> | ||||||
| <span className="m-1 p-4 text-center text-xl font-bold lg:text-4xl"> | ||||||
| <p>{`${eventDateString(arr, userTimeZone)}`}</p> | ||||||
| </span> | ||||||
| </TableHeader> | ||||||
| {arr.map( | ||||||
| (event): ReactNode => ( | ||||||
| <EventRow | ||||||
| key={event.id} | ||||||
| event={event} | ||||||
| /> | ||||||
| ), | ||||||
| )} | ||||||
| </TableBody> | ||||||
| </> | ||||||
| ), | ||||||
| )} | ||||||
| </Table> | ||||||
| </div> | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| // Needs timezone prop | ||||||
| type eventRowProps = { | ||||||
| event: Event; | ||||||
| }; | ||||||
| export function EventRow({ event }: eventRowProps) { | ||||||
| const startTimeFormatted = formatInTimeZone( | ||||||
| event.startTime, | ||||||
| userTimeZone, | ||||||
| "hh:mm a", | ||||||
| { | ||||||
| useAdditionalDayOfYearTokens: true, | ||||||
| }, | ||||||
| ); | ||||||
|
|
||||||
| const endTimeFormatted = formatInTimeZone( | ||||||
| event.endTime, | ||||||
| userTimeZone, | ||||||
| "h:mm a", | ||||||
| ); | ||||||
| const color = (c.eventTypes as Record<string, string>)[event.type]; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add fallback for unknown event types. If Proposed fix- const color = (c.eventTypes as Record<string, string>)[event.type];
+ const color = (c.eventTypes as Record<string, string>)[event.type] || c.eventTypes.Other;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| const href = "/schedule/" + event.id; | ||||||
| return ( | ||||||
| <TableRow | ||||||
| key={event.id} | ||||||
| className="flex flex-col justify-around bg-transparent px-4 pb-1 odd:bg-white/5" | ||||||
| > | ||||||
| <TableCell className="p-2 flex place-items-center"> | ||||||
| <div className="w-1/3"> | ||||||
| <Link href={href}> | ||||||
| <span className="flex font-semibold"> | ||||||
| <p>{`${startTimeFormatted}`}</p> | ||||||
| <p className="hidden sm:contents"> | ||||||
| {`- ${endTimeFormatted}`} | ||||||
| </p> | ||||||
| </span> | ||||||
| </Link> | ||||||
| </div> | ||||||
| <div className="flex w-2/3 place-items-center justify-end gap-2"> | ||||||
| <Badge | ||||||
| variant={"outline"} | ||||||
| className="flex justify-center text-center lg:w-[5rem]" | ||||||
| style={{ | ||||||
| borderColor: color, | ||||||
| }} | ||||||
| > | ||||||
| <p className="text-[0.5rem] lg:text-xs">{event.type}</p> | ||||||
| </Badge> | ||||||
|
|
||||||
| <Link href={href}> | ||||||
| <p className="p-1 text-right font-semibold lg:text-xl"> | ||||||
| {`${event.title}`} | ||||||
| </p> | ||||||
| </Link> | ||||||
| </div> | ||||||
| </TableCell> | ||||||
| <TableCell className="hidden lg:contents"> | ||||||
| <div className="p-2 w-full truncate text-ellipsis text-right"> | ||||||
| <p>{`${event.description}`}</p> | ||||||
| </div> | ||||||
| </TableCell> | ||||||
| </TableRow> | ||||||
| ); | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,7 @@ export default async function NavBarLinksGrouper() { | |
| </NavbarItem>, | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix trailing whitespace causing Prettier CI failure. Line 15 contains extra trailing whitespace after the closing brace. Please remove it (or run Prettier on the file) so 🤖 Prompt for AI Agents |
||
| return <>{toRender}</>; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing key on Fragment causes React warning.
When mapping, the
keyshould be on the outermost element. The fragment<>is outermost, but the key is onTableBodyinside. UseReact.Fragmentwith an explicit key instead.Proposed fix
{Array.from(splitByDay(schedule).entries()).map( ([dateID, arr]): ReactNode => ( - <> - <TableBody key={dateID} className="border"> + <React.Fragment key={dateID}> + <TableBody className="border"> <TableHeader className="flex justify-start"> <span className="m-1 p-4 text-center text-xl font-bold lg:text-4xl"> <p>{`${eventDateString(arr, userTimeZone)}`}</p> </span> </TableHeader> {arr.map( (event): ReactNode => ( <EventRow key={event.id} event={event} /> ), )} </TableBody> - </> + </React.Fragment> ), )}📝 Committable suggestion
🤖 Prompt for AI Agents