feat: extend user profile with onboarding data model
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user