diff --git a/bootstrap/app.php b/bootstrap/app.php index 61ef4f1..f29f562 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -12,6 +12,9 @@ return Application::configure(basePath: dirname(__DIR__)) health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { + // Derrière NPM (reverse-proxy) : faire confiance au proxy pour X-Forwarded-Proto=https + // (sinon Laravel génère des URLs http -> mixed-content, casse les assets Filament). + $middleware->trustProxies(at: '*'); // Active le flow Sanctum SPA : cookie de session + protection CSRF pour les requêtes API du front. $middleware->statefulApi(); // Pas de route web "login" nommée (SPA) : rediriger les invités vers le front plutôt que planter. diff --git a/docker-compose.yml b/docker-compose.yml index 027d436..8b1c031 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,9 +10,10 @@ services: - "192.168.1.136:8111:80" labels: - homepage.group=Développement - - homepage.name=StreakFit API - - homepage.icon=mdi-fire - - homepage.href=https://api.streakfit.nfteam.ovh - - homepage.description=API cross-training (Laravel OSDD / Octane) + - homepage.name=StreakFit — Admin + - homepage.icon=mdi-cog + - homepage.href=https://streakfit.nfteam.ovh/admin + - homepage.description=Back-office Filament (Laravel OSDD / Octane) + - homepage.weight=2 - com.centurylinklabs.watchtower.enable=true restart: unless-stopped diff --git a/functional/exercises/database/migrations/2026_07_19_014000_add_name_i18n_to_exercises.php b/functional/exercises/database/migrations/2026_07_19_014000_add_name_i18n_to_exercises.php new file mode 100644 index 0000000..281d44a --- /dev/null +++ b/functional/exercises/database/migrations/2026_07_19_014000_add_name_i18n_to_exercises.php @@ -0,0 +1,23 @@ +json('name_i18n')->nullable()->after('name'); + }); + } + + public function down(): void + { + Schema::table('exercises', function (Blueprint $table) { + $table->dropColumn('name_i18n'); + }); + } +}; diff --git a/functional/exercises/routes/api.php b/functional/exercises/routes/api.php index c9a537e..cc0d61f 100644 --- a/functional/exercises/routes/api.php +++ b/functional/exercises/routes/api.php @@ -1,6 +1,7 @@ json([ + 'exercises' => DB::table('exercises')->count(), + 'users' => DB::table('users')->count(), + 'workouts' => DB::table('workout_sessions')->where('status', 'completed')->count(), + 'active_streaks' => DB::table('streaks')->where('current_count', '>', 0)->count(), + ]); + } +} diff --git a/functional/exercises/src/Http/Resources/ExerciseListResource.php b/functional/exercises/src/Http/Resources/ExerciseListResource.php index 3cf621c..d6f6475 100644 --- a/functional/exercises/src/Http/Resources/ExerciseListResource.php +++ b/functional/exercises/src/Http/Resources/ExerciseListResource.php @@ -20,7 +20,7 @@ class ExerciseListResource extends JsonResource return [ 'id' => $this->id, - 'name' => $this->name, + 'name' => $this->resource->localizedName($l), 'slug' => $this->slug, 'body_part' => Exercise::localizeTerm($this->body_part, $l), 'equipment' => Exercise::localizeTerm($this->equipment, $l), diff --git a/functional/exercises/src/Http/Resources/ExerciseResource.php b/functional/exercises/src/Http/Resources/ExerciseResource.php index 5e08c67..d60515d 100644 --- a/functional/exercises/src/Http/Resources/ExerciseResource.php +++ b/functional/exercises/src/Http/Resources/ExerciseResource.php @@ -22,7 +22,7 @@ class ExerciseResource extends JsonResource return [ 'id' => $this->id, - 'name' => $this->name, + 'name' => $model->localizedName($l), 'slug' => $this->slug, 'body_part' => $model::localizeTerm($this->body_part, $l), 'category' => $model::localizeTerm($this->category, $l), diff --git a/functional/exercises/src/Models/Exercise.php b/functional/exercises/src/Models/Exercise.php index e4549b8..b36d756 100644 --- a/functional/exercises/src/Models/Exercise.php +++ b/functional/exercises/src/Models/Exercise.php @@ -22,7 +22,7 @@ class Exercise extends Model use HasFactory; protected $fillable = [ - 'external_id', 'name', 'slug', 'category', 'body_part', 'equipment', + 'external_id', 'name', 'name_i18n', 'slug', 'category', 'body_part', 'equipment', 'target', 'muscle_group', 'secondary_muscles', 'instructions', 'image_path', 'gif_path', 'attribution', ]; @@ -30,6 +30,7 @@ class Exercise extends Model protected $casts = [ 'secondary_muscles' => 'array', 'instructions' => 'array', + 'name_i18n' => 'array', ]; protected $appends = ['image_url', 'gif_url']; @@ -82,6 +83,14 @@ class Exercise extends Model return []; } + /** Nom localisé (name_i18n) avec repli sur le nom anglais canonique. */ + public function localizedName(string $locale): string + { + $map = $this->name_i18n ?? []; + + return $map[$locale] ?? $map[substr($locale, 0, 2)] ?? $this->name; + } + /** Traduit un terme du vocabulaire contrôlé (zone/équipement/muscle) selon la locale. Repli = anglais. */ public static function localizeTerm(?string $value, string $locale): ?string {