70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
// src/routes/traffic/Grid.tsx
|
||
import { format } from "date-fns";
|
||
import React from "react";
|
||
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
|
||
|
||
export const days = Array.from(
|
||
{ length: 5 },
|
||
(_, i) => new Date(Date.now() + i * 24 * 60 * 60 * 1000),
|
||
);
|
||
|
||
// the layout of the hours
|
||
const hoursBefore = 3;
|
||
const totalHours = 24;
|
||
|
||
// get the current hour
|
||
const currentHour = new Date().getHours();
|
||
const startHour = (currentHour - hoursBefore + 24) % 24;
|
||
|
||
// generate the hours array
|
||
const hours = Array.from(
|
||
{ length: totalHours },
|
||
(_, i) => (startHour + i) % 24,
|
||
);
|
||
|
||
export function Grid({
|
||
days,
|
||
children,
|
||
}: {
|
||
days: any;
|
||
children?: (day: Date, hour: number) => React.ReactNode;
|
||
}) {
|
||
return (
|
||
<ScrollArea className={`h-[80vh]`}>
|
||
<div
|
||
className="grid"
|
||
style={{
|
||
display: "grid",
|
||
gridTemplateColumns: `100px repeat(${days.length}, 350px)`, // each day = 180 px wide
|
||
//minWidth: `${100 + days.length * 350}px`,
|
||
}}
|
||
>
|
||
{/* Empty top-left corner */}
|
||
<div className="sticky top-0 left-0 bg-background z-30"></div>
|
||
|
||
{/* Date headers */}
|
||
{days.map((d: any) => (
|
||
<div
|
||
key={d.toDateString()}
|
||
className="sticky top-0 bg-background z-20 p-2 font-semibold text-center"
|
||
>
|
||
{format(d, "EEEE M/d/yyyy")}
|
||
</div>
|
||
))}
|
||
|
||
{hours.map((hour) => (
|
||
<React.Fragment key={hour}>
|
||
<div className="border p-1 text-right text-sm">{hour}:00</div>
|
||
{days.map((d: any) => (
|
||
<div key={`${d}-${hour}`} className="relative border h-20">
|
||
{children && children(d, hour)}
|
||
</div>
|
||
))}
|
||
</React.Fragment>
|
||
))}
|
||
</div>
|
||
<ScrollBar orientation="horizontal" />
|
||
</ScrollArea>
|
||
);
|
||
}
|