From d1da980501d97cda16ff6db54e016d6005734411 Mon Sep 17 00:00:00 2001 From: lnn0q Date: Sun, 1 Jun 2025 17:54:57 +0300 Subject: [PATCH] implemented ratings, fixes --- app/client/components/BookChapterCard.tsx | 5 +- app/client/components/BookChapterForm.tsx | 2 +- app/client/components/BookOverviewTabs.tsx | 23 +++ app/client/components/RatingPanel.tsx | 48 +++++ app/client/components/ReviewCard.tsx | 54 ++++++ app/client/components/ReviewInput.tsx | 47 +++++ app/client/components/WorkingListCard.tsx | 14 +- app/client/fragments.tsx | 13 ++ app/client/main.tsx | 2 +- app/client/pages/__root.tsx | 7 +- app/client/pages/new/book.tsx | 2 +- .../book/$bookId/chapter/$chapterId/edit.tsx | 2 +- .../book/$bookId/chapter/$chapterId/view.tsx | 97 +++++----- .../pages/work/book/$bookId/chapter/new.tsx | 9 +- .../pages/work/book/$bookId/overview.tsx | 156 +-------------- .../work/book/$bookId/overview/contents.tsx | 177 ++++++++++++++++++ .../work/book/$bookId/overview/reviews.tsx | 119 ++++++++++++ app/client/routeTree.gen.ts | 82 +++++++- app/server/config.ts | 7 +- app/server/graphql/graphql.ts | 8 +- .../graphql/resolvers/bookChapterDelete.ts | 19 +- .../resolvers/bookChapterUpdateResolver.ts | 19 +- .../graphql/resolvers/mappers/bookMapper.ts | 28 ++- .../graphql/resolvers/mappers/reviewMapper.ts | 2 + .../graphql/resolvers/ratingSetResolver.ts | 3 +- .../graphql/resolvers/reviewCreateResolver.ts | 26 +++ .../graphql/resolvers/reviewDeleteResolver.ts | 0 .../graphql/resolvers/reviewManyResolver.ts | 26 +++ .../graphql/resolvers/reviewUpdateResolver.ts | 0 app/server/graphql/schema.graphql | 9 + vite.config.ts | 5 +- 31 files changed, 775 insertions(+), 236 deletions(-) create mode 100644 app/client/components/BookOverviewTabs.tsx create mode 100644 app/client/components/RatingPanel.tsx create mode 100644 app/client/components/ReviewCard.tsx create mode 100644 app/client/components/ReviewInput.tsx create mode 100644 app/client/pages/work/book/$bookId/overview/contents.tsx create mode 100644 app/client/pages/work/book/$bookId/overview/reviews.tsx create mode 100644 app/server/graphql/resolvers/reviewCreateResolver.ts create mode 100644 app/server/graphql/resolvers/reviewDeleteResolver.ts create mode 100644 app/server/graphql/resolvers/reviewManyResolver.ts create mode 100644 app/server/graphql/resolvers/reviewUpdateResolver.ts diff --git a/app/client/components/BookChapterCard.tsx b/app/client/components/BookChapterCard.tsx index 0716ec2..8bcb8f2 100644 --- a/app/client/components/BookChapterCard.tsx +++ b/app/client/components/BookChapterCard.tsx @@ -4,7 +4,8 @@ import { BookChapterDeleteMutation } from '@generated/types'; import { Link } from '@tanstack/react-router'; import { bookFragment } from '../fragments'; import { useToastMutation } from '../hooks/useToastMutation'; -import { bookChapterListQuery } from '../pages/work/book/$bookId/overview'; +import { bookChapterQuery } from '../pages/work/book/$bookId/chapter/$chapterId/view'; +import { bookChapterListQuery } from '../pages/work/book/$bookId/overview/contents'; export function BookChapterCard({ bookId, @@ -20,7 +21,7 @@ export function BookChapterCard({ const { update: chapterDelete } = useToastMutation({ mutation, successMsg: 'Chapter deleted successfully', - refetchQueries: [bookChapterListQuery] + refetchQueries: [bookChapterListQuery, bookChapterQuery] }); return ( diff --git a/app/client/components/BookChapterForm.tsx b/app/client/components/BookChapterForm.tsx index 66f242e..e8890e8 100644 --- a/app/client/components/BookChapterForm.tsx +++ b/app/client/components/BookChapterForm.tsx @@ -82,7 +82,7 @@ export function BookChapterForm({ - + diff --git a/app/client/components/BookOverviewTabs.tsx b/app/client/components/BookOverviewTabs.tsx new file mode 100644 index 0000000..738f5f4 --- /dev/null +++ b/app/client/components/BookOverviewTabs.tsx @@ -0,0 +1,23 @@ +import { Tabs } from '@chakra-ui/react'; +import { Link } from '@tanstack/react-router'; + +export function BookOverviewTabs({ + bookId, + currentTab +}: { + readonly bookId: string; + readonly currentTab: 'contents' | 'reviews'; +}) { + return ( + + + + Contents + + + Reviews + + + + ); +} diff --git a/app/client/components/RatingPanel.tsx b/app/client/components/RatingPanel.tsx new file mode 100644 index 0000000..cbc9e9e --- /dev/null +++ b/app/client/components/RatingPanel.tsx @@ -0,0 +1,48 @@ +import { Button } from '@app/client/components/ui/button'; +import { Icon, Stack } from '@chakra-ui/react'; +import { RatingType } from '@generated/types'; + +export function RatingPanel({ + personalRating, + onRatingSet +}: { + readonly personalRating: RatingType; + readonly onRatingSet: (rating: RatingType) => Promise; +}) { + return ( + + + + + ); +} diff --git a/app/client/components/ReviewCard.tsx b/app/client/components/ReviewCard.tsx new file mode 100644 index 0000000..396394a --- /dev/null +++ b/app/client/components/ReviewCard.tsx @@ -0,0 +1,54 @@ +import { Avatar } from '@app/client/components/ui/avatar'; +import { toFormattedDate } from '@app/client/helpers'; +import { Box, Card, Stack, Text } from '@chakra-ui/react'; +import { Link } from '@tanstack/react-router'; + +export function ReviewCard({ + review +}: { + readonly review: { + readonly id: string; + readonly username: string; + readonly createdAt: string; + readonly text: string; + }; +}) { + return ( + + + + + + + + + + {review.username} + + + + {toFormattedDate({ value: review.createdAt })} + + + {review.text} + {/* */} + + + + + ); +} diff --git a/app/client/components/ReviewInput.tsx b/app/client/components/ReviewInput.tsx new file mode 100644 index 0000000..65ac550 --- /dev/null +++ b/app/client/components/ReviewInput.tsx @@ -0,0 +1,47 @@ +import { Avatar } from '@app/client/components/ui/avatar'; +import { Button, Icon, Stack, Textarea } from '@chakra-ui/react'; +import { useState } from 'react'; + +export function ReviewInput({ + username, + onReviewSubmit +}: { + readonly username: string; + readonly onReviewSubmit: (text: string) => Promise; +}) { + const [text, setText] = useState(''); + return ( + + + +