diff --git a/public/favicon/site.webmanifest b/public/favicon/site.webmanifest index 45dc8a2..0b08af1 100644 --- a/public/favicon/site.webmanifest +++ b/public/favicon/site.webmanifest @@ -1 +1,11 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file +{ + "name": "", + "short_name": "", + "icons": [ + { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/src/components/BeerById/BeerRecommendations.tsx b/src/components/BeerById/BeerRecommendations.tsx index 57b43a1..1e3b3bb 100644 --- a/src/components/BeerById/BeerRecommendations.tsx +++ b/src/components/BeerById/BeerRecommendations.tsx @@ -9,7 +9,7 @@ const BeerRecommendations: FunctionComponent = ({ beerRecommendations, }) => { return ( -
+
{beerRecommendations.map((beerPost) => (
diff --git a/src/components/BeerById/CommentCardBody.tsx b/src/components/BeerById/CommentCardBody.tsx index 6cc4142..95becc6 100644 --- a/src/components/BeerById/CommentCardBody.tsx +++ b/src/components/BeerById/CommentCardBody.tsx @@ -1,23 +1,10 @@ -import UserContext from '@/contexts/userContext'; import useBeerPostComments from '@/hooks/useBeerPostComments'; -import useTimeDistance from '@/hooks/useTimeDistance'; import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult'; -import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema'; -import { zodResolver } from '@hookform/resolvers/zod'; -import format from 'date-fns/format'; -import Link from 'next/link'; -import { Dispatch, FC, SetStateAction, useContext, useEffect, useState } from 'react'; -import { Rating } from 'react-daisyui'; -import { SubmitHandler, useForm } from 'react-hook-form'; - -import { FaEllipsisH } from 'react-icons/fa'; +import { FC, useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { z } from 'zod'; -import FormError from '../ui/forms/FormError'; -import FormInfo from '../ui/forms/FormInfo'; -import FormLabel from '../ui/forms/FormLabel'; -import FormSegment from '../ui/forms/FormSegment'; -import FormTextArea from '../ui/forms/FormTextArea'; +import CommentContentBody from './CommentContentBody'; +import EditCommentBody from './EditCommentBody'; interface CommentCardProps { comment: z.infer; @@ -25,269 +12,17 @@ interface CommentCardProps { ref?: ReturnType['ref']; } -interface CommentCardDropdownProps extends CommentCardProps { - inEditMode: boolean; - setInEditMode: Dispatch>; -} - -const CommentCardDropdown: FC = ({ - comment, - setInEditMode, -}) => { - const { user } = useContext(UserContext); - - const isCommentOwner = user?.id === comment.postedBy.id; - - return ( -
- -
    -
  • - {isCommentOwner ? ( - <> - - - ) : ( - - )} -
  • -
-
- ); -}; - -const EditCommentBody: FC = ({ - comment, - setInEditMode, - ref, - mutate, -}) => { - const { register, handleSubmit, formState, setValue, watch } = useForm< - z.infer - >({ - defaultValues: { - content: comment.content, - rating: comment.rating, - }, - resolver: zodResolver(BeerCommentValidationSchema), - }); - - const { errors } = formState; - - const [isDeleting, setIsDeleting] = useState(false); - - useEffect(() => { - return () => { - setIsDeleting(false); - }; - }, []); - - const handleDelete = async () => { - setIsDeleting(true); - const response = await fetch(`/api/beer-comments/${comment.id}`, { - method: 'DELETE', - }); - - if (!response.ok) { - throw new Error('Failed to delete comment'); - } - - await mutate(); - }; - - const onSubmit: SubmitHandler> = async ( - data, - ) => { - const response = await fetch(`/api/beer-comments/${comment.id}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - content: data.content, - rating: data.rating, - }), - }); - - if (!response.ok) { - throw new Error('Failed to update comment'); - } - - await mutate(); - setInEditMode(false); - }; - return ( -
-
-
- - Edit your comment - {errors.content?.message} - - - - -
-
- - Change your rating - {errors.rating?.message} - - { - setValue('rating', value); - }} - > - {Array.from({ length: 5 }).map((val, index) => ( - - ))} - -
-
-
- -
- -
- -
- -
- -
-
-
-
-
-
- ); -}; - -const CommentContentBody: FC = ({ - comment, - ref, - mutate, - inEditMode, - setInEditMode, -}) => { - const { user } = useContext(UserContext); - const timeDistance = useTimeDistance(new Date(comment.createdAt)); - - return ( -
-
-
-

- - {comment.postedBy.username} - -

-

- posted{' '} - {' '} - ago -

-
- - {user && ( - - )} -
- -
- - {Array.from({ length: 5 }).map((val, index) => ( - - ))} - -

{comment.content}

-
-
- ); -}; - const CommentCardBody: FC = ({ comment, mutate, ref }) => { const [inEditMode, setInEditMode] = useState(false); return !inEditMode ? ( - + ) : ( ); }; diff --git a/src/components/BeerById/CommentCardDropdown.tsx b/src/components/BeerById/CommentCardDropdown.tsx new file mode 100644 index 0000000..69e103b --- /dev/null +++ b/src/components/BeerById/CommentCardDropdown.tsx @@ -0,0 +1,47 @@ +import UserContext from '@/contexts/userContext'; +import { Dispatch, SetStateAction, FC, useContext } from 'react'; +import { FaEllipsisH } from 'react-icons/fa'; +import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult'; +import { z } from 'zod'; + +interface CommentCardDropdownProps { + comment: z.infer; + setInEditMode: Dispatch>; +} + +const CommentCardDropdown: FC = ({ + comment, + setInEditMode, +}) => { + const { user } = useContext(UserContext); + const isCommentOwner = user?.id === comment.postedBy.id; + + return ( +
+ +
    +
  • + {isCommentOwner ? ( + + ) : ( + + )} +
  • +
+
+ ); +}; + +export default CommentCardDropdown; diff --git a/src/components/BeerById/CommentContentBody.tsx b/src/components/BeerById/CommentContentBody.tsx new file mode 100644 index 0000000..c9b3416 --- /dev/null +++ b/src/components/BeerById/CommentContentBody.tsx @@ -0,0 +1,67 @@ +import UserContext from '@/contexts/userContext'; +import useTimeDistance from '@/hooks/useTimeDistance'; +import { format } from 'date-fns'; +import { Dispatch, FC, SetStateAction, useContext } from 'react'; +import { Link, Rating } from 'react-daisyui'; +import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult'; +import { useInView } from 'react-intersection-observer'; +import { z } from 'zod'; +import CommentCardDropdown from './CommentCardDropdown'; + +interface CommentContentBodyProps { + comment: z.infer; + ref: ReturnType['ref'] | undefined; + setInEditMode: Dispatch>; +} + +const CommentContentBody: FC = ({ + comment, + ref, + setInEditMode, +}) => { + const { user } = useContext(UserContext); + const timeDistance = useTimeDistance(new Date(comment.createdAt)); + + return ( +
+
+
+

+ + {comment.postedBy.username} + +

+

+ posted{' '} + {' '} + ago +

+
+ + {user && } +
+ +
+ + {Array.from({ length: 5 }).map((val, index) => ( + + ))} + +

{comment.content}

+
+
+ ); +}; + +export default CommentContentBody; diff --git a/src/components/BeerById/EditCommentBody.tsx b/src/components/BeerById/EditCommentBody.tsx new file mode 100644 index 0000000..8ac8636 --- /dev/null +++ b/src/components/BeerById/EditCommentBody.tsx @@ -0,0 +1,158 @@ +import BeerCommentValidationSchema from '@/services/BeerComment/schema/CreateBeerCommentValidationSchema'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { FC, useState, useEffect, Dispatch, SetStateAction } from 'react'; +import { Rating } from 'react-daisyui'; +import { useForm, SubmitHandler } from 'react-hook-form'; +import { z } from 'zod'; +import useBeerPostComments from '@/hooks/useBeerPostComments'; +import BeerCommentQueryResult from '@/services/BeerComment/schema/BeerCommentQueryResult'; +import { useInView } from 'react-intersection-observer'; +import FormError from '../ui/forms/FormError'; +import FormInfo from '../ui/forms/FormInfo'; +import FormLabel from '../ui/forms/FormLabel'; +import FormSegment from '../ui/forms/FormSegment'; +import FormTextArea from '../ui/forms/FormTextArea'; + +interface CommentCardDropdownProps { + comment: z.infer; + setInEditMode: Dispatch>; + ref: ReturnType['ref'] | undefined; + mutate: ReturnType['mutate']; +} + +const EditCommentBody: FC = ({ + comment, + setInEditMode, + ref, + mutate, +}) => { + const { register, handleSubmit, formState, setValue, watch } = useForm< + z.infer + >({ + defaultValues: { + content: comment.content, + rating: comment.rating, + }, + resolver: zodResolver(BeerCommentValidationSchema), + }); + + const { errors } = formState; + + const [isDeleting, setIsDeleting] = useState(false); + + useEffect(() => { + return () => { + setIsDeleting(false); + }; + }, []); + + const handleDelete = async () => { + setIsDeleting(true); + const response = await fetch(`/api/beer-comments/${comment.id}`, { + method: 'DELETE', + }); + + if (!response.ok) { + throw new Error('Failed to delete comment'); + } + + await mutate(); + }; + + const onSubmit: SubmitHandler> = async ( + data, + ) => { + const response = await fetch(`/api/beer-comments/${comment.id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + content: data.content, + rating: data.rating, + }), + }); + + if (!response.ok) { + throw new Error('Failed to update comment'); + } + + await mutate(); + setInEditMode(false); + }; + return ( +
+
+
+ + Edit your comment + {errors.content?.message} + + + + +
+
+ + Change your rating + {errors.rating?.message} + + { + setValue('rating', value); + }} + > + {Array.from({ length: 5 }).map((val, index) => ( + + ))} + +
+
+ + + +
+
+
+
+
+ ); +}; + +export default EditCommentBody; diff --git a/src/components/ui/Navbar.tsx b/src/components/ui/Navbar.tsx index 0b7bcd3..400bd6f 100644 --- a/src/components/ui/Navbar.tsx +++ b/src/components/ui/Navbar.tsx @@ -86,28 +86,34 @@ const Navbar = () => { The Biergarten App
-
-
{isDesktopView ? : }
{' '} - {theme === 'light' ? ( - - ) : ( - - )} + +
+
+ {theme === 'light' ? ( + + ) : ( + + )} +
+
{isDesktopView ? : }
); }; diff --git a/src/components/ui/alerts/ErrorAlert.tsx b/src/components/ui/alerts/ErrorAlert.tsx index 47049d2..b19b922 100644 --- a/src/components/ui/alerts/ErrorAlert.tsx +++ b/src/components/ui/alerts/ErrorAlert.tsx @@ -8,8 +8,8 @@ interface ErrorAlertProps { const ErrorAlert: FC = ({ error, setError }) => { return ( -
-
+
+
{error}
diff --git a/src/components/ui/forms/FormLabel.tsx b/src/components/ui/forms/FormLabel.tsx index ea72095..fb13dad 100644 --- a/src/components/ui/forms/FormLabel.tsx +++ b/src/components/ui/forms/FormLabel.tsx @@ -11,7 +11,7 @@ interface FormLabelProps { */ const FormLabel: FunctionComponent = ({ htmlFor, children }) => (