mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
feat: add react-hot-toast for toast notifs
This commit is contained in:
@@ -4,6 +4,7 @@ import { FC, useState } from 'react';
|
||||
import { useInView } from 'react-intersection-observer';
|
||||
import { z } from 'zod';
|
||||
import CreateCommentValidationSchema from '@/services/types/CommentSchema/CreateCommentValidationSchema';
|
||||
|
||||
import CommentContentBody from './CommentContentBody';
|
||||
import EditCommentBody from './EditCommentBody';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import { Dispatch, SetStateAction, FC, useContext } from 'react';
|
||||
import { FaEllipsisH } from 'react-icons/fa';
|
||||
import CommentQueryResult from '@/services/types/CommentSchema/CommentQueryResult';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import useTimeDistance from '@/hooks/utilities/useTimeDistance';
|
||||
import { format } from 'date-fns';
|
||||
import { Dispatch, FC, SetStateAction, useContext } from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { FC, useState, Dispatch, SetStateAction } from 'react';
|
||||
import { FC, useState, Dispatch, SetStateAction, useContext } from 'react';
|
||||
import { Rating } from 'react-daisyui';
|
||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
@@ -7,6 +7,7 @@ import useBeerPostComments from '@/hooks/data-fetching/beer-comments/useBeerPost
|
||||
import CommentQueryResult from '@/services/types/CommentSchema/CommentQueryResult';
|
||||
import CreateCommentValidationSchema from '@/services/types/CommentSchema/CreateCommentValidationSchema';
|
||||
import useBreweryPostComments from '@/hooks/data-fetching/brewery-comments/useBreweryPostComments';
|
||||
import ToastContext from '@/contexts/ToastContext';
|
||||
import FormError from '../ui/forms/FormError';
|
||||
import FormInfo from '../ui/forms/FormInfo';
|
||||
import FormLabel from '../ui/forms/FormLabel';
|
||||
@@ -42,6 +43,7 @@ const EditCommentBody: FC<EditCommentBodyProps> = ({
|
||||
resolver: zodResolver(CreateCommentValidationSchema),
|
||||
});
|
||||
|
||||
const { toast } = useContext(ToastContext);
|
||||
const { errors } = formState;
|
||||
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
@@ -58,6 +60,7 @@ const EditCommentBody: FC<EditCommentBodyProps> = ({
|
||||
setInEditMode(true);
|
||||
await handleEditRequest(comment.id, data);
|
||||
await mutate();
|
||||
toast.success('Submitted edits');
|
||||
setInEditMode(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import Link from 'next/link';
|
||||
import format from 'date-fns/format';
|
||||
import { FC, useContext } from 'react';
|
||||
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import { FaRegEdit } from 'react-icons/fa';
|
||||
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||
import { z } from 'zod';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
|
||||
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { FC, useContext } from 'react';
|
||||
import Image from 'next/image';
|
||||
import beerPostQueryResult from '@/services/BeerPost/schema/BeerPostQueryResult';
|
||||
import { z } from 'zod';
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import useGetBeerPostLikeCount from '@/hooks/data-fetching/beer-likes/useBeerPostLikeCount';
|
||||
import BeerPostLikeButton from '../BeerById/BeerPostLikeButton';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { FC, MutableRefObject, useContext, useRef } from 'react';
|
||||
import { useInView } from 'react-intersection-observer';
|
||||
import { z } from 'zod';
|
||||
import { FaPlus } from 'react-icons/fa';
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import BeerRecommendationLoadingComponent from '../BeerById/BeerRecommendationLoadingComponent';
|
||||
|
||||
interface BreweryCommentsSectionProps {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||
import { FC, MutableRefObject, useContext, useRef } from 'react';
|
||||
import { z } from 'zod';
|
||||
@@ -9,6 +9,7 @@ import APIResponseValidationSchema from '@/validation/APIResponseValidationSchem
|
||||
import CommentQueryResult from '@/services/types/CommentSchema/CommentQueryResult';
|
||||
|
||||
import useBreweryPostComments from '@/hooks/data-fetching/brewery-comments/useBreweryPostComments';
|
||||
import ToastContext from '@/contexts/ToastContext';
|
||||
import LoadingComponent from '../BeerById/LoadingComponent';
|
||||
import CommentsComponent from '../ui/CommentsComponent';
|
||||
import CommentForm from '../ui/CommentForm';
|
||||
@@ -63,6 +64,7 @@ const BreweryCommentForm: FC<BreweryCommentFormProps> = ({ breweryPost, mutate }
|
||||
resolver: zodResolver(CreateCommentValidationSchema),
|
||||
});
|
||||
|
||||
const { toast } = useContext(ToastContext);
|
||||
const onSubmit: SubmitHandler<z.infer<typeof CreateCommentValidationSchema>> = async (
|
||||
data,
|
||||
) => {
|
||||
@@ -72,6 +74,7 @@ const BreweryCommentForm: FC<BreweryCommentFormProps> = ({ breweryPost, mutate }
|
||||
breweryPostId: breweryPost.id,
|
||||
});
|
||||
await mutate();
|
||||
toast.loading('Created new comment.');
|
||||
reset();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import useGetBreweryPostLikeCount from '@/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount';
|
||||
import useTimeDistance from '@/hooks/utilities/useTimeDistance';
|
||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import useGetBreweryPostLikeCount from '@/hooks/data-fetching/brewery-likes/useGetBreweryPostLikeCount';
|
||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||
import { FC, useContext } from 'react';
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useRouter } from 'next/router';
|
||||
import { useContext, useState } from 'react';
|
||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import ToastContext from '@/contexts/ToastContext';
|
||||
import ErrorAlert from '../ui/alerts/ErrorAlert';
|
||||
import FormError from '../ui/forms/FormError';
|
||||
import FormInfo from '../ui/forms/FormInfo';
|
||||
@@ -30,12 +31,15 @@ const LoginForm = () => {
|
||||
const [responseError, setResponseError] = useState<string>('');
|
||||
|
||||
const { mutate } = useContext(UserContext);
|
||||
const { toast } = useContext(ToastContext);
|
||||
|
||||
const onSubmit: SubmitHandler<LoginT> = async (data) => {
|
||||
try {
|
||||
const id = toast.loading('Logging in.');
|
||||
await sendLoginUserRequest(data);
|
||||
await mutate!();
|
||||
await router.push(`/user/current`);
|
||||
toast.remove(id);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
setResponseError(error.message);
|
||||
|
||||
50
src/components/ui/CustomToast.tsx
Normal file
50
src/components/ui/CustomToast.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import ToastContext from '@/contexts/ToastContext';
|
||||
import { FC, ReactNode } from 'react';
|
||||
import toast, { Toast, Toaster, resolveValue } from 'react-hot-toast';
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
|
||||
const toastToClassName = (toastType: Toast['type']) => {
|
||||
let className: 'alert-success' | 'alert-error' | 'alert-info';
|
||||
|
||||
switch (toastType) {
|
||||
case 'success':
|
||||
className = 'alert-success';
|
||||
break;
|
||||
case 'error':
|
||||
className = 'alert-error';
|
||||
break;
|
||||
default:
|
||||
className = 'alert-info';
|
||||
}
|
||||
|
||||
return className;
|
||||
};
|
||||
|
||||
const CustomToast: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
return (
|
||||
<ToastContext.Provider value={{ toast }}>
|
||||
<Toaster>
|
||||
{(t) => {
|
||||
const alertType = toastToClassName(t.type);
|
||||
return (
|
||||
<div className="flex w-full items-center justify-center">
|
||||
<div
|
||||
className={`alert ${alertType} w-11/12 flex-row items-center py-[0.5rem] shadow-lg animate-in fade-in duration-200 lg:w-6/12`}
|
||||
>
|
||||
<div>{resolveValue(t.message, t)}</div>
|
||||
<button
|
||||
className="btn-ghost btn-circle btn"
|
||||
onClick={() => toast.dismiss(t.id)}
|
||||
>
|
||||
<FaTimes />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Toaster>
|
||||
{children}
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
};
|
||||
export default CustomToast;
|
||||
8
src/contexts/ToastContext.ts
Normal file
8
src/contexts/ToastContext.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { createContext } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
const ToastContext = createContext<{
|
||||
toast: typeof toast;
|
||||
}>({ toast });
|
||||
|
||||
export default ToastContext;
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useContext } from 'react';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import { useContext } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import { useContext } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useState, useEffect, useContext } from 'react';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
|
||||
import '@/styles/globals.css';
|
||||
import type { AppProps } from 'next/app';
|
||||
@@ -11,6 +11,7 @@ import { Space_Grotesk } from 'next/font/google';
|
||||
import Head from 'next/head';
|
||||
import Layout from '@/components/ui/Layout';
|
||||
import useUser from '@/hooks/auth/useUser';
|
||||
import CustomToast from '@/components/ui/CustomToast';
|
||||
|
||||
const spaceGrotesk = Space_Grotesk({
|
||||
subsets: ['latin'],
|
||||
@@ -39,9 +40,12 @@ export default function App({ Component, pageProps }: AppProps) {
|
||||
</Head>
|
||||
<UserContext.Provider value={{ user, isLoading, error, mutate }}>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
<CustomToast>
|
||||
<Component {...pageProps} />
|
||||
</CustomToast>
|
||||
</Layout>
|
||||
</UserContext.Provider>
|
||||
|
||||
<Analytics />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import BreweryCard from '@/components/BreweryIndex/BreweryCard';
|
||||
import LoadingCard from '@/components/ui/LoadingCard';
|
||||
import Spinner from '@/components/ui/Spinner';
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
import useBreweryPosts from '@/hooks/data-fetching/brewery-posts/useBreweryPosts';
|
||||
import BreweryPostQueryResult from '@/services/BreweryPost/types/BreweryPostQueryResult';
|
||||
import { NextPage } from 'next';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Spinner from '@/components/ui/Spinner';
|
||||
import withPageAuthRequired from '@/util/withPageAuthRequired';
|
||||
import UserContext from '@/contexts/userContext';
|
||||
import UserContext from '@/contexts/UserContext';
|
||||
|
||||
import { GetServerSideProps, NextPage } from 'next';
|
||||
import { useContext } from 'react';
|
||||
|
||||
Reference in New Issue
Block a user