feat: explore tab, React Query data layer, programs, sync, analytics, testing infrastructure
- Replace browse tab with Supabase-connected explore tab with filters - Add React Query for data fetching with loading states - Add 3 structured programs with weekly progression - Add Supabase anonymous auth sync service - Add PostHog analytics with screen tracking and events - Add comprehensive test strategy (Vitest + Maestro E2E) - Add RevenueCat subscription system with DEV simulation - Add i18n translations for new screens (EN/FR/DE/ES) - Add data deletion modal, sync consent modal - Add assessment screen and program routes - Add GitHub Actions CI workflow - Update activity store with sync integration
This commit is contained in:
@@ -235,3 +235,77 @@ ON CONFLICT DO NOTHING;
|
||||
-- SELECT id, email, 'admin'
|
||||
-- FROM auth.users
|
||||
-- WHERE email = 'your-email@example.com';
|
||||
|
||||
-- ============================================================
|
||||
-- USER SYNC TABLES (Premium Feature - Anonymous Auth)
|
||||
-- ============================================================
|
||||
|
||||
-- User profiles (created after opt-in to sync for personalization)
|
||||
CREATE TABLE IF NOT EXISTS public.user_profiles (
|
||||
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
email TEXT,
|
||||
name TEXT NOT NULL,
|
||||
fitness_level TEXT NOT NULL,
|
||||
goal TEXT NOT NULL,
|
||||
weekly_frequency INTEGER NOT NULL,
|
||||
barriers JSONB DEFAULT '[]',
|
||||
is_anonymous BOOLEAN DEFAULT true,
|
||||
sync_enabled BOOLEAN DEFAULT true,
|
||||
subscription_plan TEXT DEFAULT 'premium-yearly',
|
||||
onboarding_completed_at TIMESTAMP WITH TIME ZONE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Workout sessions (synced history for personalization)
|
||||
CREATE TABLE IF NOT EXISTS public.workout_sessions (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
workout_id UUID NOT NULL REFERENCES public.workouts(id),
|
||||
completed_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
duration_seconds INTEGER,
|
||||
calories_burned INTEGER,
|
||||
feeling_rating INTEGER CHECK (feeling_rating BETWEEN 1 AND 5),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- User preferences for personalization
|
||||
CREATE TABLE IF NOT EXISTS public.user_preferences (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
preferred_categories TEXT[] DEFAULT '{}',
|
||||
preferred_trainers TEXT[] DEFAULT '{}',
|
||||
preferred_durations INTEGER[] DEFAULT '{}',
|
||||
difficulty_preference TEXT DEFAULT 'matched',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(user_id)
|
||||
);
|
||||
|
||||
-- Indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_workout_sessions_user_id ON public.workout_sessions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_workout_sessions_completed_at ON public.workout_sessions(completed_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_profiles_email ON public.user_profiles(email);
|
||||
|
||||
-- RLS Policies for user data protection
|
||||
ALTER TABLE public.user_profiles ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.workout_sessions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.user_preferences ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY "Users manage own profile"
|
||||
ON public.user_profiles FOR ALL USING (id = auth.uid());
|
||||
|
||||
CREATE POLICY "Users manage own sessions"
|
||||
ON public.workout_sessions FOR ALL USING (user_id = auth.uid());
|
||||
|
||||
CREATE POLICY "Users manage own preferences"
|
||||
ON public.user_preferences FOR ALL USING (user_id = auth.uid());
|
||||
|
||||
-- Triggers for updated_at
|
||||
CREATE TRIGGER update_user_profiles_updated_at
|
||||
BEFORE UPDATE ON public.user_profiles
|
||||
FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_user_preferences_updated_at
|
||||
BEFORE UPDATE ON public.user_preferences
|
||||
FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
|
||||
|
||||
Reference in New Issue
Block a user