event page progress, make separate details component and move some stuff around
This commit is contained in:
@ -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>
|
||||||
|
@ -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>
|
||||||
|
68
web/src/components/events/EventDetails.tsx
Normal file
68
web/src/components/events/EventDetails.tsx
Normal 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>Gå til Facebook-event</span>
|
||||||
|
<Icon type="externalLink" />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<DateList event={event} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -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>Gå til Facebook-event</span>
|
|
||||||
<Icon type="externalLink" />
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.image}>
|
<div className={styles.image}>
|
||||||
{featuredImage && (
|
{featuredImage && (
|
||||||
|
@ -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 {
|
||||||
|
36
web/src/components/events/eventDetails.module.scss
Normal file
36
web/src/components/events/eventDetails.module.scss
Normal 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;
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
}
|
@ -4,6 +4,5 @@
|
|||||||
|
|
||||||
li {
|
li {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-size: var(--font-size-caption);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user