comicbox/pages/index.tsx

93 lines
2.9 KiB
TypeScript
Executable file

import { Comic } from '@prisma/client';
import type { GetServerSideProps, NextPage } from 'next';
import Head from 'next/head';
import { LinkButton } from '../components/Button';
import CompletionBar from '../components/CompletionBar';
import { prisma } from '../src/db';
interface Props {
comics: {
comic: Comic;
completion: {
completePages: number;
totalPages: number;
};
}[];
}
const Home: NextPage<Props> = (props) => {
return (
<main className='p-4'>
<Head>
<title>Comicbox</title>
</Head>
<table className='border-separate border-spacing-x-2'>
<thead>
<tr className='text-left'>
<th>Comic</th>
<th>Completion</th>
<th>Links</th>
</tr>
</thead>
<tbody>
{props.comics.map(({ comic, completion }) => {
return <tr key={comic.id}>
<td>
<LinkButton href={`/comic/${comic.slug}`}>
{comic.title}
</LinkButton>
</td>
<td className='w-96 flex flex-row items-center'>
<CompletionBar inline total={completion.totalPages} completed={completion.completePages} />
<span className='whitespace-nowrap pl-2'>
({completion.completePages}/{completion.totalPages} pages)
</span>
</td>
<td>
<LinkButton href={comic.url} target='_blank'>
{new URL(comic.url).host}
</LinkButton>
</td>
</tr>
})}
</tbody>
</table>
</main>
);
};
export default Home;
export const getServerSideProps: GetServerSideProps<Props> = async () => {
const comics = await prisma.comic.findMany();
const comicsWithCompletions = await Promise.all(comics.map(async (comic) => {
const pages = await prisma.comicPage.findMany({
where: {
comicId: comic.id,
},
select: {
_count: {
select: {
bubbles: true,
},
},
},
});
return {
comic,
completion: {
totalPages: pages.length,
completePages: pages.filter((page) => page._count.bubbles !== 0)
.length,
},
}
}));
return {
props: {
comics: comicsWithCompletions,
}
}
}