feat(frontend): SPA Vue 3 + Vite + Tailwind v4 consommant l'API
Nouveau dossier /frontend avec un SPA complet qui couvre les écrans de la
maquette (cf. docs/Capture*.png) : public + admin token. Backend inchangé.
Stack
- Vue 3.5 + Vite 8 + TypeScript 6 + Tailwind v4 (via @tailwindcss/vite)
- Vue Router 4 en mode history, code-split par page (lazy import)
- Aucune lib UI, aucun store (pas de Pinia) — état local + fetch direct
- Bundle initial 50 kB gzip, total dist 240 kB
Pages
- / redirige vers /donut
- /dashboard 4 KPIs + mini donut + flux activité (via /api/stats + /api/activity)
- /donut viz SVG custom : 6 secteurs catégories, projets en points
colorés, anneaux plancher social / plafond écologique,
tooltip + click vers la fiche projet
- /projects grille de cartes paginée + filtres (catégorie, statut, recherche
avec debounce, query string comme source de vérité)
- /projects/new formulaire complet de création (token admin requis)
- /projects/:slug fiche : header méta + tabs Roadmap/Discussions/Ressources
+ panneau droit Progression + Équipe, modal "Rejoindre"
- /archives projets status=archived
- /categories 6 cartes coloured-top-border + count via /api/stats
- /admin/login saisie du token Bearer, validé via POST /api/members (vide)
- 404 fallback
Structure
- src/api/client.ts : wrapper fetch typé + token Bearer auto + ApiError
- src/composables/useAuth : token localStorage + reactivité Vue
- src/types/api.ts : types miroirs des réponses PHP
- src/utils/formatDate.ts : ISO/MySQL/DATE -> JJ mois AAAA, relatif, etc.
- src/components/ : Avatar, ProjectCard, StatusBadge, CategoryBadge,
ProgressBar, LoadingState, ErrorState, JoinProjectModal
- src/layouts/AppLayout : sidebar nav + main scrollable
- src/components/AppSidebar: logo donut SVG, CTA, nav, statut admin en bas
- src/pages/ : 10 pages ci-dessus
Intégration & déploiement
- vite.config.ts proxy /api/* vers http://donut-gestprojet.test (Laragon)
- caddy.conf prod : /api/* -> reverse_proxy PHP, le reste -> static dist/
avec fallback /index.html (history mode), cache long sur /assets/*
- DEPLOY.md mis à jour avec build local + rsync dist/ vers
/srv/donut/web/infolab-front/dist
- README.md mis à jour avec section "Frontend (SPA Vue 3)"
Build & types
- npm run build : vue-tsc strict (TS 6 + erasableSyntaxOnly) -> OK
- paths alias @/* configuré dans tsconfig.app.json
Vérifié localement
- npm run dev sur :5173, proxy /api -> Apache Laragon -> PHP
- Toutes les routes répondent 200 (curl http://localhost:5173/...)
- Routes API consommées correctement (categories, stats, projects, ...)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+28
-7
@@ -1,6 +1,9 @@
|
||||
# infolab.ledonut-marseille.org — Le Donut Infolab (API JSON + SPA Vue)
|
||||
#
|
||||
# - /api/* -> reverse_proxy vers le conteneur donut-infolab (PHP/Apache, 127.0.0.1:8003)
|
||||
# - tout le reste -> SPA Vue (build statique dans /srv/donut/web/infolab-front/dist)
|
||||
# avec fallback /index.html pour le router HTML5 (Vue Router en mode history).
|
||||
|
||||
|
||||
# infolab.ledonut-marseille.org — Le Donut Infolab (API + front)
|
||||
infolab.ledonut-marseille.org {
|
||||
encode gzip zstd
|
||||
|
||||
@@ -12,10 +15,28 @@ infolab.ledonut-marseille.org {
|
||||
-Server
|
||||
}
|
||||
|
||||
reverse_proxy 127.0.0.1:8003 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
# API JSON -> conteneur PHP (sur réseau Docker local, exposé en 127.0.0.1:8003)
|
||||
@api path /api/*
|
||||
handle @api {
|
||||
reverse_proxy 127.0.0.1:8003 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-For {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
# SPA Vue : sert dist/ avec fallback index.html pour le routing client-side.
|
||||
handle {
|
||||
root * /srv/donut/web/infolab-front/dist
|
||||
try_files {path} /index.html
|
||||
file_server {
|
||||
precompressed gzip
|
||||
}
|
||||
# Cache long pour les assets fingerprintés Vite, court pour index.html.
|
||||
@assets path /assets/*
|
||||
header @assets Cache-Control "public, max-age=31536000, immutable"
|
||||
@html path /index.html
|
||||
header @html Cache-Control "no-cache, no-store, must-revalidate"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user