feat: extend user profile with onboarding data model

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Millian Lamiaux
2026-02-21 00:04:53 +01:00
parent 540bb015c7
commit b60083341e
4 changed files with 46 additions and 9 deletions

View File

@@ -5,6 +5,7 @@
import { useRef, useEffect, useCallback } from 'react'
import { usePlayerStore } from '../stores'
import i18n from '@/src/shared/i18n'
import type { Workout } from '../types'
export type TimerPhase = 'PREP' | 'WORK' | 'REST' | 'COMPLETE'
@@ -47,7 +48,7 @@ export function useTimer(workout: Workout | null): UseTimerReturn {
workTime: 20,
restTime: 10,
rounds: 8,
exercises: [{ name: 'Ready', duration: 20 }],
exercises: [{ name: i18n.t('screens:player.phases.prep'), duration: 20 }],
}
// Calculate phase duration
@@ -75,7 +76,7 @@ export function useTimer(workout: Workout | null): UseTimerReturn {
intervalRef.current = setInterval(() => {
const s = usePlayerStore.getState()
if (s.timeRemaining <= 1) {
if (s.timeRemaining <= 0) {
// Phase transition
if (s.phase === 'PREP') {
store.setPhase('WORK')

View File

@@ -87,7 +87,6 @@ export const useActivityStore = create<ActivityState>()(
// Standalone helper functions (use outside selectors)
export function getWeeklyActivity(history: WorkoutResult[]): DayActivity[] {
const days: DayActivity[] = []
const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const today = new Date()
const startOfWeek = new Date(today)
startOfWeek.setDate(today.getDate() - today.getDay())
@@ -100,7 +99,7 @@ export function getWeeklyActivity(history: WorkoutResult[]): DayActivity[] {
r => getDateString(r.completedAt) === dateStr
)
days.push({
date: dayNames[i],
date: String(i),
completed: workoutsOnDay.length > 0,
workoutCount: workoutsOnDay.length,
})

View File

@@ -6,7 +6,16 @@
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
import AsyncStorage from '@react-native-async-storage/async-storage'
import type { UserProfile, UserSettings, SubscriptionPlan } from '../types'
import { getLocales } from 'expo-localization'
import type { UserProfile, UserSettings, SubscriptionPlan, FitnessLevel, FitnessGoal, WeeklyFrequency } from '../types'
interface OnboardingData {
name: string
fitnessLevel: FitnessLevel
goal: FitnessGoal
weeklyFrequency: WeeklyFrequency
barriers: string[]
}
interface UserState {
profile: UserProfile
@@ -15,16 +24,22 @@ interface UserState {
updateProfile: (updates: Partial<UserProfile>) => void
updateSettings: (updates: Partial<UserSettings>) => void
setSubscription: (plan: SubscriptionPlan) => void
completeOnboarding: (data: OnboardingData) => void
}
export const useUserStore = create<UserState>()(
persist(
(set) => ({
profile: {
name: 'Alex',
email: 'alex@example.com',
joinDate: 'January 2026',
subscription: 'premium-monthly',
name: '',
email: '',
joinDate: new Date().toLocaleDateString(getLocales()[0]?.languageTag ?? 'en-US', { month: 'long', year: 'numeric' }),
subscription: 'free',
onboardingCompleted: false,
fitnessLevel: 'beginner',
goal: 'cardio',
weeklyFrequency: 3,
barriers: [],
},
settings: {
haptics: true,
@@ -48,6 +63,19 @@ export const useUserStore = create<UserState>()(
set((state) => ({
profile: { ...state.profile, subscription: plan },
})),
completeOnboarding: (data) =>
set((state) => ({
profile: {
...state.profile,
name: data.name,
fitnessLevel: data.fitnessLevel,
goal: data.goal,
weeklyFrequency: data.weeklyFrequency,
barriers: data.barriers,
onboardingCompleted: true,
},
})),
}),
{
name: 'tabatafit-user',

View File

@@ -12,11 +12,20 @@ export interface UserSettings {
reminderTime: string
}
export type FitnessLevel = 'beginner' | 'intermediate' | 'advanced'
export type FitnessGoal = 'weight-loss' | 'cardio' | 'strength' | 'wellness'
export type WeeklyFrequency = 2 | 3 | 5
export interface UserProfile {
name: string
email: string
joinDate: string
subscription: SubscriptionPlan
onboardingCompleted: boolean
fitnessLevel: FitnessLevel
goal: FitnessGoal
weeklyFrequency: WeeklyFrequency
barriers: string[]
}
export interface Achievement {