comicbox/pages/index.tsx
2022-08-01 17:29:54 +01:00

114 lines
3.8 KiB
TypeScript
Executable file

import { Comic } from '@prisma/client';
import type { GetServerSideProps } 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 = (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>Search</th>
<th>Completion</th>
<th>Link</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>
<LinkButton
href={`/comic/${comic.slug}/search`}
>
Search
</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,
},
};
};