implemented ratings, fixes

This commit is contained in:
lnn0q 2025-06-01 17:54:57 +03:00
parent 4801cf3a13
commit d1da980501
31 changed files with 775 additions and 236 deletions

View file

@ -1,20 +1,13 @@
import { gql, useQuery } from '@apollo/client';
import { BookChapterCard } from '@app/client/components/BookChapterCard';
import { PaginatedListSkeleton } from '@app/client/components/PaginatedListSkeleton';
import { Pagination } from '@app/client/components/Pagination';
import { Button } from '@app/client/components/ui/button';
import { WorkingProgressStatusBadge } from '@app/client/components/WorkingProgressStatusBadge';
import { WorkingRatingBadge } from '@app/client/components/WorkingRatingBadge';
import { WorkingReviewsBadge } from '@app/client/components/WorkingReviewsTotalBadge';
import { bookChapterFragment, bookFragment } from '@app/client/fragments';
import { bookFragment } from '@app/client/fragments';
import { toFormattedDate } from '@app/client/helpers';
import { IdentityContext, useIdentity } from '@app/client/hooks/identity';
import { usePaginatedQuery } from '@app/client/hooks/usePaginatedQuery';
import { BookOne } from '@app/client/interfaces';
import { Box, Heading, HStack, Icon, Skeleton, SkeletonText, Stack, Text } from '@chakra-ui/react';
import { BookChapterListQuery, BookOverviewQuery } from '@generated/types';
import { createFileRoute, Link } from '@tanstack/react-router';
import { useState } from 'react';
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
@ -26,28 +19,16 @@ function RouteComponent() {
variables: { id }
});
const identity = useIdentity();
return (
<Stack width="100%" justifyContent="center" alignItems="center" padding={3}>
{bookData != null ? (
<BookOverview identity={identity} book={bookData.bookOne} />
) : (
<BookOverviewSkeleton />
)}
{bookData != null ? <BookOverview book={bookData.bookOne} /> : <BookOverviewSkeleton />}
</Stack>
);
}
function BookOverview({
identity,
book
}: {
readonly identity: IdentityContext | null;
readonly book: BookOne;
}) {
function BookOverview({ book }: { readonly book: BookOne }) {
return (
<Stack width="80%" maxWidth="840px" gap={3}>
<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}
@ -101,119 +82,14 @@ function BookOverview({
<Text>{book.description}</Text>
<BookChapterList
id={book.id}
identity={identity}
isAuthor={identity?.data.id === book.author.id}
/>
</Stack>
);
}
function BookChapterList({
id,
identity,
isAuthor
}: {
readonly id: string;
readonly identity: IdentityContext | null;
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>
)}
</>
{identity != null && !isAuthor && (
<>
<Button size="sm" backgroundColor="green.500" disabled>
<Icon>
<i className="nf nf-oct-thumbsup" />
</Icon>
</Button>
<Button size="sm" backgroundColor="red.500">
<Icon>
<i className="nf nf-oct-thumbsdown" />
</Icon>
</Button>
</>
)}
</Stack>
</>
) : (
<PaginatedListSkeleton disableSearch />
)}
<Outlet />
</Stack>
);
}
function BookOverviewSkeleton() {
return (
<Stack width="80%" maxWidth="840px">
<Stack width={{ base: '100%', md: '80%' }} maxWidth="840px">
<Stack gap="6" maxWidth="100%">
<HStack width="full">
<SkeletonText noOfLines={5} />
@ -224,7 +100,7 @@ function BookOverviewSkeleton() {
);
}
const bookQuery = gql`
export const bookQuery = gql`
query BookOverview($id: ID!) {
bookOne(id: $id) {
...Book
@ -232,15 +108,3 @@ const bookQuery = gql`
}
${bookFragment}
`;
export const bookChapterListQuery = gql`
query BookChapterList($input: BookChapterManyInput!) {
bookChapterMany(input: $input) {
items {
...BookChapter
}
total
}
}
${bookChapterFragment}
`;