11"use client" ;
22
3+ import { CheckCircle2 } from "lucide-react" ;
34import { useEffect , useState } from "react" ;
45
56import { PixelAvatar } from "@/components/avatar/pixel-avatar" ;
@@ -16,19 +17,18 @@ import {
1617import { Label } from "@/components/ui/label" ;
1718import {
1819 defaultDailyQuizAnswers ,
20+ formatSleepHours ,
21+ SLEEP_HOURS_MAX ,
22+ SLEEP_HOURS_MIN ,
23+ SLEEP_HOURS_STEP ,
1924 WELLNESS_SCALE_MAX ,
2025 type DailyQuizAnswers ,
2126 type DailyQuizSubmission ,
2227} from "@/lib/avatar-state" ;
2328import {
24- getDailyQuizSubmission ,
25- getTodayDateKey ,
26- saveDailyQuizSubmission ,
29+ getDailyEntryForToday ,
30+ saveDailyEntry ,
2731} from "@/lib/daily-quiz-storage" ;
28- import {
29- getJournalEntryForToday ,
30- saveJournalEntry ,
31- } from "@/lib/journal-storage" ;
3232
3333export function DailyQuizForm ( ) {
3434 const [ answers , setAnswers ] = useState < DailyQuizAnswers > (
@@ -44,19 +44,23 @@ export function DailyQuizForm() {
4444
4545 useEffect ( ( ) => {
4646 async function loadDailyCheckIn ( ) {
47- const existingSubmission = getDailyQuizSubmission ( ) ;
48- const existingJournal = await getJournalEntryForToday ( ) ;
49-
50- if ( existingSubmission ?. date === getTodayDateKey ( ) ) {
51- setSubmission ( existingSubmission ) ;
52- setAnswers ( existingSubmission . answers ) ;
53- }
47+ try {
48+ const existingEntry = await getDailyEntryForToday ( ) ;
5449
55- if ( existingJournal ) {
56- setJournal ( existingJournal . content ) ;
50+ if ( existingEntry ) {
51+ setSubmission ( existingEntry ) ;
52+ setAnswers ( existingEntry . answers ) ;
53+ setJournal ( existingEntry . journal ) ;
54+ }
55+ } catch ( loadError ) {
56+ setError (
57+ loadError instanceof Error
58+ ? loadError . message
59+ : "Could not load today's check-in." ,
60+ ) ;
61+ } finally {
62+ setIsReady ( true ) ;
5763 }
58-
59- setIsReady ( true ) ;
6064 }
6165
6266 void loadDailyCheckIn ( ) ;
@@ -84,9 +88,8 @@ export function DailyQuizForm() {
8488 setError ( null ) ;
8589
8690 try {
87- const savedSubmission = saveDailyQuizSubmission ( answers ) ;
88- await saveJournalEntry ( journal ) ;
89- setSubmission ( savedSubmission ) ;
91+ const savedEntry = await saveDailyEntry ( answers , journal ) ;
92+ setSubmission ( savedEntry ) ;
9093 } catch ( submitError ) {
9194 setError (
9295 submitError instanceof Error
@@ -106,18 +109,77 @@ export function DailyQuizForm() {
106109
107110 return (
108111 < div className = "flex flex-col gap-6" >
109- < div className = "flex items-center justify-between" >
110- < Badge > Today's check-in</ Badge >
111- < Badge variant = { isCompleted ? "default" : "outline" } >
112- { isCompleted ? "Completed" : "Not completed" }
113- </ Badge >
114- </ div >
115-
116- < Card >
112+ { isCompleted && submission ? (
113+ < >
114+ < Card className = "border-primary/40 bg-primary/10" >
115+ < CardContent className = "flex items-start gap-4 pt-6" >
116+ < div className = "rounded-full bg-primary/15 p-2.5" >
117+ < CheckCircle2
118+ aria-hidden = "true"
119+ className = "h-7 w-7 text-primary"
120+ />
121+ </ div >
122+ < div className = "space-y-1" >
123+ < p className = "text-lg font-semibold tracking-tight" >
124+ Today's quiz is complete
125+ </ p >
126+ < p className = "text-sm text-muted-foreground" >
127+ Your wellness check-in and journal are saved for today. You
128+ can review your answers below, and come back tomorrow for
129+ your next quiz.
130+ </ p >
131+ </ div >
132+ </ CardContent >
133+ </ Card >
134+
135+ < Card >
136+ < CardHeader >
137+ < CardTitle className = "text-base" > Your pet today</ CardTitle >
138+ < CardDescription >
139+ Based on the wellness check-in you already submitted.
140+ </ CardDescription >
141+ </ CardHeader >
142+ < CardContent className = "flex flex-col items-center gap-4" >
143+ < PixelAvatar mood = { submission . condition . mood } size = "md" />
144+ < div className = "grid w-full grid-cols-3 gap-2 text-center text-sm" >
145+ < div className = "rounded-lg border bg-background px-3 py-2" >
146+ < p className = "text-muted-foreground" > Mood</ p >
147+ < p className = "font-medium capitalize" >
148+ { submission . condition . mood }
149+ </ p >
150+ </ div >
151+ < div className = "rounded-lg border bg-background px-3 py-2" >
152+ < p className = "text-muted-foreground" > Energy</ p >
153+ < p className = "font-medium" >
154+ { submission . condition . energy } /{ WELLNESS_SCALE_MAX }
155+ </ p >
156+ </ div >
157+ < div className = "rounded-lg border bg-background px-3 py-2" >
158+ < p className = "text-muted-foreground" > Health</ p >
159+ < p className = "font-medium" >
160+ { submission . condition . health } /{ WELLNESS_SCALE_MAX }
161+ </ p >
162+ </ div >
163+ </ div >
164+ </ CardContent >
165+ </ Card >
166+ </ >
167+ ) : (
168+ < div className = "flex items-center justify-between" >
169+ < Badge > Today's check-in</ Badge >
170+ < Badge variant = "outline" > Not completed</ Badge >
171+ </ div >
172+ ) }
173+
174+ < Card className = { isCompleted ? "opacity-90" : undefined } >
117175 < CardHeader >
118- < CardTitle className = "text-base" > Wellness</ CardTitle >
176+ < CardTitle className = "text-base" >
177+ { isCompleted ? "Your answers today" : "Wellness" }
178+ </ CardTitle >
119179 < CardDescription >
120- Sliders from 1 to 5 for how you're doing today.
180+ { isCompleted
181+ ? "These fields are locked until tomorrow's quiz."
182+ : "Rate your wellness from 1 to 5. Sleep length uses hours." }
121183 </ CardDescription >
122184 </ CardHeader >
123185 < CardContent className = "space-y-5" >
@@ -146,6 +208,10 @@ export function DailyQuizForm() {
146208 id = "sleep-length"
147209 label = "How long did you sleep?"
148210 value = { answers . sleepLength }
211+ min = { SLEEP_HOURS_MIN }
212+ max = { SLEEP_HOURS_MAX }
213+ step = { SLEEP_HOURS_STEP }
214+ formatValue = { formatSleepHours }
149215 disabled = { isCompleted }
150216 onChange = { ( value ) => updateAnswer ( "sleepLength" , value ) }
151217 />
@@ -159,11 +225,13 @@ export function DailyQuizForm() {
159225 </ CardContent >
160226 </ Card >
161227
162- < Card >
228+ < Card className = { isCompleted ? "opacity-90" : undefined } >
163229 < CardHeader >
164230 < CardTitle className = "text-base" > Daily journal</ CardTitle >
165231 < CardDescription >
166- Write about your day. Saved separately from your quiz answers.
232+ { isCompleted
233+ ? "Your journal entry for today."
234+ : "Write about your day." }
167235 </ CardDescription >
168236 </ CardHeader >
169237 < CardContent className = "space-y-3" >
@@ -183,37 +251,11 @@ export function DailyQuizForm() {
183251
184252 { error ? < p className = "text-sm text-red-500" > { error } </ p > : null }
185253
186- { isCompleted && submission ? (
187- < Card >
188- < CardContent className = "flex flex-col items-center gap-4 pt-6" >
189- < PixelAvatar mood = { submission . condition . mood } size = "md" />
190- < div className = "grid w-full grid-cols-3 gap-2 text-center text-sm" >
191- < div className = "rounded-lg border px-3 py-2" >
192- < p className = "text-muted-foreground" > Mood</ p >
193- < p className = "font-medium capitalize" >
194- { submission . condition . mood }
195- </ p >
196- </ div >
197- < div className = "rounded-lg border px-3 py-2" >
198- < p className = "text-muted-foreground" > Energy</ p >
199- < p className = "font-medium" >
200- { submission . condition . energy } /{ WELLNESS_SCALE_MAX }
201- </ p >
202- </ div >
203- < div className = "rounded-lg border px-3 py-2" >
204- < p className = "text-muted-foreground" > Health</ p >
205- < p className = "font-medium" >
206- { submission . condition . health } /{ WELLNESS_SCALE_MAX }
207- </ p >
208- </ div >
209- </ div >
210- </ CardContent >
211- </ Card >
212- ) : (
254+ { ! isCompleted ? (
213255 < Button className = "w-full" disabled = { ! canSubmit } onClick = { handleSubmit } >
214256 { isSubmitting ? "Saving..." : "Complete daily quiz" }
215257 </ Button >
216- ) }
258+ ) : null }
217259 </ div >
218260 ) ;
219261}
0 commit comments