event page progress, make separate details component and move some stuff around

This commit is contained in:
elise
2024-08-07 21:21:02 +02:00
parent 8c5a9ad132
commit 6d3581886f
10 changed files with 150 additions and 135 deletions

View File

@ -1,6 +1,6 @@
import { getClient } from "@/app/client"; import { getClient } from "@/app/client";
import { Blocks } from "@/components/blocks/Blocks"; import { Blocks } from "@/components/blocks/Blocks";
import { DateList } from "@/components/events/DateList"; import { EventDetails } from "@/components/events/EventDetails";
import { EventHeader } from "@/components/events/EventHeader"; import { EventHeader } from "@/components/events/EventHeader";
import { BgPig } from "@/components/general/BgPig"; import { BgPig } from "@/components/general/BgPig";
import { graphql } from "@/gql"; import { graphql } from "@/gql";
@ -54,8 +54,8 @@ export default async function Page({ params }: { params: { slug: string } }) {
<> <>
<main className="site-main" id="main"> <main className="site-main" id="main">
<EventHeader event={event} /> <EventHeader event={event} />
<EventDetails event={event} />
<section className="pageContent"> <section className="pageContent">
<DateList event={event} />
<Blocks blocks={event.body} /> <Blocks blocks={event.body} />
</section> </section>
</main> </main>

View File

@ -54,10 +54,7 @@ export const DateList = ({ event }: { event: EventFragment }) => {
return ( return (
<div className={styles.dateWrapper}> <div className={styles.dateWrapper}>
<h2 className="circlehead"> <h2 className="suphead">
<span className="circle"></span>
<span className="circle"></span>
<span className="circle"></span>
Kommende datoer{" "} Kommende datoer{" "}
<span className="number">({futureOccurrences.length})</span> <span className="number">({futureOccurrences.length})</span>
</h2> </h2>

View File

@ -0,0 +1,68 @@
import { EventFragment } from "@/lib/event";
import styles from "./eventDetails.module.scss";
import { OrganizerList } from "./OrganizerList";
import Icon from "../general/Icon";
import { DateList } from "./DateList";
function formatPrice(price: number): string {
if (price === null) {
// should not happen
return "?";
}
if (price === 0) {
return "Gratis";
}
return `${price} kr`;
}
export const EventDetails = ({ event }: { event: EventFragment }) => {
const featuredImage: any = event.featuredImage;
return (
<div className={styles.eventDetails}>
<div className={styles.content}>
<div className={styles.prices}>
<span className="suphead">Pris</span>
<ul className={styles.priceList}>
{event.free && (
<li className={styles.priceItem}>
<span>Gratis</span>
</li>
)}
{typeof event.priceRegular === "number" && (
<li className={styles.priceItem}>
<span className={styles.priceLabel}>Ordinær</span>{" "}
{formatPrice(event.priceRegular)}
</li>
)}
{typeof event.priceStudent === "number" && (
<li className={styles.priceItem}>
<span className={styles.priceLabel}>Student</span>{" "}
{formatPrice(event.priceStudent)}
</li>
)}
{typeof event.priceMember === "number" && (
<li className={styles.priceItem}>
<span className={styles.priceLabel}>Medlem</span>{" "}
{formatPrice(event.priceMember)}
</li>
)}
</ul>
</div>
{event.organizers && (
<div>
<div className="suphead">Arrangeres av</div>{" "}
<OrganizerList event={event} />
</div>
)}
{event.facebookUrl && (
<a href={event.facebookUrl} className="button tertiary">
<span> til Facebook-event</span>
<Icon type="externalLink" />
</a>
)}
</div>
<DateList event={event} />
</div>
);
};

View File

@ -1,21 +1,8 @@
import { EventFragment } from "@/lib/event"; import { EventFragment } from "@/lib/event";
import styles from "./eventHeader.module.scss"; import styles from "./eventHeader.module.scss";
import { Image } from "@/components/general/Image"; import { Image } from "@/components/general/Image";
import Link from "next/link";
import { OrganizerList } from "./OrganizerList";
import Icon from "../general/Icon";
import { Breadcrumb } from "../general/Breadcrumb"; import { Breadcrumb } from "../general/Breadcrumb";
import Icon from "../general/Icon";
function formatPrice(price: number): string {
if (price === null) {
// should not happen
return "?";
}
if (price === 0) {
return "Gratis";
}
return `${price} kr`;
}
export const EventHeader = ({ event }: { event: EventFragment }) => { export const EventHeader = ({ event }: { event: EventFragment }) => {
// TODO: where should we show image attribution for the featured image? // TODO: where should we show image attribution for the featured image?
@ -24,63 +11,23 @@ export const EventHeader = ({ event }: { event: EventFragment }) => {
return ( return (
<div className={styles.eventHeader}> <div className={styles.eventHeader}>
<div className={styles.text}> <div className={styles.heading}>
<Breadcrumb link="/arrangementer" text="Arrangement" /> {/*<Breadcrumb link="/arrangementer" text="Arrangement" />*/}
<h1 className={styles.title}>{event.title}</h1> {event.categories.length > 0 && (
<div className={styles.eventDetails}> <div className={styles.categories}>
<div className={styles.prices}> {event.categories.map(category => (
<span className={styles.label}>Pris:</span> <div key={category.name} className="tag">{category.name}</div>
<ul className={styles.priceList}> ))}
{event.free && (
<li className={styles.priceItem}>
<span>Gratis</span>
</li>
)}
{typeof event.priceRegular === "number" && (
<li className={styles.priceItem}>
<span className={styles.priceLabel}>Ordinær:</span>{" "}
{formatPrice(event.priceRegular)}
</li>
)}
{typeof event.priceStudent === "number" && (
<li className={styles.priceItem}>
<span className={styles.priceLabel}>Student:</span>{" "}
{formatPrice(event.priceStudent)}
</li>
)}
{typeof event.priceMember === "number" && (
<li className={styles.priceItem}>
<span className={styles.priceLabel}>Medlem:</span>{" "}
{formatPrice(event.priceMember)}
</li>
)}
</ul>
</div> </div>
{event.categories.length > 0 && ( )}
<div> <h1 className={styles.title}>{event.title}</h1>
<span className={styles.label}>Kategorier:</span>{" "} <p className={styles.details}>Evt. andre detaljer</p>
{event.categories.map((x) => x.name).join(", ")}
</div>
)}
{event.organizers && (
<div>
<span className={styles.label}>Arrangeres av:</span>{" "}
<OrganizerList event={event} />
</div>
)}
</div>
{event.ticketUrl && ( {event.ticketUrl && (
<a href={event.ticketUrl} className="button cta"> <a href={event.ticketUrl} className="button cta">
<span>Kjøp billetter</span> <span>Kjøp billetter</span>
<Icon type="tickets" /> <Icon type="tickets" />
</a> </a>
)} )}
{event.facebookUrl && (
<a href={event.facebookUrl} className="button tertiary">
<span> til Facebook-event</span>
<Icon type="externalLink" />
</a>
)}
</div> </div>
<div className={styles.image}> <div className={styles.image}>
{featuredImage && ( {featuredImage && (

View File

@ -1,26 +1,19 @@
.dateWrapper { .dateWrapper {
background: var(--color-background-secondary); margin-top: var(--spacing-m);
margin: 0 calc(var(--spacing-sitepadding-inline)*-1) var(--spacing-sitepadding-block);
padding: var(--spacing-s) var(--spacing-sitepadding-inline) var(--spacing-m);
} }
.dateList { .dateList {
list-style: none; list-style: none;
display: flex; margin-top: var(--spacing-xs);
gap: var(--spacing-s);
} }
.date { .date {
display: inline-block;
font-family: var(--font-serif); font-family: var(--font-serif);
font-size: var(--font-size-body); font-size: var(--font-size-body);
position: relative; position: relative;
line-height: 1.2; line-height: 1.2;
border-right: var(--border); margin: 0 2rem 1rem 0;
padding-right: var(--spacing-s);
&:last-child {
border: none;
}
} }
.time { .time {

View File

@ -0,0 +1,36 @@
.eventDetails {
background: var(--color-background-secondary);
margin: 0 calc(var(--spacing-sitepadding-inline)*-1) var(--spacing-sitepadding-block);
padding: var(--spacing-s) var(--spacing-sitepadding-inline) var(--spacing-m);
}
.content {
display: grid;
grid-template-columns: repeat(4, 1fr);
column-gap: var(--spacing-gap-column);
margin-bottom: var(--spacing-gap-row);
align-items: flex-start;
}
.priceList {
list-style: none;
max-width: 10rem;
}
.priceItem {
position: relative;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
text-align: right;
}
.priceLabel {
display: block;
text-align: left;
}
.label {
font-weight: 600;
width: 7rem;
}

View File

@ -3,8 +3,14 @@
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
column-gap: var(--spacing-gap-column); column-gap: var(--spacing-gap-column);
align-items: flex-end; row-gap: var(--spacing-gap-row);
align-items: center;
padding: 0; padding: 0;
margin: calc(var(--spacing-sitepadding-block)*-1) auto 0;
}
.categories {
margin: 0 0 var(--spacing-m);
} }
.title { .title {
@ -13,7 +19,6 @@
.image { .image {
grid-column: span 2; grid-column: span 2;
margin-top: calc(var(--spacing-sitepadding-block)*-2);
img { img {
max-width: 100%; max-width: 100%;
@ -22,58 +27,14 @@
} }
} }
.text { .details {
padding-bottom: var(--spacing-m); font-size: var(--font-size-h2);
font-family: var(--font-serif);
margin: var(--spacing-xs) 0 var(--spacing-l);
} }
.eventDetails { @media (max-width: 800px) {
font-size: var(--font-size-caption); .eventHeader {
margin: var(--spacing-m) 0; grid-template-columns: 1fr;
>div {
padding: var(--spacing-xs) 0;
border-bottom: var(--border);
display: flex;
} }
}
.prices {
padding: var(--spacing-xs) 0 0;
border-top: var(--border);
display: flex;
}
.priceList {
list-style: none;
//flex-grow: 1;
}
.priceItem {
position: relative;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
/*padding: var(--spacing-xs) 0;
border-bottom: var(--border);
&:first-child {
padding-top: 0;
}
&:last-child {
border-bottom: 0;
padding-bottom: 0;
}*/
}
.priceLabel {
display: block;
}
.label {
font-weight: 600;
}
.label {
width: 7rem;
} }

View File

@ -4,6 +4,5 @@
li { li {
display: inline; display: inline;
font-size: var(--font-size-caption);
} }
} }

View File

@ -327,4 +327,17 @@ select {
.page-header-small { .page-header-small {
max-width: var(--size-width-p); max-width: var(--size-width-p);
margin: 0 auto 1rem; margin: 0 auto 1rem;
}
.tag {
display: inline-block;
border-radius: 10rem;
background: var(--color-goldenBeige);
color: var(--color-deepBrick);
padding: 0 .7em;
margin: 0 .4em var(--spacing-s) 0;
font-family: var(--font-main);
font-size: var(--font-size-caption);
font-weight: 500;
text-decoration: none;
} }

View File

@ -62,6 +62,7 @@
// sizes // sizes
--size-width-p: 36rem; --size-width-p: 36rem;
--size-width-lead: 48rem; --size-width-lead: 48rem;
--size-width-pageheader: 54rem;
--size-icon: 1em; --size-icon: 1em;
--size-icon-circle: 2.4rem; --size-icon-circle: 2.4rem;
--size-icon-large: 3.4rem; --size-icon-large: 3.4rem;