Skip to content

Commit

Permalink
Adding some form of gamification when users can grow a tree when the…
Browse files Browse the repository at this point in the history
…y complete 5 tasks in a day
  • Loading branch information
WelldoneM committed Nov 8, 2024
1 parent 6e77c0f commit 635ef65
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 1 deletion.
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/tree.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: 1.5 },
{ start: 1.45, end: 3.2 },
{ start: 2.95, end: 4.5 },
{ start: 3.9, end: 5.5 },
{ start: 5, end: 8.5 },
]

// 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='/tree.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

0 comments on commit 635ef65

Please sign in to comment.