feat: add comic list to homepage

This commit is contained in:
Ashhhleyyy 2022-07-27 15:43:34 +01:00
parent 7e8d2da41b
commit d0d070e867
Signed by: ash
GPG key ID: 83B789081A0878FB
3 changed files with 124 additions and 19 deletions

View file

@ -0,0 +1,12 @@
interface Props {
total: number;
completed: number;
inline?: boolean;
}
export default function CompletionBar(props: Props) {
const progress = (props.completed / props.total) * 100;
return <span className={`w-full h-2 bg-red-400 ${props.inline ? 'inline-block' : 'block'} relative overflow-hidden rounded-full`} role="progressbar" aria-valuenow={props.completed} aria-valuemin={0} aria-valuemax={props.total}>
<span className='w-full h-2 absolute top-0 left-0 block bg-green-400' style={{ transform: `translateX(-${100 - progress}%)`, transformOrigin: 'left center' }} />
</span>
}

View file

@ -7,21 +7,32 @@ export default function NavBar() {
const router = useRouter();
return (
<nav className='flex flex-row h-12 bg-gray-900 justify-end items-center p-4 gap-1 shadow mb-4'>
{status === 'loading' && <>...</>}
{status === 'unauthenticated' && (
<LinkButton
href={`/login?return=${encodeURIComponent(router.asPath)}`}
>
Log in
</LinkButton>
)}
{status === 'authenticated' && (
<>
<span>{data?.user?.name}</span>
<button onClick={() => signOut()}>(Log out)</button>
</>
)}
<nav>
<ul className='flex flex-row h-12 bg-gray-900 justify-start items-center p-4 gap-1 shadow mb-4'>
<li>
<LinkButton href='/'>Comicbox</LinkButton>
</li>
<li className='flex-1' aria-hidden />
<li>
{status === 'loading' && <>...</>}
{status === 'unauthenticated' && (
<LinkButton
href={`/login?return=${encodeURIComponent(router.asPath)}`}
>
Log in
</LinkButton>
)}
{status === 'authenticated' && (
<>
<span>{data?.user?.name}</span>
<button onClick={() => signOut()}>(Log out)</button>
</>
)}
</li>
</ul>
</nav>
);
}

View file

@ -1,11 +1,93 @@
import type { NextPage } from 'next';
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';
const Home: NextPage = () => {
interface Props {
comics: {
comic: Comic;
completion: {
completePages: number;
totalPages: number;
};
}[];
}
const Home: NextPage<Props> = (props) => {
return (
<main>
<h1 className='text-4xl'>Hello, World!</h1>
<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,
}
}
}