64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
"use client"
|
|
|
|
import type { CSSProperties, MouseEvent } from "react"
|
|
import { formatEventTime } from "@/lib/agenda/agenda-date"
|
|
import { readableTextColor } from "@/lib/agenda/agenda-colors"
|
|
import type { AgendaEvent } from "@/lib/agenda/agenda-types"
|
|
import { cn } from "@/lib/utils"
|
|
|
|
/** Chip compact (vue mois / rangée journée entière). */
|
|
export function AgendaEventChip({
|
|
event,
|
|
filled,
|
|
onClick,
|
|
className,
|
|
}: {
|
|
event: AgendaEvent
|
|
/** Fond plein (journée entière / multi-jours) vs point coloré + heure. */
|
|
filled?: boolean
|
|
onClick?: (e: MouseEvent<HTMLButtonElement>) => void
|
|
className?: string
|
|
}) {
|
|
const solid = filled ?? event.allDay
|
|
const style: CSSProperties = solid
|
|
? { backgroundColor: event.color, color: readableTextColor(event.color) }
|
|
: {}
|
|
const declined = isDeclinedForAll(event)
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={onClick}
|
|
className={cn(
|
|
"flex w-full min-w-0 items-center gap-1.5 truncate rounded-md px-1.5 py-[1px] text-left text-xs leading-[1.4] transition-[filter] hover:brightness-95 dark:hover:brightness-110",
|
|
!solid && "hover:bg-mail-nav-hover",
|
|
declined && "opacity-50 line-through",
|
|
className,
|
|
)}
|
|
style={style}
|
|
title={event.title}
|
|
>
|
|
{!solid && (
|
|
<span
|
|
aria-hidden
|
|
className="size-2 shrink-0 rounded-full"
|
|
style={{ backgroundColor: event.color }}
|
|
/>
|
|
)}
|
|
{!solid && !event.allDay && (
|
|
<span className="shrink-0 text-muted-foreground">
|
|
{formatEventTime(event.start)}
|
|
</span>
|
|
)}
|
|
<span className="truncate font-medium">{event.title}</span>
|
|
</button>
|
|
)
|
|
}
|
|
|
|
function isDeclinedForAll(event: AgendaEvent): boolean {
|
|
return (
|
|
event.attendees.length > 0 &&
|
|
event.attendees.every((a) => a.status === "DECLINED")
|
|
)
|
|
}
|