implemented ratings, fixes
This commit is contained in:
parent
4801cf3a13
commit
d1da980501
31 changed files with 775 additions and 236 deletions
|
|
@ -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<BookChapterDeleteMutation>({
|
||||
mutation,
|
||||
successMsg: 'Chapter deleted successfully',
|
||||
refetchQueries: [bookChapterListQuery]
|
||||
refetchQueries: [bookChapterListQuery, bookChapterQuery]
|
||||
});
|
||||
return (
|
||||
<Card.Root width="100%" variant="elevated">
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export function BookChapterForm({
|
|||
</Box>
|
||||
<Stack direction="row">
|
||||
<Button onClick={async () => onSubmit()}>Submit</Button>
|
||||
<Link to={`/work/book/${bookId}/overview`}>
|
||||
<Link to={`/work/book/${bookId}/overview/contents`}>
|
||||
<Button>Go back</Button>
|
||||
</Link>
|
||||
</Stack>
|
||||
|
|
|
|||
23
app/client/components/BookOverviewTabs.tsx
Normal file
23
app/client/components/BookOverviewTabs.tsx
Normal file
|
|
@ -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 (
|
||||
<Tabs.Root defaultValue="members" value={currentTab}>
|
||||
<Tabs.List>
|
||||
<Link to={`/work/book/${bookId}/overview/contents`}>
|
||||
<Tabs.Trigger value="contents">Contents</Tabs.Trigger>
|
||||
</Link>
|
||||
<Link to={`/work/book/${bookId}/overview/reviews`}>
|
||||
<Tabs.Trigger value="reviews">Reviews</Tabs.Trigger>
|
||||
</Link>
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
);
|
||||
}
|
||||
48
app/client/components/RatingPanel.tsx
Normal file
48
app/client/components/RatingPanel.tsx
Normal file
|
|
@ -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<void>;
|
||||
}) {
|
||||
return (
|
||||
<Stack direction="row">
|
||||
<Button
|
||||
size="sm"
|
||||
backgroundColor={personalRating === RatingType.Up ? 'green.500/80' : 'green.500'}
|
||||
borderColor="green.500"
|
||||
onClick={async () => {
|
||||
if (personalRating !== RatingType.Up) {
|
||||
await onRatingSet(RatingType.Up);
|
||||
return;
|
||||
}
|
||||
await onRatingSet(RatingType.None);
|
||||
}}
|
||||
>
|
||||
<Icon>
|
||||
<i className="nf nf-oct-thumbsup" />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
backgroundColor={personalRating === RatingType.Down ? 'red.500/80' : 'red.500'}
|
||||
borderColor="red.500"
|
||||
onClick={async () => {
|
||||
if (personalRating !== RatingType.Down) {
|
||||
await onRatingSet(RatingType.Down);
|
||||
return;
|
||||
}
|
||||
await onRatingSet(RatingType.None);
|
||||
}}
|
||||
>
|
||||
<Icon>
|
||||
<i className="nf nf-oct-thumbsdown" />
|
||||
</Icon>
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
54
app/client/components/ReviewCard.tsx
Normal file
54
app/client/components/ReviewCard.tsx
Normal file
|
|
@ -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 (
|
||||
<Stack direction="row" alignItems="start">
|
||||
<Link to={`/profile/${review.username}`}>
|
||||
<Avatar size="sm" fallback={review.username[0]} />
|
||||
</Link>
|
||||
<Card.Root variant="subtle" width="100%">
|
||||
<Card.Body paddingX="3" paddingY="1">
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" gap={1}>
|
||||
<Link to={`/profile/${review.username}`}>
|
||||
<Text
|
||||
color="colorPalette.400"
|
||||
_hover={{
|
||||
textDecoration: 'underline',
|
||||
textDecorationColor: 'colorPalette.700'
|
||||
}}
|
||||
>
|
||||
{review.username}
|
||||
</Text>
|
||||
</Link>
|
||||
|
||||
<Text color="fg.muted">{toFormattedDate({ value: review.createdAt })}</Text>
|
||||
</Stack>
|
||||
<Box width="100%" position="relative" padding={0}>
|
||||
<Text>{review.text}</Text>
|
||||
{/* <Button */}
|
||||
{/* size="sm" */}
|
||||
{/* position="absolute" */}
|
||||
{/* right="2px" */}
|
||||
{/* bottom="5px" */}
|
||||
{/* padding={0} */}
|
||||
{/* variant="ghost" */}
|
||||
{/* // onClick={async () => onReviewSubmit(text)} */}
|
||||
{/* ></Button> */}
|
||||
</Box>
|
||||
</Card.Body>
|
||||
</Card.Root>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
47
app/client/components/ReviewInput.tsx
Normal file
47
app/client/components/ReviewInput.tsx
Normal file
|
|
@ -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<void>;
|
||||
}) {
|
||||
const [text, setText] = useState<string>('');
|
||||
return (
|
||||
<Stack direction="row" alignItems="start">
|
||||
<Avatar size="sm" fallback={username[0]} />
|
||||
<Stack width="100%" position="relative" borderRadius="md">
|
||||
<Textarea
|
||||
variant="subtle"
|
||||
placeholder="Write your review here..."
|
||||
resize="none"
|
||||
maxLength={700}
|
||||
maxLines={10}
|
||||
fontSize="md"
|
||||
autoresize
|
||||
value={text}
|
||||
onChange={event => setText(event.target.value)}
|
||||
/>
|
||||
<Button
|
||||
size="sm"
|
||||
position="absolute"
|
||||
right="2px"
|
||||
bottom="5px"
|
||||
padding={0}
|
||||
variant="ghost"
|
||||
onClick={async () => {
|
||||
await onReviewSubmit(text);
|
||||
setText('');
|
||||
}}
|
||||
>
|
||||
<Icon>
|
||||
<i className="nf nf-fa-send" />
|
||||
</Icon>
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
|
@ -22,9 +22,9 @@ export function WorkingListCard({
|
|||
<Card.Root width="100%" variant="elevated">
|
||||
<Card.Body>
|
||||
<Stack>
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Stack direction={'row'} justifyContent="space-between">
|
||||
<Text as="div" minWidth={0}>
|
||||
<Link to={`/work/book/${id}/overview`}>
|
||||
<Link to={`/work/book/${id}/overview/contents`}>
|
||||
<Heading
|
||||
color="colorPalette.400"
|
||||
_hover={{
|
||||
|
|
@ -37,7 +37,7 @@ export function WorkingListCard({
|
|||
</Link>
|
||||
</Text>
|
||||
|
||||
<Stack direction="row" justifyContent="center" alignItems="center">
|
||||
<Stack direction="row" justifyContent="center" alignItems="center" hideBelow="md">
|
||||
<WorkingRatingBadge ratingTotal={ratingTotal} />
|
||||
<WorkingReviewsBadge reviewsTotal={reviewsTotal} />
|
||||
<WorkingProgressStatusBadge progressStatus={progressStatus} />
|
||||
|
|
@ -60,7 +60,7 @@ export function WorkingListCard({
|
|||
</Link>
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row">
|
||||
<Stack maxWidth="100%" direction="row" overflow="auto" flexWrap="wrap">
|
||||
<Box>
|
||||
<Badge size="md" variant="solid">
|
||||
<Stack direction="row">
|
||||
|
|
@ -88,6 +88,12 @@ export function WorkingListCard({
|
|||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row" justifyContent="left" alignItems="center" hideFrom="md">
|
||||
<WorkingRatingBadge ratingTotal={ratingTotal} />
|
||||
<WorkingReviewsBadge reviewsTotal={reviewsTotal} />
|
||||
<WorkingProgressStatusBadge progressStatus={progressStatus} />
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<Text lineClamp={4}>{description}</Text>
|
||||
</Stack>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue