-
Notifications
You must be signed in to change notification settings - Fork 26
Open
Labels
Description
Goal
Make a minimal wrapper for the ScheduleTimeline pattern that:
- accepts
schedule(full event objects, not just a minimal type) - computes / accepts
timezone - splits events by day
- iterates and renders using caller-provided components so pages can swap UI without re-writing the logic
- passes the already-calculated timezone into the custom components (so they don't have to figure it out)
Props (recommended)
schedule: Event[](same shape you already use inScheduleTimeline)timezone?: stringDayHeader?: React.ComponentType<{ dayName: string }>RenderEventRow: React.ComponentType<{ event: Event; userTimeZone: string }>
If timezone is not provided, compute it internally:
const userTimeZone = getClientTimeZone(c.hackathonTimezone)
Acceptance Criteria
- New component exists (e.g.
ScheduleTimelineBare.tsx) - Uses existing
splitByDay(schedule)logic - Iterates days, then iterates events within each day
- Calls
RenderEventRowfor each event and passes:eventuserTimeZone(already computed)
- Optional
DayHeadercan be overridden - Works with existing
EventRowwithout changes
Example Implementation
components/schedule/ScheduleTimelineBare.tsx
import { type EventType as Event } from "@/lib/types/events";
import { getClientTimeZone } from "@/lib/utils/client/shared";
import c from "config";
import { ReactNode } from "react";
const daysOfWeek = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
function splitByDay(schedule: Event[]) {
const days: Map<string, Event[]> = new Map();
schedule.forEach((event) => {
const day = daysOfWeek[event.startTime.getDay()];
const existing = days.get(day);
if (existing) existing.push(event);
else days.set(day, [event]);
});
return days;
}
type DayHeaderProps = { dayName: string };
const DefaultDayHeader = ({ dayName }: DayHeaderProps) => (
<tr key={dayName + " title"} className="py-8">
<td></td>
<td className="w-1" style={{ backgroundColor: `hsl(var(--secondary))` }} />
<td>
<h2 className="ml-16 w-full border-b py-4 text-6xl font-black">
{dayName}
</h2>
</td>
</tr>
);
type RowProps = { event: Event; userTimeZone: string };
export default function ScheduleTimelineBare({
schedule,
timezone,
DayHeader = DefaultDayHeader,
RenderEventRow,
}: {
schedule: Event[];
timezone?: string;
DayHeader?: React.ComponentType<DayHeaderProps>;
RenderEventRow: React.ComponentType<RowProps>;
}) {
const userTimeZone = timezone ?? getClientTimeZone(c.hackathonTimezone);
const days = Array.from(splitByDay(schedule).entries());
return (
<div className="mx-auto mt-5 w-3/4">
<table className="p-4">
<tbody>
{days.map(([dayName, arr]): ReactNode => (
<>
<DayHeader dayName={dayName} />
{arr.map((event) => (
<RenderEventRow
key={event.id}
event={event}
userTimeZone={userTimeZone}
/>
))}
</>
))}
</tbody>
</table>
</div>
);
}Usage example (your current page + existing EventRow)
import ScheduleTimelineBare from "@/components/schedule/ScheduleTimelineBare";
import { EventRow } from "../dash/schedule/schedule-timeline";
import { getAllEvents } from "db/functions";
import { getClientTimeZone } from "@/lib/utils/client/shared";
import c from "config";
export default async function Page() {
const sched = await getAllEvents();
const userTimeZone = getClientTimeZone(c.hackathonTimezone);
return (
<>
<h1 className="mx-auto my-8 w-3/4 text-8xl font-black">Schedule</h1>
<ScheduleTimelineBare
schedule={sched}
timezone={userTimeZone}
RenderEventRow={EventRow}
/>
</>
);
}
export const revalidate = 60;Reactions are currently unavailable