chore: refactor to take advantage of routing instead of rendering the same component twice

This commit is contained in:
2024-04-20 11:51:05 +02:00
parent 172e9e4c10
commit 2126e6bdbc
6 changed files with 96 additions and 53 deletions

View File

@@ -0,0 +1,53 @@
import { Link, useParams } from "react-router-dom";
import { usePodcastEpisodesQuery } from "../services/podcasts/podcast.hooks";
export function PodcastEpisodesList() {
const { podcastId } = useParams<{ podcastId: string }>();
const { data: episodesData } = usePodcastEpisodesQuery(podcastId);
return (
<div>
<div>Episodes: {episodesData?.podcast.trackCount}</div>
<div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Release Date</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
{episodesData?.episodes?.map((episode) => {
const formattedDate = formatDate(episode.releaseDate);
const formattedDuration = formatDuration(episode.durationSeconds);
const url = `/podcast/${podcastId}/episode/${episode.id}`;
return (
<tr key={episode.id}>
<td>
<Link to={url}>{episode.title}</Link>
</td>
<td>{formattedDate}</td>
<td>{formattedDuration}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}
function formatDuration(duration?: number) {
if (!duration) {
return "N/A";
}
const minutes = Math.floor(duration / 60);
const seconds = Math.floor(duration % 60);
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
}
function formatDate(date: string) {
return new Date(date).toLocaleDateString();
}

View File

@@ -5,12 +5,12 @@ type Props = {
imageURL: string; imageURL: string;
}; };
export const PodcastInfoCard = ({ export function PodcastInfoCard({
title, title,
author, author,
description, description,
imageURL, imageURL,
}: Props) => { }: Props) {
return ( return (
<div> <div>
<h1>{title}</h1> <h1>{title}</h1>
@@ -19,4 +19,4 @@ export const PodcastInfoCard = ({
<p>{description}</p> <p>{description}</p>
</div> </div>
); );
}; }

View File

@@ -1,3 +1,26 @@
import { useParams } from "react-router-dom";
import { usePodcastEpisodesQuery } from "../services/podcasts/podcast.hooks";
export function Episode() { export function Episode() {
return <h1>Episode page</h1>; const { podcastId, episodeId } = useParams<{
podcastId: string;
episodeId: string;
}>();
const { data: episodesData } = usePodcastEpisodesQuery(podcastId);
const episode = episodesData?.episodes.find(
(episode) => episode.id.toString() === episodeId,
);
return (
<div>
<div>{episode?.description}</div>
<div>
<audio controls src={episode?.audioUrl}>
Audio is not supported by your browser
</audio>
</div>
</div>
);
} }

View File

@@ -1,4 +1,4 @@
import { Link, useParams } from "react-router-dom"; import { Outlet, useParams } from "react-router-dom";
import { import {
usePodcastEpisodesQuery, usePodcastEpisodesQuery,
useTopPodcastsQuery, useTopPodcastsQuery,
@@ -26,7 +26,7 @@ export function Podcast() {
if (!podcast) { if (!podcast) {
return <h1>Podcast not found</h1>; return <h1>Podcast not found</h1>;
} }
// TODO: break into smaller components
return ( return (
<div> <div>
<PodcastInfoCard <PodcastInfoCard
@@ -35,48 +35,7 @@ export function Podcast() {
description={podcast.description} description={podcast.description}
imageURL={episodesData?.podcast.images.large ?? ""} imageURL={episodesData?.podcast.images.large ?? ""}
/> />
<div>Episodes: {episodesData?.podcast.trackCount}</div> <Outlet />
<div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Release Date</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
{episodesData?.episodes?.map((episode) => {
const formattedDate = formatDate(episode.releaseDate);
const formattedDuration = formatDuration(episode.durationSeconds);
const url = `/podcast/${podcastId}/episode/${episode.id}`;
return (
<tr key={episode.id}>
<td>
<Link to={url}>{episode.title}</Link>
</td>
<td>{formattedDate}</td>
<td>{formattedDuration}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div> </div>
); );
} }
function formatDuration(duration?: number) {
if (!duration) {
return "N/A";
}
const minutes = Math.floor(duration / 60);
const seconds = Math.floor(duration % 60);
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
}
function formatDate(date: string) {
return new Date(date).toLocaleDateString();
}

View File

@@ -2,6 +2,7 @@ import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Home } from "./pages/home"; import { Home } from "./pages/home";
import { Podcast } from "./pages/podcast"; import { Podcast } from "./pages/podcast";
import { Episode } from "./pages/episode"; import { Episode } from "./pages/episode";
import { PodcastEpisodesList } from "./components/podcast-episodes-list";
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
@@ -9,13 +10,19 @@ const router = createBrowserRouter([
element: <Home />, element: <Home />,
}, },
{ {
path: "/podcast/:podcastId", path: "/podcast",
element: <Podcast />, element: <Podcast />,
children: [
{
path: ":podcastId",
element: <PodcastEpisodesList />,
}, },
{ {
path: "/podcast/:podcastId/episode/:episodeId", path: ":podcastId/episode/:episodeId",
element: <Episode />, element: <Episode />,
}, },
],
},
]); ]);
export function Router() { export function Router() {

View File

@@ -28,6 +28,7 @@ class PodcastsService {
const response: GetEpisodesResponse = await this.fetchWithoutCors( const response: GetEpisodesResponse = await this.fetchWithoutCors(
url.toString(), url.toString(),
); );
let podcast: PodcastExtraDTO = {} as PodcastExtraDTO; let podcast: PodcastExtraDTO = {} as PodcastExtraDTO;
const episodes: EpisodeDto[] = []; const episodes: EpisodeDto[] = [];