Skip to content

Commit

Permalink
feat: add manga detail page
Browse files Browse the repository at this point in the history
  • Loading branch information
oae committed Oct 16, 2022
1 parent bc5b14c commit 707560e
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 21 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"execa": "5.1.1",
"express": "^4.18.1",
"json-diff": "^0.9.0",
"mantine-datatable": "^1.7.9",
"meow": "^9.0.0",
"moment": "^2.29.4",
"next": "12.3.1",
Expand Down
2 changes: 1 addition & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ model Manga {
source String
library Library @relation(fields: [libraryId], references: [id], onDelete: Cascade)
libraryId Int
chapter Chapter[]
chapters Chapter[]
metadata Metadata @relation(fields: [metadataId], references: [id])
metadataId Int @unique
}
Expand Down
63 changes: 63 additions & 0 deletions src/components/chaptersTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Box } from '@mantine/core';
import { Prisma } from '@prisma/client';
import { DataTable } from 'mantine-datatable';

import dayjs from 'dayjs';

import prettyBytes from 'pretty-bytes';
import { useEffect, useState } from 'react';
import { showNotification } from '@mantine/notifications';
import { sanitizer } from '../utils/sanitize';

const mangaWithMetadataAndChaptersLibrary = Prisma.validator<Prisma.MangaArgs>()({
include: { metadata: true, chapters: true, library: true },
});

export type MangaWithMetadataAndChaptersLibrary = Prisma.MangaGetPayload<typeof mangaWithMetadataAndChaptersLibrary>;

const PAGE_SIZE = 100;

export function ChaptersTable({ manga }: { manga: MangaWithMetadataAndChaptersLibrary }) {
const [page, setPage] = useState(1);
const [records, setRecords] = useState(manga.chapters.slice(0, PAGE_SIZE));

useEffect(() => {
const from = (page - 1) * PAGE_SIZE;
const to = from + PAGE_SIZE;
setRecords(manga.chapters.slice(from, to));
}, [manga.chapters, page]);

return (
<Box sx={{ height: 700, marginTop: 30 }}>
<DataTable
withBorder
withColumnBorders
striped
highlightOnHover
records={records}
recordsPerPage={PAGE_SIZE}
page={page}
totalRecords={manga.chapters.length}
onPageChange={(p) => setPage(p)}
columns={[
{ accessor: 'Download Date', render: ({ createdAt }) => dayjs(createdAt).fromNow() },
{ accessor: 'Chapter', render: ({ index }) => `No #${index + 1}` },
{
accessor: 'File',
render: ({ fileName }) => `${manga.library.path}/${sanitizer(manga.title)}/${fileName}`,
},
{ accessor: 'Size', render: ({ size }) => prettyBytes(size) },
]}
rowContextMenu={{
items: () => [
{
key: 'download',
title: 'Download Again',
onClick: () => showNotification({ message: `Chapter queued for the download` }),
},
],
}}
/>
</Box>
);
}
101 changes: 101 additions & 0 deletions src/components/mangaDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Badge, createStyles, Divider, Grid, Group, Image, Text, Title, Tooltip } from '@mantine/core';
import { Prisma } from '@prisma/client';

const useStyles = createStyles((_theme) => ({
root: {},
placeHolder: {
alignItems: 'start !important',
justifyContent: 'flex-start !important',
},
}));

const mangaWithMetadataAndChapters = Prisma.validator<Prisma.MangaArgs>()({
include: { metadata: true, chapters: true },
});

export type MangaWithMetadataAndChapters = Prisma.MangaGetPayload<typeof mangaWithMetadataAndChapters>;

