Refactorings.

This commit is contained in:
2023-02-07 06:30:50 -08:00
parent fff2aef2c6
commit 28bec5b242
8 changed files with 1736 additions and 204 deletions

View File

@@ -1,175 +1,7 @@
export const dynamic = 'force-dynamic'
import { Suspense } from "react";
import Link from 'next/link'
import { ArrowLongLeftIcon, ArrowLongRightIcon } from '@heroicons/react/20/solid'
import { Container } from '@/components/Container'
import { FormattedDate } from '@/components/FormattedDate'
import { getEpisodes } from '@/data/episodes'
import Player from '@/app/Player'
function EpisodeEntry({ episode }) {
let date = new Date(episode.published)
return (
<article
aria-labelledby={`episode-${episode.id}-title`}
className="py-10 sm:py-12"
>
<Container>
<div className="flex flex-col items-start">
<h2
id={`episode-${episode.id}-title`}
className="mt-2 text-lg font-bold text-slate-900"
>
<Link href={`/podcast/${episode?.slug}`}>{episode.title}</Link>
</h2>
<FormattedDate
date={date}
className="order-first font-mono text-sm leading-7 text-slate-500"
/>
<p className="mt-1 text-base leading-7 text-slate-700">
{episode.description}
</p>
<div className="mt-4 flex items-center gap-4">
<Player episode={episode}>
<span className="ml-3" aria-hidden="true">
Listen
</span>
</Player>
<span
aria-hidden="true"
className="text-sm font-bold text-slate-400"
>
/
</span>
<Link
href={`/podcast/${episode.slug}`}
className="flex items-center text-sm font-bold leading-6 text-pink-500 hover:text-pink-700 active:text-pink-900"
aria-label={`Show notes for episode ${episode.title}`}
>
Show notes
</Link>
{episode?.transcript &&
(
<>
<span
aria-hidden="true"
className="text-sm font-bold text-slate-400"
>
/
</span>
<Link
href={`/podcast/${episode.slug}#transcript`}
className="flex items-center text-sm font-bold leading-6 text-pink-500 hover:text-pink-700 active:text-pink-900"
aria-label={`Transcript for episode ${episode.title}`}
>
Transcript
</Link>
</>
)}
</div>
</div>
</Container>
</article>
)
}
function pageClasses(page, i) {
return `inline-flex items-center border-t-2 border-transparent px-4 pt-4 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700 ${page === i ? 'border-indigo-500 text-indigo-600': ''}`
};
async function Content({ page }) {
const episodes = await getEpisodes()
await new Promise(resolve => setTimeout(resolve, 1000));
const pages = Math.ceil(episodes.length / 10);
return (
<>
<div className="divide-y divide-slate-100 sm:mt-4 lg:mt-8 lg:border-t lg:border-slate-100">
{episodes.slice((page - 1) * 10, page * 10).map((episode) => (
<EpisodeEntry key={episode.id} episode={episode} />
))}
</div>
<Container>
<nav className="flex items-center justify-between border-t border-gray-200 px-4 sm:px-0">
<div className="-mt-px flex w-0 flex-1">
<Link
href={`/?page=${page - 1}`}
className={`inline-flex items-center border-t-2 border-transparent pt-4 pr-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700 ${page <= 1 ? 'pointer-events-none' : ''}`}
>
<ArrowLongLeftIcon className="mr-3 h-5 w-5 text-gray-400" aria-hidden="true" />
Previous
</Link>
</div>
<div className="hidden md:-mt-px md:flex">
{page > 2 && (
<Link
href="/?page=1"
className={pageClasses(page, 1)}
>
1
</Link>
)}
{page > 2 && (
<span className="inline-flex items-center border-t-2 border-transparent px-4 pt-4 text-sm font-medium text-gray-500">
...
</span>
)}
{page > 1 && (
<Link
href={`/?page=${page - 1}`}
className={pageClasses(page - 1, page)}
>
{page - 1}
</Link>
)}
<Link
href={`/?page=${page}`}
className={pageClasses(page, page)}
>
{page}
</Link>
{page < pages && (
<Link
href={`/?page=${page + 1}`}
className={pageClasses(page + 1, page)}
>
{page + 1}
</Link>
)}
{(page + 1) < pages && (
<span className="inline-flex items-center border-t-2 border-transparent px-4 pt-4 text-sm font-medium text-gray-500">
...
</span>
)}
{(page + 1) < pages && (
<Link
href={`/?page=${pages}`}
className={pageClasses(page, pages)}
>
{pages}
</Link>
)}
</div>
<div className="-mt-px flex w-0 flex-1 justify-end">
<Link
href={`/?page=${page + 1}`}
className={`inline-flex items-center border-t-2 border-transparent pt-4 pl-1 text-sm font-medium text-gray-500 hover:border-gray-300 hover:text-gray-700 ${page >= pages ? 'pointer-events-none' : ''}`}
>
Next
<ArrowLongRightIcon className="ml-3 h-5 w-5 text-gray-400" aria-hidden="true" />
</Link>
</div>
</nav>
</Container>
</>
);
}
import Episodes from '@/components/Episodes'
function Skeleton({ width, height, className, color }) {
const w = width ? '' : 'w-full';
@@ -229,19 +61,18 @@ function Loading() {
);
}
export default async function Home({ searchParams }) {
export default async function Home() {
return (
<>
<div className="pt-16 pb-12 sm:pb-4 lg:pt-12">
<Container>
<h1 className="text-2xl font-bold leading-7 text-slate-900">
Episodes
</h1>
</Container>
<Suspense fallback={<Loading />}>
<Content page={searchParams?.page ? parseInt(searchParams?.page, 10) : 1} />
</Suspense>
</div>
<Episodes limit={15} />
<Container>
<Link
href="/episodes"
className="flex items-center text-md font-bold leading-6 text-pink-500 hover:text-pink-700 active:text-pink-900"
>
View All Episodes
</Link>
</Container>
</>
)
);
}