mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 20:13:49 +00:00
Feat: Add create brewery comments and brewery cluster map
This commit is contained in:
@@ -3,39 +3,118 @@ import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQuer
|
||||
import { FC, MutableRefObject, useContext, useRef } from 'react';
|
||||
import { z } from 'zod';
|
||||
import useBreweryPostComments from '@/hooks/useBreweryPostComments';
|
||||
import CreateCommentValidationSchema from '@/services/types/CommentSchema/CreateCommentValidationSchema';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import CommentQueryResult from '@/services/types/CommentSchema/CommentQueryResult';
|
||||
import LoadingComponent from '../BeerById/LoadingComponent';
|
||||
import CommentsComponent from '../ui/CommentsComponent';
|
||||
import CommentForm from '../ui/CommentForm';
|
||||
|
||||
interface BreweryBeerSectionProps {
|
||||
breweryPost: z.infer<typeof BreweryPostQueryResult>;
|
||||
}
|
||||
|
||||
const BreweryCommentForm: FC = () => {
|
||||
return null;
|
||||
interface BreweryCommentFormProps {
|
||||
breweryPost: z.infer<typeof BreweryPostQueryResult>;
|
||||
mutate: ReturnType<typeof useBreweryPostComments>['mutate'];
|
||||
}
|
||||
|
||||
const BreweryCommentValidationSchemaWithId = CreateCommentValidationSchema.extend({
|
||||
breweryPostId: z.string(),
|
||||
});
|
||||
|
||||
const sendCreateBreweryCommentRequest = async ({
|
||||
content,
|
||||
rating,
|
||||
breweryPostId,
|
||||
}: z.infer<typeof BreweryCommentValidationSchemaWithId>) => {
|
||||
const response = await fetch(`/api/breweries/${breweryPostId}/comments`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ content, rating }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const parsedResponse = APIResponseValidationSchema.safeParse(data);
|
||||
if (!parsedResponse.success) {
|
||||
throw new Error('Invalid API response');
|
||||
}
|
||||
|
||||
const parsedPayload = CommentQueryResult.safeParse(parsedResponse.data.payload);
|
||||
if (!parsedPayload.success) {
|
||||
throw new Error('Invalid API response payload');
|
||||
}
|
||||
|
||||
return parsedPayload.data;
|
||||
};
|
||||
|
||||
const BreweryCommentForm: FC<BreweryCommentFormProps> = ({ breweryPost, mutate }) => {
|
||||
const { register, handleSubmit, formState, watch, reset, setValue } = useForm<
|
||||
z.infer<typeof CreateCommentValidationSchema>
|
||||
>({
|
||||
defaultValues: { rating: 0 },
|
||||
resolver: zodResolver(CreateCommentValidationSchema),
|
||||
});
|
||||
|
||||
const onSubmit: SubmitHandler<z.infer<typeof CreateCommentValidationSchema>> = async (
|
||||
data,
|
||||
) => {
|
||||
await sendCreateBreweryCommentRequest({
|
||||
content: data.content,
|
||||
rating: data.rating,
|
||||
breweryPostId: breweryPost.id,
|
||||
});
|
||||
await mutate();
|
||||
reset();
|
||||
};
|
||||
|
||||
return (
|
||||
<CommentForm
|
||||
handleSubmit={handleSubmit}
|
||||
onSubmit={onSubmit}
|
||||
watch={watch}
|
||||
setValue={setValue}
|
||||
formState={formState}
|
||||
register={register}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const BreweryCommentsSection: FC<BreweryBeerSectionProps> = ({ breweryPost }) => {
|
||||
const { user } = useContext(UserContext);
|
||||
|
||||
const { id } = breweryPost;
|
||||
|
||||
const PAGE_SIZE = 4;
|
||||
|
||||
const { comments, isLoading, setSize, size, isLoadingMore, isAtEnd } =
|
||||
useBreweryPostComments({ id, pageSize: PAGE_SIZE });
|
||||
const {
|
||||
isLoading,
|
||||
setSize,
|
||||
size,
|
||||
isLoadingMore,
|
||||
isAtEnd,
|
||||
mutate,
|
||||
comments: breweryComments,
|
||||
} = useBreweryPostComments({ id: breweryPost.id, pageSize: PAGE_SIZE });
|
||||
|
||||
const commentSectionRef: MutableRefObject<HTMLDivElement | null> = useRef(null);
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-3" ref={commentSectionRef}>
|
||||
<div className="card">
|
||||
{user ? (
|
||||
<BreweryCommentForm />
|
||||
) : (
|
||||
<div className="flex h-52 flex-col items-center justify-center">
|
||||
<div className="text-lg font-bold">Log in to leave a comment.</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="card-body h-full">
|
||||
{user ? (
|
||||
<BreweryCommentForm breweryPost={breweryPost} mutate={mutate} />
|
||||
) : (
|
||||
<div className="flex h-52 flex-col items-center justify-center">
|
||||
<div className="text-lg font-bold">Log in to leave a comment.</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
/**
|
||||
@@ -48,7 +127,7 @@ const BreweryCommentsSection: FC<BreweryBeerSectionProps> = ({ breweryPost }) =>
|
||||
</div>
|
||||
) : (
|
||||
<CommentsComponent
|
||||
comments={comments}
|
||||
comments={breweryComments}
|
||||
isLoadingMore={isLoadingMore}
|
||||
isAtEnd={isAtEnd}
|
||||
pageSize={PAGE_SIZE}
|
||||
|
||||
Reference in New Issue
Block a user