Skip to content

Commit

Permalink
New Goal Setting UI with SMART list
Browse files Browse the repository at this point in the history
  • Loading branch information
hppanpaliya committed Apr 30, 2023
1 parent 2018fc2 commit bc6cbcb
Show file tree
Hide file tree
Showing 5 changed files with 821 additions and 311 deletions.
117 changes: 117 additions & 0 deletions src/components/GoalSetting/EditGoalModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useState, useEffect } from "react";
import {
Box,
Button,
TextField,
Checkbox,
FormGroup,
FormControlLabel,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
FormControl,
FormLabel,
} from "@mui/material";
import { styled } from "@mui/material/styles";
import firebase from "../../utils/firebase";
import { useSelector } from "react-redux";

const StyledFormControl = styled(FormControl)`
margin: 8px 0;
width: 100%;
`;

function EditGoalModal({ open, handleClose, goalId }) {
const [goalTitle, setGoalTitle] = useState("");
const [description, setDescription] = useState("");
const [smartGoal, setSmartGoal] = useState({
specific: false,
measurable: false,
achievable: false,
relevant: false,
timeBound: false,
});

const user = useSelector((state) => state.auth.user);
const uid = user.uid;
const goalRef = firebase.firestore().collection("users").doc(uid).collection("goals");

useEffect(() => {
if (!goalId) {
return;
}

const fetchGoalData = async () => {
try {
const goalDoc = await firebase.firestore().collection("users").doc(uid).collection("goals").doc(goalId).get();
if (goalDoc.exists) {
const goalData = goalDoc.data();
setGoalTitle(goalData.title);
setDescription(goalData.description);
setSmartGoal(goalData.smartGoal);
} else {
console.error("No goal found with the provided goalId.");
}
} catch (error) {
console.error("Error fetching goal:", error);
}
};

fetchGoalData();
}, [goalId, uid]);

const handleSave = async () => {
const updatedGoal = {
title: goalTitle,
description,
smartGoal,
};

await updateGoal(goalId, updatedGoal);
handleClose();
};

const updateGoal = async (goalId, goal) => {
// Update the goal in Firestore
await goalRef.doc(goalId).update(goal);
};

return (
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Edit Goal</DialogTitle>
<DialogContent>
<Box>
<StyledFormControl>
<TextField label="Goal Title" value={goalTitle} onChange={(e) => setGoalTitle(e.target.value)} />
</StyledFormControl>
<StyledFormControl>
<TextField label="Description" multiline rows={4} value={description} onChange={(e) => setDescription(e.target.value)} />
</StyledFormControl>
<StyledFormControl>
<FormLabel component="legend">SMART Goal Checklist</FormLabel>
<FormGroup>
{Object.keys(smartGoal).map((key) => (
<FormControlLabel
key={key}
control={<Checkbox checked={smartGoal[key]} onChange={(e) => setSmartGoal({ ...smartGoal, [key]: e.target.checked })} name={key} />}
label={key.charAt(0).toUpperCase() + key.slice(1)}
/>
))}
</FormGroup>
</StyledFormControl>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleSave} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
);
}

export default EditGoalModal;
178 changes: 178 additions & 0 deletions src/components/GoalSetting/GoalsList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import React, { useState, useEffect } from "react";
import {
Box,
Typography,
Card,
CardContent,
CardActions,
Button,
Grid,
List,
ListItem,
ListItemText,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
LinearProgress,
} from "@mui/material";
import { styled } from "@mui/material/styles";
import { useSelector } from "react-redux";
import firebase from "../../utils/firebase";
import EditGoalModal from "./EditGoalModal";
import UpdateProgressModal from "./UpdateProgressModal";

const StyledCard = styled(Card)`
margin-bottom: 16px;
`;

