remove legacy admin panel, assessment, collection & workout routes

Remove the in-app admin panel (app/admin/, src/admin/), assessment
screen, collection detail routes, and workout detail/category/body-zone
routes. These features have been superseded by the admin-web dashboard
and the new program-based navigation. Also removes stale CLAUDE.md
context files and an accidentally committed image blob.
This commit is contained in:
Millian Lamiaux
2026-04-21 21:49:58 +02:00
parent 791f432334
commit d82205cd71
20 changed files with 0 additions and 3614 deletions

View File

@@ -1,65 +0,0 @@
import { createContext, useContext, useState, useEffect, ReactNode } from 'react'
import { adminService } from '../services/adminService'
import { logger } from '@/src/shared/utils/logger'
interface AdminAuthContextType {
isAuthenticated: boolean
isAdmin: boolean
isLoading: boolean
signIn: (email: string, password: string) => Promise<void>
signOut: () => Promise<void>
}
const AdminAuthContext = createContext<AdminAuthContextType | undefined>(undefined)
export function AdminAuthProvider({ children }: { children: ReactNode }) {
const [isAuthenticated, setIsAuthenticated] = useState(false)
const [isAdmin, setIsAdmin] = useState(false)
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
checkAuth()
}, [])
async function checkAuth() {
try {
const user = await adminService.getCurrentUser()
if (user) {
setIsAuthenticated(true)
const adminStatus = await adminService.isAdmin()
setIsAdmin(adminStatus)
}
} catch (error) {
logger.error('Auth check failed:', error)
} finally {
setIsLoading(false)
}
}
const signIn = async (email: string, password: string) => {
await adminService.signIn(email, password)
setIsAuthenticated(true)
const adminStatus = await adminService.isAdmin()
setIsAdmin(adminStatus)
}
const signOut = async () => {
await adminService.signOut()
setIsAuthenticated(false)
setIsAdmin(false)
}
return (
<AdminAuthContext.Provider value={{ isAuthenticated, isAdmin, isLoading, signIn, signOut }}>
{children}
</AdminAuthContext.Provider>
)
}
export function useAdminAuth() {
const context = useContext(AdminAuthContext)
if (context === undefined) {
throw new Error('useAdminAuth must be used within an AdminAuthProvider')
}
return context
}

View File

