refactor: code quality cleanup — remove any types, add logger, rename Kine to Tabata

- Phase 0: Rename all Kine references to Tabata (types, files, imports, i18n, analytics events)
- Phase 1: Add test coverage for tabataProgramStore, workoutProgramStore, and color utils (47 tests)
- Phase 2: Remove all `any` types from production code with proper typed replacements
- Phase 3: Replace ~60 raw console.* calls with __DEV__-gated logger utility
- Phase 4: Verify .DS_Store housekeeping (already clean)

0 TypeScript errors, 583/583 tests passing.
This commit is contained in:
Millian Lamiaux
2026-04-17 18:56:24 +02:00
parent e0e02c4550
commit 791f432334
176 changed files with 16508 additions and 2305 deletions

View File

@@ -0,0 +1,66 @@
import { Metadata } from "next"
import Link from "next/link"
import { notFound } from "next/navigation"
import { ArrowLeft } from "lucide-react"
import { Button } from "@/components/ui/button"
import TrainerForm from "@/components/trainer-form"
import { supabase } from "@/lib/supabase"
interface EditTrainerPageProps {
params: Promise<{
id: string
}>
}
async function getTrainer(id: string) {
const { data, error } = await (supabase.from("trainers") as any)
.select("*")
.eq("id", id)
.single()
if (error || !data) {
return null
}
return data
}
export async function generateMetadata({ params }: EditTrainerPageProps): Promise<Metadata> {
const resolvedParams = await params
const trainer = await getTrainer(resolvedParams.id)
if (!trainer) {
return {
title: "Trainer Not Found | TabataFit Admin",
}
}
return {
title: `Edit ${trainer.name} | TabataFit Admin`,
}
}
export default async function EditTrainerPage({ params }: EditTrainerPageProps) {
const resolvedParams = await params
const trainer = await getTrainer(resolvedParams.id)
if (!trainer) {
notFound()
}
return (
<div className="p-8 max-w-2xl">
<Button variant="ghost" asChild className="mb-4 text-neutral-400 hover:text-white">
<Link href="/trainers">
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Trainers
</Link>
</Button>
<h1 className="text-2xl font-bold text-white mb-6">Edit Trainer</h1>
<TrainerForm initialData={trainer} mode="edit" />
</div>
)
}

View File

@@ -0,0 +1,10 @@
import TrainerForm from "@/components/trainer-form"
export default function NewTrainerPage() {
return (
<div className="p-8 max-w-2xl">
<h1 className="text-2xl font-bold text-white mb-6">Add New Trainer</h1>
<TrainerForm mode="create" />
</div>
)
}

View File

@@ -16,6 +16,7 @@ import { Plus, Trash2, Edit, Loader2, Users, AlertCircle } from "lucide-react";
import Link from "next/link";
import { toast } from "sonner";
import type { Database } from "@/lib/supabase";
import { useRouter } from "next/navigation";
type Trainer = Database["public"]["Tables"]["trainers"]["Row"];
@@ -145,12 +146,21 @@ export default function TrainersPage() {
<CardContent className="p-6">
<div className="flex items-start justify-between">
<div className="flex items-center gap-4">
<div
className="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold"
style={{ backgroundColor: trainer.color }}
>
{trainer.name[0]}
</div>
{trainer.avatar_url ? (
<img
src={trainer.avatar_url}
alt={trainer.name}
className="w-12 h-12 rounded-full object-cover border-2"
style={{ borderColor: trainer.color }}
/>
) : (
<div
className="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold"
style={{ backgroundColor: trainer.color }}
>
{trainer.name[0]}
</div>
)}
<div>
<h3 className="text-lg font-semibold text-white">{trainer.name}</h3>
<p className="text-neutral-400">{trainer.specialty}</p>
@@ -161,9 +171,11 @@ export default function TrainersPage() {
</div>
<div className="flex gap-2">
<Button variant="ghost" size="icon" className="text-neutral-400 hover:text-white">
<Edit className="w-4 h-4" />
</Button>
<Link href={`/trainers/${trainer.id}/edit`}>
<Button variant="ghost" size="icon" className="text-neutral-400 hover:text-white">
<Edit className="w-4 h-4" />
</Button>
</Link>
<Button
variant="ghost"
size="icon"