web: fetch less data when just listing events and news articles on home page

This commit is contained in:
2026-05-19 23:47:30 +02:00
parent 80b9cdbc33
commit e4c0558527
10 changed files with 120 additions and 52 deletions
+6 -1
View File
@@ -6,6 +6,7 @@ import { Image } from "@/components/general/Image";
import { import {
SingularEvent, SingularEvent,
EventFragment, EventFragment,
EventListItemFragment,
getFutureOccurrences, getFutureOccurrences,
} from "@/lib/event"; } from "@/lib/event";
import { import {
@@ -22,7 +23,11 @@ export const EventItem = ({
size, size,
imageLoading, imageLoading,
}: { }: {
event: SingularEvent | EventFragment; event:
| SingularEvent
| SingularEvent<EventListItemFragment>
| EventFragment
| EventListItemFragment;
mode: "list" | "calendar" | "singular-time-only"; mode: "list" | "calendar" | "singular-time-only";
size?: "small" | "medium" | "large"; size?: "small" | "medium" | "large";
imageLoading?: "eager" | "lazy"; imageLoading?: "eager" | "lazy";
+2 -2
View File
@@ -1,10 +1,10 @@
import { EventFragment } from "@/gql/graphql"; import { EventListItemFragment } from "@/gql/graphql";
import { EventItem } from "./EventItem"; import { EventItem } from "./EventItem";
import styles from "./featuredEvents.module.scss"; import styles from "./featuredEvents.module.scss";
import { SectionHeader } from "../general/SectionHeader"; import { SectionHeader } from "../general/SectionHeader";
import { SectionFooter } from "../general/SectionFooter"; import { SectionFooter } from "../general/SectionFooter";
export const FeaturedEvents = ({ events }: { events: EventFragment[] }) => { export const FeaturedEvents = ({ events }: { events: EventListItemFragment[] }) => {
return ( return (
<section className={styles.featuredEvents}> <section className={styles.featuredEvents}>
<SectionHeader heading="Arrangementer" link="/arrangementer" linkText="Se alle arrangementer" /> <SectionHeader heading="Arrangementer" link="/arrangementer" linkText="Se alle arrangementer" />
+3 -5
View File
@@ -1,18 +1,16 @@
import { EventFragment } from "@/gql/graphql"; import { EventListItemFragment } from "@/gql/graphql";
import { isTodayOrFuture, formatDate } from "@/lib/date"; import { isTodayOrFuture } from "@/lib/date";
import { parse } from "date-fns";
import { import {
getSingularEvents, getSingularEvents,
organizeEventsByDate, organizeEventsByDate,
sortSingularEvents, sortSingularEvents,
} from "@/lib/event"; } from "@/lib/event";
import Link from "next/link";
import { EventItem } from "./EventItem"; import { EventItem } from "./EventItem";
import styles from "./upcomingEvents.module.scss"; import styles from "./upcomingEvents.module.scss";
import { SectionHeader } from "../general/SectionHeader"; import { SectionHeader } from "../general/SectionHeader";
import { SectionFooter } from "../general/SectionFooter"; import { SectionFooter } from "../general/SectionFooter";
export const UpcomingEvents = ({ events }: { events: EventFragment[] }) => { export const UpcomingEvents = ({ events }: { events: EventListItemFragment[] }) => {
const upcomingSingularEvents = sortSingularEvents( const upcomingSingularEvents = sortSingularEvents(
getSingularEvents(events).filter((event) => getSingularEvents(events).filter((event) =>
isTodayOrFuture(event.occurrence.start) isTodayOrFuture(event.occurrence.start)
+8 -8
View File
@@ -2,8 +2,8 @@ import Link from "next/link";
import { graphql } from "@/gql"; import { graphql } from "@/gql";
import { HomeFragment } from "@/gql/graphql"; import { HomeFragment } from "@/gql/graphql";
import { getClient } from "@/app/client"; import { getClient } from "@/app/client";
import { EventFragment } from "@/lib/event"; import { EventListItemFragment } from "@/lib/event";
import { NewsFragment } from "@/lib/news"; import { NewsListItemFragment } from "@/lib/news";
import { FeaturedEvents } from "@/components/events/FeaturedEvents"; import { FeaturedEvents } from "@/components/events/FeaturedEvents";
import { UpcomingEvents } from "@/components/events/UpcomingEvents"; import { UpcomingEvents } from "@/components/events/UpcomingEvents";
import { Icon } from "@/components/general/Icon"; import { Icon } from "@/components/general/Icon";
@@ -28,7 +28,7 @@ const homeQuery = graphql(`
... on EventIndex { ... on EventIndex {
futureEvents { futureEvents {
... on EventPage { ... on EventPage {
...Event ...EventListItem
} }
} }
} }
@@ -40,7 +40,7 @@ const homeQuery = graphql(`
} }
news: pages(contentType: "news.newsPage", order: "-first_published_at", limit: 4) { news: pages(contentType: "news.newsPage", order: "-first_published_at", limit: 4) {
... on NewsPage { ... on NewsPage {
...News ...NewsListItem
} }
} }
} }
@@ -48,8 +48,8 @@ const homeQuery = graphql(`
export type HomePageViewProps = { export type HomePageViewProps = {
home: HomeFragment; home: HomeFragment;
events: EventFragment[]; events: EventListItemFragment[];
news: NewsFragment[]; news: NewsListItemFragment[];
}; };
export async function loadHomePageProps(overrides?: { export async function loadHomePageProps(overrides?: {
@@ -59,8 +59,8 @@ export async function loadHomePageProps(overrides?: {
if (error) throw new Error(error.message); if (error) throw new Error(error.message);
const home = overrides?.homeOverride ?? (data?.home as HomeFragment | undefined); const home = overrides?.homeOverride ?? (data?.home as HomeFragment | undefined);
if (!home) throw new Error("Failed to load /"); if (!home) throw new Error("Failed to load /");
const events = (data?.events?.futureEvents ?? []) as EventFragment[]; const events = (data?.events?.futureEvents ?? []) as EventListItemFragment[];
const news = (data?.news ?? []) as NewsFragment[]; const news = (data?.news ?? []) as NewsListItemFragment[];
return { home, events, news }; return { home, events, news };
} }
+2 -2
View File
@@ -1,10 +1,10 @@
import styles from "./newsItem.module.scss"; import styles from "./newsItem.module.scss";
import { Image } from "@/components/general/Image"; import { Image } from "@/components/general/Image";
import { NewsFragment } from "@/lib/news"; import { NewsFragment, NewsListItemFragment } from "@/lib/news";
import { formatDate } from "@/lib/date"; import { formatDate } from "@/lib/date";
import Link from "next/link"; import Link from "next/link";
export const NewsItem = ({ news }: { news: NewsFragment }) => { export const NewsItem = ({ news }: { news: NewsFragment | NewsListItemFragment }) => {
const featuredImage: any = news.featuredImage; const featuredImage: any = news.featuredImage;
return ( return (
+2 -2
View File
@@ -3,7 +3,7 @@ import { useState } from "react";
import { SectionHeader } from "../general/SectionHeader"; import { SectionHeader } from "../general/SectionHeader";
import { NewsItem } from "./NewsItem"; import { NewsItem } from "./NewsItem";
import styles from "./newsList.module.scss"; import styles from "./newsList.module.scss";
import { NewsFragment } from "@/lib/news"; import { NewsFragment, NewsListItemFragment } from "@/lib/news";
import { SectionFooter } from "../general/SectionFooter"; import { SectionFooter } from "../general/SectionFooter";
export const NewsList = ({ export const NewsList = ({
@@ -11,7 +11,7 @@ export const NewsList = ({
heading, heading,
featured featured
}: { }: {
news: NewsFragment[]; news: (NewsFragment | NewsListItemFragment)[];
heading?: string; heading?: string;
featured?: boolean; featured?: boolean;
}) => { }) => {
+15 -3
View File
@@ -45,7 +45,7 @@ type Documents = {
"\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n seoTitle\n searchDescription\n title\n lead\n pig\n body {\n ...Blocks\n }\n }\n": typeof types.GenericFragmentDoc, "\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n seoTitle\n searchDescription\n title\n lead\n pig\n body {\n ...Blocks\n }\n }\n": typeof types.GenericFragmentDoc,
"\n query genericPageByUrl($urlPath: String!) {\n page: page(contentType: \"generic.GenericPage\", urlPath: $urlPath) {\n ... on GenericPage {\n ...Generic\n }\n }\n }\n": typeof types.GenericPageByUrlDocument, "\n query genericPageByUrl($urlPath: String!) {\n page: page(contentType: \"generic.GenericPage\", urlPath: $urlPath) {\n ... on GenericPage {\n ...Generic\n }\n }\n }\n": typeof types.GenericPageByUrlDocument,
"\n fragment Home on HomePage {\n __typename\n featuredEvents {\n id\n }\n }\n": typeof types.HomeFragmentDoc, "\n fragment Home on HomePage {\n __typename\n featuredEvents {\n id\n }\n }\n": typeof types.HomeFragmentDoc,
"\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": typeof types.HomeDocument, "\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...EventListItem\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...NewsListItem\n }\n }\n }\n": typeof types.HomeDocument,
"\n query newsBySlug($slug: String!) {\n news: page(contentType: \"news.NewsPage\", slug: $slug) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": typeof types.NewsBySlugDocument, "\n query newsBySlug($slug: String!) {\n news: page(contentType: \"news.NewsPage\", slug: $slug) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": typeof types.NewsBySlugDocument,
"\n fragment Sponsor on SponsorBlock {\n id\n name\n logo {\n ...Image\n }\n text\n website\n }\n": typeof types.SponsorFragmentDoc, "\n fragment Sponsor on SponsorBlock {\n id\n name\n logo {\n ...Image\n }\n text\n website\n }\n": typeof types.SponsorFragmentDoc,
"\n fragment SponsorsPage on SponsorsPage {\n __typename\n title\n seoTitle\n searchDescription\n lead\n body {\n ...Blocks\n }\n sponsors {\n ... on SponsorBlock {\n ...Sponsor\n }\n }\n }\n": typeof types.SponsorsPageFragmentDoc, "\n fragment SponsorsPage on SponsorsPage {\n __typename\n title\n seoTitle\n searchDescription\n lead\n body {\n ...Blocks\n }\n sponsors {\n ... on SponsorBlock {\n ...Sponsor\n }\n }\n }\n": typeof types.SponsorsPageFragmentDoc,
@@ -65,10 +65,12 @@ type Documents = {
"\n fragment ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n": typeof types.ContactEntityFragmentDoc, "\n fragment ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n": typeof types.ContactEntityFragmentDoc,
"\n fragment EventCategory on EventCategory {\n __typename\n name\n slug\n pig\n showInFilters\n }\n": typeof types.EventCategoryFragmentDoc, "\n fragment EventCategory on EventCategory {\n __typename\n name\n slug\n pig\n showInFilters\n }\n": typeof types.EventCategoryFragmentDoc,
"\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n": typeof types.EventOrganizerFragmentDoc, "\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n": typeof types.EventOrganizerFragmentDoc,
"\n fragment EventListItem on EventPage {\n __typename\n id\n slug\n title\n subtitle\n featuredImage {\n ...Image\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n }\n }\n }\n": typeof types.EventListItemFragmentDoc,
"\n fragment Event on EventPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n subtitle\n lead\n body {\n ...OneLevelOfBlocks\n }\n featuredImage {\n ...Image\n }\n pig\n facebookUrl\n ticketUrl\n free\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n ...EventCategory\n }\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n preposition\n url\n }\n venueCustom\n }\n }\n organizers {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n }\n": typeof types.EventFragmentDoc, "\n fragment Event on EventPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n subtitle\n lead\n body {\n ...OneLevelOfBlocks\n }\n featuredImage {\n ...Image\n }\n pig\n facebookUrl\n ticketUrl\n free\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n ...EventCategory\n }\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n preposition\n url\n }\n venueCustom\n }\n }\n organizers {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n }\n": typeof types.EventFragmentDoc,
"\n fragment EventIndex on EventIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n }\n": typeof types.EventIndexFragmentDoc, "\n fragment EventIndex on EventIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n }\n": typeof types.EventIndexFragmentDoc,
"\n query eventIndexMetadata {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n }\n": typeof types.EventIndexMetadataDocument, "\n query eventIndexMetadata {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n }\n": typeof types.EventIndexMetadataDocument,
"\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n": typeof types.FutureEventsDocument, "\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n": typeof types.FutureEventsDocument,
"\n fragment NewsListItem on NewsPage {\n __typename\n id\n slug\n title\n firstPublishedAt\n excerpt\n featuredImage {\n ...Image\n }\n }\n": typeof types.NewsListItemFragmentDoc,
"\n fragment News on NewsPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n firstPublishedAt\n excerpt\n lead\n featuredImage {\n ...Image\n }\n body {\n ...Blocks\n }\n }\n": typeof types.NewsFragmentDoc, "\n fragment News on NewsPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n firstPublishedAt\n excerpt\n lead\n featuredImage {\n ...Image\n }\n body {\n ...Blocks\n }\n }\n": typeof types.NewsFragmentDoc,
"\n fragment NewsIndex on NewsIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n lead\n }\n": typeof types.NewsIndexFragmentDoc, "\n fragment NewsIndex on NewsIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n lead\n }\n": typeof types.NewsIndexFragmentDoc,
"\n query news {\n index: newsIndex {\n ... on NewsIndex {\n ...NewsIndex\n }\n }\n news: pages(contentType: \"news.NewsPage\", order: \"-first_published_at\", limit: 1000) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": typeof types.NewsDocument, "\n query news {\n index: newsIndex {\n ... on NewsIndex {\n ...NewsIndex\n }\n }\n news: pages(contentType: \"news.NewsPage\", order: \"-first_published_at\", limit: 1000) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": typeof types.NewsDocument,
@@ -109,7 +111,7 @@ const documents: Documents = {
"\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n seoTitle\n searchDescription\n title\n lead\n pig\n body {\n ...Blocks\n }\n }\n": types.GenericFragmentDoc, "\n fragment Generic on GenericPage {\n __typename\n id\n urlPath\n seoTitle\n searchDescription\n title\n lead\n pig\n body {\n ...Blocks\n }\n }\n": types.GenericFragmentDoc,
"\n query genericPageByUrl($urlPath: String!) {\n page: page(contentType: \"generic.GenericPage\", urlPath: $urlPath) {\n ... on GenericPage {\n ...Generic\n }\n }\n }\n": types.GenericPageByUrlDocument, "\n query genericPageByUrl($urlPath: String!) {\n page: page(contentType: \"generic.GenericPage\", urlPath: $urlPath) {\n ... on GenericPage {\n ...Generic\n }\n }\n }\n": types.GenericPageByUrlDocument,
"\n fragment Home on HomePage {\n __typename\n featuredEvents {\n id\n }\n }\n": types.HomeFragmentDoc, "\n fragment Home on HomePage {\n __typename\n featuredEvents {\n id\n }\n }\n": types.HomeFragmentDoc,
"\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": types.HomeDocument, "\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...EventListItem\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...NewsListItem\n }\n }\n }\n": types.HomeDocument,
"\n query newsBySlug($slug: String!) {\n news: page(contentType: \"news.NewsPage\", slug: $slug) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": types.NewsBySlugDocument, "\n query newsBySlug($slug: String!) {\n news: page(contentType: \"news.NewsPage\", slug: $slug) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": types.NewsBySlugDocument,
"\n fragment Sponsor on SponsorBlock {\n id\n name\n logo {\n ...Image\n }\n text\n website\n }\n": types.SponsorFragmentDoc, "\n fragment Sponsor on SponsorBlock {\n id\n name\n logo {\n ...Image\n }\n text\n website\n }\n": types.SponsorFragmentDoc,
"\n fragment SponsorsPage on SponsorsPage {\n __typename\n title\n seoTitle\n searchDescription\n lead\n body {\n ...Blocks\n }\n sponsors {\n ... on SponsorBlock {\n ...Sponsor\n }\n }\n }\n": types.SponsorsPageFragmentDoc, "\n fragment SponsorsPage on SponsorsPage {\n __typename\n title\n seoTitle\n searchDescription\n lead\n body {\n ...Blocks\n }\n sponsors {\n ... on SponsorBlock {\n ...Sponsor\n }\n }\n }\n": types.SponsorsPageFragmentDoc,
@@ -129,10 +131,12 @@ const documents: Documents = {
"\n fragment ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n": types.ContactEntityFragmentDoc, "\n fragment ContactEntity on ContactEntity {\n id\n name\n contactType\n title\n email\n phoneNumber\n image {\n ...Image\n }\n }\n": types.ContactEntityFragmentDoc,
"\n fragment EventCategory on EventCategory {\n __typename\n name\n slug\n pig\n showInFilters\n }\n": types.EventCategoryFragmentDoc, "\n fragment EventCategory on EventCategory {\n __typename\n name\n slug\n pig\n showInFilters\n }\n": types.EventCategoryFragmentDoc,
"\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n": types.EventOrganizerFragmentDoc, "\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n": types.EventOrganizerFragmentDoc,
"\n fragment EventListItem on EventPage {\n __typename\n id\n slug\n title\n subtitle\n featuredImage {\n ...Image\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n }\n }\n }\n": types.EventListItemFragmentDoc,
"\n fragment Event on EventPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n subtitle\n lead\n body {\n ...OneLevelOfBlocks\n }\n featuredImage {\n ...Image\n }\n pig\n facebookUrl\n ticketUrl\n free\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n ...EventCategory\n }\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n preposition\n url\n }\n venueCustom\n }\n }\n organizers {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n }\n": types.EventFragmentDoc, "\n fragment Event on EventPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n subtitle\n lead\n body {\n ...OneLevelOfBlocks\n }\n featuredImage {\n ...Image\n }\n pig\n facebookUrl\n ticketUrl\n free\n priceRegular\n priceMember\n priceStudent\n categories {\n ... on EventCategory {\n ...EventCategory\n }\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n venue {\n __typename\n id\n slug\n title\n preposition\n url\n }\n venueCustom\n }\n }\n organizers {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n }\n": types.EventFragmentDoc,
"\n fragment EventIndex on EventIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n }\n": types.EventIndexFragmentDoc, "\n fragment EventIndex on EventIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n }\n": types.EventIndexFragmentDoc,
"\n query eventIndexMetadata {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n }\n": types.EventIndexMetadataDocument, "\n query eventIndexMetadata {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n }\n": types.EventIndexMetadataDocument,
"\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n": types.FutureEventsDocument, "\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n": types.FutureEventsDocument,
"\n fragment NewsListItem on NewsPage {\n __typename\n id\n slug\n title\n firstPublishedAt\n excerpt\n featuredImage {\n ...Image\n }\n }\n": types.NewsListItemFragmentDoc,
"\n fragment News on NewsPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n firstPublishedAt\n excerpt\n lead\n featuredImage {\n ...Image\n }\n body {\n ...Blocks\n }\n }\n": types.NewsFragmentDoc, "\n fragment News on NewsPage {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n firstPublishedAt\n excerpt\n lead\n featuredImage {\n ...Image\n }\n body {\n ...Blocks\n }\n }\n": types.NewsFragmentDoc,
"\n fragment NewsIndex on NewsIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n lead\n }\n": types.NewsIndexFragmentDoc, "\n fragment NewsIndex on NewsIndex {\n __typename\n id\n slug\n seoTitle\n searchDescription\n title\n lead\n }\n": types.NewsIndexFragmentDoc,
"\n query news {\n index: newsIndex {\n ... on NewsIndex {\n ...NewsIndex\n }\n }\n news: pages(contentType: \"news.NewsPage\", order: \"-first_published_at\", limit: 1000) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": types.NewsDocument, "\n query news {\n index: newsIndex {\n ... on NewsIndex {\n ...NewsIndex\n }\n }\n news: pages(contentType: \"news.NewsPage\", order: \"-first_published_at\", limit: 1000) {\n ... on NewsPage {\n ...News\n }\n }\n }\n": types.NewsDocument,
@@ -283,7 +287,7 @@ export function graphql(source: "\n fragment Home on HomePage {\n __typename
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
export function graphql(source: "\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...News\n }\n }\n }\n"): (typeof documents)["\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...News\n }\n }\n }\n"]; export function graphql(source: "\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...EventListItem\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...NewsListItem\n }\n }\n }\n"): (typeof documents)["\n query home {\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...EventListItem\n }\n }\n }\n }\n home: page(contentType: \"home.HomePage\", urlPath: \"/home/\") {\n ... on HomePage {\n ...Home\n }\n }\n news: pages(contentType: \"news.newsPage\", order: \"-first_published_at\", limit: 4) {\n ... on NewsPage {\n ...NewsListItem\n }\n }\n }\n"];
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
@@ -360,6 +364,10 @@ export function graphql(source: "\n fragment EventCategory on EventCategory {\n
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
export function graphql(source: "\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n"): (typeof documents)["\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n"]; export function graphql(source: "\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n"): (typeof documents)["\n fragment EventOrganizer on EventOrganizer {\n __typename\n id\n name\n slug\n externalUrl\n association {\n ... on AssociationPage {\n url\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment EventListItem on EventPage {\n __typename\n id\n slug\n title\n subtitle\n featuredImage {\n ...Image\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n }\n }\n }\n"): (typeof documents)["\n fragment EventListItem on EventPage {\n __typename\n id\n slug\n title\n subtitle\n featuredImage {\n ...Image\n }\n occurrences(limit: 5000) {\n ... on EventOccurrence {\n __typename\n id\n start\n end\n }\n }\n }\n"];
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
@@ -376,6 +384,10 @@ export function graphql(source: "\n query eventIndexMetadata {\n index: even
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
export function graphql(source: "\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n"): (typeof documents)["\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n"]; export function graphql(source: "\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n"): (typeof documents)["\n query futureEvents {\n index: eventIndex {\n ... on EventIndex {\n ...EventIndex\n }\n }\n events: eventIndex {\n ... on EventIndex {\n futureEvents {\n ... on EventPage {\n ...Event\n }\n }\n }\n }\n eventCategories: eventCategories(limit: 5000) {\n ... on EventCategory {\n ...EventCategory\n }\n }\n eventOrganizers: eventOrganizers(limit: 5000) {\n ... on EventOrganizer {\n ...EventOrganizer\n }\n }\n venues: pages(contentType: \"venues.VenuePage\") {\n ... on VenuePage {\n id\n title\n slug\n preposition\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment NewsListItem on NewsPage {\n __typename\n id\n slug\n title\n firstPublishedAt\n excerpt\n featuredImage {\n ...Image\n }\n }\n"): (typeof documents)["\n fragment NewsListItem on NewsPage {\n __typename\n id\n slug\n title\n firstPublishedAt\n excerpt\n featuredImage {\n ...Image\n }\n }\n"];
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
File diff suppressed because one or more lines are too long
+56 -23
View File
@@ -12,17 +12,23 @@ import { graphql, unmaskFragment } from "@/gql";
import { import {
type EventCategoryFragment, type EventCategoryFragment,
type EventFragment, type EventFragment,
type EventListItemFragment,
type EventOrganizerFragment, type EventOrganizerFragment,
} from "@/gql/graphql"; } from "@/gql/graphql";
import { PIG_NAMES, randomElement } from "@/lib/common"; import { PIG_NAMES, randomElement } from "@/lib/common";
export type EventOccurrence = EventFragment["occurrences"][number]; export type EventOccurrence = EventFragment["occurrences"][number];
export type EventListItemOccurrence = EventListItemFragment["occurrences"][number];
export type EventCategory = EventCategoryFragment; export type EventCategory = EventCategoryFragment;
export type EventOrganizer = EventOrganizerFragment; export type EventOrganizer = EventOrganizerFragment;
export type { EventFragment }; export type { EventFragment, EventListItemFragment };
export type SingularEvent = EventFragment & { type EventListable = {
occurrence: EventOccurrence; occurrences: ReadonlyArray<{ id: string | null; start: string; end: string | null }>;
};
export type SingularEvent<E extends EventListable = EventFragment> = E & {
occurrence: E["occurrences"][number];
}; };
export const EventCategoryFragmentDefinition = graphql(` export const EventCategoryFragmentDefinition = graphql(`
@@ -50,6 +56,27 @@ export const EventOrganizerFragmentDefinition = graphql(`
} }
`); `);
const EventListItemFragmentDefinition = graphql(`
fragment EventListItem on EventPage {
__typename
id
slug
title
subtitle
featuredImage {
...Image
}
occurrences(limit: 5000) {
... on EventOccurrence {
__typename
id
start
end
}
}
}
`);
const EventFragmentDefinition = graphql(` const EventFragmentDefinition = graphql(`
fragment Event on EventPage { fragment Event on EventPage {
__typename __typename
@@ -161,37 +188,39 @@ export const eventsOverviewQuery = graphql(`
} }
`); `);
export function getSingularEvents(events: EventFragment[]): SingularEvent[] { export function getSingularEvents<E extends EventListable>(
return events events: E[]
.map((event) => { ): SingularEvent<E>[] {
return event.occurrences.map((occurrence) => { return events.flatMap((event) =>
const eventOccurrence: any = structuredClone(event); event.occurrences.map((occurrence) => {
const eventOccurrence = structuredClone(event) as SingularEvent<E>;
eventOccurrence.occurrence = occurrence; eventOccurrence.occurrence = occurrence;
return eventOccurrence; return eventOccurrence;
});
}) })
.flat(); );
} }
export function sortSingularEvents(events: SingularEvent[]) { export function sortSingularEvents<E extends EventListable>(
events: SingularEvent<E>[]
) {
return events.sort((a, b) => return events.sort((a, b) =>
compareDates(a.occurrence.start, b.occurrence.start) compareDates(a.occurrence.start, b.occurrence.start)
); );
} }
interface EventCalendar { interface EventCalendar<E extends EventListable = EventFragment> {
[yearMonth: string]: { [yearMonth: string]: {
[week: string]: { [week: string]: {
[day: string]: SingularEvent[]; [day: string]: SingularEvent<E>[];
}; };
}; };
} }
export function organizeEventsInCalendar( export function organizeEventsInCalendar<E extends EventListable>(
events: SingularEvent[] events: SingularEvent<E>[]
): EventCalendar { ): EventCalendar<E> {
const sortedEvents = sortSingularEvents(events); const sortedEvents = sortSingularEvents(events);
const calendar: EventCalendar = {}; const calendar: EventCalendar<E> = {};
const minDate = new Date(sortedEvents[0]?.occurrence.start); const minDate = new Date(sortedEvents[0]?.occurrence.start);
const maxDate = new Date( const maxDate = new Date(
@@ -243,13 +272,15 @@ export function organizeEventsInCalendar(
return calendar; return calendar;
} }
interface EventsByDate { interface EventsByDate<E extends EventListable = EventFragment> {
[day: string]: SingularEvent[]; [day: string]: SingularEvent<E>[];
} }
export function organizeEventsByDate(events: SingularEvent[]): EventsByDate { export function organizeEventsByDate<E extends EventListable>(
events: SingularEvent<E>[]
): EventsByDate<E> {
const sortedEvents = sortSingularEvents(events); const sortedEvents = sortSingularEvents(events);
const eventsByDate: EventsByDate = {}; const eventsByDate: EventsByDate<E> = {};
sortedEvents.forEach((event) => { sortedEvents.forEach((event) => {
const start = toLocalTime(event.occurrence.start); const start = toLocalTime(event.occurrence.start);
@@ -263,7 +294,9 @@ export function organizeEventsByDate(events: SingularEvent[]): EventsByDate {
return eventsByDate; return eventsByDate;
} }
export function getFutureOccurrences(event: EventFragment): EventOccurrence[] { export function getFutureOccurrences<E extends EventListable>(
event: E
): E["occurrences"][number][] {
const today = startOfToday(); const today = startOfToday();
const occurrences = event?.occurrences ?? []; const occurrences = event?.occurrences ?? [];
const futureOccurrences = occurrences.filter((occurrence) => const futureOccurrences = occurrences.filter((occurrence) =>
@@ -272,7 +305,7 @@ export function getFutureOccurrences(event: EventFragment): EventOccurrence[] {
futureOccurrences.sort( futureOccurrences.sort(
(a, b) => parseISO(a.start).getTime() - parseISO(b.start).getTime() (a, b) => parseISO(a.start).getTime() - parseISO(b.start).getTime()
); );
return futureOccurrences as EventOccurrence[]; return futureOccurrences as E["occurrences"][number][];
} }
export function getEventPig(event: EventFragment): string | null { export function getEventPig(event: EventFragment): string | null {
+15 -1
View File
@@ -1,7 +1,21 @@
import { graphql } from "@/gql"; import { graphql } from "@/gql";
import { NewsFragment } from "@/gql/graphql"; import { NewsFragment } from "@/gql/graphql";
export type { NewsFragment, NewsIndexFragment } from "@/gql/graphql"; export type { NewsFragment, NewsIndexFragment, NewsListItemFragment } from "@/gql/graphql";
const NewsListItemFragmentDefinition = graphql(`
fragment NewsListItem on NewsPage {
__typename
id
slug
title
firstPublishedAt
excerpt
featuredImage {
...Image
}
}
`);
const NewsFragmentDefinition = graphql(` const NewsFragmentDefinition = graphql(`
fragment News on NewsPage { fragment News on NewsPage {