@@ -1,282 +0,0 @@
import { supabase, isSupabaseConfigured } from '../../shared/supabase'
import type { Database } from '../../shared/supabase/database.types'
type WorkoutInsert = Database['public']['Tables']['workouts']['Insert']
type WorkoutUpdate = Database['public']['Tables']['workouts']['Update']
type TrainerInsert = Database['public']['Tables']['trainers']['Insert']
type TrainerUpdate = Database['public']['Tables']['trainers']['Update']
type CollectionInsert = Database['public']['Tables']['collections']['Insert']
type CollectionWorkoutInsert = Database['public']['Tables']['collection_workouts']['Insert']
export class AdminService {
private checkConfiguration(): boolean {
if (!isSupabaseConfigured()) {
throw new Error('Supabase is not configured. Please set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY')
}
return true
}
// Workouts
async createWorkout(workout: Omit<WorkoutInsert, 'id' | 'created_at' | 'updated_at'>): Promise<string> {
this.checkConfiguration()
const { data, error } = await supabase
.from('workouts')
.insert(workout as any)
.select('id')
.single()
if (error) {
throw new Error(`Failed to create workout: ${error.message}`)
}
return (data as any).id
}
async updateWorkout(id: string, workout: WorkoutUpdate): Promise<void> {
this.checkConfiguration()
const { error } = await (supabase
.from('workouts') as any)
.update({ ...workout, updated_at: new Date().toISOString() })
.eq('id', id)
if (error) {
throw new Error(`Failed to update workout: ${error.message}`)
}
}
async deleteWorkout(id: string): Promise<void> {
this.checkConfiguration()
const { error } = await supabase
.from('workouts')
.delete()
.eq('id', id)
if (error) {
throw new Error(`Failed to delete workout: ${error.message}`)
}
}
// Trainers
async createTrainer(trainer: Omit<TrainerInsert, 'id' | 'created_at' | 'updated_at'>): Promise<string> {
this.checkConfiguration()
const { data, error } = await supabase
.from('trainers')
.insert(trainer as any)
.select('id')
.single()
if (error) {
throw new Error(`Failed to create trainer: ${error.message}`)
}
return (data as any).id
}
async updateTrainer(id: string, trainer: TrainerUpdate): Promise<void> {
this.checkConfiguration()
const { error } = await (supabase
.from('trainers') as any)
.update({ ...trainer, updated_at: new Date().toISOString() })
.eq('id', id)
if (error) {
throw new Error(`Failed to update trainer: ${error.message}`)
}
}
async deleteTrainer(id: string): Promise<void> {
this.checkConfiguration()
const { error } = await supabase
.from('trainers')
.delete()
.eq('id', id)
if (error) {
throw new Error(`Failed to delete trainer: ${error.message}`)
}
}
// Collections
async createCollection(
collection: Omit<CollectionInsert, 'id' | 'created_at' | 'updated_at'>,
workoutIds: string[]
): Promise<string> {
this.checkConfiguration()
const { data: collectionData, error: collectionError } = await supabase
.from('collections')
.insert(collection as any)
.select('id')
.single()
if (collectionError) {
throw new Error(`Failed to create collection: ${collectionError.message}`)
}
const collectionWorkouts: CollectionWorkoutInsert[] = workoutIds.map((workoutId, index) => ({
collection_id: (collectionData as any).id,
workout_id: workoutId,
sort_order: index,
}))
const { error: linkError } = await supabase
.from('collection_workouts')
.insert(collectionWorkouts as any)
if (linkError) {
throw new Error(`Failed to link workouts to collection: ${linkError.message}`)
}
return (collectionData as any).id
}
async updateCollectionWorkouts(collectionId: string, workoutIds: string[]): Promise<void> {
this.checkConfiguration()
const { error: deleteError } = await supabase
.from('collection_workouts')
.delete()
.eq('collection_id', collectionId)
if (deleteError) {
throw new Error(`Failed to remove existing workouts: ${deleteError.message}`)
}
const collectionWorkouts: CollectionWorkoutInsert[] = workoutIds.map((workoutId, index) => ({
collection_id: collectionId,
workout_id: workoutId,
sort_order: index,
}))
const { error: insertError } = await supabase
.from('collection_workouts')
.insert(collectionWorkouts as any)
if (insertError) {
throw new Error(`Failed to add new workouts: ${insertError.message}`)
}
}
// Storage
async uploadVideo(file: File, path: string): Promise<string> {
this.checkConfiguration()
const { error: uploadError } = await supabase.storage
.from('videos')
.upload(path, file)
if (uploadError) {
throw new Error(`Failed to upload video: ${uploadError.message}`)
}
const { data: { publicUrl } } = supabase.storage
.from('videos')
.getPublicUrl(path)
return publicUrl
}
async uploadThumbnail(file: File, path: string): Promise<string> {
this.checkConfiguration()
const { error: uploadError } = await supabase.storage
.from('thumbnails')
.upload(path, file)
if (uploadError) {
throw new Error(`Failed to upload thumbnail: ${uploadError.message}`)
}
const { data: { publicUrl } } = supabase.storage
.from('thumbnails')
.getPublicUrl(path)
return publicUrl
}
async uploadAvatar(file: File, path: string): Promise<string> {
this.checkConfiguration()
const { error: uploadError } = await supabase.storage
.from('avatars')
.upload(path, file)
if (uploadError) {
throw new Error(`Failed to upload avatar: ${uploadError.message}`)
}
const { data: { publicUrl } } = supabase.storage
.from('avatars')
.getPublicUrl(path)
return publicUrl
}
async deleteVideo(path: string): Promise<void> {
this.checkConfiguration()
const { error } = await supabase.storage
.from('videos')
.remove([path])
if (error) {
throw new Error(`Failed to delete video: ${error.message}`)
}
}
async deleteThumbnail(path: string): Promise<void> {
this.checkConfiguration()
const { error } = await supabase.storage
.from('thumbnails')
.remove([path])
if (error) {
throw new Error(`Failed to delete thumbnail: ${error.message}`)
}
}
// Admin authentication
async signIn(email: string, password: string): Promise<void> {
this.checkConfiguration()
const { error } = await supabase.auth.signInWithPassword({
email,
password,
})
if (error) {
throw new Error(`Authentication failed: ${error.message}`)
}
}
async signOut(): Promise<void> {
await supabase.auth.signOut()
}
async getCurrentUser() {
const { data: { user } } = await supabase.auth.getUser()
return user
}
async isAdmin(): Promise<boolean> {
const user = await this.getCurrentUser()
if (!user) return false
const { data, error } = await supabase
.from('admin_users')
.select('*')
.eq('id', user.id)
.single()
return !error && !!data
}
}
export const adminService = new AdminService()