ik hou van kaas
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
// Deterministic per-room theming: background image + accent color.
|
||||
|
||||
import type { CSSProperties } from "react"
|
||||
import type { CalendarEvent, SignupStatus } from "./types"
|
||||
|
||||
const ROOM_BACKGROUNDS = [
|
||||
"/backgrounds/room-1.png",
|
||||
"/backgrounds/room-2.png",
|
||||
@@ -27,6 +30,85 @@ export function getRoomBackground(roomId: number | null): string {
|
||||
return ROOM_BACKGROUNDS[roomId % ROOM_BACKGROUNDS.length]
|
||||
}
|
||||
|
||||
export function getRoomColor(roomId: number) {
|
||||
return ROOM_COLORS[roomId % ROOM_COLORS.length]
|
||||
// Guarded against null/undefined/NaN room ids (e.g. personal blocks that
|
||||
// arrive without a valid room_id) so we never hand back an undefined color,
|
||||
// which previously rendered as no background color at all.
|
||||
export function getRoomColor(roomId: number | null | undefined) {
|
||||
const id = typeof roomId === "number" && Number.isFinite(roomId) ? roomId : 0
|
||||
const idx = ((id % ROOM_COLORS.length) + ROOM_COLORS.length) % ROOM_COLORS.length
|
||||
return ROOM_COLORS[idx]
|
||||
}
|
||||
|
||||
// ---------- Event coloring by type / status / RSVP ----------
|
||||
//
|
||||
// Confirmed and busy events each pick a color from a small themed pool,
|
||||
// deterministically by room so the same room always looks the same.
|
||||
// Private, proposed, declined and cancelled get one fixed look each so
|
||||
// they're recognizable at a glance regardless of room.
|
||||
|
||||
export interface EventStyle {
|
||||
bg: string
|
||||
ring: string
|
||||
/** Dashed border — signals "not yet settled" (pending proposal). */
|
||||
dashed?: boolean
|
||||
/** Diagonal hatch pattern — signals "you've declined this". */
|
||||
striped?: boolean
|
||||
/** Reduced opacity — signals "you're not going". */
|
||||
muted?: boolean
|
||||
/** Outline only, transparent fill — signals "private, details hidden". */
|
||||
outline?: boolean
|
||||
}
|
||||
|
||||
const CONFIRMED_PALETTE = [
|
||||
{ bg: "bg-emerald-500", ring: "ring-emerald-400" },
|
||||
{ bg: "bg-blue-500", ring: "ring-blue-400" },
|
||||
{ bg: "bg-purple-500", ring: "ring-purple-400" },
|
||||
]
|
||||
|
||||
const BUSY_PALETTE = [
|
||||
{ bg: "bg-orange-500", ring: "ring-orange-400" },
|
||||
{ bg: "bg-yellow-400", ring: "ring-yellow-300" },
|
||||
{ bg: "bg-red-500", ring: "ring-red-400" },
|
||||
]
|
||||
|
||||
function pickFromPalette(
|
||||
palette: { bg: string; ring: string }[],
|
||||
roomId: number | null | undefined,
|
||||
) {
|
||||
const id = typeof roomId === "number" && Number.isFinite(roomId) ? roomId : 0
|
||||
const idx = ((id % palette.length) + palette.length) % palette.length
|
||||
return palette[idx]
|
||||
}
|
||||
|
||||
const PRIVATE_STYLE: EventStyle = { bg: "bg-white/10", ring: "ring-white/60", outline: true }
|
||||
const PROPOSED_STYLE: EventStyle = { bg: "bg-white/25", ring: "ring-white/50", dashed: true }
|
||||
const CANCELLED_STYLE: EventStyle = { bg: "bg-red-500", ring: "ring-red-400" }
|
||||
const DECLINED_STYLE: EventStyle = {
|
||||
bg: "bg-neutral-500",
|
||||
ring: "ring-neutral-400",
|
||||
striped: true,
|
||||
muted: true,
|
||||
}
|
||||
|
||||
// Inline CSS for diagonal hatch patterns — Tailwind has no built-in
|
||||
// striped-background utility, so this is applied via style prop.
|
||||
export const STRIPE_STYLE: CSSProperties = {
|
||||
backgroundImage:
|
||||
"repeating-linear-gradient(135deg, rgba(255,255,255,0.18) 0px, rgba(255,255,255,0.18) 6px, transparent 6px, transparent 12px)",
|
||||
}
|
||||
|
||||
export function getEventStyle(
|
||||
event: Pick<CalendarEvent, "type" | "status" | "room_id">,
|
||||
myResponse: SignupStatus | undefined,
|
||||
): EventStyle {
|
||||
if (event.type === "private") return PRIVATE_STYLE
|
||||
if (event.type === "busy") return pickFromPalette(BUSY_PALETTE, event.room_id)
|
||||
|
||||
// Proposal-type events: colored by where they stand.
|
||||
if (event.status === "cancelled") return CANCELLED_STYLE
|
||||
if (myResponse === "declined") return DECLINED_STYLE
|
||||
if (event.status === "proposed" || event.status === "draft") return PROPOSED_STYLE
|
||||
|
||||
// Confirmed proposal: pick from the confirmed palette, by room.
|
||||
return pickFromPalette(CONFIRMED_PALETTE, event.room_id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user