110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { gql, useQuery } from '@apollo/client';
|
|
import { WorkingProgressStatusBadge } from '@app/client/components/WorkingProgressStatusBadge';
|
|
import { WorkingRatingBadge } from '@app/client/components/WorkingRatingBadge';
|
|
import { WorkingReviewsBadge } from '@app/client/components/WorkingReviewsTotalBadge';
|
|
import { bookFragment } from '@app/client/fragments';
|
|
import { toFormattedDate } from '@app/client/helpers';
|
|
import { BookOne } from '@app/client/interfaces';
|
|
import { Heading, HStack, Skeleton, SkeletonText, Stack, Text } from '@chakra-ui/react';
|
|
import { BookOverviewQuery } from '@generated/types';
|
|
import { createFileRoute, Link, Outlet } from '@tanstack/react-router';
|
|
|
|
export const Route = createFileRoute('/work/book/$bookId/overview')({
|
|
component: RouteComponent
|
|
});
|
|
|
|
function RouteComponent() {
|
|
const { bookId: id } = Route.useParams();
|
|
const { data: bookData } = useQuery<BookOverviewQuery>(bookQuery, {
|
|
variables: { id }
|
|
});
|
|
|
|
return (
|
|
<Stack width="100%" justifyContent="center" alignItems="center" padding={3}>
|
|
{bookData != null ? <BookOverview book={bookData.bookOne} /> : <BookOverviewSkeleton />}
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
function BookOverview({ book }: { readonly book: BookOne }) {
|
|
return (
|
|
<Stack width={{ base: '100%', md: '80%' }} maxWidth="840px" gap={3}>
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
<Heading color="colorPalette.400" size="2xl" overflow="auto">
|
|
{book.title}
|
|
</Heading>
|
|
</Stack>
|
|
|
|
<Stack direction="column" gap={1}>
|
|
<Stack direction="row">
|
|
<Link>
|
|
<Text fontWeight="bold">by:</Text>
|
|
</Link>
|
|
<Link to={`/profile/${book.author.username}`}>
|
|
<Text
|
|
color="colorPalette.400"
|
|
_hover={{
|
|
textDecoration: 'underline',
|
|
textDecorationColor: 'colorPalette.700'
|
|
}}
|
|
>
|
|
{book.author.username}
|
|
</Text>
|
|
</Link>
|
|
</Stack>
|
|
|
|
<Stack direction="row">
|
|
<Text fontWeight="bold">created at:</Text>
|
|
<Text>{toFormattedDate({ value: book.createdAt })}</Text>
|
|
</Stack>
|
|
|
|
<Stack direction="row">
|
|
<Text fontWeight="bold">last updated:</Text>
|
|
<Text>{toFormattedDate({ value: book.updatedAt })}</Text>
|
|
</Stack>
|
|
|
|
<Stack direction="row">
|
|
<Text fontWeight="bold">chapters:</Text>
|
|
<Text>{book.chaptersTotal}</Text>
|
|
</Stack>
|
|
|
|
<Stack direction="row">
|
|
<Text fontWeight="bold">words:</Text>
|
|
<Text>{book.wordsTotal}</Text>
|
|
</Stack>
|
|
</Stack>
|
|
|
|
<Stack direction="row" justifyContent="left" alignItems="center">
|
|
<WorkingRatingBadge ratingTotal={book.ratingTotal} />
|
|
<WorkingReviewsBadge reviewsTotal={book.reviewsTotal} />
|
|
<WorkingProgressStatusBadge progressStatus={book.progressStatus} />
|
|
</Stack>
|
|
|
|
<Text>{book.description}</Text>
|
|
|
|
<Outlet />
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
function BookOverviewSkeleton() {
|
|
return (
|
|
<Stack width={{ base: '100%', md: '80%' }} maxWidth="840px">
|
|
<Stack gap="6" maxWidth="100%">
|
|
<HStack width="full">
|
|
<SkeletonText noOfLines={5} />
|
|
</HStack>
|
|
<Skeleton height="200px" />
|
|
</Stack>
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
export const bookQuery = gql`
|
|
query BookOverview($id: ID!) {
|
|
bookOne(id: $id) {
|
|
...Book
|
|
}
|
|
}
|
|
${bookFragment}
|
|
`;
|