ultisuite-client/components/agenda/agenda-mini-month.tsx
R3D347HR4Y 3bbf3691b0
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
bordel c'est beau
2026-06-11 10:10:39 +02:00

102 lines
3.0 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import {
addDays,
addMonths,
format,
isSameDay,
isSameMonth,
startOfMonth,
startOfWeek,
} from "date-fns"
import { fr } from "date-fns/locale"
import { ChevronLeft, ChevronRight } from "lucide-react"
import { WEEK_OPTS } from "@/lib/agenda/agenda-date"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
const WEEKDAYS = ["L", "M", "M", "J", "V", "S", "D"]
export function AgendaMiniMonth({
selected,
onSelect,
}: {
selected: Date
onSelect: (date: Date) => void
}) {
const [cursor, setCursor] = useState(() => startOfMonth(selected))
useEffect(() => {
setCursor(startOfMonth(selected))
}, [selected])
const gridStart = startOfWeek(cursor, WEEK_OPTS)
const today = new Date()
const cells: Date[] = []
for (let i = 0; i < 42; i++) cells.push(addDays(gridStart, i))
return (
<div className="select-none px-1">
<div className="flex items-center justify-between pb-1 pl-2">
<span className="text-sm font-medium text-foreground/90">
{format(cursor, "MMMM yyyy", { locale: fr }).replace(/^./, (c) =>
c.toUpperCase(),
)}
</span>
<div className="flex">
<Button
variant="ghost"
size="icon"
className="size-7 rounded-full text-muted-foreground"
aria-label="Mois précédent"
onClick={() => setCursor((c) => addMonths(c, -1))}
>
<ChevronLeft className="size-4" />
</Button>
<Button
variant="ghost"
size="icon"
className="size-7 rounded-full text-muted-foreground"
aria-label="Mois suivant"
onClick={() => setCursor((c) => addMonths(c, 1))}
>
<ChevronRight className="size-4" />
</Button>
</div>
</div>
<div className="grid grid-cols-7 text-center">
{WEEKDAYS.map((d, i) => (
<span
key={`${d}-${i}`}
className="py-1 text-[0.65rem] font-medium text-muted-foreground"
>
{d}
</span>
))}
{cells.map((day) => {
const isToday = isSameDay(day, today)
const isSelected = isSameDay(day, selected)
const inMonth = isSameMonth(day, cursor)
return (
<button
key={day.getTime()}
type="button"
onClick={() => onSelect(day)}
className={cn(
"mx-auto flex size-6 items-center justify-center rounded-full text-[0.7rem] transition-colors",
inMonth ? "text-foreground/85" : "text-muted-foreground/50",
isToday && "bg-primary font-semibold text-primary-foreground",
isSelected && !isToday && "bg-primary/15 font-semibold text-primary",
!isToday && !isSelected && "hover:bg-mail-nav-hover",
)}
>
{format(day, "d")}
</button>
)
})}
</div>
</div>
)
}