Files
tabatago/admin-web/lib/supabase.ts
Millian Lamiaux 8c90b73d90 update config, admin-web tooling & relocate agent skills
Update app.json config and add new dependencies in package.json. Update
.gitignore for new patterns. Add timed-exercise editor/list components,
warmup/stretch video migration, and Supabase helpers in admin-web.
Relocate agent skills from .agents/skills/ to .opencode/skills/.
2026-04-21 21:51:11 +02:00

393 lines
12 KiB
TypeScript

import { createBrowserClient } from '@supabase/ssr'
// Support both EXPO_PUBLIC_ (mobile) and NEXT_PUBLIC_ (web) prefixes
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
|| process.env.EXPO_PUBLIC_SUPABASE_URL
|| 'http://localhost:54321'
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|| process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY
|| 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0'
if (typeof window !== 'undefined') {
console.log('Supabase URL:', supabaseUrl)
console.log('Using EXPO_PUBLIC:', !!process.env.EXPO_PUBLIC_SUPABASE_URL)
console.log('Using NEXT_PUBLIC:', !!process.env.NEXT_PUBLIC_SUPABASE_URL)
}
// Use createBrowserClient for proper cookie handling in Next.js
// This stores the session in cookies so middleware can access it
export const supabase = createBrowserClient<Database>(
supabaseUrl,
supabaseKey
)
export const isSupabaseConfigured = () => {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL
return url !== 'your_supabase_project_url' && url !== 'http://localhost:54321' && !!url
}
export type Json =
| string
| number
| boolean
| null
| { [key: string]: Json | undefined }
| Json[]
export const MUSIC_GENRES = [
'edm', 'hip-hop', 'pop', 'rock', 'latin', 'house',
'drum-and-bass', 'dubstep', 'r-and-b', 'country', 'metal', 'ambient',
] as const
export type MusicGenre = typeof MUSIC_GENRES[number]
export const GENRE_LABELS: Record<MusicGenre, string> = {
'edm': 'EDM',
'hip-hop': 'Hip Hop',
'pop': 'Pop',
'rock': 'Rock',
'latin': 'Latin',
'house': 'House',
'drum-and-bass': 'Drum & Bass',
'dubstep': 'Dubstep',
'r-and-b': 'R&B',
'country': 'Country',
'metal': 'Metal',
'ambient': 'Ambient',
}
export interface Database {
public: {
Tables: {
workouts: {
Row: {
id: string
title: string
trainer_id: string
category: 'full-body' | 'core' | 'upper-body' | 'lower-body' | 'cardio'
level: 'Beginner' | 'Intermediate' | 'Advanced'
duration: number
calories: number
rounds: number
prep_time: number
work_time: number
rest_time: number
equipment: string[]
music_vibe: 'electronic' | 'hip-hop' | 'pop' | 'rock' | 'chill'
exercises: { name: string; duration: number }[]
thumbnail_url: string | null
video_url: string | null
is_featured: boolean
created_at: string
updated_at: string
}
Insert: {
id?: string
title: string
trainer_id: string
category: 'full-body' | 'core' | 'upper-body' | 'lower-body' | 'cardio'
level: 'Beginner' | 'Intermediate' | 'Advanced'
duration: number
calories: number
rounds: number
prep_time: number
work_time: number
rest_time: number
equipment?: string[]
music_vibe: 'electronic' | 'hip-hop' | 'pop' | 'rock' | 'chill'
exercises: { name: string; duration: number }[]
thumbnail_url?: string | null
video_url?: string | null
is_featured?: boolean
}
Update: Partial<Database['public']['Tables']['workouts']['Insert']>
}
trainers: {
Row: {
id: string
name: string
specialty: string
color: string
avatar_url: string | null
workout_count: number
created_at: string
updated_at: string
}
Insert: {
id?: string
name: string
specialty: string
color: string
avatar_url?: string | null
workout_count?: number
}
Update: Partial<Omit<Database['public']['Tables']['trainers']['Insert'], 'id'>>
}
collections: {
Row: {
id: string
title: string
description: string
icon: string
gradient: string[] | null
created_at: string
updated_at: string
}
Insert: {
id?: string
title: string
description: string
icon: string
gradient?: string[] | null
}
Update: Partial<Omit<Database['public']['Tables']['collections']['Insert'], 'id'>>
}
collection_workouts: {
Row: {
id: string
collection_id: string
workout_id: string
sort_order: number
}
}
workout_programs: {
Row: {
id: string
title: string
description: string
body_zone: 'upper-body' | 'lower-body' | 'full-body'
level: 'Beginner' | 'Intermediate' | 'Advanced'
is_free: boolean
estimated_duration: number
estimated_calories: number
icon: string | null
accent_color: string | null
sort_order: number
created_at: string
updated_at: string
}
Insert: {
id?: string
title: string
description?: string
body_zone: 'upper-body' | 'lower-body' | 'full-body'
level: 'Beginner' | 'Intermediate' | 'Advanced'
is_free?: boolean
estimated_duration?: number
estimated_calories?: number
icon?: string | null
accent_color?: string | null
sort_order?: number
}
Update: Partial<Omit<Database['public']['Tables']['workout_programs']['Insert'], 'id'>>
}
program_tabatas: {
Row: {
id: string
program_id: string
position: number
exercise_1_name: string
exercise_1_name_en: string | null
exercise_1_tip: string | null
exercise_1_tip_en: string | null
exercise_1_modification: string | null
exercise_1_modification_en: string | null
exercise_1_progression: string | null
exercise_1_progression_en: string | null
exercise_2_name: string
exercise_2_name_en: string | null
exercise_2_tip: string | null
exercise_2_tip_en: string | null
exercise_2_modification: string | null
exercise_2_modification_en: string | null
exercise_2_progression: string | null
exercise_2_progression_en: string | null
exercise_1_video_url: string | null
exercise_2_video_url: string | null
rounds: number
work_time: number
rest_time: number
}
Insert: {
id?: string
program_id: string
position: number
exercise_1_name: string
exercise_1_name_en?: string | null
exercise_1_tip?: string | null
exercise_1_tip_en?: string | null
exercise_1_modification?: string | null
exercise_1_modification_en?: string | null
exercise_1_progression?: string | null
exercise_1_progression_en?: string | null
exercise_2_name: string
exercise_2_name_en?: string | null
exercise_2_tip?: string | null
exercise_2_tip_en?: string | null
exercise_2_modification?: string | null
exercise_2_modification_en?: string | null
exercise_2_progression?: string | null
exercise_2_progression_en?: string | null
exercise_1_video_url?: string | null
exercise_2_video_url?: string | null
rounds?: number
work_time?: number
rest_time?: number
}
Update: Partial<Omit<Database['public']['Tables']['program_tabatas']['Insert'], 'id' | 'program_id'>>
}
workout_warmup_exercises: {
Row: {
id: string
program_id: string
position: number
name: string
name_en: string | null
tip: string | null
tip_en: string | null
duration: number
video_url: string | null
created_at: string
}
Insert: {
id?: string
program_id: string
position: number
name: string
name_en?: string | null
tip?: string | null
tip_en?: string | null
duration: number
video_url?: string | null
}
Update: Partial<Omit<Database['public']['Tables']['workout_warmup_exercises']['Insert'], 'id' | 'program_id'>>
}
workout_stretch_exercises: {
Row: {
id: string
program_id: string
position: number
name: string
name_en: string | null
tip: string | null
tip_en: string | null
duration: number
video_url: string | null
created_at: string
}
Insert: {
id?: string
program_id: string
position: number
name: string
name_en?: string | null
tip?: string | null
tip_en?: string | null
duration: number
video_url?: string | null
}
Update: Partial<Omit<Database['public']['Tables']['workout_stretch_exercises']['Insert'], 'id' | 'program_id'>>
}
workout_videos: {
Row: {
id: string
workout_id: string
trainer_id: string
video_url: string
video_path: string
created_at: string
}
Insert: {
id?: string
workout_id: string
trainer_id: string
video_url: string
video_path: string
}
Update: {
video_url?: string
video_path?: string
}
}
exercise_videos: {
Row: {
id: string
workout_id: string
trainer_id: string
exercise_name: string
video_url: string
video_path: string
video_type: 'exercise' | 'rest'
duration_seconds: number | null
created_at: string
}
Insert: {
id?: string
workout_id: string
trainer_id: string
exercise_name: string
video_url: string
video_path: string
video_type?: 'exercise' | 'rest'
duration_seconds?: number | null
}
Update: {
video_url?: string
video_path?: string
video_type?: 'exercise' | 'rest'
duration_seconds?: number | null
}
}
admin_users: {
Row: {
id: string
email: string
role: 'admin' | 'editor'
created_at: string
last_login: string | null
}
}
download_jobs: {
Row: {
id: string
playlist_url: string
playlist_title: string | null
status: 'pending' | 'processing' | 'completed' | 'failed'
total_items: number
completed_items: number
failed_items: number
created_by: string
created_at: string
updated_at: string
}
Insert: {
id?: string
playlist_url: string
playlist_title?: string | null
status?: 'pending' | 'processing' | 'completed' | 'failed'
total_items?: number
completed_items?: number
failed_items?: number
created_by: string
}
Update: Partial<Omit<Database['public']['Tables']['download_jobs']['Insert'], 'id'>>
}
download_items: {
Row: {
id: string
job_id: string
video_id: string
title: string | null
duration_seconds: number | null
thumbnail_url: string | null
status: 'pending' | 'downloading' | 'completed' | 'failed'
storage_path: string | null
public_url: string | null
error_message: string | null
genre: MusicGenre | null
created_at: string
}
}
}
}
}