18 KiB
Focus, Dashboard, And Progress Model Work Report
#Overview
Today the timer work moved from a sprint-only model toward a more general session flow that can support both focused work and breaks.
The main goal was to start closing the vision gap around focus -> break -> continue, while keeping the implementation local to the existing timer route instead of introducing a larger navigation or state-management rewrite.
The work therefore covered both app-side session-model changes and the Supabase function updates needed to make the new flow actually start and finalize sessions correctly.
Later in the same work session, the scope also expanded into the dashboard and the progress presentation on the detail screens so the app better matches the remaining vision-gap plan.
The scope then expanded one step further into first-time-user friction, so the work also covered a guided onboarding path and clearer empty states for new accounts.
Later still, the work expanded beyond the app itself into the signup-confirmation path around account creation. That included auth-screen behavior fixes, a shorter guided-setup timer for quick verification, a minimal confirmation landing page for VPS deployment, Caddy routing, and a less boilerplate-looking confirmation email template.
#ImplementedFeatures
#GeneralSessionModel
Changed the local timer model from a sprint-specific structure into a more general session structure:
- added
SessionTypeinlib/types.ts - introduced the session types:
focusshort_breaklong_break
- replaced the old
ActiveSprintshape withActiveSessioninlib/asyncStorage.ts - stored
sessionTypetogether withsessionId,taskId,durationSeconds, andendTime
This means the active timer is no longer assumed to always be a task-linked focus sprint.
#TimerSessionStartAndRestore
Updated the timer screen so it can start and restore different session types:
- replaced sprint-specific storage calls with
GetActiveSession(...),SaveActiveSession(...), andRemoveActiveSession(...) - generalized the timer start path into
startSession(...) - passed
p_session_typeinto the Supabasestart_sprint_session(...)RPC - kept task linkage only for
focussessions - updated the restore logic so a focus session restores by
tId, while break sessions restore bysessionType
This gives the existing timer screen enough information to behave differently for focus sessions and break sessions without creating a second timer screen.
#DashboardAndTaskIntegration
Updated the surrounding screens so they understand the new active-session shape:
- updated
app/task/viewDetailsTask.tsxto read the new active session model - updated
app/(tabs)/index.tsxso the dashboard card can describe either a focus session or a break session - made the dashboard open the timer with either a task id or a break-session configuration, depending on what is active
This keeps the rest of the app aligned with the timer change, instead of leaving the new session model isolated to one file.
#DashboardProgressAndHistory
Extended the dashboard so it works more clearly as a study-activity overview:
- added a compact
Study progresssummary near the top of the dashboard - showed:
Focus sessions todayMinutes todayMinutes this week
- loaded the summary from
sprint_sessionsinstead of from planning data - added a
Recent sessionssection showing:- task title when available
- session type
- duration
- final status
- date and time
- added a small
Recently completed taskssection based on recent task completion updates
This moved the dashboard closer to the vision requirement that progress should reflect actual study behavior rather than only task structure.
#DashboardLayoutRestructure
Reworked the order of the dashboard sections so the screen reads more clearly as a home surface:
- kept the active-session card at the top when relevant
- placed
Study progressbefore the task lists - moved
Tasks with upcoming deadlinesdirectly under the progress summary - pushed
Recent sessionsandRecently completed taskslower as secondary context - made the lower history area work as a side-by-side layout when screen width allows it
- changed the dashboard body to a scrollable layout so the extra sections still fit without clipping
The result is a dashboard that moves from orientation, to next action, to history instead of feeling like a stacked report page.
#ConsistentProgressModel
Aligned the progress language across the detail screens so each layer measures one clear thing:
- on the subject details screen, changed the progress label from
Assignment ProgresstoAssignments completed - added helper text clarifying that subject progress is based only on completed assignments
- on the assignment details screen, changed the progress label from
Task ProgresstoTasks completed - added helper text clarifying that assignment progress is based only on completed tasks
- on the task details screen, separated completion state from study activity
- added a dedicated
Study activityblock showing:- tracked focus time from
tasks.totalTimeInSeconds - completed focus-session count from
sprint_sessions
- tracked focus time from
- added an explicit task status label so completion state is not confused with study effort
This made the meaning of progress more consistent:
Subjectnow reads as assignment completionAssignmentnow reads as task completionTasknow reads as study effort plus completion stateDashboardnow reads as recent study activity
#FirstTimeSetupAndEmptyStates
Added the first guided setup flow so new users are pushed into one clear study path instead of landing in an empty app:
- added a dedicated
app/setup.tsxroute for first-time setup - changed signup so a newly authenticated user is routed to setup instead of directly to the dashboard
- built the setup flow as a strict sequence:
- create first subject
- create first assignment
- create first task
- start first sprint
- updated the subject, assignment, and task creation screens so they can advance automatically to the next setup step
- removed the setup-breaking success popups between those guided creation steps
- added short auth-screen explanations describing:
- what the app does
- why an account exists
- that study structure and progress follow the user
- added clearer empty states on the dashboard and subjects screen that point the user into guided setup
- tightened the empty-state copy on subject and assignment details so each one points toward the next required object in the hierarchy
This closes a large part of the first-run friction gap without introducing a separate onboarding system or broader navigation rewrite.
#AuthScreenKeyboardHandling
Adjusted the auth screens so text inputs do not stay buried behind the on-screen keyboard:
- updated
app/login.tsxso the login content scrolls and shifts upward when the keyboard opens - updated
app/createUser.tsxso the entire create-account content block lifts upward with the keyboard instead of only trying to scroll one input into view - kept the changes local to the auth screens instead of introducing a broader shared keyboard abstraction
This was aimed specifically at the real usability problem where the password field could end up hidden during login or signup.
#SignupNavigationAndHeaderAlignment
Adjusted the signup screen navigation so it matches the rest of the app more closely:
- removed the temporary in-screen back button experiment from the signup page
- re-enabled the normal stack header for
createUserinapp/_layout.tsx - kept signup navigation on the default app-style back arrow instead of a one-off local control
This kept the auth flow visually more consistent with the rest of the route stack.
#GuidedSetupFiveSecondSprint
Changed guided setup so the first sprint can be tested almost immediately:
- updated
app/setup.tsxso the setup flow opens the timer with a fixed5second duration - extended
app/task/timer.tsxso it can also accept an explicitdurationSecondsroute param - kept the rest of the timer behavior unchanged, so the setup-specific shortcut still runs through the same session start, storage, and completion flow as normal timers
This made the first-run path quicker to test without changing the broader timer model back to a special-case setup implementation.
#SignupConfirmationDeployment
Built the first deployable confirmation landing page outside the Expo app:
- added
deploy/signup-confirmation/site/index.htmlas a minimal static confirmation page - added
deploy/signup-confirmation/docker-compose.ymlso the page can be served withnginx:alpine - added a small README for VPS deployment notes and port mapping
- verified the page deployment path together with the external VPS/domain setup already in use
This created a concrete destination URL for signup confirmation emails instead of leaving the email to resolve into a blank or undefined endpoint.
#CaddyAndEmailConfirmationPolish
Finished the external confirmation flow around signup:
- corrected the Caddy reverse-proxy target from container port
8080to80for thenginxconfirmation container - confirmed that the confirmation page then resolved correctly behind the existing Caddy-plus-Docker setup
- replaced the original bare confirmation email body with a cleaner branded HTML email using the existing
{{ .ConfirmationURL }}placeholder
This moved the signup confirmation flow from a functional but rough setup into something that is both deployable and presentable.
#PostSessionBreakFlow
Added the first real post-session flow in the timer UI:
- after a completed focus session, the timer now shows:
Start short breakSkip break
- starting the break reopens the same timer route in
short_breakmode - after a completed short break, the timer now shows:
Continue with same taskBack to dashboard
- passed
returnTaskIdthrough the route so the timer can return the user to the original task after the break
This is the first implementation of an actual study loop rather than a timer that simply ends and disappears.
#BreakTimerPresentation
Adjusted the timer UI so break sessions read more clearly:
- added a fixed-duration block for break sessions instead of showing the normal duration picker
- used a fixed 5-minute short-break duration for the first implementation
- kept the focus-session picker unchanged
- made the break start button match the existing
Start Sprintbutton styling, but show onlyStart - removed the bug where picker or pre-start break elements remained visible on top of the running break session
This keeps the first break flow minimal and visually consistent with the existing timer screen.
#SupabaseFunctionAlignment
Adjusted the Supabase side so the new app flow could actually run:
- updated
start_sprint_session(...)to acceptp_session_type - allowed break sessions to start with
taskId = null - aligned the SQL with the real table schema using:
sessionIdtaskIduserIdsessionTypecountedIntoTaskTotal
- corrected function-return behavior so the app receives the created session id in the shape it expects
- kept finalize logic so only
focussessions contribute totasks.totalTimeInSeconds
Without this database alignment, the app-side session model would compile but still fail when starting real sessions.
#ProblemsAndSetbacks
#SchemaMismatch
The main blocker today was that the first SQL version assumed table columns that did not exist in the real Supabase schema.
The actual sprint_sessions table already contained:
sessionIdtaskIduserIdplannedDurationstartedAtendedAtelapsedSecondsstatuscountedIntoTaskTotalsessionType
But it did not contain createdAt or updatedAt, so the first function version failed at runtime.
#FunctionReturnShape
Another blocker was the shape of the return value from start_sprint_session(...).
Even after the insert worked, the app still showed:
Session could not be created.
The issue was not the insert itself, but that the returned value shape did not match what getSessionId(...) was looking for on the app side.
This had to be corrected so the RPC returned the created session id in a directly readable object shape.
#PauseUIScreenOverlap
The first version of the break UI had presentation bugs:
- the pause start button text looked cramped and awkward
- pre-start pause UI stayed visible after the break actually started
- picker or fixed-duration elements overlapped the running break session
This was corrected by hiding pre-start break UI while the timer is running and by reverting the pause start button back to the same visual model as the existing sprint start button.
#ConfirmationRoutePortMismatch
The external signup-confirmation deployment initially failed behind Caddy with HTTP ERROR 502.
The actual issue was not the Docker network arrangement itself, but that the reverse proxy was targeting signup-confirmation:8080 even though the nginx container listens internally on port 80.
Changing the upstream target to the real container port fixed the route.
#CurrentState
The timer flow now goes further than the previous sprint-only model.
The app now supports:
- starting a
focussession tied to a task - starting a
short_breaksession with no task linkage - storing and restoring the active session with its type
- showing a post-focus decision between taking a break or skipping it
- returning from a completed short break into the same task flow or back to the dashboard
- keeping break sessions out of task time totals
At this point, the app has the first working version of the focus-and-break loop described in the vision plan, even though the cycle logic and long-break offer are not implemented yet.
The dashboard also now gives a clearer answer to:
What have I done today?What should I work on next?
And the detail screens now separate planning completion from study activity more explicitly, which makes the app easier to read without having to infer what each progress bar means.
For a brand-new user, the app also no longer drops straight into a generic empty state after account creation. There is now a clearer route from signup to:
- first subject
- first assignment
- first task
- first sprint
That makes the hierarchy feel more guided and less like a blank structure the user has to interpret alone.
The signup path also now has a more complete confirmation loop around it:
- the auth screens behave more safely when the mobile keyboard opens
- guided setup can launch a very short first sprint for fast verification
- the confirmation email can point to a real public landing page
- that landing page has a working Docker/Caddy deployment path on the VPS
- the email itself no longer looks like a raw boilerplate template
#Verification
During today's work, the following behaviors were verified through implementation checks and runtime iteration:
- the new session model compiles across timer, dashboard, task details, and local storage
start_sprint_session(...)now succeeds after the Supabase function updates- the timer can start using the new session-based flow
- break sessions no longer leave the picker or fixed-duration setup visible on top of the running timer
- the dashboard compiles with the new progress-summary, recent-session, and recent-completion sections
- the task details screen compiles with a new
sprint_sessions-based completed-session count - the subject and assignment detail screens now label completion metrics more explicitly
- the new guided setup route compiles and links correctly with the subject, assignment, and task creation flow
- the login and signup screens compile after the keyboard-handling adjustments
- the guided setup route now opens the timer with an explicit 5-second fixed duration
- the deployable signup-confirmation page was brought up behind the VPS Caddy setup after correcting the upstream container port from
8080to80 - the confirmation email template was updated to a cleaner HTML version while keeping
{{ .ConfirmationURL }}as the actual confirmation link placeholder
Static verification also passed:
npx tsc --noEmit
exited successfully
npm run lint
exited with existing warning only in:
- app/task/timer.tsx
I did not run a live interactive app test for the later dashboard and progress-model changes. That part of the verification is static rather than runtime-confirmed.
#FilesChanged
Main app files worked on:
app/task/timer.tsx
app/task/viewDetailsTask.tsx
app/(tabs)/index.tsx
app/(tabs)/subjects.tsx
app/setup.tsx
app/subject/viewDetailsSubject.tsx
app/subject/upsertSubject.tsx
app/assignment/viewDetailsAssignment.tsx
app/assignment/upsertAssignment.tsx
app/task/upsertTask.tsx
app/createUser.tsx
app/login.tsx
app/_layout.tsx
lib/asyncStorage.ts
lib/types.ts
deploy/signup-confirmation/docker-compose.yml
deploy/signup-confirmation/site/index.html
deploy/signup-confirmation/README.md
New note added:
notes/work-report-timer-2026-05-03.md
#Conclusion
The main result today was not just a timer change, but a broader step toward closing the remaining vision gaps around study flow and progress clarity.
The app now has:
- a session model that can represent both focused work and breaks
- the first concrete
focus -> break -> continuepath from the vision plan - a dashboard that reflects recent study effort more directly
- detail screens that use more explicit and consistent progress meanings
- a first guided onboarding path that leads a new user from signup to their first workable sprint path
- more usable auth screens when entering credentials on mobile
- a complete basic signup-confirmation flow that now reaches a real deployed landing page and a cleaner confirmation email
The remaining work in this area is now less about inventing the model from scratch and more about extending, polishing, and live-validating the pieces that are already in place.