56 lines
2.1 KiB
TypeScript
56 lines
2.1 KiB
TypeScript
"use client";
|
|
import { usePoll } from "@/lib/use-poll";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { CardSkeleton } from "@/components/skeleton";
|
|
import { EmptyState } from "@/components/empty-state";
|
|
|
|
interface CalEvent {
|
|
summary: string;
|
|
date: string;
|
|
time: string;
|
|
location?: string;
|
|
start: string;
|
|
}
|
|
|
|
export function CalendarCard() {
|
|
const { data } = usePoll<{ events: CalEvent[]; total?: number }>("/api/calendar", 300000); // 5min
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<div className="flex items-center justify-between">
|
|
<CardTitle className="text-sm font-medium">Calendar</CardTitle>
|
|
{data?.total != null && (
|
|
<span className="text-[10px] text-muted-foreground">{data.total} upcoming</span>
|
|
)}
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{!data ? (
|
|
<CardSkeleton lines={3} />
|
|
) : data.events.length === 0 ? (
|
|
<EmptyState icon={"o"} title="No upcoming events" description="Your calendar is clear" />
|
|
) : (
|
|
<div className="space-y-3">
|
|
{data.events.map((event, i) => (
|
|
<div key={i} className="flex gap-3 items-start">
|
|
<div className="text-center min-w-[44px] rounded-lg bg-white/[0.04] border border-white/[0.06] px-2 py-1.5">
|
|
<p className="text-[10px] font-medium text-blue-400">{event.date.split(" ")[0]}</p>
|
|
<p className="text-lg font-bold leading-none">{event.date.split(" ")[1]}</p>
|
|
</div>
|
|
<div className="min-w-0">
|
|
<p className="text-xs font-medium text-foreground truncate">{event.summary}</p>
|
|
<p className="text-[10px] text-muted-foreground">{event.time}</p>
|
|
{event.location && (
|
|
<p className="text-[10px] text-muted-foreground/60 truncate">{event.location}</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|