From f99c04f00538e53704a7e5625cd4d4ece781c270 Mon Sep 17 00:00:00 2001 From: Justin Walrath Date: Thu, 15 May 2025 22:40:35 -0400 Subject: [PATCH] [#30] Stubbed out a functional landing page. --- public/icons/pause.svg | 1 + public/icons/play.svg | 1 + public/icons/search.svg | 1 + src/app/[stream]/podcasts/podcastCard.tsx | 2 +- src/app/page.tsx | 95 ++++++++++++++++++++++- src/common/data/db.ts | 6 ++ src/pages/api/podcasts/random.ts | 11 +++ 7 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 public/icons/pause.svg create mode 100644 public/icons/play.svg create mode 100644 public/icons/search.svg create mode 100644 src/pages/api/podcasts/random.ts diff --git a/public/icons/pause.svg b/public/icons/pause.svg new file mode 100644 index 0000000..afadaa4 --- /dev/null +++ b/public/icons/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/play.svg b/public/icons/play.svg new file mode 100644 index 0000000..d40e7d6 --- /dev/null +++ b/public/icons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/search.svg b/public/icons/search.svg new file mode 100644 index 0000000..1aaa56f --- /dev/null +++ b/public/icons/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/[stream]/podcasts/podcastCard.tsx b/src/app/[stream]/podcasts/podcastCard.tsx index 786d639..d76b33d 100644 --- a/src/app/[stream]/podcasts/podcastCard.tsx +++ b/src/app/[stream]/podcasts/podcastCard.tsx @@ -21,7 +21,7 @@ export default function PodcastCard({ return (
- {title + {title
diff --git a/src/app/page.tsx b/src/app/page.tsx index 5a52c13..2cd2b51 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,10 +1,101 @@ +"use client"; + +import Image from 'next/image'; import Main from './layout/main'; +import { useRef, useState, useEffect } from 'react'; +import { PodcastDto } from '@/common/dtos/podcastDto'; +import { useRouter } from 'next/navigation'; export default function Home() { + const inputRef = useRef(null), + [podcasts, setPodcasts] = useState([]), + router = useRouter(), + handleSearchClick = () => { + alert(inputRef.current?.value); + }, + handlePodcastClick = (podcast: PodcastDto) => { + if (podcast.streamId != null) { + router.push(`${process.env.NEXT_PUBLIC_API_BASE_URL}/${podcast.streamId}/podcasts`); // TODO: This should eventually go to the individual player page. + } + }; + + useEffect(() => { + fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/podcasts/random?limit=12`) + .then(res => res.json()) + .then(setPodcasts) + .catch(() => setPodcasts([])); + }, []); + return (
-

Welcome

- Go to podcast list. +
+
+ Site Icon +
+
+
+
+ + +
+
+ +
+
+

+ Not sure what you are looking for? +

+

+ Get started by selecting something of interest: +

+
+
+ +
+
+ {podcasts.map(podcast => ( + + ))} +
+
); } diff --git a/src/common/data/db.ts b/src/common/data/db.ts index 65bff56..29846f7 100644 --- a/src/common/data/db.ts +++ b/src/common/data/db.ts @@ -62,6 +62,12 @@ export const getPodcasts = async (stream: string) => { return db.data?.podcasts.filter((podcast) => podcast.streamId === stream) ?? []; }; +export const getRandomPodcasts = async (limit: number = 20) => { + const podcasts = db.data?.podcasts ?? []; + const shuffled = podcasts.slice().sort(() => Math.random() - 0.5); + return shuffled.slice(0, limit); +}; + export const publishPodcast = async (podcast: PodcastDto) => { await queueWrite(async () => { db.data?.podcasts.push(podcast); diff --git a/src/pages/api/podcasts/random.ts b/src/pages/api/podcasts/random.ts new file mode 100644 index 0000000..2d23a7b --- /dev/null +++ b/src/pages/api/podcasts/random.ts @@ -0,0 +1,11 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import { getRandomPodcasts } from '@/common/data/db'; +import { PodcastDto } from '@/common/dtos/podcastDto'; +import { preparePodcastItem } from '@/common/helpers/data'; + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : undefined, + podcasts = (await getRandomPodcasts(limit)).map(preparePodcastItem); + + res.status(200).json(podcasts); +} \ No newline at end of file