function GoalsList({}) {
const [goals, setGoals] = useState([]);
const [editGoalId, setEditGoalId] = useState(null);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [updateGoalId, setUpdateGoalId] = useState(null);
const [updateProgressModalOpen, setUpdateProgressModalOpen] = useState(false);
const [categoryFilter, setCategoryFilter] = useState("all"); // "completed", "not-completed", "all"
const [deleteGoalId, setDeleteGoalId] = useState(null);
const [isDeleteConfirmationOpen, setIsDeleteConfirmationOpen] = useState(false);
const user = useSelector((state) => state.auth.user);
const uid = user.uid;

useEffect(() => {
const unsubscribe = firebase
.firestore()
.collection("users")
.doc(uid)
.collection("goals")
.onSnapshot((snapshot) => {
const goalsData = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setGoals(goalsData);
});
return () => unsubscribe();
}, [uid]);

const handleEditGoal = (goalId) => {
setEditGoalId(goalId);
setIsEditModalOpen(true);
};

const handleCloseEditModal = () => {
setIsEditModalOpen(false);
};

const handleUpdateProgress = (goalId) => {
setUpdateGoalId(goalId);
setUpdateProgressModalOpen(true);
};

const handleCloseUpdateProgressModal = () => {
setUpdateProgressModalOpen(false);
};

const handleDeleteGoal = (goalId) => {
setDeleteGoalId(goalId);
setIsDeleteConfirmationOpen(true);
};

const handleDeleteConfirmation = async () => {
try {
await firebase.firestore().collection("users").doc(uid).collection("goals").doc(deleteGoalId).delete();
setDeleteGoalId(null);
setIsDeleteConfirmationOpen(false);
console.log("Goal deleted:", deleteGoalId);
} catch (error) {
console.error("Error deleting goal:", error);
}
};

const handleCancelDelete = () => {
setDeleteGoalId(null);
setIsDeleteConfirmationOpen(false);
};

const filteredGoals = goals.filter((goal) => {
switch (categoryFilter) {
case "completed":
return goal.progress === 100;
case "not-completed":
return goal.progress < 100;
default:
return true;
}
});

return (
<Box>
<Typography variant="h5" gutterBottom>
Goals List
</Typography>
<Box sx={{ display: "flex", justifyContent: "center", alignItems: "center" }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 2, paddingBottom: 2 }}>
<Button variant={categoryFilter === "all" ? "contained" : "outlined"} onClick={() => setCategoryFilter("all")}>
All Goals
</Button>
<Button variant={categoryFilter === "completed" ? "contained" : "outlined"} onClick={() => setCategoryFilter("completed")}>
Completed Goals
</Button>
<Button variant={categoryFilter === "not-completed" ? "contained" : "outlined"} onClick={() => setCategoryFilter("not-completed")}>
Not Completed Goals
</Button>
</Box>
</Box>
{filteredGoals.map((goal) => (
<StyledCard key={goal.id}>
<CardContent>
<Typography variant="h6">{goal.title}</Typography>
<LinearProgress variant="determinate" value={goal.progress} />
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1">Description:</Typography>
<Typography color="textSecondary">{goal.description}</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="subtitle1">SMART Goal Checklist:</Typography>
<List dense>
<EditGoalModal open={isEditModalOpen} handleClose={handleCloseEditModal} goalId={editGoalId} />
<UpdateProgressModal open={updateProgressModalOpen} handleClose={handleCloseUpdateProgressModal} goalId={updateGoalId} />
{Object.keys(goal.smartGoal).map((key) => (
<ListItem key={key}>
<ListItemText primary={key.charAt(0).toUpperCase() + key.slice(1)} secondary={goal.smartGoal[key] ? "Yes" : "No"} />
</ListItem>
))}
</List>
</Grid>
</Grid>
</CardContent>
<CardActions>
<Button size="small" onClick={() => handleEditGoal(goal.id)}>
Edit
</Button>
<Button size="small" onClick={() => handleDeleteGoal(goal.id)}>
Delete
</Button>
<Button size="small" onClick={() => handleUpdateProgress(goal.id)}>
Update Progress
</Button>
</CardActions>
</StyledCard>
))}
<Dialog open={isDeleteConfirmationOpen} onClose={handleCancelDelete}>
<DialogTitle>Delete Goal</DialogTitle>
<DialogContent>
<Typography variant="body1">Are you sure you want to delete this goal?</Typography>
</DialogContent>
<DialogActions>
<Button onClick={handleCancelDelete}>Cancel</Button>
<Button onClick={handleDeleteConfirmation} variant="contained" color="error">
Delete
</Button>
</DialogActions>
</Dialog>
</Box>
);
}

export default GoalsList;
95 changes: 95 additions & 0 deletions src/components/GoalSetting/NewGoalModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useState } from "react";
import {
Box,
Button,
TextField,
Checkbox,
FormGroup,
FormControlLabel,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
FormControl,
FormLabel,
} from "@mui/material";
import { styled } from "@mui/material/styles";
import { useSelector } from "react-redux";
import firebase from "../../utils/firebase";

const StyledFormControl = styled(FormControl)`
margin: 8px 0;
width: 100%;
`;

function NewGoalModal({ open, handleClose }) {
const [goalTitle, setGoalTitle] = useState("");
const [description, setDescription] = useState("");
const [smartGoal, setSmartGoal] = useState({
specific: false,
measurable: false,
achievable: false,
relevant: false,
timeBound: false,
});

const user = useSelector((state) => state.auth.user);
const uid = user.uid;
const goalsRef = firebase.firestore().collection("users").doc(uid).collection("goals");

const handleSave = async () => {
const newGoal = {
title: goalTitle,
description,
smartGoal,
createdAt: Date.now(),
progress: 0,
};

await saveGoal(newGoal);
handleClose();
};

const saveGoal = async (goal) => {
// Add the new goal to the goals collection in Firestore
await goalsRef.add(goal);
};

return (
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Create a New Goal</DialogTitle>
<DialogContent>
<Box>
<StyledFormControl>
<TextField label="Goal Title" value={goalTitle} onChange={(e) => setGoalTitle(e.target.value)} />
</StyledFormControl>
<StyledFormControl>
<TextField label="Description" multiline rows={4} value={description} onChange={(e) => setDescription(e.target.value)} />
</StyledFormControl>
<StyledFormControl>
<FormLabel component="legend">SMART Goal Checklist</FormLabel>
<FormGroup>
{Object.keys(smartGoal).map((key) => (
<FormControlLabel
key={key}
control={<Checkbox checked={smartGoal[key]} onChange={(e) => setSmartGoal({ ...smartGoal, [key]: e.target.checked })} name={key} />}
label={key.charAt(0).toUpperCase() + key.slice(1)}
/>
))}
</FormGroup>
</StyledFormControl>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Cancel
</Button>
<Button onClick={handleSave} color="primary">
Save
</Button>
</DialogActions>
</Dialog>
);
}

export default NewGoalModal;
Loading

0 comments on commit bc6cbcb

Please sign in to comment.