114 lines
3.8 KiB
TypeScript
Executable file
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,
|
|
},
|
|
};
|
|
};
|