added book details, update, delete. fixes
This commit is contained in:
parent
d1da980501
commit
b5738c610d
12 changed files with 290 additions and 16 deletions
|
|
@ -32,10 +32,14 @@ function RouteComponent() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<BookOverviewTabs bookId={id} currentTab="contents" />
|
||||
|
||||
{data != null ? (
|
||||
<>
|
||||
<BookOverviewTabs
|
||||
isAuthor={data?.bookOne.author.id === identity?.data.id}
|
||||
bookId={id}
|
||||
currentTab="contents"
|
||||
/>
|
||||
|
||||
<BookChapterList
|
||||
id={data.bookOne.id}
|
||||
isAuthor={identity?.data.id === data.bookOne.author.id}
|
||||
|
|
|
|||
151
app/client/pages/work/book/$bookId/overview/details.tsx
Normal file
151
app/client/pages/work/book/$bookId/overview/details.tsx
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
import { gql, useQuery } from '@apollo/client';
|
||||
import { BookOverviewTabs } from '@app/client/components/BookOverviewTabs';
|
||||
import { bookListQuery } from '@app/client/components/BookSearchList';
|
||||
import { bookFragment } from '@app/client/fragments';
|
||||
import { useIdentity } from '@app/client/hooks/identity';
|
||||
import { useToastMutation } from '@app/client/hooks/useToastMutation';
|
||||
import { Button, Input, NativeSelect, Skeleton, Stack, Textarea } from '@chakra-ui/react';
|
||||
import { BookDetailsQuery, WorkingProgressStatus } from '@generated/types';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { useState } from 'react';
|
||||
|
||||
export const Route = createFileRoute('/work/book/$bookId/overview/details')({
|
||||
component: RouteComponent
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { bookId: id } = Route.useParams();
|
||||
|
||||
const identity = useIdentity();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { data } = useQuery<BookDetailsQuery>(bookQuery, {
|
||||
variables: { id }
|
||||
});
|
||||
|
||||
const { update: bookUpdate } = useToastMutation({
|
||||
mutation: bookUpdateMutation,
|
||||
successMsg: 'Book updated successfully'
|
||||
});
|
||||
|
||||
const { update: bookDelete } = useToastMutation({
|
||||
mutation: bookDeleteMutation,
|
||||
successMsg: 'Book deleted successfully',
|
||||
refetchQueries: [bookListQuery]
|
||||
});
|
||||
|
||||
const [title, setTitle] = useState<string | undefined>(data?.bookOne.title);
|
||||
const [description, setDescription] = useState<string | undefined>(data?.bookOne.description);
|
||||
|
||||
const [progress, setProgress] = useState<WorkingProgressStatus | undefined>(
|
||||
data?.bookOne.progressStatus
|
||||
);
|
||||
|
||||
if (data == null) return <Skeleton />;
|
||||
|
||||
return (
|
||||
<>
|
||||
<BookOverviewTabs
|
||||
isAuthor={data.bookOne.author.id === identity?.data.id}
|
||||
bookId={id}
|
||||
currentTab="details"
|
||||
/>
|
||||
<Stack justifyContent="center" alignItems="center">
|
||||
<Stack width="70%">
|
||||
<Input
|
||||
value={title}
|
||||
onChange={event => setTitle(event.currentTarget.value)}
|
||||
placeholder="title"
|
||||
maxLength={60}
|
||||
/>
|
||||
|
||||
<NativeSelect.Root>
|
||||
<NativeSelect.Field
|
||||
value={progress}
|
||||
onChange={event => {
|
||||
const updatedStatus = event.currentTarget.value;
|
||||
ensureProgressStatus(updatedStatus);
|
||||
setProgress(updatedStatus);
|
||||
}}
|
||||
>
|
||||
<option value={WorkingProgressStatus.InProgress}>In progress</option>
|
||||
<option value={WorkingProgressStatus.Frozen}>Frozen</option>
|
||||
<option value={WorkingProgressStatus.Complete}>Complete</option>
|
||||
</NativeSelect.Field>
|
||||
<NativeSelect.Indicator />
|
||||
</NativeSelect.Root>
|
||||
<Textarea
|
||||
value={description}
|
||||
onChange={event => setDescription(event.currentTarget.value)}
|
||||
placeholder="description"
|
||||
maxLength={500}
|
||||
autoresize
|
||||
/>
|
||||
|
||||
<Button
|
||||
width="100%"
|
||||
onClick={async () => {
|
||||
await bookUpdate({
|
||||
variables: {
|
||||
input: {
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
progressStatus: progress
|
||||
}
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
width="100%"
|
||||
backgroundColor="red.500"
|
||||
onClick={async () => {
|
||||
await bookDelete({ variables: { id } });
|
||||
navigate({ to: '/' });
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ensureProgressStatus(value: string): asserts value is WorkingProgressStatus {
|
||||
if (value === WorkingProgressStatus.Complete) return;
|
||||
if (value === WorkingProgressStatus.InProgress) return;
|
||||
if (value === WorkingProgressStatus.Frozen) return;
|
||||
|
||||
throw new Error('Invalid WorkingPrgoressStatus');
|
||||
}
|
||||
|
||||
const bookQuery = gql`
|
||||
query BookDetails($id: ID!) {
|
||||
bookOne(id: $id) {
|
||||
...Book
|
||||
}
|
||||
}
|
||||
${bookFragment}
|
||||
`;
|
||||
|
||||
const bookUpdateMutation = gql`
|
||||
mutation BookDetailsUpdate($input: BookUpdateInput!) {
|
||||
bookUpdate(input: $input) {
|
||||
...Book
|
||||
}
|
||||
}
|
||||
${bookFragment}
|
||||
`;
|
||||
|
||||
const bookDeleteMutation = gql`
|
||||
mutation BookDetailsDelete($id: ID!) {
|
||||
bookDelete(id: $id)
|
||||
}
|
||||
`;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { gql } from '@apollo/client';
|
||||
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';
|
||||
|
|
@ -6,7 +6,7 @@ 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, BookReviewsQuery } from '@generated/types';
|
||||
import { BookReviewCreateMutation, BookReviewsDataQuery, BookReviewsQuery } from '@generated/types';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { useState } from 'react';
|
||||
import { bookQuery } from '../overview';
|
||||
|
|
@ -36,17 +36,25 @@ function RouteComponent() {
|
|||
}
|
||||
});
|
||||
|
||||
const { data: authorData } = useQuery<BookReviewsDataQuery>(bookAuthorQuery, {
|
||||
variables: { id }
|
||||
});
|
||||
|
||||
const { update: reviewCreate } = useToastMutation<BookReviewCreateMutation>({
|
||||
mutation: bookReviewCreateMutation,
|
||||
successMsg: 'Review posted!',
|
||||
refetchQueries: [bookReviewsQuery, bookQuery]
|
||||
});
|
||||
|
||||
if (data == null) return <Skeleton />;
|
||||
if (data == null || authorData == null) return <Skeleton />;
|
||||
|
||||
return (
|
||||
<>
|
||||
<BookOverviewTabs bookId={id} currentTab="reviews" />
|
||||
<BookOverviewTabs
|
||||
isAuthor={authorData.bookOne.author.id === identity?.data.id}
|
||||
bookId={id}
|
||||
currentTab="reviews"
|
||||
/>
|
||||
|
||||
{identity != null && reviewsPage === 1 && (
|
||||
<ReviewInput
|
||||
|
|
@ -97,6 +105,17 @@ function RouteComponent() {
|
|||
);
|
||||
}
|
||||
|
||||
const bookAuthorQuery = gql`
|
||||
query BookReviewsData($id: ID!) {
|
||||
bookOne(id: $id) {
|
||||
id
|
||||
author {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const bookReviewsQuery = gql`
|
||||
query BookReviews($input: ReviewManyInput!) {
|
||||
reviewMany(input: $input) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue