236 lines
7.3 KiB
Markdown
236 lines
7.3 KiB
Markdown
# Story 3.1: Structure de Données JSON pour les Projets
|
|
|
|
## Status
|
|
|
|
Ready for Dev
|
|
|
|
## Story
|
|
|
|
**As a** développeur,
|
|
**I want** définir et créer le fichier JSON contenant les données des projets,
|
|
**so that** je centralise les informations et facilite la maintenance.
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. Le fichier `data/projects.json` est créé avec la structure définie
|
|
2. La structure supporte : id, title, slug, category (vedette/secondaire), thumbnail, url, technologies[], context, solution, teamwork, duration, testimonial, screenshots[]
|
|
3. Au moins 2 projets de test sont ajoutés pour valider la structure
|
|
4. Une fonction PHP `getProjects()` lit et décode le JSON
|
|
5. La fonction gère les erreurs (fichier manquant, JSON invalide)
|
|
|
|
## Tasks / Subtasks
|
|
|
|
- [] **Task 1 : Définir la structure JSON** (AC: 2)
|
|
- [] Documenter tous les champs requis et optionnels
|
|
- [] Définir les types de données pour chaque champ
|
|
- [] Définir les valeurs possibles pour category
|
|
|
|
- [] **Task 2 : Créer le fichier projects.json** (AC: 1, 3)
|
|
- [] Créer `data/projects.json`
|
|
- [] Ajouter 2-3 projets de test
|
|
- [] Valider la syntaxe JSON
|
|
|
|
- [] **Task 3 : Créer les fonctions PHP d'accès** (AC: 4, 5)
|
|
- [] Créer `loadJsonData()` générique
|
|
- [] Créer `getProjects()`
|
|
- [] Créer `getProjectsByCategory()`
|
|
- [] Créer `getProjectBySlug()`
|
|
- [] Gérer les erreurs (fichier manquant, JSON invalide)
|
|
|
|
- [] **Task 4 : Tester les fonctions**
|
|
- [] Tester avec fichier valide
|
|
- [] Tester avec fichier manquant
|
|
- [] Tester avec JSON invalide
|
|
|
|
## Dev Notes
|
|
|
|
### Structure data/projects.json
|
|
|
|
```json
|
|
{
|
|
"projects": [
|
|
{
|
|
"id": 1,
|
|
"title": "Site E-commerce XYZ",
|
|
"slug": "ecommerce-xyz",
|
|
"category": "vedette",
|
|
"thumbnail": "ecommerce-xyz-thumb.webp",
|
|
"url": "https://example.com",
|
|
"github": "https://github.com/user/project",
|
|
"technologies": ["PHP", "JavaScript", "Tailwind CSS", "MySQL"],
|
|
"context": "Client souhaitant moderniser sa boutique en ligne pour améliorer l'expérience utilisateur et augmenter les conversions.",
|
|
"solution": "Développement d'une solution e-commerce sur mesure avec panier persistant, paiement sécurisé Stripe, et interface d'administration.",
|
|
"teamwork": "Projet réalisé en collaboration avec un designer UI/UX. J'ai pris en charge l'intégration et le développement backend.",
|
|
"duration": "3 mois",
|
|
"screenshots": [
|
|
"ecommerce-xyz-screen-1.webp",
|
|
"ecommerce-xyz-screen-2.webp",
|
|
"ecommerce-xyz-screen-3.webp"
|
|
]
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Application de Gestion",
|
|
"slug": "app-gestion",
|
|
"category": "vedette",
|
|
"thumbnail": "app-gestion-thumb.webp",
|
|
"url": null,
|
|
"github": "https://github.com/user/app-gestion",
|
|
"technologies": ["React", "Node.js", "PostgreSQL", "Docker"],
|
|
"context": "Startup ayant besoin d'un outil interne pour gérer ses ressources et planifier ses projets.",
|
|
"solution": "Application web full-stack avec authentification, gestion des rôles, tableaux de bord et exports PDF.",
|
|
"teamwork": null,
|
|
"duration": "4 mois",
|
|
"screenshots": [
|
|
"app-gestion-screen-1.webp"
|
|
]
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Site Vitrine Restaurant",
|
|
"slug": "restaurant-vitrine",
|
|
"category": "secondaire",
|
|
"thumbnail": "restaurant-thumb.webp",
|
|
"url": "https://restaurant-example.com",
|
|
"github": null,
|
|
"technologies": ["HTML", "CSS", "JavaScript"],
|
|
"context": "Restaurant local souhaitant une présence en ligne simple.",
|
|
"solution": null,
|
|
"teamwork": null,
|
|
"duration": "2 semaines",
|
|
"screenshots": []
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Champs du Projet
|
|
|
|
| Champ | Type | Requis | Description |
|
|
|-------|------|--------|-------------|
|
|
| id | number | Oui | Identifiant unique |
|
|
| title | string | Oui | Titre du projet |
|
|
| slug | string | Oui | URL-friendly (unique) |
|
|
| category | string | Oui | "vedette" ou "secondaire" |
|
|
| thumbnail | string | Oui | Nom du fichier image |
|
|
| url | string/null | Non | URL du projet en ligne |
|
|
| github | string/null | Non | URL du repo GitHub |
|
|
| technologies | array | Oui | Liste des technos |
|
|
| context | string | Oui | Description du contexte |
|
|
| solution | string/null | Non | Description technique |
|
|
| teamwork | string/null | Non | Travail d'équipe |
|
|
| duration | string | Oui | Durée du projet |
|
|
| screenshots | array | Non | Liste des captures |
|
|
|
|
### Fonctions PHP (includes/functions.php)
|
|
|
|
```php
|
|
/**
|
|
* Charge et parse un fichier JSON
|
|
*/
|
|
function loadJsonData(string $filename): array
|
|
{
|
|
$path = __DIR__ . "/../data/{$filename}";
|
|
|
|
if (!file_exists($path)) {
|
|
error_log("JSON file not found: {$filename}");
|
|
return [];
|
|
}
|
|
|
|
$content = file_get_contents($path);
|
|
$data = json_decode($content, true);
|
|
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
error_log("JSON parse error in {$filename}: " . json_last_error_msg());
|
|
return [];
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Récupère tous les projets
|
|
*/
|
|
function getProjects(): array
|
|
{
|
|
$data = loadJsonData('projects.json');
|
|
return $data['projects'] ?? [];
|
|
}
|
|
|
|
/**
|
|
* Récupère les projets par catégorie
|
|
*/
|
|
function getProjectsByCategory(string $category): array
|
|
{
|
|
return array_filter(getProjects(), fn($p) => $p['category'] === $category);
|
|
}
|
|
|
|
/**
|
|
* Récupère un projet par son slug
|
|
*/
|
|
function getProjectBySlug(string $slug): ?array
|
|
{
|
|
$projects = getProjects();
|
|
foreach ($projects as $project) {
|
|
if ($project['slug'] === $slug) {
|
|
return $project;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Récupère les technologies uniques de tous les projets
|
|
*/
|
|
function getAllTechnologies(): array
|
|
{
|
|
$technologies = [];
|
|
foreach (getProjects() as $project) {
|
|
foreach ($project['technologies'] ?? [] as $tech) {
|
|
if (!in_array($tech, $technologies)) {
|
|
$technologies[] = $tech;
|
|
}
|
|
}
|
|
}
|
|
sort($technologies);
|
|
return $technologies;
|
|
}
|
|
```
|
|
|
|
## Testing
|
|
|
|
- [] Le fichier JSON est valide (pas d'erreur de syntaxe)
|
|
- [] `getProjects()` retourne un tableau de projets
|
|
- [] `getProjectsByCategory('vedette')` retourne les projets vedettes
|
|
- [] `getProjectBySlug('ecommerce-xyz')` retourne le bon projet
|
|
- [] `getProjectBySlug('inexistant')` retourne null
|
|
- [] Fichier manquant → tableau vide, pas d'exception
|
|
|
|
## Dev Agent Record
|
|
|
|
### Agent Model Used
|
|
Claude Opus 4.5 (claude-opus-4-5-20251101)
|
|
|
|
### File List
|
|
| File | Action | Description |
|
|
|------|--------|-------------|
|
|
| `data/projects.json` | Created | Fichier JSON avec 3 projets de test |
|
|
| `includes/functions.php` | Modified | Ajout des fonctions d'accès aux données JSON |
|
|
|
|
### Completion Notes
|
|
- Structure JSON complète avec tous les champs requis et optionnels
|
|
- 3 projets de test ajoutés (2 vedettes, 1 secondaire)
|
|
- Fonctions PHP: `loadJsonData()`, `getProjects()`, `getProjectsByCategory()`, `getProjectBySlug()`, `getAllTechnologies()`
|
|
- Gestion des erreurs: fichier manquant et JSON invalide retournent tableau vide avec log
|
|
- Tous les tests passent (8/8)
|
|
|
|
### Debug Log References
|
|
Aucun problème rencontré.
|
|
|
|
## Change Log
|
|
|
|
| Date | Version | Description | Author |
|
|
|------|---------|-------------|--------|
|
|
| 2026-01-22 | 0.1 | Création initiale | Sarah (PO) |
|
|
| 2026-01-23 | 1.0 | Implémentation complète | James (Dev) |
|