Skip to content
This repository was archived by the owner on Mar 31, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
Binary file added public/treee.mov
Binary file not shown.
22 changes: 21 additions & 1 deletion src/components/Home/MicroGoal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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 (
<Paper
Expand Down Expand Up @@ -51,7 +64,7 @@ const MicroGoal = ({ microGoal, macroGoalIndex, microGoalIndex }) => {
microGoalIndex={microGoalIndex}
taskIndex={taskIndex}
onToggle={() =>
toggleTaskCompletion(macroGoalIndex, microGoalIndex, taskIndex)
handleTaskCompletion(macroGoalIndex, microGoalIndex, taskIndex)
}
/>
))}
Expand All @@ -63,6 +76,13 @@ const MicroGoal = ({ microGoal, macroGoalIndex, microGoalIndex }) => {
}
/>
</Collapse>

{/* TaskCompletionModal */}
<TaskCompletionModal
open={modalOpen}
handleClose={() => setModalOpen(false)}
count={todayCount} // Pass today's task completion count to the modal
/>
</Paper>
)
}
Expand Down
116 changes: 116 additions & 0 deletions src/components/Home/TaskCompletionModal.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<Modal open={open} onClose={handleClose}>
<Box
sx={{
p: 3,
bgcolor: theme.palette.primary.light, // Light purple background
borderRadius: 2,
textAlign: 'center',
width: '80%', // Make modal wider
maxWidth: 600,
mx: 'auto',
my: '20vh',
}}
>
{/* Full-screen confetti with purple and white colors */}
{confetti && (
<Confetti
width={window.innerWidth}
height={window.innerHeight}
colors={[
theme.palette.primary.main,
'#FFFFFF',
theme.palette.primary.light,
]} // Purple and white confetti
/>
)}

<Box
component='video'
src='/treee.mov'
alt='Growing Tree'
ref={videoRef}
controls={false}
muted
sx={{
width: '100%', // Full width of the modal
borderRadius: 1,
}}
/>

<Typography variant='body1' sx={{ mt: 2 }}>
{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!'}
</Typography>

<Button onClick={handleClose} sx={{ mt: 2 }} variant='contained'>
Keep Going!
</Button>
</Box>
</Modal>
)
}

export default TaskCompletionModal