- Removed the handleGoToToday function and its associated prop from CalendarPage, streamlining the component's logic. - Eliminated the isLoading and onRefresh props from CalendarHeader, enhancing clarity and reducing complexity. - Updated internationalization messages to remove references to "Today" and "Refresh," aligning with the component changes.
83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
/**
|
|
* Calendar header: month title, prev/next navigation, weekday labels.
|
|
* Replaces the header from webapp index.html and calendar.js month title.
|
|
*/
|
|
|
|
"use client";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { useTranslation } from "@/i18n/use-translation";
|
|
import { cn } from "@/lib/utils";
|
|
import {
|
|
ChevronLeft as ChevronLeftIcon,
|
|
ChevronRight as ChevronRightIcon,
|
|
} from "lucide-react";
|
|
|
|
export interface CalendarHeaderProps {
|
|
/** Currently displayed month (used for title). */
|
|
month: Date;
|
|
/** Whether month navigation is disabled (e.g. during loading). */
|
|
disabled?: boolean;
|
|
onPrevMonth: () => void;
|
|
onNextMonth: () => void;
|
|
className?: string;
|
|
}
|
|
|
|
export function CalendarHeader({
|
|
month,
|
|
disabled = false,
|
|
onPrevMonth,
|
|
onNextMonth,
|
|
className,
|
|
}: CalendarHeaderProps) {
|
|
const { t, monthName, weekdayLabels } = useTranslation();
|
|
const year = month.getFullYear();
|
|
const monthIndex = month.getMonth();
|
|
const labels = weekdayLabels();
|
|
|
|
return (
|
|
<header className={cn("flex flex-col", className)}>
|
|
<div className="flex items-center justify-between mb-3">
|
|
<Button
|
|
type="button"
|
|
variant="secondary"
|
|
size="icon"
|
|
className="size-10 rounded-[10px] bg-surface text-accent hover:bg-[var(--surface-hover)] focus-visible:outline-accent active:scale-95 disabled:opacity-50"
|
|
aria-label={t("nav.prev_month")}
|
|
disabled={disabled}
|
|
onClick={onPrevMonth}
|
|
>
|
|
<ChevronLeftIcon className="size-5" aria-hidden />
|
|
</Button>
|
|
<div className="flex flex-col items-center gap-0.5">
|
|
<h1
|
|
className="m-0 flex items-center justify-center gap-2 text-[1.1rem] font-semibold sm:text-[1.25rem]"
|
|
aria-live="polite"
|
|
aria-atomic="true"
|
|
>
|
|
{monthName(monthIndex)} {year}
|
|
</h1>
|
|
</div>
|
|
<Button
|
|
type="button"
|
|
variant="secondary"
|
|
size="icon"
|
|
className="size-10 rounded-[10px] bg-surface text-accent hover:bg-[var(--surface-hover)] focus-visible:outline-accent active:scale-95 disabled:opacity-50"
|
|
aria-label={t("nav.next_month")}
|
|
disabled={disabled}
|
|
onClick={onNextMonth}
|
|
>
|
|
<ChevronRightIcon className="size-5" aria-hidden />
|
|
</Button>
|
|
</div>
|
|
<div className="grid grid-cols-7 gap-0.5 mb-1.5 text-center text-[0.75rem] text-muted">
|
|
{labels.map((label, i) => (
|
|
<span key={i} aria-hidden>
|
|
{label}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|