export function MangaDetail({ manga }: { manga: MangaWithMetadataAndChapters }) {
const { classes } = useStyles();

return (
<Grid className={classes.root}>
<Grid.Col span="auto" style={{ maxWidth: 300 }}>
<Image
classNames={{
placeholder: classes.placeHolder,
}}
sx={(theme) => ({
width: 210,
boxShadow: theme.shadows.xl,
})}
withPlaceholder
placeholder={
<Image
sx={(theme) => ({
width: 210,
boxShadow: theme.shadows.xl,
})}
src="/cover-not-found.jpg"
alt={manga.title}
/>
}
src={manga.metadata.cover}
/>
</Grid.Col>
<Grid.Col span="auto">
<Divider mb="xs" labelPosition="left" label={<Title order={3}>{manga.title}</Title>} />
<Group spacing="xs">
{manga.metadata.synonyms.map((synonym) => (
<Tooltip label={synonym} key={synonym}>
<div style={{ maxWidth: 100 }}>
<Badge color="blue" variant="filled" size="sm" fullWidth>
{synonym}
</Badge>
</div>
</Tooltip>
))}
</Group>
<Divider variant="dashed" my="xs" label="Status" />
<Badge color="cyan" variant="filled" size="sm">
{manga.metadata.status}
</Badge>

<Divider variant="dashed" my="xs" label="Chapters" />
<Text>
There are &nbsp;
<Badge color="teal" variant="outline" size="lg">
{manga.chapters.length}
</Badge>
&nbsp; chapters
</Text>
<Divider variant="dashed" my="xs" label="Summary" />
<Text size="sm">{manga.metadata.summary || 'No summary...'}</Text>
<Divider variant="dashed" my="xs" label="Genres" />
<Group spacing="xs">
{manga.metadata.genres.map((genre) => (
<Tooltip label={genre} key={genre}>
<div style={{ maxWidth: 100 }}>
<Badge color="indigo" variant="light" size="xs" fullWidth>
{genre}
</Badge>
</div>
</Tooltip>
))}
</Group>
<Divider variant="dashed" my="xs" label="Tags" />
<Group spacing="xs">
{manga.metadata.tags.map((tag) => (
<Tooltip label={tag} key={tag}>
<div style={{ maxWidth: 100 }}>
<Badge color="violet" variant="light" size="xs" fullWidth>
{tag}
</Badge>
</div>
</Tooltip>
))}
</Group>
</Grid.Col>
</Grid>
);
}
28 changes: 14 additions & 14 deletions src/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Image,
MantineColor,
Navbar,
ScrollArea,
SimpleGrid,
Skeleton,
Text,
Expand Down Expand Up @@ -37,7 +38,6 @@ const useStyles = createStyles((theme) => ({
navbar: {
paddingTop: 0,
boxShadow: theme.shadows.md,
overflowY: 'auto',
fontSize: theme.fontSizes.xs,
},
history: {
Expand Down Expand Up @@ -261,20 +261,20 @@ export function KaizokuNavbar() {
{activityQuery.data && <Activity data={activityQuery.data} />}
</Navbar.Section>

<Navbar.Section>
<Divider
mb="md"
labelPosition="left"
mt="md"
variant="solid"
label={
<Text color="dimmed" size="md" weight={500}>
Latest Downloads
</Text>
}
/>
<Divider
mb="md"
labelPosition="left"
mt="md"
variant="solid"
label={
<Text color="dimmed" size="md" weight={500}>
Latest Downloads
</Text>
}
/>
<Navbar.Section grow component={ScrollArea}>
{historyQuery.isLoading && <NavBarSkeleton />}
{historyQuery.data && <History data={historyQuery.data} />}
<Box mx={8}>{historyQuery.data && <History data={historyQuery.data} />}</Box>
</Navbar.Section>
</Navbar>
);
Expand Down
18 changes: 15 additions & 3 deletions src/pages/manga/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Code, LoadingOverlay } from '@mantine/core';
import { Grid, LoadingOverlay } from '@mantine/core';
import { useRouter } from 'next/router';
import { ChaptersTable } from '../../components/chaptersTable';
import { MangaDetail } from '../../components/mangaDetail';
import { trpc } from '../../utils/trpc';

export default function LibraryPage() {
Expand All @@ -20,9 +22,19 @@ export default function LibraryPage() {
return <LoadingOverlay visible overlayBlur={2} />;
}

if (mangaQuery.isError) {
if (mangaQuery.isError || !mangaQuery.data) {
router.push('/404');
return null;
}

return <Code>{JSON.stringify(mangaQuery.data, null, 2)}</Code>;
return (
<Grid gutter={5}>
<Grid.Col span={12}>
<MangaDetail manga={mangaQuery.data} />
</Grid.Col>
<Grid.Col span={12}>
<ChaptersTable manga={mangaQuery.data} />
</Grid.Col>
</Grid>
);
}
6 changes: 3 additions & 3 deletions src/server/trpc/router/manga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ export const mangaRouter = t.router({
const { id } = input;
return ctx.prisma.manga.findUniqueOrThrow({
include: {
chapter: {
chapters: {
orderBy: {
index: 'asc',
index: 'desc',
},
},
library: true,
Expand Down Expand Up @@ -176,7 +176,7 @@ export const mangaRouter = t.router({
orderBy: {
createdAt: 'desc',
},
take: 10,
take: 50,
include: {
manga: {
include: {
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3891,6 +3891,11 @@ make-error@^1.1.1:
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==

mantine-datatable@^1.7.9:
version "1.7.9"
resolved "https://registry.yarnpkg.com/mantine-datatable/-/mantine-datatable-1.7.9.tgz#4e97fbfc67c2f8777ac2745199210bdd5c775cff"
integrity sha512-D4lkckNBPtTZl9cy9ONGZ1D/qFcOLvyfqcXI/6VM17o3VLyNQDEBzsikv1NVgTZKrtqDKLGonkLJAMuxVuekKA==

map-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
Expand Down

0 comments on commit 707560e

Please sign in to comment.