From 46f925663e595fa8dd87f7aa15a0061abcfae3d7 Mon Sep 17 00:00:00 2001
From: Michael Hunteman <michael@huntm.net>
Date: Mon, 2 Sep 2024 16:27:12 -0700
Subject: Add ui error messages

---
 client/src/components/AdminLogin.tsx | 41 +++++++++++++++++++++++++++++++-----
 client/src/components/GuestLogin.tsx | 41 +++++++++++++++++++++++++++++++-----
 client/src/components/RsvpForm.tsx   | 27 +++++++++++++-----------
 3 files changed, 87 insertions(+), 22 deletions(-)

(limited to 'client/src/components')

diff --git a/client/src/components/AdminLogin.tsx b/client/src/components/AdminLogin.tsx
index 4f53566..4271d60 100644
--- a/client/src/components/AdminLogin.tsx
+++ b/client/src/components/AdminLogin.tsx
@@ -1,16 +1,38 @@
-import React from 'react';
+import React, { useState } from 'react';
 import { useNavigate } from 'react-router-dom';
 import { useDispatch } from 'react-redux';
-import { Button, Paper, TextField, Typography } from '@mui/material';
+import {
+  Alert,
+  Button,
+  Paper,
+  Snackbar,
+  TextField,
+  Typography,
+} from '@mui/material';
 import { useForm } from 'react-hook-form';
 import { setAdmin } from '../slices/auth/adminSlice';
 import { useLoginAdminMutation } from '../slices/api/adminSlice';
-import type { Credentials } from '../models';
+import type { Credentials, StatusProps } from '../models';
+import { isFetchBaseQueryError } from '../error';
+import type { Data } from '../error';
+
+const Status = ({ error, setOpen }: StatusProps) => {
+  return isFetchBaseQueryError(error) ? (
+    <Alert severity="error" onClose={() => setOpen(false)}>
+      {(error.data as Data).message}
+    </Alert>
+  ) : (
+    <Alert severity="error" onClose={() => setOpen(false)}>
+      Admin login failed
+    </Alert>
+  );
+};
 
 function GuestLogin() {
   const dispatch = useDispatch();
   const navigate = useNavigate();
-  const [login] = useLoginAdminMutation();
+  const [login, { isLoading, error }] = useLoginAdminMutation();
+  const [open, setOpen] = useState<boolean>(false);
 
   const {
     register,
@@ -28,7 +50,7 @@ function GuestLogin() {
       dispatch(setAdmin(await login(data).unwrap()));
       navigate('/dashboard');
     } catch (e) {
-      console.log(e);
+      setOpen(true);
     }
   };
 
@@ -83,6 +105,15 @@ function GuestLogin() {
           Log in
         </Button>
       </Paper>
+      <Snackbar
+        open={!isLoading && open}
+        onClose={() => setOpen(false)}
+        autoHideDuration={5000}
+      >
+        <div>
+          <Status {...({ error, setOpen } as StatusProps)} />
+        </div>
+      </Snackbar>
     </form>
   );
 }
diff --git a/client/src/components/GuestLogin.tsx b/client/src/components/GuestLogin.tsx
index f42c1d6..acf229f 100644
--- a/client/src/components/GuestLogin.tsx
+++ b/client/src/components/GuestLogin.tsx
@@ -1,16 +1,38 @@
-import React from 'react';
+import React, { useState } from 'react';
 import { useNavigate } from 'react-router-dom';
 import { useDispatch } from 'react-redux';
-import { Button, Paper, TextField, Typography } from '@mui/material';
+import {
+  Alert,
+  Button,
+  Paper,
+  Snackbar,
+  TextField,
+  Typography,
+} from '@mui/material';
 import { useForm } from 'react-hook-form';
 import { setGuest } from '../slices/auth/guestSlice';
 import { useLoginGuestMutation } from '../slices/api/guestSlice';
-import type { Name } from '../models';
+import type { Name, StatusProps } from '../models';
+import { isFetchBaseQueryError } from '../error';
+import type { Data } from '../error';
+
+const Status = ({ error, setOpen }: StatusProps) => {
+  return isFetchBaseQueryError(error) ? (
+    <Alert severity="error" onClose={() => setOpen(false)}>
+      {(error.data as Data).message}
+    </Alert>
+  ) : (
+    <Alert severity="error" onClose={() => setOpen(false)}>
+      Guest login failed
+    </Alert>
+  );
+};
 
 function GuestLogin() {
   const dispatch = useDispatch();
   const navigate = useNavigate();
-  const [login] = useLoginGuestMutation();
+  const [login, { isLoading, error }] = useLoginGuestMutation();
+  const [open, setOpen] = useState<boolean>(false);
 
   const {
     register,
@@ -28,7 +50,7 @@ function GuestLogin() {
       dispatch(setGuest(await login(data).unwrap()));
       navigate('/rsvp');
     } catch (e) {
-      console.log(e);
+      setOpen(true);
     }
   };
 
@@ -83,6 +105,15 @@ function GuestLogin() {
           Log in
         </Button>
       </Paper>
+      <Snackbar
+        open={!isLoading && open}
+        onClose={() => setOpen(false)}
+        autoHideDuration={5000}
+      >
+        <div>
+          <Status {...({ error, setOpen } as StatusProps)} />
+        </div>
+      </Snackbar>
     </form>
   );
 }
diff --git a/client/src/components/RsvpForm.tsx b/client/src/components/RsvpForm.tsx
index 33ca108..7b2892f 100644
--- a/client/src/components/RsvpForm.tsx
+++ b/client/src/components/RsvpForm.tsx
@@ -17,18 +17,21 @@ import {
 import MailIcon from '@mui/icons-material/Mail';
 import { useForm, Controller, useFieldArray } from 'react-hook-form';
 import { useUpdateGuestMutation } from '../slices/api/guestSlice';
-import type { Guest } from '../models';
+import type { Guest, StatusProps } from '../models';
+import { isFetchBaseQueryError } from '../error';
+import type { Data } from '../error';
 
-interface StatusProps {
-  isError: boolean;
-  setOpen: (open: boolean) => void;
-}
-
-const Status = ({ isError, setOpen }: StatusProps) => {
+const Status = ({ isError, error, setOpen }: StatusProps) => {
   return isError ? (
-    <Alert severity="error" onClose={() => setOpen(false)}>
-      RSVP failed
-    </Alert>
+    isFetchBaseQueryError(error) ? (
+      <Alert severity="error" onClose={() => setOpen(false)}>
+        {(error.data as Data).message}
+      </Alert>
+    ) : (
+      <Alert severity="error" onClose={() => setOpen(false)}>
+        RSVP failed
+      </Alert>
+    )
   ) : (
     <Alert severity="success" onClose={() => setOpen(false)}>
       RSVP updated
@@ -37,7 +40,7 @@ const Status = ({ isError, setOpen }: StatusProps) => {
 };
 
 function RsvpForm() {
-  const [updateGuest, { isLoading, isSuccess, isError }] =
+  const [updateGuest, { isLoading, isSuccess, isError, error }] =
     useUpdateGuestMutation();
   const guest: Guest = useOutletContext();
   const previousPartySize = useRef((guest.partySize ?? 1) - 1);
@@ -278,7 +281,7 @@ function RsvpForm() {
             autoHideDuration={5000}
           >
             <div>
-              <Status isError={isError} setOpen={setOpen} />
+              <Status {...({ isError, error, setOpen } as StatusProps)} />
             </div>
           </Snackbar>
         </Grid>
-- 
cgit v1.2.3