diff --git a/package-lock.json b/package-lock.json
index 7dac78c..6deb902 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
"firebase": "^11.0.1",
"react": "^18.3.1",
"react-calendar": "^5.1.0",
+ "react-confetti": "^6.1.0",
"react-dom": "^18.3.0",
"react-router-dom": "^6.27.0"
},
@@ -6609,6 +6610,21 @@
}
}
},
+ "node_modules/react-confetti": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz",
+ "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==",
+ "license": "MIT",
+ "dependencies": {
+ "tween-functions": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=10.18"
+ },
+ "peerDependencies": {
+ "react": "^16.3.0 || ^17.0.1 || ^18.0.0"
+ }
+ },
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
@@ -7467,6 +7483,12 @@
"integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
"license": "0BSD"
},
+ "node_modules/tween-functions": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz",
+ "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==",
+ "license": "BSD"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index d579c37..0fd50c5 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"firebase": "^11.0.1",
"react": "^18.3.1",
"react-calendar": "^5.1.0",
+ "react-confetti": "^6.1.0",
"react-dom": "^18.3.0",
"react-router-dom": "^6.27.0"
},
diff --git a/public/treee.mov b/public/treee.mov
new file mode 100644
index 0000000..9dd1a7b
Binary files /dev/null and b/public/treee.mov differ
diff --git a/src/components/Home/MicroGoal.jsx b/src/components/Home/MicroGoal.jsx
index dfb3e4b..ee8adb3 100644
--- a/src/components/Home/MicroGoal.jsx
+++ b/src/components/Home/MicroGoal.jsx
@@ -2,6 +2,8 @@ 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 TaskCompletionModal from '@/components/Home/TaskCompletionModal'
+import { useUser } from '@/contexts/UserContext'
import useGoalsUpdater from '@/hooks/useGoalsUpdater'
import { calculateProgress } from '@/utils/calculateProgress'
import { ExpandLess, ExpandMore } from '@mui/icons-material'
@@ -14,10 +16,21 @@ import {
Paper,
Typography,
} from '@mui/material'
+import { useState } from 'react'
const MicroGoal = ({ microGoal, macroGoalIndex, microGoalIndex }) => {
const { addTask, toggleExpansion, toggleTaskCompletion } = useGoalsUpdater()
const progress = calculateProgress([microGoal])
+ const [modalOpen, setModalOpen] = useState(false)
+ const { user } = useUser()
+
+ // Access today's task completion count
+ const todayCount = user?.streak?.todayCount || 0
+
+ const handleTaskCompletion = (macroGoalIndex, microGoalIndex, taskIndex) => {
+ toggleTaskCompletion(macroGoalIndex, microGoalIndex, taskIndex)
+ setModalOpen(true) // Open the modal after each task completion
+ }
return (
{
microGoalIndex={microGoalIndex}
taskIndex={taskIndex}
onToggle={() =>
- toggleTaskCompletion(macroGoalIndex, microGoalIndex, taskIndex)
+ handleTaskCompletion(macroGoalIndex, microGoalIndex, taskIndex)
}
/>
))}
@@ -63,6 +76,13 @@ const MicroGoal = ({ microGoal, macroGoalIndex, microGoalIndex }) => {
}
/>
+
+ {/* TaskCompletionModal */}
+ setModalOpen(false)}
+ count={todayCount} // Pass today's task completion count to the modal
+ />
)
}
diff --git a/src/components/Home/TaskCompletionModal.jsx b/src/components/Home/TaskCompletionModal.jsx
new file mode 100644
index 0000000..2e4d102
--- /dev/null
+++ b/src/components/Home/TaskCompletionModal.jsx
@@ -0,0 +1,116 @@
+import { useUser } from '@/contexts/UserContext' // Import useUser hook
+import { Box, Button, Modal, Typography, useTheme } from '@mui/material'
+import { useEffect, useRef, useState } from 'react'
+import Confetti from 'react-confetti'
+
+const TaskCompletionModal = ({ open, handleClose }) => {
+ const { user } = useUser()
+ const theme = useTheme() // Access the theme for colors
+ const todayCount = user?.streak?.todayCount || 0 // Get the daily task completion count
+
+ const [confetti, setConfetti] = useState(false)
+ const videoRef = useRef(null) // Reference to the video element
+
+ // Define the start and end times for each stage in seconds
+ const timeRanges = [
+ { start: 0, end: 2.5 },
+ { start: 2.5, end: 4 },
+ { start: 4, end: 6 },
+ { start: 6, end: 8 },
+ { start: 6.5, end: 11 },
+ ]
+
+ // Show confetti when exactly 5 tasks are completed
+ useEffect(() => {
+ if (todayCount === 5) {
+ setConfetti(true)
+ setTimeout(() => setConfetti(false), 5000)
+ }
+ }, [todayCount])
+
+ // Control video playback based on `todayCount`
+ useEffect(() => {
+ const video = videoRef.current
+ if (open && video && todayCount <= 5) {
+ const { start, end } = timeRanges[todayCount - 1] || { start: 0, end: 0 } // Get time range based on task count
+ video.currentTime = start // Set video start time
+ video.play()
+
+ // Stop video at the specified end time
+ const handleTimeUpdate = () => {
+ if (video.currentTime >= end) {
+ video.pause()
+ }
+ }
+
+ video.addEventListener('timeupdate', handleTimeUpdate)
+
+ // Clean up event listener when the component unmounts or task count changes
+ return () => {
+ video.removeEventListener('timeupdate', handleTimeUpdate)
+ }
+ }
+ }, [open, todayCount])
+
+ // Only render the modal content if todayCount is 5 or fewer
+ if (todayCount === 6 && todayCount > 5) {
+ return null // Prevent modal from rendering if more than 5 tasks are completed
+ }
+
+ return (
+
+
+ {/* Full-screen confetti with purple and white colors */}
+ {confetti && (
+
+ )}
+
+
+
+
+ {todayCount === 4
+ ? 'Just one more task to go, you got this!!'
+ : todayCount < 5
+ ? `Complete ${5 - todayCount} more tasks to grow your tree today!` // General message for counts less than 5
+ : 'Congratulations! You Completed 5 tasks today!'}
+
+
+
+
+
+ )
+}
+
+export default TaskCompletionModal