Skip to content

Commit

Permalink
feat(DeleteItem): Add deletion of goals, microgoals, and tasks (#18)
Browse files Browse the repository at this point in the history
- Refactor: Merge all deletion logic inside the hook are all merged into
single function `deleteItem`
- Feat: Add new component to enable delete goals, microgoals, and tasks
by just single click on the delete icon (with mistake handling).
- Feat: Add new common components `ConfirmationDialog`.

---------

Co-authored-by: ZL Asica <[email protected]>
  • Loading branch information
marycaserio and ZL-Asica authored Nov 4, 2024
1 parent f5f8525 commit 4e31a55
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 66 deletions.
42 changes: 42 additions & 0 deletions src/components/Home/DeleteItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import ConfirmationDialog from '@components/common/ConfirmationDialog';
import useGoalsUpdater from '@hooks/useGoalsUpdater';
import DeleteIcon from '@mui/icons-material/Delete';
import { IconButton, Tooltip } from '@mui/material';
import { useState } from 'react';

const DeleteItem = ({ goalIndex, microGoalIndex, taskIndex }) => {
const { deleteItem } = useGoalsUpdater();
const [isDialogOpen, setIsDialogOpen] = useState(false);

const handleDelete = async () => {
await deleteItem({ goalIndex, microGoalIndex, taskIndex });
setIsDialogOpen(false); // Close the dialog after deletion
};

return (
<>
<Tooltip title="Delete">
<IconButton
edge="end"
aria-label="delete"
onClick={() => setIsDialogOpen(true)}
sx={{ color: 'error.main' }} // Set color to indicate delete action
>
<DeleteIcon />
</IconButton>
</Tooltip>

{/* Delete Confirmation Dialog */}
<ConfirmationDialog
open={isDialogOpen}
onClose={() => setIsDialogOpen(false)}
onConfirm={handleDelete}
title="Confirm Delete"
description="Are you sure you want to delete this item?"
confirmText="Delete"
/>
</>
);
};

export default DeleteItem;
2 changes: 2 additions & 0 deletions src/components/Home/MacroGoal.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AddItem from '@components/Home/AddItem';
import DeleteItem from '@components/Home/DeleteItem';
import MicroGoal from '@components/Home/MicroGoal';
import ProgressIndicator from '@components/Home/ProgressIndicator';
import useGoalsUpdater from '@hooks/useGoalsUpdater';
Expand All @@ -17,6 +18,7 @@ const MacroGoal = ({ macroGoal, macroGoalIndex }) => {
<Typography variant="h6" sx={{ flexGrow: 1, ml: 2 }}>
{macroGoal.name}
</Typography>
<DeleteItem goalIndex={macroGoalIndex} />
<IconButton onClick={() => toggleGoalExpansion(macroGoalIndex)} size="small">
{macroGoal.expanded ? <ExpandLess /> : <ExpandMore />}
</IconButton>
Expand Down
5 changes: 5 additions & 0 deletions src/components/Home/MicroGoal.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AddItem from '@components/Home/AddItem';
import DeleteItem from '@components/Home/DeleteItem';
import ProgressIndicator from '@components/Home/ProgressIndicator';
import Task from '@components/Home/Task';
import useGoalsUpdater from '@hooks/useGoalsUpdater';
Expand All @@ -17,6 +18,7 @@ const MicroGoal = ({ microGoal, macroGoalIndex, microGoalIndex }) => {
<Typography variant="subtitle1" sx={{ flexGrow: 1, ml: 1 }}>
{microGoal.name}
</Typography>
<DeleteItem goalIndex={macroGoalIndex} microGoalIndex={microGoalIndex} />
<IconButton
onClick={() => toggleMicroGoalExpansion(macroGoalIndex, microGoalIndex)}
size="small"
Expand All @@ -30,6 +32,9 @@ const MicroGoal = ({ microGoal, macroGoalIndex, microGoalIndex }) => {
<Task
key={taskIndex}
task={task}
macroGoalIndex={macroGoalIndex}
microGoalIndex={microGoalIndex}
taskIndex={taskIndex}
onToggle={() => toggleTaskCompletion(macroGoalIndex, microGoalIndex, taskIndex)}
/>
))}
Expand Down
68 changes: 38 additions & 30 deletions src/components/Home/Task.jsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,43 @@
import DeleteItem from '@components/Home/DeleteItem';
import { Checkbox, ListItem, ListItemText } from '@mui/material';

const Task = ({ task, onToggle }) => (
<ListItem
dense
sx={{
display: 'flex',
alignItems: 'center',
padding: 1,
bgcolor: task.completed ? 'action.hover' : 'background.paper',
borderRadius: 1,
mb: 1,
'&:hover': { bgcolor: 'action.hover' },
}}
>
<Checkbox
edge="start"
checked={task.completed}
onChange={onToggle}
size="medium"
sx={{ '& .MuiSvgIcon-root': { fontSize: 28 } }} // Enlarge the checkbox icon
/>
<ListItemText
primary={task.name}
primaryTypographyProps={{
sx: {
textDecoration: task.completed ? 'line-through' : 'none',
color: task.completed ? 'text.disabled' : 'text.primary',
},
const Task = ({ task, onToggle, macroGoalIndex, microGoalIndex, taskIndex }) => {
return (
<ListItem
dense
sx={{
display: 'flex',
alignItems: 'center',
padding: 1,
bgcolor: task.completed ? 'action.hover' : 'background.paper',
borderRadius: 1,
mb: 1,
'&:hover': { bgcolor: 'action.hover' },
}}
/>
</ListItem>
);
>
<Checkbox
edge="start"
checked={task.completed}
onChange={onToggle}
size="medium"
sx={{ '& .MuiSvgIcon-root': { fontSize: 28 } }} // Enlarge the checkbox icon
/>
<ListItemText
primary={task.name}
primaryTypographyProps={{
sx: {
textDecoration: task.completed ? 'line-through' : 'none',
color: task.completed ? 'text.disabled' : 'text.primary',
},
}}
/>
<DeleteItem
goalIndex={macroGoalIndex}
microGoalIndex={microGoalIndex}
taskIndex={taskIndex}
/>
</ListItem>
);
};

export default Task;
26 changes: 0 additions & 26 deletions src/components/common/ConfirmSignOutDialog.jsx

This file was deleted.

43 changes: 43 additions & 0 deletions src/components/common/ConfirmationDialog.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from '@mui/material';

const ConfirmationDialog = ({
open,
onClose,
onConfirm,
title,
description = '', // If null, no description will be shown
confirmText = 'Confirm',
cancelText = 'Cancel',
confirmColor = 'error', // 'primary' or 'error'
}) => {
return (
<Dialog
open={open}
onClose={onClose}
aria-describedby={description ? 'confirmation-dialog-description' : undefined}
role="alertdialog"
>
<DialogTitle id="confirmation-dialog-title">{title}</DialogTitle>
<DialogContent>
{description && (
<DialogContentText id="confirmation-dialog-description">{description}</DialogContentText>
)}
</DialogContent>
<DialogActions>
<Button onClick={onClose}>{cancelText}</Button>
<Button onClick={onConfirm} color={confirmColor} autoFocus>
{confirmText}
</Button>
</DialogActions>
</Dialog>
);
};

export default ConfirmationDialog;
14 changes: 11 additions & 3 deletions src/components/common/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ConfirmationDialog from '@components/common/ConfirmationDialog';
import { useUser } from '@contexts/UserContext';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import FireIcon from '@mui/icons-material/Whatshot';
import { AppBar, Avatar, Box, Button, IconButton, Toolbar, Typography } from '@mui/material';
import { useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import ConfirmSignOutDialog from './ConfirmSignOutDialog';

const Header = () => {
const { user, handleSignIn } = useUser();
const { user, handleSignIn, handleSignOut } = useUser();
const location = useLocation();
const navigate = useNavigate();

Expand Down Expand Up @@ -65,9 +65,17 @@ const Header = () => {
</IconButton>

{/* Dialog for Confirm Sign Out */}
<ConfirmSignOutDialog
<ConfirmationDialog
open={openConfirmDialog}
onClose={() => setOpenConfirmDialog(false)}
onConfirm={async () => {
navigate('/');
await handleSignOut();
onClose();
}}
title="Confirm Sign Out"
description="Are you sure you want to sign out?"
confirmText="Sign Out"
/>
</>
) : (
Expand Down
10 changes: 3 additions & 7 deletions src/hooks/useGoalsUpdater.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const useGoalsUpdater = () => {
};

// Delete a goal, microgoal, or task
const deleteItem = async ({ goalIndex, microGoalIndex, taskIndex }) => {
const deleteItem = async ({ goalIndex, microGoalIndex = undefined, taskIndex = undefined }) => {
const updatedGoals = [...user.goals];

if (taskIndex !== undefined) {
Expand Down Expand Up @@ -92,12 +92,8 @@ const useGoalsUpdater = () => {
addTask: (goalIndex, microGoalIndex, taskName) =>
addItem(goalIndex, microGoalIndex, { name: taskName, completed: false }, 'task'),

// Delete a goal, microgoal, or task
deleteGoal: (goalIndex) => deleteItem(goalIndex),
deleteMicrogoal: (goalIndex, microGoalIndex) => deleteItem(goalIndex, microGoalIndex),
deleteTask: (goalIndex, microGoalIndex, taskIndex) =>
deleteItem(goalIndex, microGoalIndex, taskIndex),

// Delete
deleteItem,
toggleTaskCompletion,

toggleGoalExpansion: (goalIndex) => toggleExpansion(goalIndex),
Expand Down

0 comments on commit 4e31a55

Please sign in to comment.