"use client"; import { useState } from "react"; import { ChevronLeft, ChevronRight, Plus } from "lucide-react"; import { Empty } from "@/components/ui/primitives"; import { cn } from "@/lib/utils"; import type { RowOut } from "@/lib/databases/types"; import { dateOf } from "@/lib/databases/values"; import { useDb } from "../hooks"; import { CellDisplay } from "../cells/Cell"; const iso = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; const DOW = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; export function CalendarView() { const ctx = useDb(); const dp = ctx.props.find((p) => p.id === ctx.view.config.dateProperty); const [cur, setCur] = useState(() => { const d = new Date(); d.setDate(1); d.setHours(0, 0, 0, 0); return d; }); if (!dp) return ; const byDay = new Map(); for (const r of ctx.rows) { const d = dateOf(r.values[dp.id]); if (!d) continue; const k = iso(d); byDay.set(k, [...(byDay.get(k) ?? []), r]); } const start = new Date(cur); start.setDate(1 - ((cur.getDay() + 6) % 7)); const days: Date[] = []; for (let i = 0; i < 42; i++) { const d = new Date(start); d.setDate(start.getDate() + i); days.push(d); } const today = iso(new Date()); const month = cur.getMonth(); const label = cur.toLocaleDateString("en-CA", { month: "long", year: "numeric" }); const nav = (n: number) => setCur((c) => { const d = new Date(c); d.setMonth(d.getMonth() + n); return d; }); const add = (d: Date) => ctx.addRow({ [dp.id]: dp.type === "date" ? iso(d) : undefined }); const canAdd = dp.type === "date"; const undated = ctx.rows.filter((r) => !dateOf(r.values[dp.id])); const header =
{label}
; if (ctx.isMobile) { const inMonth = days.filter((d) => d.getMonth() === month && byDay.has(iso(d))); return
{header}{inMonth.length === 0 &&
Nothing this month.
}
{inMonth.map((d) =>
{d.toLocaleDateString("en-CA", { weekday: "short", day: "numeric", month: "short" })}
{byDay.get(iso(d))!.map((r) => )}
)}
{canAdd && }
; } return (
{header}
{DOW.map((d) =>
{d}
)} {days.map((d) => { const k = iso(d); const evs = byDay.get(k) ?? []; return (
canAdd && add(d)} className={cn("group/day relative min-h-[6rem] border-b border-r border-line p-1", d.getMonth() !== month && "bg-bg-sunk/40 text-fg-faint")}>
{d.getDate()}{canAdd && }
{evs.slice(0, 4).map((r) => )}{evs.length > 4 &&
+{evs.length - 4} more
}
); })}
{undated.length > 0 &&
{undated.length} row{undated.length > 1 ? "s" : ""} without a date (visible in the table view).
}
); } function Chip({ row, big }: { row: RowOut; big?: boolean }) { const ctx = useDb(); const st = ctx.props.find((p) => p.type === "status" || p.type === "select"); return ; }