From 4c30af27b6dec0fdb7ead2aab97bfd8443965ec5 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Mon, 22 May 2023 22:41:37 -0400 Subject: [PATCH] Update: add more toast notifications, update position Also set Account page to use UserContext. Refactored api requests out of components. --- src/components/Account/AccountInfo.tsx | 51 ++++++------ .../CommentContentBody.tsx | 3 +- .../BeerBreweryComments/EditCommentBody.tsx | 45 +++++++---- src/components/BeerById/BeerCommentForm.tsx | 14 ++-- .../BeerById/BeerPostCommentsSection.tsx | 4 +- .../BeerById/BeerRecommendations.tsx | 13 ++-- .../BreweryById/BreweryBeerSection.tsx | 13 ++-- .../BreweryById/BreweryCommentForm.tsx | 60 ++++++++++++++ .../BreweryById/BreweryCommentsSection.tsx | 78 +------------------ src/components/Login/LoginForm.tsx | 6 +- src/components/ui/CommentsComponent.tsx | 14 ++-- src/components/ui/CustomToast.tsx | 2 +- src/hooks/utilities/useMediaQuery.ts | 9 ++- src/pages/account/index.tsx | 44 ++--------- .../sendCreateBreweryCommentRequest.ts | 39 ++++++++++ src/requests/User/sendEditUserRequest.ts | 35 +++++++++ 16 files changed, 242 insertions(+), 188 deletions(-) create mode 100644 src/components/BreweryById/BreweryCommentForm.tsx create mode 100644 src/requests/BreweryComment/sendCreateBreweryCommentRequest.ts create mode 100644 src/requests/User/sendEditUserRequest.ts diff --git a/src/components/Account/AccountInfo.tsx b/src/components/Account/AccountInfo.tsx index 570c715..954d873 100644 --- a/src/components/Account/AccountInfo.tsx +++ b/src/components/Account/AccountInfo.tsx @@ -1,24 +1,23 @@ import validateEmailRequest from '@/requests/User/validateEmailRequest'; import validateUsernameRequest from '@/requests/validateUsernameRequest'; import { BaseCreateUserSchema } from '@/services/User/schema/CreateUserValidationSchemas'; -import GetUserSchema from '@/services/User/schema/GetUserSchema'; import { Switch } from '@headlessui/react'; import { zodResolver } from '@hookform/resolvers/zod'; -import { useRouter } from 'next/router'; -import { FC, useState } from 'react'; +import { FC, useContext, useState } from 'react'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; +import UserContext from '@/contexts/UserContext'; +import sendEditUserRequest from '@/requests/User/sendEditUserRequest'; +import createErrorToast from '@/util/createErrorToast'; +import { toast } from 'react-hot-toast'; import FormError from '../ui/forms/FormError'; import FormInfo from '../ui/forms/FormInfo'; import FormLabel from '../ui/forms/FormLabel'; import FormTextInput from '../ui/forms/FormTextInput'; -interface AccountInfoProps { - user: z.infer; -} +const AccountInfo: FC = () => { + const { user, mutate } = useContext(UserContext); -const AccountInfo: FC = ({ user }) => { - const router = useRouter(); const EditUserSchema = BaseCreateUserSchema.pick({ username: true, email: true, @@ -30,7 +29,7 @@ const AccountInfo: FC = ({ user }) => { .email({ message: 'Email must be a valid email address.' }) .refine( async (email) => { - if (user.email === email) return true; + if (user!.email === email) return true; return validateEmailRequest(email); }, { message: 'Email is already taken.' }, @@ -41,7 +40,7 @@ const AccountInfo: FC = ({ user }) => { .max(20, { message: 'Username must be less than 20 characters.' }) .refine( async (username) => { - if (user.username === username) return true; + if (user!.username === username) return true; return validateUsernameRequest(username); }, { message: 'Username is already taken.' }, @@ -53,29 +52,29 @@ const AccountInfo: FC = ({ user }) => { >({ resolver: zodResolver(EditUserSchema), defaultValues: { - username: user.username, - email: user.email, - firstName: user.firstName, - lastName: user.lastName, + username: user!.username, + email: user!.email, + firstName: user!.firstName, + lastName: user!.lastName, }, }); const [inEditMode, setInEditMode] = useState(false); const onSubmit = async (data: z.infer) => { - const response = await fetch(`/api/users/${user.id}/edit`, { - body: JSON.stringify(data), - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - }); - - if (!response.ok) { - throw new Error('Something went wrong.'); + const loadingToast = toast.loading('Submitting edits...'); + try { + await sendEditUserRequest({ user: user!, data }); + await mutate!(); + setInEditMode(false); + toast.remove(loadingToast); + toast.success('Edits submitted successfully.'); + } catch (error) { + setInEditMode(false); + toast.remove(loadingToast); + createErrorToast(error); + await mutate!(); } - - await response.json(); - - router.reload(); }; return ( diff --git a/src/components/BeerBreweryComments/CommentContentBody.tsx b/src/components/BeerBreweryComments/CommentContentBody.tsx index 9d6a41a..f0e7bf1 100644 --- a/src/components/BeerBreweryComments/CommentContentBody.tsx +++ b/src/components/BeerBreweryComments/CommentContentBody.tsx @@ -2,7 +2,8 @@ import UserContext from '@/contexts/UserContext'; import useTimeDistance from '@/hooks/utilities/useTimeDistance'; import { format } from 'date-fns'; import { Dispatch, FC, SetStateAction, useContext } from 'react'; -import { Link, Rating } from 'react-daisyui'; +import { Rating } from 'react-daisyui'; +import Link from 'next/link'; import CommentQueryResult from '@/services/types/CommentSchema/CommentQueryResult'; import { z } from 'zod'; diff --git a/src/components/BeerBreweryComments/EditCommentBody.tsx b/src/components/BeerBreweryComments/EditCommentBody.tsx index 5bb1e85..704bc3d 100644 --- a/src/components/BeerBreweryComments/EditCommentBody.tsx +++ b/src/components/BeerBreweryComments/EditCommentBody.tsx @@ -8,6 +8,7 @@ import CommentQueryResult from '@/services/types/CommentSchema/CommentQueryResul import CreateCommentValidationSchema from '@/services/types/CommentSchema/CreateCommentValidationSchema'; import useBreweryPostComments from '@/hooks/data-fetching/brewery-comments/useBreweryPostComments'; import toast from 'react-hot-toast'; +import createErrorToast from '@/util/createErrorToast'; import FormError from '../ui/forms/FormError'; import FormInfo from '../ui/forms/FormInfo'; import FormLabel from '../ui/forms/FormLabel'; @@ -31,7 +32,6 @@ interface EditCommentBodyProps { const EditCommentBody: FC = ({ comment, setInEditMode, - mutate, handleDeleteRequest, handleEditRequest, @@ -43,24 +43,41 @@ const EditCommentBody: FC = ({ resolver: zodResolver(CreateCommentValidationSchema), }); - const { errors } = formState; + const { errors, isSubmitting } = formState; const [isDeleting, setIsDeleting] = useState(false); const onDelete = async () => { + const loadingToast = toast.loading('Deleting comment...'); setIsDeleting(true); - await handleDeleteRequest(comment.id); - await mutate(); + try { + await handleDeleteRequest(comment.id); + await mutate(); + toast.remove(loadingToast); + toast.success('Deleted comment.'); + } catch (error) { + toast.remove(loadingToast); + createErrorToast(error); + } }; const onEdit: SubmitHandler> = async ( data, ) => { - setInEditMode(true); - await handleEditRequest(comment.id, data); - await mutate(); - toast.success('Submitted edits'); - setInEditMode(false); + const loadingToast = toast.loading('Submitting comment edits...'); + + try { + setInEditMode(true); + await handleEditRequest(comment.id, data); + await mutate(); + toast.remove(loadingToast); + toast.success('Comment edits submitted successfully.'); + setInEditMode(false); + } catch (error) { + toast.remove(loadingToast); + createErrorToast(error); + setInEditMode(false); + } }; return ( @@ -78,7 +95,7 @@ const EditCommentBody: FC = ({ placeholder="Comment" rows={2} error={!!errors.content?.message} - disabled={formState.isSubmitting || isDeleting} + disabled={isSubmitting || isDeleting} />
@@ -97,8 +114,8 @@ const EditCommentBody: FC = ({ ))} @@ -108,7 +125,7 @@ const EditCommentBody: FC = ({