add podcast landing page
All checks were successful
ci/woodpecker/push/build Pipeline was successful
All checks were successful
ci/woodpecker/push/build Pipeline was successful
This commit is contained in:
parent
ecc4f47321
commit
93bde35cbf
5 changed files with 92 additions and 4 deletions
|
@ -83,6 +83,10 @@ const routes = [
|
|||
component: () => (
|
||||
<Protected>{lazy(() => import("./routes/admin/episode"))()}</Protected>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/:podcastId",
|
||||
component: lazy(() => import("./routes/podcast")),
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ export default function AdminPodcast() {
|
|||
<Show when={podcastQuery.data?.image_filename}>
|
||||
<div class="column">
|
||||
<figure class="image is-128x128">
|
||||
<img src={new URL(params.podcastId + "/" + podcastQuery.data!.image_filename, SERVER_URL).href} />
|
||||
<img src={new URL(`/files/${params.podcastId}/${podcastQuery.data!.image_filename}`, SERVER_URL).href} />
|
||||
</figure>
|
||||
</div>
|
||||
</Show>
|
||||
|
|
|
@ -57,7 +57,7 @@ export default function AdminPodcasts() {
|
|||
<Show when={podcast.image_filename}>
|
||||
<div class="column">
|
||||
<figure class="image is-64x64">
|
||||
<img src={new URL(podcast.id + "/" + podcast.image_filename, SERVER_URL).href} />
|
||||
<img src={new URL("/files/" + podcast.id + "/" + podcast.image_filename, SERVER_URL).href} />
|
||||
</figure>
|
||||
</div>
|
||||
</Show>
|
||||
|
|
85
client/src/routes/podcast.tsx
Normal file
85
client/src/routes/podcast.tsx
Normal file
|
@ -0,0 +1,85 @@
|
|||
import { useParams } from "@solidjs/router";
|
||||
import { createQuery } from "@tanstack/solid-query";
|
||||
import { readPodcastOptions, readEpisodesOptions } from "../client/@tanstack/solid-query.gen";
|
||||
import { ErrorBoundary, For, Show, Suspense } from "solid-js";
|
||||
import Error from "../components/error";
|
||||
import Loading from "../components/loading";
|
||||
import { DownloadIcon, MusicIcon } from "lucide-solid";
|
||||
import { SERVER_URL } from "../constants";
|
||||
|
||||
export default function Podcast() {
|
||||
const params = useParams();
|
||||
|
||||
const podcastQuery = createQuery(() => ({
|
||||
...readPodcastOptions({
|
||||
path: {
|
||||
podcast_id: params.podcastId,
|
||||
}
|
||||
})
|
||||
}));
|
||||
const episodeQuery = createQuery(() => ({
|
||||
...readEpisodesOptions({
|
||||
path: {
|
||||
podcast_id: params.podcastId,
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
return (
|
||||
<main>
|
||||
<ErrorBoundary fallback={(err, reset) => <Error message={err} reset={reset} />}>
|
||||
<Suspense fallback={<Loading />}>
|
||||
<section class="hero is-medium is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="columns">
|
||||
<Show when={podcastQuery.data?.image_filename}>
|
||||
<div class="column">
|
||||
<figure class="image is-128x128">
|
||||
<img src={new URL(`/files/${params.podcastId}/${podcastQuery.data!.image_filename}`, SERVER_URL).href} />
|
||||
</figure>
|
||||
</div>
|
||||
</Show>
|
||||
<div class="column is-full">
|
||||
<h1 class="title">{podcastQuery.data?.name}</h1>
|
||||
<p class="subtitle">{podcastQuery.data?.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section">
|
||||
<div class="container is-max-desktop">
|
||||
<For each={episodeQuery.data}>
|
||||
{(episode) => (
|
||||
<article class="media">
|
||||
<figure class="media-left">
|
||||
<p class="image is-64x64 has-background-primary is-flex is-align-content-center">
|
||||
<MusicIcon class="p-4 has-text-dark" />
|
||||
</p>
|
||||
</figure>
|
||||
<div class="media-content">
|
||||
<div class="content">
|
||||
<p class="title is-5">{episode.name}</p>
|
||||
<Show when={episode.publish_date}>
|
||||
<p class="subtitle is-6">{new Date(episode.publish_date!).toLocaleDateString()}</p>
|
||||
</Show>
|
||||
<figure class="m-0 mb-4">
|
||||
<audio controls src={new URL(`/files/${episode.podcast_id}/${episode.id}.m4a`, SERVER_URL).toString()}></audio>
|
||||
</figure>
|
||||
<Show when={episode.description_html}>
|
||||
<p innerHTML={episode.description_html!}></p>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-right">
|
||||
<a href={new URL(`/files/${episode.podcast_id}/${episode.id}.m4a`, SERVER_URL).toString()}><DownloadIcon /></a>
|
||||
</div>
|
||||
</article>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
</section>
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</main>
|
||||
)
|
||||
}
|
|
@ -23,9 +23,8 @@
|
|||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"*": ["src/types/*"]
|
||||
"*": ["./src/types/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "src/types"]
|
||||
|
|
Loading…
Reference in a new issue