Skip to content

Commit

Permalink
fetch events
Browse files Browse the repository at this point in the history
  • Loading branch information
nimarion committed Oct 11, 2024
1 parent e49d346 commit fdc36c2
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 6 deletions.
65 changes: 65 additions & 0 deletions app/.server/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { z } from "zod";
import { marked } from "marked";

const EventSchema = z.object({
id: z.number(),
name: z.string(),
slug: z.string(),
date: z.string(),
content: z.string().transform((content) => marked(content)),
results: z.boolean()
});

export type Event = z.infer<typeof EventSchema>;


export async function getLatestEventsAndResults() {
const [events, results] = await Promise.all([
getEvents({ results: false, limit: 5 }).then((res) => {
return res.filter((event) => {
return new Date(event.date) >=
new Date();
});
}),
getEvents({ results: true, limit: 5 }),
]);
return {
events,
results
}
}

export function getEvents({
results,
limit,
}: {
limit?: number;
results: boolean;
}) {
return fetch(
`${process.env.STRAPI_URL}/api/veranstaltungs?sort[0]=date:desc&populate=*&filters[results][$eq]=${results}&pagination[limit]=${limit}`
).then((res) => res.json()).then((res) => {
const events = res.data.map((data: unknown) => {
const event = EventSchema.safeParse(data)
if(event.success) {
return event.data;
}
return null;
}).filter((event: Event | null) => event !== null) as Event[];
return events;
});
}

