ln/app/client/pages/work/book/$bookId/overview/reviews.tsx

138 lines
3.8 KiB
TypeScript

import { gql, useQuery } from '@apollo/client';
import { BookOverviewTabs } from '@app/client/components/BookOverviewTabs';
import { Pagination } from '@app/client/components/Pagination';
import { reviewFragment } from '@app/client/fragments';
import { useIdentity } from '@app/client/hooks/identity';
import { usePaginatedQuery } from '@app/client/hooks/usePaginatedQuery';
import { useToastMutation } from '@app/client/hooks/useToastMutation';
import { Skeleton, Stack, Text } from '@chakra-ui/react';
import { BookReviewCreateMutation, BookReviewsDataQuery, BookReviewsQuery } from '@generated/types';
import { createFileRoute } from '@tanstack/react-router';
import { useState } from 'react';
import { bookQuery } from '../overview';
import { ReviewInput } from '@app/client/components/ReviewInput';
import { ReviewCard } from '@app/client/components/ReviewCard';
export const Route = createFileRoute('/work/book/$bookId/overview/reviews')({
component: RouteComponent
});
function RouteComponent() {
const { bookId: id } = Route.useParams();
const identity = useIdentity();
const [reviewsPage, setChaptersListPage] = useState<number>(1);
const [reviewsPageSize, setChaptersListPageSize] = useState<number>(10);
const startIndex = (reviewsPage - 1) * reviewsPageSize;
const { data } = usePaginatedQuery<BookReviewsQuery>({
query: bookReviewsQuery,
input: {
bookId: id,
filter: {
offset: startIndex,
size: reviewsPageSize
}
}
});
const { data: authorData } = useQuery<BookReviewsDataQuery>(bookAuthorQuery, {
variables: { id }
});
const { update: reviewCreate } = useToastMutation<BookReviewCreateMutation>({
mutation: bookReviewCreateMutation,
successMsg: 'Review posted!',
refetchQueries: [bookReviewsQuery, bookQuery]
});
if (data == null || authorData == null) return <Skeleton />;
return (
<>
<BookOverviewTabs
isAuthor={authorData.bookOne.author.id === identity?.data.id}
bookId={id}
currentTab="reviews"
/>
{identity != null && reviewsPage === 1 && (
<ReviewInput
username={identity?.data.user.username}
onReviewSubmit={async text => {
await reviewCreate({
variables: {
input: {
bookId: id,
text
}
}
});
}}
/>
)}
{data.reviewMany.items.length === 0 ? (
<Stack justifyContent="center" alignItems="center" pt={8}>
<Text>No reviews here yet!</Text>
</Stack>
) : (
data.reviewMany.items.map(item => (
<ReviewCard
key={`bookReview#${item.id}`}
review={{
id: item.id,
username: item.author.username,
text: item.text,
createdAt: item.createdAt
}}
/>
))
)}
{data.reviewMany.total > reviewsPageSize && (
<Stack justifyContent="center" alignItems="center">
<Pagination
total={data.reviewMany.total}
page={reviewsPage}
setPage={setChaptersListPage}
pageSize={reviewsPageSize}
setPageSize={setChaptersListPageSize}
/>
</Stack>
)}
</>
);
}
const bookAuthorQuery = gql`
query BookReviewsData($id: ID!) {
bookOne(id: $id) {
id
author {
id
}
}
}
`;
const bookReviewsQuery = gql`
query BookReviews($input: ReviewManyInput!) {
reviewMany(input: $input) {
items {
...Review
}
total
}
}
${reviewFragment}
`;
const bookReviewCreateMutation = gql`
mutation BookReviewCreate($input: ReviewCreateInput!) {
reviewCreate(input: $input) {
...Review
}
}
${reviewFragment}
`;