Files
neuf-www/web/src/components/events/EventItem.tsx
T
2026-06-01 04:30:14 +02:00

107 lines
3.3 KiB
TypeScript

"use client";
import styles from "./eventItem.module.scss";
import Link from "next/link";
import { Image } from "@/components/general/Image";
import {
SingularEvent,
EventFragment,
EventListItemFragment,
EventOverviewItemFragment,
getFutureOccurrences,
} from "@/lib/event";
import {
formatDate,
formatDateRange,
groupConsecutiveDates,
} from "@/lib/date";
const DATE_PILLS_TO_SHOW = 2;
export const EventItem = ({
event,
mode,
size,
imageLoading,
imageFetchPriority,
}: {
event:
| SingularEvent
| SingularEvent<EventListItemFragment>
| SingularEvent<EventOverviewItemFragment>
| EventFragment
| EventListItemFragment
| EventOverviewItemFragment;
mode: "list" | "calendar" | "singular-time-only";
size?: "small" | "medium" | "large";
imageLoading?: "eager" | "lazy";
imageFetchPriority?: "high" | "low" | "auto";
}) => {
const futureOccurrences = getFutureOccurrences(event);
const groupedOccurrences = groupConsecutiveDates(
futureOccurrences.map((occurrence) => occurrence.start)
);
const numOccurrences = event?.occurrences?.length ?? 0;
const nextOccurrence = numOccurrences ? futureOccurrences[0] : null;
const featuredImage: any = event.featuredImage;
return (
<li
className={`${styles.eventItem} ${
size ? styles[size] : styles.large
} linkItem`}
>
<div className={styles.image}>
{featuredImage && (
<Image
src={featuredImage.url}
alt={featuredImage.alt}
width={0}
height={0}
sizes="(max-width: 900px) calc(100vw - 2rem), 30vw"
loading={imageLoading}
fetchPriority={imageFetchPriority}
/>
)}
</div>
<div className={styles.text}>
{mode === "singular-time-only" &&
"occurrence" in event &&
event.occurrence?.start && (
<p className={styles.day}>
{formatDate(event.occurrence?.start, "eeee dd.MM.")} {formatDate(event.occurrence?.start, "'kl.' HH:mm")}
</p>
)}
<h1 className={styles.title}>{event.title}</h1>
{event.subtitle && <p className={styles.details}>{event.subtitle}</p>}
<div className={styles.time}>
{mode === "list" && nextOccurrence && (
<div className={styles.dates}>
{groupedOccurrences.slice(0, DATE_PILLS_TO_SHOW).map((group) => (
<span key={group[0]} className={styles.datePill}>
{formatDateRange(group)}
</span>
))}
{groupedOccurrences.length > DATE_PILLS_TO_SHOW && (
<span className={styles.moreDates}>{`+${groupedOccurrences
.slice(DATE_PILLS_TO_SHOW)
.reduce((sum, group) => sum + group.length, 0)}`}</span>
)}
</div>
)}
{(mode === "calendar") &&
"occurrence" in event &&
event.occurrence?.start && (
<p className={styles.dates}>
{formatDate(event.occurrence?.start, "'kl.' HH:mm")}
</p>
)}
</div>
</div>
<Link href={`/arrangementer/${event.slug}`} className="hiddenLink">
Mer om arrangementet {event.title}
</Link>
</li>
);
};