export function getEvent({ slug }: { slug: string }) {
return fetch(`
${process.env.STRAPI_URL}/api/veranstaltungs?sort[0]=date:desc&populate=*&filters[slug][$eq]=${slug}`
).then((res) => res.json()).then((res) => {
const event = z.array(EventSchema).min(1).max(1).safeParse(res.data);
if(event.success) {
return event.data[0];
}
throw new Response("Veranstaltung existiert nicht", {
status: 404,
});
});
}
14 changes: 14 additions & 0 deletions app/components/pages/home/events/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ export default function Events({ results, events }: EventsProps) {
</Link>
</ListItem>
))}
{events.length === 0 && (
<ListItem>
<div className="font-medium flex-1 p-4">
Keine bevorstehenden Veranstaltungen
</div>
</ListItem>
)}
</List>
</div>
</>
Expand Down Expand Up @@ -64,6 +71,13 @@ export default function Events({ results, events }: EventsProps) {
</Link>
</ListItem>
))}
{events.length === 0 && (
<ListItem>
<div className="font-medium flex-1 p-4">
Keine Ergebnisse gefunden
</div>
</ListItem>
)}
</List>
</div>
</>
Expand Down
2 changes: 1 addition & 1 deletion app/components/shared/list/List.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default function List({ children }: { children: React.ReactNode }) {
return (
<ul className="flex w-full flex-col gap-2 rounded-lg bg-th-background-secondary p-4">
<ul className="flex w-full flex-col gap-2 rounded-lg bg-gray-300 p-4">
{children}
</ul>
);
Expand Down
2 changes: 1 addition & 1 deletion app/components/shared/list/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default function ListItem({ children }: { children: React.ReactNode }) {
flex-row
items-center
rounded-md
bg-th-background
bg-gray-200
transition
duration-500
ease-in-out
Expand Down
91 changes: 91 additions & 0 deletions app/routes/ergebnisse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import type { MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
import { getEvents } from "~/.server/events";
import ContentContainer from "~/components/ContentContainer";
import Title from "~/components/Title";

export const meta: MetaFunction = () => {
return [
{
title: "Wettkampfergebnisse",
}
]
};

export async function loader() {
const results = await getEvents({ results: true }).then((res) => {
return res.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
});
const years: number[] = [];
results
.forEach((result) => {
const year = new Date(result.date).getFullYear();
if (!years.includes(year)) {
years.push(year);
}
});
return json({
results: results.reverse(),
years: years.reverse(),
});
}

export default function ResultPage() {
const { results, years } = useLoaderData<typeof loader>();
return (
<ContentContainer>
<Title name="Wettkampfergebnisse" />
<div className="w-full overflow-x-auto">
<table className="whitespace-no-wrap w-full">
{years.map((year) => (
<tbody key={year} className="divide-y bg-white">
<tr>
<td>
<p className="text-bold my-4 max-w-min rounded-md p-3 text-3xl ">
{year}
</p>
</td>
</tr>
{results
.filter(
(result) => new Date(result.date).getFullYear() === year
)
.map((result, index) => (
<tr key={index} className="text-gray-700 even:bg-gray-300">
<td className="px-4 py-3">
<time className="font-semibold">
{new Date(result.date).toLocaleDateString("de-DE", {
timeZone: "Europe/Berlin",
year: "numeric",
month: "2-digit",
day: "2-digit",
})}
</time>
</td>
<td className="px-4 py-3">
<p>{result.name}</p>
</td>
<td className="px-4 py-3">
<Link to={`/veranstaltungen/${result.slug}`}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 md:h-6 md:w-6"
viewBox="0 0 512 512"
>
<path d="M480.6 341.4c-11.3 0-20.4 9.1-20.4 20.4v98.4H51.8v-98.4c0-11.3-9.1-20.4-20.4-20.4-11.3 0-20.4 9.1-20.4 20.4v118.8c0 11.3 9.1 20.4 20.4 20.4h449.2c11.3 0 20.4-9.1 20.4-20.4V361.8c0-11.3-9.1-20.4-20.4-20.4z" />
<path d="M241 365.6c11.5 11.6 25.6 5.2 29.9 0l117.3-126.2c7.7-8.3 7.2-21.2-1.1-28.9-8.3-7.7-21.2-7.2-28.8 1.1l-81.9 88.1V34.5c0-11.3-9.1-20.4-20.4-20.4-11.3 0-20.4 9.1-20.4 20.4v265.3l-81.9-88.1c-7.7-8.3-20.6-8.7-28.9-1.1-8.3 7.7-8.7 20.6-1.1 28.9L241 365.6z" />
</svg>
</Link>
</td>
</tr>
))}
</tbody>
))}
</table>
</div>
</ContentContainer>
);
}
17 changes: 13 additions & 4 deletions app/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ArticleHighlightList from "~/components/shared/article/ArticleHighlightLi
import { getArticles } from "~/.server/articles";
import { json, useLoaderData } from "@remix-run/react";
import { MetaFunction } from "@remix-run/node";
import { getLatestEventsAndResults } from "~/.server/events";

export const meta: MetaFunction = () => {
return [
Expand All @@ -23,12 +24,20 @@ export const meta: MetaFunction = () => {
};

export const loader = async () => {
const articles = await getArticles({ start: 0, limit: 6 });
return json({ articles });
const [articles, latest] = await Promise.all([
getArticles({ start: 0, limit: 6 }),
getLatestEventsAndResults(),
]);
const { events, results } = latest;
return json({
articles,
events,
results,
});
};

export default function Index() {
const { articles } = useLoaderData<typeof loader>();
const { articles, events, results } = useLoaderData<typeof loader>();
return (
<>
<BackgroundHeader title="Herzlich Willkommen beim Leichtathletik Club Rehlingen" />
Expand All @@ -40,7 +49,7 @@ export default function Index() {
<div className="mx-auto flex flex-col items-center justify-center gap-8 px-4 md:px-10 lg:max-w-6xl">
<Sponsor />
<PromoSection />
<Events events={[]} results={[]} />
<Events events={events} results={results} />
<Reha />
<Pfingstsportfest />
<FSJ />
Expand Down
24 changes: 24 additions & 0 deletions app/routes/training/konzept.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import ContentContainer from "~/components/ContentContainer";
import Title from "~/components/Title";

import Component from "~/assets/sport-konzept.mdx";
import type { MetaFunction } from "@remix-run/node";

export const meta: MetaFunction = () => {
return [
{
title: "Nachwuchs- und Leistungssportkonzept",
}
]
};

export default function Page() {
return (
<ContentContainer className="gap-4">
<Title name="Nachwuchs- und Leistungssportkonzept" />
<div className="prose max-w-none text-left">
<Component />
</div>
</ContentContainer>
);
}
38 changes: 38 additions & 0 deletions app/routes/veranstaltungen/$slug.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { json, LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { getEvent } from "~/.server/events";
import ContentContainer from "~/components/ContentContainer";

export async function loader({ params }: LoaderFunctionArgs) {
const event = await getEvent({ slug: params.slug ? params.slug : "" });
return json({
event,
});
}

export default function AthleteProfilePage() {
const { event } = useLoaderData<typeof loader>();
return (
<ContentContainer className="gap-4">
<h1 className="text-left text-3xl font-bold">{event.name}</h1>
<time className="text-left font-semibold">
{new Date(event.date).toLocaleDateString("de-DE", {
timeZone: "Europe/Berlin",
year: "numeric",
month: "2-digit",
day: "2-digit",
})}
</time>
{event.content ? (
<div
className="prose prose-lg max-w-none text-left"
dangerouslySetInnerHTML={{ __html: event.content }}
/>
) : (
<p className="font-medium">
Noch keine weiteren Informationen vorhanden
</p>
)}
</ContentContainer>
);
}
68 changes: 68 additions & 0 deletions app/routes/veranstaltungen/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { getEvents } from "~/.server/events";
import ContentContainer from "~/components/ContentContainer";
import Title from "~/components/Title";
import EventCard from "~/components/pages/veranstaltungen/EventCard";

export const meta: MetaFunction = () => {
return [
{
title: "Veranstaltungen",
},
{
name: "description",
content: "Kommende Veranstaltungen vom LC Rehlingen"
}
]
};

export async function loader() {
const events = await getEvents({
results: false,
}).then((res) => {
return res.filter((event) => {
return new Date(event.date) >= new Date();
});
});
return json({
events,
});
}

export default function EventListPage() {
const { events } = useLoaderData<typeof loader>();
return (
<ContentContainer className="gap-4">
<Title name="Veranstaltungen" />
<ul className="grid grid-cols-1 gap-4 md:grid-cols-3">
{events.map((event, index: number) => (
<li key={index}>
<EventCard
event={{
date: event.date,
name: event.name,
slug: event.slug,
}}
image={{
height: 1080,
width: 1920,
src: "logo.png",
}}
/>
</li>
))}
{
events.length === 0 && (
<li>
<div className="font-medium flex-1 p-4">
Keine bevorstehenden Veranstaltungen
</div>
</li>
)
}
</ul>
</ContentContainer>
);
}

0 comments on commit fdc36c2

Please sign in to comment.