diff --git a/api/app/Models/Project.php b/api/app/Models/Project.php new file mode 100644 index 0000000..5bedf50 --- /dev/null +++ b/api/app/Models/Project.php @@ -0,0 +1,48 @@ + 'date', + 'is_featured' => 'boolean', + ]; + } + + public function skills(): BelongsToMany + { + return $this->belongsToMany(Skill::class, 'skill_project') + ->withPivot(['level_before', 'level_after', 'level_description_key']) + ->withTimestamps(); + } + + public function scopeFeatured(Builder $query): Builder + { + return $query->where('is_featured', true); + } + + public function scopeOrdered(Builder $query): Builder + { + return $query->orderBy('display_order'); + } +} diff --git a/api/app/Models/Skill.php b/api/app/Models/Skill.php new file mode 100644 index 0000000..c863540 --- /dev/null +++ b/api/app/Models/Skill.php @@ -0,0 +1,37 @@ +belongsToMany(Project::class, 'skill_project') + ->withPivot(['level_before', 'level_after', 'level_description_key']) + ->withTimestamps(); + } + + public function scopeByCategory(Builder $query, string $category): Builder + { + return $query->where('category', $category); + } + + public function scopeOrdered(Builder $query): Builder + { + return $query->orderBy('display_order'); + } +} diff --git a/api/app/Models/Translation.php b/api/app/Models/Translation.php new file mode 100644 index 0000000..1750c6f --- /dev/null +++ b/api/app/Models/Translation.php @@ -0,0 +1,27 @@ +where('lang', $lang); + } + + public static function getTranslation(string $key, string $lang, string $fallback = 'fr'): ?string + { + $translation = static::where('key_name', $key)->where('lang', $lang)->first(); + + if (!$translation && $lang !== $fallback) { + $translation = static::where('key_name', $key)->where('lang', $fallback)->first(); + } + + return $translation?->value; + } +} diff --git a/api/database/migrations/2026_02_05_000001_create_translations_table.php b/api/database/migrations/2026_02_05_000001_create_translations_table.php new file mode 100644 index 0000000..c48326f --- /dev/null +++ b/api/database/migrations/2026_02_05_000001_create_translations_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('lang', 5); + $table->string('key_name', 255); + $table->text('value'); + $table->timestamps(); + + $table->unique(['lang', 'key_name'], 'unique_translation'); + $table->index('lang', 'idx_lang'); + }); + } + + public function down(): void + { + Schema::dropIfExists('translations'); + } +}; diff --git a/api/database/migrations/2026_02_05_000002_create_projects_table.php b/api/database/migrations/2026_02_05_000002_create_projects_table.php new file mode 100644 index 0000000..5b8373e --- /dev/null +++ b/api/database/migrations/2026_02_05_000002_create_projects_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('slug')->unique(); + $table->string('title_key'); + $table->string('description_key'); + $table->string('short_description_key'); + $table->string('image')->nullable(); + $table->string('url')->nullable(); + $table->string('github_url')->nullable(); + $table->date('date_completed'); + $table->boolean('is_featured')->default(false); + $table->integer('display_order')->default(0); + $table->timestamps(); + + $table->index('display_order'); + }); + } + + public function down(): void + { + Schema::dropIfExists('projects'); + } +}; diff --git a/api/database/migrations/2026_02_05_000003_create_skills_table.php b/api/database/migrations/2026_02_05_000003_create_skills_table.php new file mode 100644 index 0000000..205a09b --- /dev/null +++ b/api/database/migrations/2026_02_05_000003_create_skills_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('slug')->unique(); + $table->string('name_key'); + $table->string('description_key'); + $table->string('icon')->nullable(); + $table->string('category'); + $table->integer('max_level')->default(5); + $table->integer('display_order')->default(0); + $table->timestamps(); + + $table->index('category'); + }); + } + + public function down(): void + { + Schema::dropIfExists('skills'); + } +}; diff --git a/api/database/migrations/2026_02_05_000004_create_skill_project_table.php b/api/database/migrations/2026_02_05_000004_create_skill_project_table.php new file mode 100644 index 0000000..8a0e776 --- /dev/null +++ b/api/database/migrations/2026_02_05_000004_create_skill_project_table.php @@ -0,0 +1,28 @@ +id(); + $table->foreignId('skill_id')->constrained()->cascadeOnDelete(); + $table->foreignId('project_id')->constrained()->cascadeOnDelete(); + $table->integer('level_before'); + $table->integer('level_after'); + $table->string('level_description_key')->nullable(); + $table->timestamps(); + + $table->unique(['skill_id', 'project_id']); + }); + } + + public function down(): void + { + Schema::dropIfExists('skill_project'); + } +}; diff --git a/api/database/seeders/DatabaseSeeder.php b/api/database/seeders/DatabaseSeeder.php index 6b901f8..7659065 100644 --- a/api/database/seeders/DatabaseSeeder.php +++ b/api/database/seeders/DatabaseSeeder.php @@ -2,7 +2,6 @@ namespace Database\Seeders; -use App\Models\User; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; @@ -10,16 +9,13 @@ class DatabaseSeeder extends Seeder { use WithoutModelEvents; - /** - * Seed the application's database. - */ public function run(): void { - // User::factory(10)->create(); - - User::factory()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', + $this->call([ + TranslationSeeder::class, + SkillSeeder::class, + ProjectSeeder::class, + SkillProjectSeeder::class, ]); } } diff --git a/api/database/seeders/ProjectSeeder.php b/api/database/seeders/ProjectSeeder.php new file mode 100644 index 0000000..cd593a6 --- /dev/null +++ b/api/database/seeders/ProjectSeeder.php @@ -0,0 +1,55 @@ + 'skycel-portfolio', + 'title_key' => 'project.skycel-portfolio.title', + 'description_key' => 'project.skycel-portfolio.description', + 'short_description_key' => 'project.skycel-portfolio.short_description', + 'image' => 'projects/skycel-portfolio.png', + 'url' => 'https://skycel.dev', + 'github_url' => 'https://git.araneite.dev/skycel/Portfolio-Game', + 'date_completed' => '2026-03-01', + 'is_featured' => true, + 'display_order' => 1, + ], + [ + 'slug' => 'ecommerce-app', + 'title_key' => 'project.ecommerce-app.title', + 'description_key' => 'project.ecommerce-app.description', + 'short_description_key' => 'project.ecommerce-app.short_description', + 'image' => 'projects/ecommerce-app.png', + 'url' => null, + 'github_url' => 'https://github.com/skycel/ecommerce-app', + 'date_completed' => '2025-09-15', + 'is_featured' => true, + 'display_order' => 2, + ], + [ + 'slug' => 'analytics-dashboard', + 'title_key' => 'project.analytics-dashboard.title', + 'description_key' => 'project.analytics-dashboard.description', + 'short_description_key' => 'project.analytics-dashboard.short_description', + 'image' => 'projects/analytics-dashboard.png', + 'url' => null, + 'github_url' => null, + 'date_completed' => '2025-06-01', + 'is_featured' => false, + 'display_order' => 3, + ], + ]; + + foreach ($projects as $project) { + Project::create($project); + } + } +} diff --git a/api/database/seeders/SkillProjectSeeder.php b/api/database/seeders/SkillProjectSeeder.php new file mode 100644 index 0000000..928cf91 --- /dev/null +++ b/api/database/seeders/SkillProjectSeeder.php @@ -0,0 +1,83 @@ +first(); + $ecommerce = Project::where('slug', 'ecommerce-app')->first(); + $dashboard = Project::where('slug', 'analytics-dashboard')->first(); + + // Skycel Portfolio: Vue.js, Nuxt, Laravel, TailwindCSS, Git + $skycel->skills()->attach(Skill::where('slug', 'vuejs')->first()->id, [ + 'level_before' => 2, + 'level_after' => 4, + 'level_description_key' => 'skill_project.skycel-portfolio.vuejs.level_description', + ]); + $skycel->skills()->attach(Skill::where('slug', 'nuxt')->first()->id, [ + 'level_before' => 0, + 'level_after' => 3, + 'level_description_key' => 'skill_project.skycel-portfolio.nuxt.level_description', + ]); + $skycel->skills()->attach(Skill::where('slug', 'laravel')->first()->id, [ + 'level_before' => 2, + 'level_after' => 3, + 'level_description_key' => 'skill_project.skycel-portfolio.laravel.level_description', + ]); + $skycel->skills()->attach(Skill::where('slug', 'tailwindcss')->first()->id, [ + 'level_before' => 1, + 'level_after' => 3, + 'level_description_key' => 'skill_project.skycel-portfolio.tailwindcss.level_description', + ]); + $skycel->skills()->attach(Skill::where('slug', 'git')->first()->id, [ + 'level_before' => 3, + 'level_after' => 4, + 'level_description_key' => null, + ]); + + // E-commerce App: Laravel, Vue.js, PHP, Docker + $ecommerce->skills()->attach(Skill::where('slug', 'laravel')->first()->id, [ + 'level_before' => 1, + 'level_after' => 2, + 'level_description_key' => 'skill_project.ecommerce-app.laravel.level_description', + ]); + $ecommerce->skills()->attach(Skill::where('slug', 'vuejs')->first()->id, [ + 'level_before' => 1, + 'level_after' => 2, + 'level_description_key' => 'skill_project.ecommerce-app.vuejs.level_description', + ]); + $ecommerce->skills()->attach(Skill::where('slug', 'php')->first()->id, [ + 'level_before' => 2, + 'level_after' => 3, + 'level_description_key' => null, + ]); + $ecommerce->skills()->attach(Skill::where('slug', 'docker')->first()->id, [ + 'level_before' => 0, + 'level_after' => 1, + 'level_description_key' => null, + ]); + + // Analytics Dashboard: TypeScript, Node.js, Git + $dashboard->skills()->attach(Skill::where('slug', 'typescript')->first()->id, [ + 'level_before' => 1, + 'level_after' => 3, + 'level_description_key' => 'skill_project.analytics-dashboard.typescript.level_description', + ]); + $dashboard->skills()->attach(Skill::where('slug', 'nodejs')->first()->id, [ + 'level_before' => 1, + 'level_after' => 2, + 'level_description_key' => 'skill_project.analytics-dashboard.nodejs.level_description', + ]); + $dashboard->skills()->attach(Skill::where('slug', 'git')->first()->id, [ + 'level_before' => 2, + 'level_after' => 3, + 'level_description_key' => null, + ]); + } +} diff --git a/api/database/seeders/SkillSeeder.php b/api/database/seeders/SkillSeeder.php new file mode 100644 index 0000000..14086b8 --- /dev/null +++ b/api/database/seeders/SkillSeeder.php @@ -0,0 +1,36 @@ + 'vuejs', 'name_key' => 'skill.vuejs.name', 'description_key' => 'skill.vuejs.description', 'icon' => 'vuejs', 'category' => 'Frontend', 'max_level' => 5, 'display_order' => 1], + ['slug' => 'nuxt', 'name_key' => 'skill.nuxt.name', 'description_key' => 'skill.nuxt.description', 'icon' => 'nuxt', 'category' => 'Frontend', 'max_level' => 5, 'display_order' => 2], + ['slug' => 'typescript', 'name_key' => 'skill.typescript.name', 'description_key' => 'skill.typescript.description', 'icon' => 'typescript', 'category' => 'Frontend', 'max_level' => 5, 'display_order' => 3], + ['slug' => 'tailwindcss', 'name_key' => 'skill.tailwindcss.name', 'description_key' => 'skill.tailwindcss.description', 'icon' => 'tailwindcss', 'category' => 'Frontend', 'max_level' => 5, 'display_order' => 4], + + // Backend + ['slug' => 'laravel', 'name_key' => 'skill.laravel.name', 'description_key' => 'skill.laravel.description', 'icon' => 'laravel', 'category' => 'Backend', 'max_level' => 5, 'display_order' => 5], + ['slug' => 'php', 'name_key' => 'skill.php.name', 'description_key' => 'skill.php.description', 'icon' => 'php', 'category' => 'Backend', 'max_level' => 5, 'display_order' => 6], + ['slug' => 'nodejs', 'name_key' => 'skill.nodejs.name', 'description_key' => 'skill.nodejs.description', 'icon' => 'nodejs', 'category' => 'Backend', 'max_level' => 5, 'display_order' => 7], + + // Tools + ['slug' => 'git', 'name_key' => 'skill.git.name', 'description_key' => 'skill.git.description', 'icon' => 'git', 'category' => 'Tools', 'max_level' => 5, 'display_order' => 8], + ['slug' => 'docker', 'name_key' => 'skill.docker.name', 'description_key' => 'skill.docker.description', 'icon' => 'docker', 'category' => 'Tools', 'max_level' => 5, 'display_order' => 9], + + // Soft skills + ['slug' => 'communication', 'name_key' => 'skill.communication.name', 'description_key' => 'skill.communication.description', 'icon' => 'communication', 'category' => 'Soft skills', 'max_level' => 5, 'display_order' => 10], + ]; + + foreach ($skills as $skill) { + Skill::create($skill); + } + } +} diff --git a/api/database/seeders/TranslationSeeder.php b/api/database/seeders/TranslationSeeder.php new file mode 100644 index 0000000..344a0f7 --- /dev/null +++ b/api/database/seeders/TranslationSeeder.php @@ -0,0 +1,124 @@ + $lang, + 'key_name' => $key_name, + 'value' => $value, + ]); + } + } +} diff --git a/docs/implementation-artifacts/1-2-base-donnees-migrations-initiales.md b/docs/implementation-artifacts/1-2-base-donnees-migrations-initiales.md index d33ecd0..c784b10 100644 --- a/docs/implementation-artifacts/1-2-base-donnees-migrations-initiales.md +++ b/docs/implementation-artifacts/1-2-base-donnees-migrations-initiales.md @@ -1,6 +1,6 @@ # Story 1.2: Base de données et migrations initiales -Status: ready-for-dev +Status: review ## Story @@ -20,71 +20,71 @@ so that l'API peut servir du contenu bilingue. ## Tasks / Subtasks -- [ ] **Task 1: Configuration connexion MariaDB** (AC: #1) - - [ ] Vérifier que MariaDB est installé et accessible - - [ ] Créer la base de données `skycel` si elle n'existe pas - - [ ] Configurer `api/.env` avec les variables DB_* correctes - - [ ] Tester la connexion avec `php artisan db:show` +- [x] **Task 1: Configuration connexion MariaDB** (AC: #1) + - [x] Vérifier que MariaDB est installé et accessible + - [x] Créer la base de données `skycel` si elle n'existe pas + - [x] Configurer `api/.env` avec les variables DB_* correctes + - [x] Tester la connexion avec `php artisan db:show` -- [ ] **Task 2: Migration table translations** (AC: #1) - - [ ] Créer migration `create_translations_table` - - [ ] Colonnes: id, lang (VARCHAR 5), key_name (VARCHAR 255), value (TEXT), timestamps - - [ ] Index unique composite sur (lang, key_name) - - [ ] Index simple sur lang pour les requêtes par langue +- [x] **Task 2: Migration table translations** (AC: #1) + - [x] Créer migration `create_translations_table` + - [x] Colonnes: id, lang (VARCHAR 5), key_name (VARCHAR 255), value (TEXT), timestamps + - [x] Index unique composite sur (lang, key_name) + - [x] Index simple sur lang pour les requêtes par langue -- [ ] **Task 3: Migration table projects** (AC: #2) - - [ ] Créer migration `create_projects_table` - - [ ] Colonnes: id, slug (unique), title_key, description_key, short_description_key, image, url (nullable), github_url (nullable), date_completed (date), is_featured (boolean, default false), display_order (integer, default 0), timestamps - - [ ] Index sur slug (unique) - - [ ] Index sur display_order pour le tri +- [x] **Task 3: Migration table projects** (AC: #2) + - [x] Créer migration `create_projects_table` + - [x] Colonnes: id, slug (unique), title_key, description_key, short_description_key, image, url (nullable), github_url (nullable), date_completed (date), is_featured (boolean, default false), display_order (integer, default 0), timestamps + - [x] Index sur slug (unique) + - [x] Index sur display_order pour le tri -- [ ] **Task 4: Migration table skills** (AC: #3) - - [ ] Créer migration `create_skills_table` - - [ ] Colonnes: id, slug (unique), name_key, description_key, icon (nullable), category (enum ou string: Frontend, Backend, Tools, Soft skills), max_level (integer, default 5), display_order (integer, default 0), timestamps - - [ ] Index sur slug (unique) - - [ ] Index sur category pour le filtrage +- [x] **Task 4: Migration table skills** (AC: #3) + - [x] Créer migration `create_skills_table` + - [x] Colonnes: id, slug (unique), name_key, description_key, icon (nullable), category (enum ou string: Frontend, Backend, Tools, Soft skills), max_level (integer, default 5), display_order (integer, default 0), timestamps + - [x] Index sur slug (unique) + - [x] Index sur category pour le filtrage -- [ ] **Task 5: Migration table pivot skill_project** (AC: #4) - - [ ] Créer migration `create_skill_project_table` - - [ ] Colonnes: id, skill_id (FK), project_id (FK), level_before (integer), level_after (integer), level_description_key (nullable), timestamps - - [ ] Foreign key skill_id → skills.id avec ON DELETE CASCADE - - [ ] Foreign key project_id → projects.id avec ON DELETE CASCADE - - [ ] Index composite sur (skill_id, project_id) pour éviter les doublons +- [x] **Task 5: Migration table pivot skill_project** (AC: #4) + - [x] Créer migration `create_skill_project_table` + - [x] Colonnes: id, skill_id (FK), project_id (FK), level_before (integer), level_after (integer), level_description_key (nullable), timestamps + - [x] Foreign key skill_id → skills.id avec ON DELETE CASCADE + - [x] Foreign key project_id → projects.id avec ON DELETE CASCADE + - [x] Index composite sur (skill_id, project_id) pour éviter les doublons -- [ ] **Task 6: Model Translation** (AC: #5) - - [ ] Créer `app/Models/Translation.php` - - [ ] Propriétés fillable: lang, key_name, value - - [ ] Scope `scopeForLang($query, $lang)` pour filtrer par langue - - [ ] Méthode statique `getTranslation($key, $lang, $fallback = 'fr')` +- [x] **Task 6: Model Translation** (AC: #5) + - [x] Créer `app/Models/Translation.php` + - [x] Propriétés fillable: lang, key_name, value + - [x] Scope `scopeForLang($query, $lang)` pour filtrer par langue + - [x] Méthode statique `getTranslation($key, $lang, $fallback = 'fr')` -- [ ] **Task 7: Model Project avec relations** (AC: #5) - - [ ] Créer `app/Models/Project.php` - - [ ] Propriétés fillable: slug, title_key, description_key, short_description_key, image, url, github_url, date_completed, is_featured, display_order - - [ ] Casts: date_completed → date, is_featured → boolean - - [ ] Relation `skills()`: belongsToMany(Skill::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps() - - [ ] Scope `scopeFeatured($query)` pour les projets mis en avant - - [ ] Scope `scopeOrdered($query)` pour le tri par display_order +- [x] **Task 7: Model Project avec relations** (AC: #5) + - [x] Créer `app/Models/Project.php` + - [x] Propriétés fillable: slug, title_key, description_key, short_description_key, image, url, github_url, date_completed, is_featured, display_order + - [x] Casts: date_completed → date, is_featured → boolean + - [x] Relation `skills()`: belongsToMany(Skill::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps() + - [x] Scope `scopeFeatured($query)` pour les projets mis en avant + - [x] Scope `scopeOrdered($query)` pour le tri par display_order -- [ ] **Task 8: Model Skill avec relations** (AC: #5) - - [ ] Créer `app/Models/Skill.php` - - [ ] Propriétés fillable: slug, name_key, description_key, icon, category, max_level, display_order - - [ ] Relation `projects()`: belongsToMany(Project::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps() - - [ ] Scope `scopeByCategory($query, $category)` pour filtrer par catégorie - - [ ] Scope `scopeOrdered($query)` pour le tri par display_order +- [x] **Task 8: Model Skill avec relations** (AC: #5) + - [x] Créer `app/Models/Skill.php` + - [x] Propriétés fillable: slug, name_key, description_key, icon, category, max_level, display_order + - [x] Relation `projects()`: belongsToMany(Project::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps() + - [x] Scope `scopeByCategory($query, $category)` pour filtrer par catégorie + - [x] Scope `scopeOrdered($query)` pour le tri par display_order -- [ ] **Task 9: Seeders de base** (AC: #6, #7) - - [ ] Créer `database/seeders/TranslationSeeder.php` avec traductions FR et EN de test - - [ ] Créer `database/seeders/SkillSeeder.php` avec 8-10 compétences de test (Frontend, Backend, Tools) - - [ ] Créer `database/seeders/ProjectSeeder.php` avec 3-4 projets de test - - [ ] Créer `database/seeders/SkillProjectSeeder.php` pour lier compétences et projets - - [ ] Mettre à jour `DatabaseSeeder.php` pour appeler les seeders dans l'ordre correct (translations → skills → projects → skill_project) +- [x] **Task 9: Seeders de base** (AC: #6, #7) + - [x] Créer `database/seeders/TranslationSeeder.php` avec traductions FR et EN de test + - [x] Créer `database/seeders/SkillSeeder.php` avec 8-10 compétences de test (Frontend, Backend, Tools) + - [x] Créer `database/seeders/ProjectSeeder.php` avec 3-4 projets de test + - [x] Créer `database/seeders/SkillProjectSeeder.php` pour lier compétences et projets + - [x] Mettre à jour `DatabaseSeeder.php` pour appeler les seeders dans l'ordre correct (translations → skills → projects → skill_project) -- [ ] **Task 10: Validation finale** (AC: tous) - - [ ] `php artisan migrate:fresh` fonctionne sans erreur - - [ ] `php artisan db:seed` fonctionne sans erreur - - [ ] Vérifier en BDD que les tables sont créées avec les bons schémas - - [ ] Vérifier que les relations fonctionnent: `Project::first()->skills` et `Skill::first()->projects` - - [ ] Vérifier que les traductions fonctionnent: `Translation::getTranslation('project.skycel.title', 'fr')` +- [x] **Task 10: Validation finale** (AC: tous) + - [x] `php artisan migrate:fresh` fonctionne sans erreur + - [x] `php artisan db:seed` fonctionne sans erreur + - [x] Vérifier en BDD que les tables sont créées avec les bons schémas + - [x] Vérifier que les relations fonctionnent: `Project::first()->skills` et `Skill::first()->projects` + - [x] Vérifier que les traductions fonctionnent: `Translation::getTranslation('project.skycel-portfolio.title', 'fr')` ## Dev Notes @@ -259,16 +259,41 @@ api/ ### Agent Model Used -{{agent_model_name_version}} +Claude Opus 4.5 (claude-opus-4-5-20251101) ### Debug Log References +- Pivot table naming: Laravel attend `project_skill` (ordre alphabétique), mais la story spécifie `skill_project`. Résolu en ajoutant le nom de table explicite dans les relations `belongsToMany`. +- Connexion MySQL: `DB_PASSWORD=` (vide) requis pour root@localhost sur Laragon. + ### Completion Notes List +- 4 migrations créées et fonctionnelles (translations, projects, skills, skill_project) +- 3 models Eloquent avec relations belongsToMany, scopes et casts +- 4 seeders de test: 37 traductions FR + 37 EN, 10 skills, 3 projets, 12 liens skill_project +- `migrate:fresh --seed` fonctionne sans erreur +- Relations vérifiées: Project->skills (5), Skill->projects (2) +- Traductions vérifiées: FR, EN et fallback fonctionnent +- Scopes vérifiés: featured (2), byCategory Frontend (4), Backend (3) + ### Change Log | Date | Change | Author | |------|--------|--------| | 2026-02-03 | Story créée avec contexte complet | SM Agent | +| 2026-02-05 | Tasks 1-10 implémentées et validées | Dev Agent (Claude Opus 4.5) | ### File List +- `api/database/migrations/2026_02_05_000001_create_translations_table.php` — CRÉÉ +- `api/database/migrations/2026_02_05_000002_create_projects_table.php` — CRÉÉ +- `api/database/migrations/2026_02_05_000003_create_skills_table.php` — CRÉÉ +- `api/database/migrations/2026_02_05_000004_create_skill_project_table.php` — CRÉÉ +- `api/app/Models/Translation.php` — CRÉÉ +- `api/app/Models/Project.php` — CRÉÉ +- `api/app/Models/Skill.php` — CRÉÉ +- `api/database/seeders/TranslationSeeder.php` — CRÉÉ +- `api/database/seeders/SkillSeeder.php` — CRÉÉ +- `api/database/seeders/ProjectSeeder.php` — CRÉÉ +- `api/database/seeders/SkillProjectSeeder.php` — CRÉÉ +- `api/database/seeders/DatabaseSeeder.php` — MODIFIÉ + diff --git a/docs/implementation-artifacts/sprint-status.yaml b/docs/implementation-artifacts/sprint-status.yaml index 6685b05..bd72b33 100644 --- a/docs/implementation-artifacts/sprint-status.yaml +++ b/docs/implementation-artifacts/sprint-status.yaml @@ -45,7 +45,7 @@ development_status: # ═══════════════════════════════════════════════════════════════════════════ epic-1: in-progress 1-1-initialisation-monorepo-infrastructure: review - 1-2-base-donnees-migrations-initiales: ready-for-dev + 1-2-base-donnees-migrations-initiales: review 1-3-systeme-i18n-frontend-api-bilingue: ready-for-dev 1-4-layouts-routing-transitions-page: ready-for-dev 1-5-landing-page-choix-heros: ready-for-dev