From 6e2f85b75ab2c09ca3cf4d7a3c95fd99e0b747bf Mon Sep 17 00:00:00 2001 From: hanan o <77591083+heosman@users.noreply.github.com> Date: Wed, 3 Jul 2024 21:11:18 -0700 Subject: [PATCH] nsc-events-nextjs_9_491_update-buttons-in-edit-user-role-dialog (#494) * Update icon on Done button - Done button: removed edit icon on left and added checkmark icon on right - Moved edit icon to right side for consistency and ease * Update UserCard.tsx * Only renders Done button if role is changed * Changes "Edit" to "Cancel" when dialog is opened * Add Done button next to Cancel button Other updates: - Fixed the user role being updated before the Done button is clicked - Added "Selected Role" field to avoid confusion when updating roles - Centered confirmation message --- components/EditUserRoleDialog.tsx | 114 +++++------------------------- components/UserCard.tsx | 92 ++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 100 deletions(-) diff --git a/components/EditUserRoleDialog.tsx b/components/EditUserRoleDialog.tsx index 58addf53..411afca0 100644 --- a/components/EditUserRoleDialog.tsx +++ b/components/EditUserRoleDialog.tsx @@ -11,34 +11,19 @@ import RadioGroup from "@mui/material/RadioGroup"; 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'; - const options = ["admin", "creator", "user"]; -/** - * Props for the ConfirmationDialogRaw component. - */ + interface ConfirmationDialogRawProps { id: string; keepMounted: boolean; value: string; open: boolean; onClose: (value?: string, success?: boolean) => void; - setSnackbarOpen: (open: boolean) => void; - setSnackbarMessage: (message: string) => void; - setSnackbarSeverity: (severity: 'error' | 'warning' | 'info' | 'success') => void; } -/** - * Renders a confirmation dialog for editing user roles. - * - * @param props - The component props. - * @returns The rendered ConfirmationDialogRaw component. - */ -export function ConfirmationDialogRaw(props: ConfirmationDialogRawProps & { user: UserCardProps }) { - const { onClose, value: valueProp, open, user, ...other } = props; +export function ConfirmationDialogRaw(props: ConfirmationDialogRawProps) { + const { onClose, value: valueProp, open, ...other } = props; const [value, setValue] = useState(valueProp); const radioGroupRef = useRef(null); @@ -48,60 +33,24 @@ export function ConfirmationDialogRaw(props: ConfirmationDialogRawProps & { user } }, [valueProp, open]); -/** - * Handles the entering event of the dialog. - */ const handleEntering = () => { if (radioGroupRef.current != null) { radioGroupRef.current.focus(); } }; - /** - * Handles the cancel action. - */ const handleCancel = () => { onClose(); }; - /** - * Handles the click event when the user confirms the role update. - * @returns {void} - */ - const handleOk = async () => { - const token = localStorage.getItem('token'); - try { - const apiUrl = process.env.NSC_EVENTS_PUBLIC_API_URL || `http://localhost:3000/api`; - const response = await fetch(`${apiUrl}/users/update/${user.id}`, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${token}` - }, - body: JSON.stringify({ role: value }) - }); - if (response.ok) { - onClose(value, true); // Indicate success - 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); // Indicate success + } else { + onClose(); } }; - /** - * Handles the change event of the input element. - * @param event - The change event object. - */ + const handleChange = (event: React.ChangeEvent) => { setValue((event.target as HTMLInputElement).value); }; @@ -143,39 +92,23 @@ export function ConfirmationDialogRaw(props: ConfirmationDialogRawProps & { user ); } -/** - * Renders a dialog for editing the user role. - * - * @component - * @param {Object} props - The component props. - * @param {UserCardProps} props.user - The user object containing user information. - * @param {Function} props.onClose - The function to be called when the dialog is closed. - * @returns {JSX.Element} The rendered EditUserRoleDialog component. - */ - export default function EditUserRoleDialog({ user, onClose, }: { - user: UserCardProps; - onClose: (success: boolean) => void; + user: { id: string; role: string }; + 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, success: boolean = false) => { + const handleClose = (newValue?: string, success?: boolean) => { setOpen(false); - if (newValue) { - setValue(newValue); - } - onClose(success); + onClose(newValue, success); }; return ( @@ -199,23 +132,14 @@ export default function EditUserRoleDialog({ > - - setSnackbarOpen(false)}> - setSnackbarOpen(false)} severity={snackbarSeverity} sx={{ width: '100%' }}> - {snackbarMessage} - - ); } diff --git a/components/UserCard.tsx b/components/UserCard.tsx index 0460aced..b4d903de 100644 --- a/components/UserCard.tsx +++ b/components/UserCard.tsx @@ -1,7 +1,10 @@ import React, { useState } from "react"; import { Box, Button, Container, Stack, Typography } from "@mui/material"; import EditIcon from "@mui/icons-material/Edit"; +import CheckIcon from '@mui/icons-material/Check'; import EditUserRoleDialog from "./EditUserRoleDialog"; +import Snackbar from '@mui/material/Snackbar'; +import Alert, { AlertColor } from '@mui/material/Alert'; export interface UserCardProps { id: string; @@ -14,22 +17,69 @@ export interface UserCardProps { function UserCard({ user }: { user: UserCardProps }) { const [openDialog, setOpenDialog] = useState(false); 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 handleEditClick = () => { + const handleEditClick = async () => { if (editCompleted) { window.location.reload(); + } else if (openDialog) { + setOpenDialog(false); } else { setOpenDialog(true); } + + if (editCompleted) { + const token = localStorage.getItem('token'); + try { + const apiUrl = process.env.NSC_EVENTS_PUBLIC_API_URL || `http://localhost:3000/api`; + const response = await fetch(`${apiUrl}/users/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 = (success: boolean) => { + const handleCloseDialog = (newRole?: string, success?: boolean) => { setOpenDialog(false); - if (success) { + if (success && newRole) { + setNewRole(newRole); setEditCompleted(true); } }; + const handleCancel = () => { + if (editCompleted) { + setOpenDialog(false); + setEditCompleted(false); + + } else { + setOpenDialog(false); + } + }; + return ( 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} + + ); }