177 lines
5.2 KiB
TypeScript
177 lines
5.2 KiB
TypeScript
import { gql, useMutation, useQuery } from '@apollo/client';
|
|
import { BookChapterCard } from '@app/client/components/BookChapterCard';
|
|
import { BookOverviewTabs } from '@app/client/components/BookOverviewTabs';
|
|
import { PaginatedListSkeleton } from '@app/client/components/PaginatedListSkeleton';
|
|
import { Pagination } from '@app/client/components/Pagination';
|
|
import { RatingPanel } from '@app/client/components/RatingPanel';
|
|
import { Button } from '@app/client/components/ui/button';
|
|
import { bookChapterFragment } from '@app/client/fragments';
|
|
import { useIdentity } from '@app/client/hooks/identity';
|
|
import { usePaginatedQuery } from '@app/client/hooks/usePaginatedQuery';
|
|
import { Box, Skeleton, Stack, Text } from '@chakra-ui/react';
|
|
import { BookChapterListQuery, BookOverviewRatingQuery } from '@generated/types';
|
|
import { createFileRoute, Link } from '@tanstack/react-router';
|
|
import { useState } from 'react';
|
|
|
|
export const Route = createFileRoute('/work/book/$bookId/overview/contents')({
|
|
component: RouteComponent
|
|
});
|
|
|
|
function RouteComponent() {
|
|
const { bookId: id } = Route.useParams();
|
|
|
|
const identity = useIdentity();
|
|
|
|
const { data } = useQuery<BookOverviewRatingQuery>(bookRatingQuery, {
|
|
variables: { id }
|
|
});
|
|
|
|
const [ratingUpdate] = useMutation<BookOverviewRatingQuery>(bookRatingMutation, {
|
|
refetchQueries: [bookRatingQuery]
|
|
});
|
|
|
|
return (
|
|
<>
|
|
<BookOverviewTabs bookId={id} currentTab="contents" />
|
|
|
|
{data != null ? (
|
|
<>
|
|
<BookChapterList
|
|
id={data.bookOne.id}
|
|
isAuthor={identity?.data.id === data.bookOne.author.id}
|
|
/>
|
|
|
|
{identity != null &&
|
|
identity?.data.id !== data.bookOne.author.id &&
|
|
data.bookOne.chaptersTotal > 0 && (
|
|
<RatingPanel
|
|
personalRating={data.bookOne.personalRating}
|
|
onRatingSet={async ratingType => {
|
|
await ratingUpdate({
|
|
variables: {
|
|
input: {
|
|
bookId: data.bookOne.id,
|
|
ratingType
|
|
}
|
|
}
|
|
});
|
|
}}
|
|
/>
|
|
)}
|
|
</>
|
|
) : (
|
|
<Skeleton height="200px" />
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
function BookChapterList({ id, isAuthor }: { readonly id: string; readonly isAuthor: boolean }) {
|
|
const [chaptersListPage, setChaptersListPage] = useState<number>(1);
|
|
const [chaptersListPageSize, setChaptersListPageSize] = useState<number>(10);
|
|
const startIndex = (chaptersListPage - 1) * chaptersListPageSize;
|
|
|
|
const { data } = usePaginatedQuery<BookChapterListQuery>({
|
|
query: bookChapterListQuery,
|
|
input: {
|
|
bookId: id,
|
|
filter: {
|
|
offset: startIndex,
|
|
size: chaptersListPageSize
|
|
}
|
|
}
|
|
});
|
|
|
|
return (
|
|
<Stack>
|
|
{data != null ? (
|
|
<>
|
|
<Stack>
|
|
{data.bookChapterMany.items.length > 0 ? (
|
|
<>
|
|
{data.bookChapterMany.items.map(item => (
|
|
<Stack key={`bookChapterList-${item.id}`}>
|
|
<BookChapterCard
|
|
bookId={id}
|
|
chapterId={item.id}
|
|
title={item.title}
|
|
isAuthor={isAuthor}
|
|
/>
|
|
</Stack>
|
|
))}
|
|
</>
|
|
) : (
|
|
<Stack justifyContent="center" alignItems="center" pt={8}>
|
|
<Text>No chapters here yet!</Text>
|
|
{isAuthor && (
|
|
<Link to={`/work/book/${id}/chapter/new`}>
|
|
<Button variant="outline" size="sm">
|
|
Create new chapter
|
|
</Button>
|
|
</Link>
|
|
)}
|
|
</Stack>
|
|
)}
|
|
</Stack>
|
|
{data.bookChapterMany.total > chaptersListPageSize && (
|
|
<Stack justifyContent="center" alignItems="center">
|
|
<Pagination
|
|
total={data.bookChapterMany.total}
|
|
page={chaptersListPage}
|
|
setPage={setChaptersListPage}
|
|
pageSize={chaptersListPageSize}
|
|
setPageSize={setChaptersListPageSize}
|
|
/>
|
|
</Stack>
|
|
)}
|
|
|
|
<Stack direction="row">
|
|
<>
|
|
{isAuthor && data.bookChapterMany.items.length !== 0 && (
|
|
<Box>
|
|
<Link to={`/work/book/${id}/chapter/new`}>
|
|
<Button size="sm">Create new chapter</Button>
|
|
</Link>
|
|
</Box>
|
|
)}
|
|
</>
|
|
</Stack>
|
|
</>
|
|
) : (
|
|
<PaginatedListSkeleton disableSearch />
|
|
)}
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
export const bookChapterListQuery = gql`
|
|
query BookChapterList($input: BookChapterManyInput!) {
|
|
bookChapterMany(input: $input) {
|
|
items {
|
|
...BookChapter
|
|
}
|
|
total
|
|
}
|
|
}
|
|
${bookChapterFragment}
|
|
`;
|
|
|
|
const bookRatingQuery = gql`
|
|
query BookOverviewRating($id: ID!) {
|
|
bookOne(id: $id) {
|
|
id
|
|
ratingTotal
|
|
personalRating
|
|
chaptersTotal
|
|
author {
|
|
id
|
|
}
|
|
}
|
|
}
|
|
`;
|
|
|
|
const bookRatingMutation = gql`
|
|
mutation BookOverviewRatingUpdate($input: RatingSetInput!) {
|
|
ratingSet(input: $input)
|
|
}
|
|
`;
|