From 9590ac2ee0c5daf9a9dd3a9b95b9a3c44c110f10 Mon Sep 17 00:00:00 2001 From: intisarosman1 <77607212+intisarosman1@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:24:25 -0700 Subject: [PATCH] belindas-closet-nextjs_10_517_edit-user-role-cancel-button (#524) * belindas-closet-nextjs_10_517_edit-user-role-cancel-button Resolves #517 This PR implements a Cancel button for when changes haven't been made to the user role. The Done button is available along with the Cancel button when changes are made, so the user can choose to go on and have the page reloaded with the new changes or not. * Added styling and responsive UI --- components/EditUserRoleDialog.tsx | 81 +++-------------- components/UserCard.tsx | 142 +++++++++++++++++++++++------- 2 files changed, 118 insertions(+), 105 deletions(-) diff --git a/components/EditUserRoleDialog.tsx b/components/EditUserRoleDialog.tsx index c18ff6b1..6582018b 100644 --- a/components/EditUserRoleDialog.tsx +++ b/components/EditUserRoleDialog.tsx @@ -12,8 +12,6 @@ import Radio from "@mui/material/Radio"; import FormControlLabel from "@mui/material/FormControlLabel"; import React, { useEffect, useRef, useState } from "react"; import { UserCardProps } from "./UserCard"; -import Snackbar from "@mui/material/Snackbar"; -import Alert, { AlertColor } from "@mui/material/Alert"; import { useMediaQuery, useTheme } from "@mui/material"; // WARNING: You won't be able to connect to local backend unless you remove the env variable below. const URL = @@ -29,12 +27,7 @@ interface ConfirmationDialogRawProps { keepMounted: boolean; value: string; open: boolean; - onClose: (value?: string) => void; - setSnackbarOpen: (open: boolean) => void; - setSnackbarMessage: (message: string) => void; - setSnackbarSeverity: ( - severity: "error" | "warning" | "info" | "success" - ) => void; + onClose: (value?: string, success?: boolean) => void; } /** @@ -74,39 +67,11 @@ export function ConfirmationDialogRaw( onClose(); }; - /** - * Handles the click event when the user confirms the role update. - * @returns {void} - */ - const handleOk = async () => { - const token = localStorage.getItem("token"); - console.log("Token:", token); - // TODO: Update user role in the database - try { - const response = await fetch(`${URL}/user/update/${user.id}`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - body: JSON.stringify({ role: value }), - }); - if (response.ok) { - onClose(value); - props.setSnackbarSeverity("success"); - props.setSnackbarMessage("User role updated successfully!"); - props.setSnackbarOpen(true); - } else { - console.error("Failed to update user role:", response.statusText); - props.setSnackbarSeverity("error"); - props.setSnackbarMessage("Failed to update user role"); - props.setSnackbarOpen(true); - } - } catch (error) { - console.error("Error updating user role:", error); - props.setSnackbarSeverity("error"); - props.setSnackbarMessage("Error updating user role"); - props.setSnackbarOpen(true); + const handleOk = () => { + if (value !== valueProp) { + onClose(value, true); + } else { + onClose(); } }; @@ -175,30 +140,21 @@ export function ConfirmationDialogRaw( */ export default function EditUserRoleDialog({ user, - onRoleChange, + onClose, }: { user: UserCardProps; - onClose: () => void; - onRoleChange: (newRole: string) => void; + onClose: (newRole?: string, success?: boolean) => void; }): JSX.Element { const [open, setOpen] = useState(false); const [value, setValue] = useState(user.role); - const [snackbarOpen, setSnackbarOpen] = useState(false); - const [snackbarMessage, setSnackbarMessage] = useState(""); - const [snackbarSeverity, setSnackbarSeverity] = - useState("success"); const handleClickListItem = () => { setOpen(true); }; - const handleClose = (newValue?: string) => { + const handleClose =(newValue?: string, success?: boolean) => { setOpen(false); - - if (newValue) { - setValue(newValue); - onRoleChange(newValue); - } + onClose(newValue, success); }; const theme = useTheme(); @@ -240,25 +196,8 @@ export default function EditUserRoleDialog({ onClose={handleClose} value={value} user={user} - setSnackbarOpen={setSnackbarOpen} - setSnackbarMessage={setSnackbarMessage} - setSnackbarSeverity={setSnackbarSeverity} /> - setSnackbarOpen(false)} - anchorOrigin={{ vertical: "bottom", horizontal: "center" }} - > - setSnackbarOpen(false)} - severity={snackbarSeverity} - sx={{ width: "100%" }} - > - {snackbarMessage} - - ); } diff --git a/components/UserCard.tsx b/components/UserCard.tsx index 4eea3414..dd017eee 100644 --- a/components/UserCard.tsx +++ b/components/UserCard.tsx @@ -1,7 +1,9 @@ import React, { useState } from "react"; -import { Box, Button, Container, Stack, Typography } from "@mui/material"; +import { Box, Button, Container, Snackbar, Stack, Typography, useMediaQuery, useTheme } from "@mui/material"; import EditIcon from "@mui/icons-material/Edit"; +import CheckIcon from '@mui/icons-material/Check'; import EditUserRoleDialog from "./EditUserRoleDialog"; +import Alert, { AlertColor } from '@mui/material/Alert'; export interface UserCardProps { id: string; @@ -13,30 +15,72 @@ export interface UserCardProps { function UserCard({ user }: { user: UserCardProps }) { const [openDialog, setOpenDialog] = useState(false); - const [menuOpen, setMenuOpen] = useState(false); - const [currentRole, setCurrentRole] = useState(user.role); + const [editCompleted, setEditCompleted] = useState(false); + const [snackbarOpen, setSnackbarOpen] = useState(false); + const [snackbarMessage, setSnackbarMessage] = useState(''); + const [snackbarSeverity, setSnackbarSeverity] = useState('success'); + const [newRole, setNewRole] = useState(user.role); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const handleEditClick = () => { - if (menuOpen) { - setMenuOpen(false); + const handleEditClick = async () => { + if (editCompleted) { + window.location.reload(); + } else if (openDialog) { setOpenDialog(false); - if (currentRole !== user.role) { - window.location.reload(); - } } else { setOpenDialog(true); - setMenuOpen(true); } - }; - const handleRoleChange = (newRole: string) => { - setCurrentRole(newRole); + if (editCompleted) { + const token = localStorage.getItem('token'); + try { + const apiUrl = process.env.BELINDAS_CLOSET_PUBLIC_API_URL || `http://localhost:3000/api`; + const response = await fetch(`${apiUrl}/user/update/${user.id}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ role: newRole }) + }); + if (response.ok) { + setSnackbarSeverity('success'); + setSnackbarMessage('User role updated successfully!'); + setSnackbarOpen(true); + } else { + console.error('Failed to update user role:', response.statusText); + setSnackbarSeverity('error'); + setSnackbarMessage('Failed to update user role'); + setSnackbarOpen(true); + } + } catch (error) { + console.error('Error updating user role:', error); + setSnackbarSeverity('error'); + setSnackbarMessage('Error updating user role'); + setSnackbarOpen(true); + } + } }; - const handleCloseDialog = () => { + const handleCloseDialog = (newRole?: string, success?: boolean) => { setOpenDialog(false); - setMenuOpen(false); + if (success && newRole) { + setNewRole(newRole); + setEditCompleted(true); + } + }; + + const handleCancel = () => { + if (editCompleted) { + setOpenDialog(false); + setEditCompleted(false); + + } else { + setOpenDialog(false); + } }; + return ( - - User ID: {user.id} - - - Full Name: {user.firstName} {user.lastName} - - - Email: {user.email} - - - Current Role: {user.role} - + + + User ID: {user.id} + + + Full Name: {user.firstName} {user.lastName} + + + Email: {user.email} + + + Current Role: {user.role} + + {editCompleted && ( + + Selected Role: {newRole} + + )} + {openDialog && ( - + )} + {!openDialog && ( + )} + {openDialog && ( + + )} + {editCompleted && ( + + )} + setSnackbarOpen(false)} anchorOrigin={{ vertical: "bottom", horizontal: "center" }}> + setSnackbarOpen(false)} severity={snackbarSeverity} sx={{ width: '100%' }}> + {snackbarMessage} + + ); }