# Lesstime Application de gestion de projet. Monorepo Symfony 8 (API Platform 4) + Nuxt 4. ## Stack - **Backend** : PHP 8.4, Symfony 8.0, API Platform 4, Doctrine ORM, PostgreSQL 16 - **Frontend** : Nuxt 4 (SSR off / SPA), Vue 3, Pinia, Tailwind CSS, @malio/layer-ui, nuxt-toast, @nuxtjs/i18n, @nuxt/icon - **Auth** : JWT HTTP-only cookie (lexik/jwt-authentication-bundle), login à `/login_check`, cookie `BEARER` - **Docker** : PHP-FPM + Node 24, Nginx (port 8082), PostgreSQL (port 5435) ## Structure ``` src/Entity/ # Entités Doctrine (User, Client, Project, Task, TaskStatus, TaskEffort, TaskPriority, TaskTag, TaskGroup, TimeEntry, GiteaConfiguration, ClientTicket, Notification, TaskDocument, BookStackConfiguration, TaskBookStackLink, TaskRecurrence, ZimbraConfiguration) src/ApiResource/ # Ressources API Platform (si découplées des entités) (ZimbraSettings, ZimbraTestConnection) src/Enum/ # PHP enums (RecurrenceType) src/State/ # Providers et Processors API Platform (MeProvider, AppVersionProvider, ActiveTimeEntryProvider, UserPasswordHasherProcessor, TaskNumberProcessor, ClientTicket*Provider/Processor, NotificationProvider, Gitea*Provider, Gitea*Processor, ZimbraSettingsProvider/Processor, ZimbraTestConnectionProvider, TaskCalendarProcessor, RecurrenceHandler) src/Service/ # Services métier (NotificationService, CalDavService, RecurrenceCalculator) src/Controller/ # Controllers custom Symfony (NotificationUnreadCountController, MarkAllReadController, UserAvatarController, TaskDocumentDownloadController) src/Mcp/Tool/ # MCP tools organisés par domaine (Project/, Task/, TaskMeta/, TimeEntry/, Reference/) src/Security/ # Authenticators custom (ApiTokenAuthenticator pour MCP HTTP) src/Command/ # Commandes console (GenerateApiTokenCommand) src/Repository/ # Repositories Doctrine src/DataFixtures/ # Fixtures config/ # Config Symfony (security, api_platform, lexik_jwt, nelmio_cors, doctrine) config/jwt/ # Clés JWT (private.pem, public.pem) migrations/ # Migrations Doctrine docs/plans/ # Plans d'implémentation docs/superpowers/ # Plans et specs superpowers frontend/ # App Nuxt 4 frontend/pages/ # Pages (index, login, my-tasks, profile, projects, projects/[id], projects/[id]/groups, projects/[id]/archives, time-tracking, admin, portal/, portal/projects/[id], portal/projects/[id]/new-ticket) frontend/layouts/ # Layouts (default, portal) frontend/components/ # Composants Vue organisés en sous-dossiers (ui/, client/, project/, task/, user/, admin/, time-tracking/, client-ticket/, notification/) — inclut admin/AdminZimbraTab frontend/composables/# Composables (useApi, useAppVersion, useNotifications, useClientTicketHelpers, useAvatarService) frontend/stores/ # Stores Pinia (auth, ui, timer) frontend/services/ # Services API (auth, clients, gitea, projects, tasks, task-statuses, task-efforts, task-groups, task-priorities, task-tags, users, time-entries, client-tickets, notifications, task-documents, zimbra, task-recurrences) frontend/services/dto/ # Types TypeScript frontend/i18n/locales/ # Fichiers de traduction (langDir résolu depuis i18n/) ``` ## Commandes ```bash make start # Démarrer les containers make stop # Arrêter les containers make restart # Redémarrer les containers make install # Install complet (composer, migrations, fixtures, build Nuxt) make reset # Tout supprimer et réinstaller (supprime la BDD) make dev-nuxt # Dev server Nuxt (hot reload, port 3002) make shell # Shell dans le container PHP make shell-root # Shell root dans le container PHP make cache-clear # Vider le cache Symfony make migration-migrate # Lancer les migrations make fixtures # Charger les fixtures make db-reset # Reset BDD + migrations + fixtures make test # PHPUnit make php-cs-fixer-allow-risky # Fix code style PHP make logs-dev # Tail logs Symfony ``` ## Conventions ### Commits Format : `() : ` (espace avant et après `:`) Types autorisés (minuscules) : `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test` Exemples : `feat : add login page`, `fix(auth) : prevent null token crash` ### Tags & Versioning - La version de l'app est dans `config/version.yaml` (paramètre `app.version`) - À chaque création de tag, **toujours** mettre à jour `config/version.yaml` avec la même version - Faire un commit séparé de bump : `chore : bump version to v` - Puis créer le tag et pusher : `git tag v && git push origin develop --tags` ### Backend - Toujours `declare(strict_types=1)` en haut des fichiers PHP - API Platform : utiliser ApiResource, Providers (`src/State/`), Processors — pas de controllers - Routes API préfixées `/api` (via `config/routes/api_platform.yaml`) - Le login (`/login_check`) est hors prefix `/api`, nginx réécrit `REQUEST_URI` vers `/login_check` - PHP CS Fixer : règles Symfony + PSR-12 + strict types - Rôles : `ROLE_ADMIN`, `ROLE_USER`, `ROLE_CLIENT` — hiérarchie dans `security.yaml` - `User::getRoles()` n'ajoute PAS `ROLE_USER` si l'user a `ROLE_CLIENT` (isolation) - PostgreSQL : `LIKE` sur colonne JSON ne marche pas → utiliser `roles::text LIKE` via native SQL - Controllers custom sous `/api/` : ajouter `priority: 1` sur `#[Route]` pour éviter le conflit avec API Platform `{id}` - Serialization : pour embarquer une relation (pas IRI), ajouter le groupe du parent aux propriétés de l'entité cible - Upload fichiers : utiliser `$file->getMimeType()` (pas `getClientMimeType()`) pour valider côté serveur — nécessite `symfony/mime` - Auth endpoints mixtes (ROLE_USER + ROLE_CLIENT) : utiliser `#[IsGranted('IS_AUTHENTICATED_FULLY')]` au lieu d'un rôle spécifique ### Frontend - TypeScript strict - Composable `useApi()` pour tous les appels API (gère cookies, erreurs, toasts, i18n) - Stores Pinia : `useAuthStore` (auth), `useUiStore` (ui), `useTimerStore` (timer) - Middleware global `auth.global.ts` protège les routes - Traductions dans `frontend/i18n/locales/` (le module résout `langDir` depuis `i18n/`) - 4 espaces d'indentation - MalioSelect : options `{ label: string, value: number | null }` uniquement — pas de string values, utiliser `