Initial events Astro site
This commit is contained in:
commit
69a5937ead
41 changed files with 12166 additions and 0 deletions
259
src/components/EventPage.astro
Normal file
259
src/components/EventPage.astro
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
---
|
||||
import type { Event, EventPageEntry } from "../data/events";
|
||||
import {
|
||||
getEventBasePath,
|
||||
getEventOverviewSectionIndex,
|
||||
getEventPageEntries,
|
||||
} from "../data/events";
|
||||
import EventSchedule from "./EventSchedule.astro";
|
||||
import { getEventNavItems } from "../data/eventNav";
|
||||
import SiteLayout from "../layouts/SiteLayout.astro";
|
||||
|
||||
type Props = {
|
||||
event: Event;
|
||||
pageEntry?: EventPageEntry;
|
||||
};
|
||||
|
||||
const { event } = Astro.props;
|
||||
const eventPages = getEventPageEntries(event);
|
||||
const pageEntry = Astro.props.pageEntry ?? eventPages[0];
|
||||
const theme = event.theme ?? "default";
|
||||
const basePath = getEventBasePath(event);
|
||||
const overviewSectionIndex = getEventOverviewSectionIndex(event);
|
||||
const overviewSection =
|
||||
typeof overviewSectionIndex === "number" ? event.sections?.[overviewSectionIndex] : undefined;
|
||||
const overviewSections = overviewSection ? [overviewSection] : [];
|
||||
const currentSection =
|
||||
pageEntry.type === "section" && typeof pageEntry.sectionIndex === "number"
|
||||
? event.sections?.[pageEntry.sectionIndex]
|
||||
: undefined;
|
||||
const schedulePage = eventPages.find((page) => page.type === "schedule");
|
||||
const eventTitle = event.shortTitle ?? event.title;
|
||||
const isOverview = pageEntry.type === "overview";
|
||||
const pageTitle = isOverview ? eventTitle : `${pageEntry.label} - ${eventTitle}`;
|
||||
const pageContext = `${event.kind} / ${event.year}`;
|
||||
const navItems = getEventNavItems(event);
|
||||
const showOverviewContent = event.showOverviewContent !== false;
|
||||
const showScheduleBlock = Boolean(
|
||||
event.schedule && (pageEntry.type === "schedule" || (isOverview && event.showScheduleOnOverview)),
|
||||
);
|
||||
const shouldRenderBody = !isOverview || showOverviewContent || showScheduleBlock;
|
||||
const shouldUseWideBody = Boolean(isOverview && event.showScheduleOnOverview);
|
||||
const scheduleAsTabs =
|
||||
showScheduleBlock && event.scheduleDisplay === "tabs" && (event.schedule?.length ?? 0) > 1;
|
||||
const showHeroScheduleLink = Boolean(schedulePage && !event.showScheduleOnOverview);
|
||||
const hasHeroActions = Boolean(event.sourceUrl || showHeroScheduleLink);
|
||||
|
||||
---
|
||||
|
||||
<SiteLayout
|
||||
title={pageTitle}
|
||||
description={event.summary}
|
||||
theme={theme}
|
||||
brandHref={basePath}
|
||||
brandTitle={eventTitle}
|
||||
brandSubtitle="Event home"
|
||||
navItems={navItems}
|
||||
>
|
||||
{isOverview ? (
|
||||
<section class:list={["event-hero", `event-hero--${theme}`]}>
|
||||
<div class="event-hero__content">
|
||||
<p class="eyebrow">{event.kind} / {event.year}</p>
|
||||
<h1>{event.title}</h1>
|
||||
{event.subtitle && <p class="lede">{event.subtitle}</p>}
|
||||
<p>{event.summary}</p>
|
||||
{hasHeroActions && (
|
||||
<div class="hero-actions">
|
||||
{event.sourceUrl && <a class="button button--secondary" href={event.sourceUrl}>Event website</a>}
|
||||
{showHeroScheduleLink && schedulePage && <a class="button" href={schedulePage.href}>Schedule</a>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<aside class="event-hero__panel" aria-label="Event facts">
|
||||
{event.image ? (
|
||||
<img src={event.image.src} alt={event.image.alt} loading="eager" />
|
||||
) : (
|
||||
<div class="event-visual" aria-hidden="true">
|
||||
<span></span><span></span><span></span><span></span>
|
||||
</div>
|
||||
)}
|
||||
<dl>
|
||||
<div>
|
||||
<dt>Date</dt>
|
||||
<dd>{event.date}</dd>
|
||||
</div>
|
||||
{event.location && (
|
||||
<div>
|
||||
<dt>Location</dt>
|
||||
<dd>{event.location}</dd>
|
||||
</div>
|
||||
)}
|
||||
{event.showRoleInHero !== false && (
|
||||
<div>
|
||||
<dt>Role</dt>
|
||||
<dd>{event.role}</dd>
|
||||
</div>
|
||||
)}
|
||||
{event.facts?.map((fact) => (
|
||||
<div>
|
||||
<dt>{fact.label}</dt>
|
||||
<dd>{fact.value}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
</aside>
|
||||
</section>
|
||||
) : (
|
||||
<section class="event-page-heading">
|
||||
<nav class="event-breadcrumb" aria-label="Event breadcrumb">
|
||||
<a href={basePath}>{eventTitle}</a>
|
||||
<span aria-hidden="true">/</span>
|
||||
<span>{pageEntry.label}</span>
|
||||
</nav>
|
||||
<p class="eyebrow">{pageContext}</p>
|
||||
<h1>{pageEntry.label}</h1>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{shouldRenderBody && (
|
||||
<div class:list={["event-shell", "event-shell--single", shouldUseWideBody && "event-shell--wide"]}>
|
||||
<div class="event-content">
|
||||
{showScheduleBlock && event.schedule && (
|
||||
<EventSchedule schedule={event.schedule} asTabs={scheduleAsTabs} />
|
||||
)}
|
||||
|
||||
{isOverview && showOverviewContent && event.links && (
|
||||
<section class="link-strip" aria-label="Related links">
|
||||
{event.links.map((link) => <a href={link.href}>{link.label}</a>)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
{isOverview && showOverviewContent && overviewSections.map((section) => (
|
||||
<section class="content-section">
|
||||
{section.eyebrow && <p class="eyebrow">{section.eyebrow}</p>}
|
||||
<h2>{section.title}</h2>
|
||||
{section.body?.map((paragraph) => <p>{paragraph}</p>)}
|
||||
{section.numbered && (
|
||||
<ol class="numbered-list">
|
||||
{section.numbered.map((item) => <li>{item}</li>)}
|
||||
</ol>
|
||||
)}
|
||||
{section.bullets && (
|
||||
<ul class="check-list">
|
||||
{section.bullets.map((bullet) => <li>{bullet}</li>)}
|
||||
</ul>
|
||||
)}
|
||||
{section.table && (
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>{section.table.headers.map((header) => <th>{header}</th>)}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{section.table.rows.map((row) => (
|
||||
<tr>{row.map((cell) => <td>{cell}</td>)}</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
{section.tables?.map((table) => (
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>{table.headers.map((header) => <th>{header}</th>)}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{table.rows.map((row) => (
|
||||
<tr>{row.map((cell) => <td>{cell}</td>)}</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
))}
|
||||
|
||||
{isOverview && showOverviewContent && !overviewSection && (
|
||||
<section class="content-section">
|
||||
<h2>Overview</h2>
|
||||
<p>{event.summary}</p>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{pageEntry.type === "section" && currentSection && (
|
||||
<section class="content-section">
|
||||
{currentSection.eyebrow && <p class="eyebrow">{currentSection.eyebrow}</p>}
|
||||
<h2>{currentSection.title}</h2>
|
||||
{currentSection.body?.map((paragraph) => <p>{paragraph}</p>)}
|
||||
{currentSection.numbered && (
|
||||
<ol class="numbered-list">
|
||||
{currentSection.numbered.map((item) => <li>{item}</li>)}
|
||||
</ol>
|
||||
)}
|
||||
{currentSection.bullets && (
|
||||
<ul class="check-list">
|
||||
{currentSection.bullets.map((bullet) => <li>{bullet}</li>)}
|
||||
</ul>
|
||||
)}
|
||||
{currentSection.table && (
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>{currentSection.table.headers.map((header) => <th>{header}</th>)}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentSection.table.rows.map((row) => (
|
||||
<tr>{row.map((cell) => <td>{cell}</td>)}</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
{currentSection.tables?.map((table) => (
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>{table.headers.map((header) => <th>{header}</th>)}</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{table.rows.map((row) => (
|
||||
<tr>{row.map((cell) => <td>{cell}</td>)}</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
)}
|
||||
|
||||
{pageEntry.type === "visual" && (
|
||||
<section class="content-section image-section">
|
||||
<h2>Visual Material</h2>
|
||||
{event.gallery ? (
|
||||
<div class="gallery-grid">
|
||||
{event.gallery.map((image) => (
|
||||
<figure>
|
||||
<img src={image.src} alt={image.alt} loading="lazy" />
|
||||
<figcaption>{image.caption}</figcaption>
|
||||
</figure>
|
||||
))}
|
||||
</div>
|
||||
) : event.image && (
|
||||
<img src={event.image.src} alt={event.image.alt} loading="lazy" />
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
{pageEntry.type === "people" && event.people && (
|
||||
<section class="content-section">
|
||||
<h2>Participants</h2>
|
||||
<ul class="people-list">
|
||||
{event.people.map((person) => <li>{person}</li>)}
|
||||
</ul>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</SiteLayout>
|
||||
Loading…
Add table
Add a link
Reference in a new issue