From 543dbec030d6e8af2b86015c9e2b3c17ea81ea3a Mon Sep 17 00:00:00 2001 From: Lucy <67001048+hhuolu@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:21:59 +1000 Subject: [PATCH] feat(client): Styled Dialog Component (#852) * feat(client): added dialog for when user wants to log out * feat(client): creating component for dialogs * style(client): removing unused imports --- client/src/components/StyledDialog.tsx | 93 +++++++++++++++++++ client/src/components/controls/History.tsx | 49 +++------- client/src/components/sidebar/UserAccount.tsx | 74 +++++++++------ .../timetableTabs/TimetableTabContextMenu.tsx | 39 +++----- package-lock.json | 6 ++ 5 files changed, 170 insertions(+), 91 deletions(-) create mode 100644 client/src/components/StyledDialog.tsx create mode 100644 package-lock.json diff --git a/client/src/components/StyledDialog.tsx b/client/src/components/StyledDialog.tsx new file mode 100644 index 000000000..0825f5394 --- /dev/null +++ b/client/src/components/StyledDialog.tsx @@ -0,0 +1,93 @@ +import React from 'react'; +import { Dialog, DialogTitle, DialogContent, DialogActions, Button, IconButton } from '@mui/material'; +import { Close as CloseIcon } from '@mui/icons-material'; +import { styled } from '@mui/system'; + +const ContentContainer = styled('div')` + display: flex; + flex-direction: column; + justify-content: space-between; + height: 100%; + width: 100%; + padding-top: 10px; +`; + +const StyledDialogTitleFont = styled('div')` + font-size: 18px; + font-weight: 500; +`; + +const StyledDialogContent = styled(DialogContent)` + padding-bottom: 20px; +`; + +const StyledDialogButtons = styled(DialogActions)` + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: flex-end; + gap: 12px; + padding-bottom: 20px; + padding-right: 24px; +`; + +export const StyledDialogTitle = styled(DialogTitle)` + display: flex; + flex-direction: row; + padding: 8px 12px 8px 24px; + justify-content: space-between; + align-items: center; +`; + +const CustomCloseIconButton = styled(IconButton)` + width: 40px; + height: 40px; + border-radius: 8px; +`; + +// Props definition +interface StyledDialogProps { + open: boolean; + onClose: () => void; + onConfirm: () => void; + title: string; + content: string; + confirmButtonText: string; + cancelButtonText?: string; + disableConfirm?: boolean; + confirmButtonId?: string; +} + +const StyledDialog: React.FC = ({ + open, + onClose, + onConfirm, + title, + content, + confirmButtonText, + cancelButtonText = 'Cancel', + disableConfirm = false, + confirmButtonId, +}) => ( + + + + {title} + + + + + {content} + + + + + + +); + +export default StyledDialog; diff --git a/client/src/components/controls/History.tsx b/client/src/components/controls/History.tsx index 5063fceab..670aa1478 100644 --- a/client/src/components/controls/History.tsx +++ b/client/src/components/controls/History.tsx @@ -21,6 +21,7 @@ import { extractHistoryInfo, TimetableActions, } from '../../utils/timetableHelpers'; +import StyledDialog from '../StyledDialog'; // Two actions are created when the page first loads // One, when selectedClasses is initialised, and two, when createdEvents is initialised @@ -290,40 +291,20 @@ const History: React.FC = () => { return ( <> {/* Clear timetable(s) Dialog */} - setClearOpen(false)} open={clearOpen}> - - - Confirm Clear - { - setClearOpen(false); - }} - /> - - Are you sure you want to clear all timetables? - - - - - - + setClearOpen(false)} + onConfirm={() => { + clearAll(); + setClearOpen(false); + }} + title="Confirm Clear" + content="Are you sure you want to clear all timetables?" + confirmButtonText="Clear" + cancelButtonText="Cancel" + disableConfirm={disableReset.all} + confirmButtonId="confirm-delete-button" + /> setClearOpen(true)} size="large"> diff --git a/client/src/components/sidebar/UserAccount.tsx b/client/src/components/sidebar/UserAccount.tsx index 15dba3d45..0584e1230 100644 --- a/client/src/components/sidebar/UserAccount.tsx +++ b/client/src/components/sidebar/UserAccount.tsx @@ -1,9 +1,9 @@ +import React, { useEffect, useState } from 'react'; import { AccountCircle, LoginRounded, LogoutRounded } from '@mui/icons-material'; import { Button, IconButton, Tooltip } from '@mui/material'; import { styled } from '@mui/system'; -import React, { useEffect, useState } from 'react'; - import { API_URL } from '../../api/config'; +import StyledDialog from '../StyledDialog'; interface UserAccountProps { collapsed: boolean; @@ -42,13 +42,15 @@ const StyledAccountIcon = styled(AccountCircle)` height: 28px; `; -interface User { +interface User { zid: string; -}; +} const UserAccount: React.FC = ({ collapsed }) => { const [login, setLogin] = useState(false); - const [windowLocation, setWindowLocation] = useState(""); - const [user, setUser] = useState({zid: ""}); + const [windowLocation, setWindowLocation] = useState(''); + const [user, setUser] = useState({ zid: '' }); + const [logoutDialog, setLogoutDialog] = useState(false); + useEffect(() => { async function runAsync() { try { @@ -59,9 +61,9 @@ const UserAccount: React.FC = ({ collapsed }) => { // const userResponse = await response.text(); if (userResponse !== '') { setLogin(true); - setUser({zid: JSON.parse(userResponse)}); + setUser({ zid: JSON.parse(userResponse) }); } else { - setUser({zid: ""}); + setUser({ zid: '' }); setLogin(false); } } catch (error) { @@ -81,7 +83,6 @@ const UserAccount: React.FC = ({ collapsed }) => { console.log(error); } // window.location.replace(`${API_URL.server}/auth/login`); - }; const logoutCall = async () => { try { @@ -92,13 +93,13 @@ const UserAccount: React.FC = ({ collapsed }) => { console.log(error); } window.location.replace(windowLocation); - setUser({zid: ""}); + setUser({ zid: '' }); }; // https://stackoverflow.com/a/32108184/1098564 // const isEmpty = (obj: Object) => { // return Object.keys(obj).length === 0 && obj.constructor === Object; // }; - + if (!login) { return collapsed ? ( @@ -112,29 +113,42 @@ const UserAccount: React.FC = ({ collapsed }) => { } return ( - - {collapsed ? ( - - - - - - ) : ( - <> - - - {/* TODO: handle user's name */} -

{user.zid}

-
+ <> + setLogoutDialog(false)} + onConfirm={() => { + logoutCall(); + setLogoutDialog(false); + }} + title='Confirm Log out' + content='Are you sure you want to log out?' + confirmButtonText='Log out' + /> + + {collapsed ? ( - {/* TODO: error handling for when logging out */} - + setLogoutDialog(true)}> - - )} - + ) : ( + <> + + + {/* TODO: handle user's name */} +

{user.zid}

+
+ + {/* TODO: error handling for when logging out */} + + + + + + )} +
+ ); }; diff --git a/client/src/components/timetableTabs/TimetableTabContextMenu.tsx b/client/src/components/timetableTabs/TimetableTabContextMenu.tsx index 6958872e6..14bfd3e1a 100644 --- a/client/src/components/timetableTabs/TimetableTabContextMenu.tsx +++ b/client/src/components/timetableTabs/TimetableTabContextMenu.tsx @@ -19,11 +19,8 @@ import { CourseContext } from '../../context/CourseContext'; import { CourseData, CreatedEvents, SelectedClasses, TimetableData } from '../../interfaces/Periods'; import { TimetableTabContextMenuProps } from '../../interfaces/PropTypes'; import { - StyledCloseIcon, - StyledDialogButtons, StyledDialogContent, StyledDialogTitle, - StyledDialogTitleFont, StyledTitleContainer, StyledTopIcons, } from '../../styles/ControlStyles'; @@ -31,6 +28,7 @@ import { ExecuteButton, RedDeleteIcon, RedListItemText, StyledMenu } from '../.. import { StyledSnackbar } from '../../styles/TimetableTabStyles'; import storage from '../../utils/storage'; import { duplicateClasses, duplicateEvents } from '../../utils/timetableHelpers'; +import StyledDialog from '../StyledDialog'; const TimetableTabContextMenu: React.FC = ({ anchorElement, setAnchorElement }) => { const TIMETABLE_LIMIT = 13; @@ -405,30 +403,17 @@ const TimetableTabContextMenu: React.FC = ({ ancho {/* Delete timetable Dialog */} - - - - Confirm Deletion - - - Are you sure you want to delete this current timetable? - - - - - - + { + handleDeleteTimetable(selectedTimetable); + handleMenuClose(); + }} + title="Confirm Deletion" + content="Are you sure you want to delete this current timetable?" + confirmButtonText="Delete" + /> {/* Restore deleted timetable Alert */}