22import React , { useState , useEffect } from 'react' ;
33import { Link } from 'react-router-dom' ;
44import { useAuth } from '../utils/auth' ;
5- import { updateStreak , getUserProfile } from '../utils/firebase' ;
5+ import { updateStreak , getUserProfile , updateStreakStart } from '../utils/firebase' ;
66import { cn } from '@/lib/utils' ;
77import {
88 ArrowRight ,
99 Calendar ,
1010 Trophy ,
1111 TrendingUp ,
1212 MessageCircle ,
13+ Map ,
14+ HeartPulse ,
15+ CheckIcon
1316 HeartPulse ,
1417 BookOpen
1518} from 'lucide-react' ;
@@ -22,6 +25,7 @@ import CommunityMap from '@/components/CommunityMap';
2225import { motion } from 'framer-motion' ;
2326import { toast } from 'sonner' ;
2427import VerseSlideshow from '@/components/VerseSlideshow' ;
28+ import DatePicker from '@/components/ui/date-picker' ;
2529
2630const formatDate = ( date : Date ) => {
2731 return new Intl . DateTimeFormat ( 'en-US' , {
@@ -36,6 +40,8 @@ const Dashboard: React.FC = () => {
3640 const [ streak , setStreak ] = useState ( 0 ) ;
3741 const [ lastCheckIn , setLastCheckIn ] = useState < Date | null > ( null ) ;
3842 const [ isCheckedInToday , setIsCheckedInToday ] = useState ( false ) ;
43+ const [ isCheckInSide , setIsCheckInSide ] = useState ( true ) ;
44+ const [ selectedDate , setSelectedDate ] = useState < Date > ( new Date ( ) ) ;
3945
4046 const featuredMeditations = [
4147 {
@@ -78,9 +84,10 @@ const Dashboard: React.FC = () => {
7884
7985 const handleCheckIn = async ( ) => {
8086 if ( ! currentUser ) return ;
81-
87+ console . log ( currentUser . uid )
8288 try {
8389 const result = await updateStreak ( currentUser . uid ) ;
90+ console . log ( result )
8491
8592 if ( result . success ) {
8693 const updatedProfile = await getUserProfile ( currentUser . uid ) ;
@@ -109,6 +116,44 @@ const Dashboard: React.FC = () => {
109116 }
110117 } ;
111118
119+ const handleStreakSet = async ( ) => {
120+ if ( ! currentUser ) return ;
121+
122+ try {
123+ const result = await updateStreakStart ( currentUser . uid , selectedDate ) ;
124+
125+ if ( result . success ) {
126+ // Refresh user data
127+ const updatedProfile = await getUserProfile ( currentUser . uid ) ;
128+
129+ if ( updatedProfile ) {
130+ setStreak ( updatedProfile . streakDays || 0 ) ;
131+ }
132+
133+ if ( result . message === 'Streak start updated successfully' ) {
134+ toast . success ( "Streak start updated!" , {
135+ description : `Your streak has been reset to start from ${ formatDate ( selectedDate ) } .` ,
136+ } ) ;
137+ }
138+ }
139+
140+ if ( ! result . success && result . message === 'Invalid Date' ) {
141+ toast . error ( "Invalid date selected" , {
142+ description : "Please select a valid date to start your streak." ,
143+ } ) ;
144+ }
145+
146+ } catch ( error ) {
147+ console . error ( 'Error updating streak:' , error ) ;
148+ toast . error ( "Failed to set streak start date" , {
149+ description : "Please try again later." ,
150+ } ) ;
151+ } finally {
152+ setIsCheckInSide ( true ) ;
153+ }
154+ } ;
155+
156+
112157 return (
113158 < motion . div
114159 className = "container py-8 pb-16"
@@ -145,40 +190,96 @@ const Dashboard: React.FC = () => {
145190 "border-primary/20 h-full" ,
146191 streak > 0 && "bg-gradient-to-br from-primary/10 to-transparent"
147192 ) } >
148- < CardHeader className = "pb-2" >
149- < CardTitle className = "flex items-center" >
150- < Trophy className = "h-5 w-5 mr-2 text-primary" />
151- Your Current Streak
152- </ CardTitle >
153- < CardDescription >
154- { isCheckedInToday
155- ? 'You\'ve checked in today. Great job!'
156- : 'Remember to check in daily to maintain your streak' }
157- </ CardDescription >
158- </ CardHeader >
159- < CardContent >
160- < div className = "flex items-center justify-center py-6" >
161- < div className = "text-center" >
162- < div className = "text-5xl font-bold mb-2 text-primary" >
163- { streak }
164- </ div >
165- < div className = "text-muted-foreground" >
166- consecutive { streak === 1 ? 'day' : 'days' }
193+ { /* Current Streak Card - Check In Side */ }
194+ { isCheckInSide ? (
195+ < motion . div
196+ key = "check-in-side"
197+ initial = { { opacity : 0 } }
198+ animate = { { opacity : 1 } }
199+ transition = { { duration : 0.5 } }
200+ >
201+ < CardHeader className = "pb-2" >
202+ < CardTitle className = "flex items-center" >
203+ < Trophy className = "h-5 w-5 mr-2 text-primary" />
204+ Your Current Streak
205+ </ CardTitle >
206+ < CardDescription >
207+ { isCheckedInToday
208+ ? 'You\'ve checked in today. Great job!'
209+ : 'Remember to check in daily to maintain your streak' }
210+ </ CardDescription >
211+ </ CardHeader >
212+ < CardContent >
213+ < div className = "flex items-center justify-center py-6" >
214+ < div className = "text-center" >
215+ < div className = "text-5xl font-bold mb-2 text-primary" >
216+ { streak }
217+ </ div >
218+ < div className = "text-muted-foreground" >
219+ consecutive { streak === 1 ? 'day' : 'days' }
220+ </ div >
221+ </ div >
167222 </ div >
168- </ div >
169- </ div >
170- </ CardContent >
171- < CardFooter >
172- < Button
173- onClick = { handleCheckIn }
174- disabled = { isCheckedInToday }
175- variant = { isCheckedInToday ? "outline" : "default" }
176- className = "w-full"
223+ </ CardContent >
224+ < CardFooter className = "flex flex-col items-center space-y-2" >
225+ < Button
226+ onClick = { handleCheckIn }
227+ disabled = { isCheckedInToday }
228+ variant = { isCheckedInToday ? "outline" : "default" }
229+ className = "w-full"
230+ >
231+ { isCheckedInToday ? 'Already Checked In Today' : 'Check In for Today' }
232+ { ! isCheckedInToday && < Calendar className = "ml-2 h-4 w-4" /> }
233+ </ Button >
234+ < Button
235+ variant = "outline"
236+ className = "w-full text-xs"
237+ onClick = { ( ) => setIsCheckInSide ( false ) }
238+ >
239+ Edit Streak Start Date
240+ </ Button >
241+ </ CardFooter >
242+ </ motion . div >
243+ ) : (
244+ // Current Streak Card - Set Streak Start Date Side
245+ < motion . div
246+ key = "streak-start-side"
247+ initial = { { opacity : 0 } }
248+ animate = { { opacity : 1 } }
249+ transition = { { duration : 0.5 } }
177250 >
178- { isCheckedInToday ? 'Already Checked In Today' : 'Check In for Today' }
179- { ! isCheckedInToday && < Calendar className = "ml-2 h-4 w-4" /> }
180- </ Button >
181- </ CardFooter >
251+ < CardHeader className = "pb-2" >
252+ < CardTitle className = "flex items-center" >
253+ < Trophy className = "h-5 w-5 mr-2 text-primary" />
254+ Set Your Streak
255+ </ CardTitle >
256+ < CardDescription >
257+ Change Your Streak Start Date
258+ </ CardDescription >
259+ </ CardHeader >
260+ < CardContent >
261+ < div className = "flex items-center justify-center" >
262+ { /* calculate the streak start date to display in DatePicker */ }
263+ < DatePicker onDateChange = { setSelectedDate } preselectedDate = { new Date ( Date . now ( ) - streak * 24 * 60 * 60 * 1000 ) } />
264+ </ div >
265+ </ CardContent >
266+ < CardFooter className = "flex flex-col items-center space-y-2" >
267+ < Button
268+ onClick = { handleStreakSet }
269+ className = "w-full"
270+ >
271+ Set Streak Start Date < CheckIcon />
272+ </ Button >
273+ < Button
274+ variant = "outline"
275+ className = "w-full text-xs"
276+ onClick = { ( ) => setIsCheckInSide ( true ) }
277+ >
278+ Cancel
279+ </ Button >
280+ </ CardFooter >
281+ </ motion . div >
282+ ) }
182283 </ Card >
183284 </ motion . div >
184285
0 commit comments