Sommaire
Contents
01 Vue d'ensemble Overview
Le panneau d'administration contrôle le catalogue de produits, les prix et la configuration exposée sur le site menuiserie-surmesure.fr et dans le configurateur de fenêtres/portes.
The admin panel controls the product catalogue, pricing and configuration exposed on menuiserie-surmesure.fr and in the window/door configurator.
Comment ça fonctionne
How it works
Le panneau sauvegarde la configuration dans localStorage (instantané) et synchronise de manière asynchrone avec l'API backend (quand disponible). Le backend est la source de vérité — à la connexion, les données API écrasent les données locales.
The panel saves configuration to localStorage (instant) and syncs asynchronously with the backend API (when available). The backend is the source of truth — on login, API data overwrites local data.
02 Authentification Authentication
Au premier accès, un overlay de connexion apparaît. Seuls les utilisateurs avec le rôle ADMIN_SALES ou SUPER_ADMIN ont accès.
On first access, a login overlay appears. Only users with role ADMIN_SALES or SUPER_ADMIN have access.
- Entrez votre email — le même que dans le backend (ex:
admin@tech-menuiserie.fr) - Entrez le mot de passe et cliquez Connecter
- Succès : l'overlay disparaît, le badge utilisateur apparaît dans l'en-tête
- Erreur de rôle : message "Accès interdit — rôle insuffisant"
- Enter your email — the same as in the backend (e.g.
admin@tech-menuiserie.fr) - Enter the password and click Connect
- Success: the overlay disappears, the user badge appears in the header
- Role error: message "Access denied — insufficient role"
Session
Session
Le token JWT est stocké dans localStorage (tech-admin-jwt). À l'expiration, l'overlay réapparaît automatiquement. Déconnexion : cliquez sur ⏻ dans l'en-tête.
The JWT token is stored in localStorage (tech-admin-jwt). On expiry, the overlay reappears automatically. Logout: click ⏻ in the header.
Mode hors ligne
Offline mode
Si l'API est indisponible (VPS arrêté, réseau down), le panneau fonctionne intégralement avec les données locales. L'indicateur sidebar affiche "Local only (API offline)" en orange.
If the API is unavailable (VPS stopped, network down), the panel works fully with local data. The sidebar indicator shows "Local only (API offline)" in orange.
03 Onglets Admin Admin Tabs
La navigation se fait depuis la barre latérale gauche. Chaque onglet gère une partie du catalogue :
Navigation is done from the left sidebar. Each tab manages a part of the catalogue:
| Onglet | Fonction | Portée |
|---|---|---|
| 📐 Séries | Activer/désactiver séries et sous-séries | Par produit |
| 🔩 Profils | Profils PVC/ALU et armatures | Par produit |
| 🎨 Couleurs | Couleurs avec majoration, catégorie, filtre | Par produit |
| ⚙ Quincaillerie | Types quincaillerie ROTO + défauts par ouverture | Par produit |
| 🪟 Vitrages | Catalogue vitrages (658 types, filtre Ug) | Global |
| ↗ Ouvertures | Types d'ouverture, schémas, séparateurs | Par produit |
| 🔧 Accessoires | Volet roulant, moustiquaire, grille | Par produit |
| 🛍 Produits Site | Produits exposés sur le site (FR/EN, SEO) | Global — NOUVEAU |
| 🎯 Défauts | Valeurs par défaut du configurateur | Par produit |
| 💰 Prix | Formule V10, couches de coût, remises, BOM | Global |
| 🏷 Branding | Logo, couleurs, infos société | Global |
| 💾 Export | Export/Import JSON, Publier, sync API | Global |
| Tab | Function | Scope |
|---|---|---|
| 📐 Series | Enable/disable series and sub-series | Per product |
| 🔩 Profiles | PVC/ALU profiles and reinforcements | Per product |
| 🎨 Colours | Colours with markup, category, filter | Per product |
| ⚙ Hardware | ROTO hardware types + defaults per opening | Per product |
| 🪟 Glazing | Glazing catalogue (658 types, Ug filter) | Global |
| ↗ Openings | Opening types, schemas, separators | Per product |
| 🔧 Accessories | Roller shutter, mosquito net, grille | Per product |
| 🛍 Site Products | Products exposed on site (FR/EN, SEO) | Global — NEW |
| 🎯 Defaults | Configurator default values | Per product |
| 💰 Pricing | V10 formula, cost layers, discounts, BOM | Global |
| 🏷 Branding | Logo, colours, company info | Global |
| 💾 Export | Export/Import JSON, Publish, API sync | Global |
Par produit vs Global
Per product vs Global
Les onglets "par produit" changent quand vous sélectionnez un autre produit dans le menu déroulant de l'en-tête (Fenêtre / Porte / Porte-fenêtre). Les onglets "global" affectent tous les produits.
"Per product" tabs change when you select another product from the header dropdown (Window / Door / Balcony door). "Global" tabs affect all products.
04 Produits Site (Nouveau) Site Products (New)
Cet onglet gère les produits affichés sur le site public. Chaque produit a une version FR et EN, peut être lié à une série du catalogue, et possède des champs SEO.
This tab manages products displayed on the public site. Each product has FR and EN versions, can be linked to a catalogue series, and has SEO fields.
Créer un produit
Create a product
- Cliquez + Ajouter produit
- Remplissez Nom FR (obligatoire) et optionnellement Nom EN
- Choisissez la Catégorie (Fenêtres, Portes, etc.)
- Sélectionnez un Badge : Populaire ou Nouveau (optionnel)
- Liez à une Série du catalogue admin (optionnel)
- Définissez Prix à partir de en EUR (ou laissez vide pour auto)
- Remplissez les champs SEO : Meta Title (max 60 car.) et Meta Description (max 160 car.)
- Cliquez Créer
- Click + Add product
- Fill in Name FR (required) and optionally Name EN
- Choose the Category (Windows, Doors, etc.)
- Select a Badge: Popular or New (optional)
- Link to a Series from the admin catalogue (optional)
- Set Price from in EUR (or leave blank for auto)
- Fill in SEO fields: Meta Title (max 60 chars) and Meta Description (max 160 chars)
- Click Create
Actions rapides
Quick actions
| Action | Description |
|---|---|
| ✏ Éditer | Ouvre le même formulaire que la création, pré-rempli |
| ⚯ Réordonner | Glissez-déposez le grip ⠿ pour changer l'ordre |
| 👁 Activer/Désactiver | Le produit devient semi-transparent (inactif) — n'apparaît plus sur le site |
| 🗑 Supprimer | Confirmation avant suppression — irréversible |
| Action | Description |
|---|---|
| ✏ Edit | Opens the same form as creation, pre-filled |
| ⚯ Reorder | Drag the ⠿ grip to change display order |
| 👁 Enable/Disable | Product becomes semi-transparent (inactive) — hidden from site |
| 🗑 Delete | Confirmation required — irreversible |
05 Sauvegarde & Synchronisation Save & Synchronisation
Boutons de l'en-tête
Header buttons
| Bouton | Fonction |
|---|---|
| 🔄 Flush | Recharge depuis les fichiers JSON (efface le cache localStorage) |
| ✕ Reset | Annule les modifications non sauvegardées |
| 💾 Save | Sauvegarde dans localStorage + push asynchrone vers l'API |
| Button | Function |
|---|---|
| 🔄 Flush | Reload from JSON files (clears localStorage cache) |
| ✕ Reset | Undo unsaved changes |
| 💾 Save | Save to localStorage + async push to API |
Indicateur de synchronisation
Sync indicator
| Couleur | Colour | Status | Signification | Meaning |
|---|---|---|---|---|
| ● | Synced (API) | Données sauvegardées et synchronisées avec le backend | Data saved and synced with backend | |
| ● | Published | Config publiée pour déploiement | Config published for deployment | |
| ● | Local only | API hors ligne — données uniquement dans le navigateur | API offline — data only in browser | |
| ● | Modified | Modifications non sauvegardées | Unsaved changes |
Sauvegarde automatique
Auto-save
La plupart des modifications sont sauvegardées automatiquement dans localStorage. Le bouton Save fait aussi le push vers l'API.
Most changes are auto-saved to localStorage. The Save button also pushes to the API.
06Export / Import
Export/Import local (fichier JSON)
Local Export/Import (JSON file)
- Exporter JSON : télécharge la configuration actuelle
- Importer JSON : restaure une configuration sauvegardée
- Publish All : génère
filter-config.json+pricing-engine.json
- Export JSON: downloads current configuration
- Import JSON: restores a saved configuration
- Publish All: generates
filter-config.json+pricing-engine.json
Synchronisation API (Backend)
API Sync (Backend)
- Sélectionnez le module (Séries, Couleurs, Vitrages, Quincaillerie, Accessoires)
- Export depuis API : télécharge les données actuelles du backend en JSON
- Import dans API : sélectionnez un fichier JSON → aperçu du diff
- Cliquez Appliquer pour sauvegarder ou Annuler
- Après import : bouton ↩ Rollback disponible pour annuler
- Select the module (Series, Colours, Glazing, Hardware, Accessories)
- Export from API: download current backend data as JSON
- Import to API: select a JSON file → diff preview appears
- Click Apply to save or Cancel
- After import: ↩ Rollback button available to undo
07 Intégration API API Integration
Configuration
Configuration
// Before admin-app.js:
<script>window.ADMIN_API_BASE = 'https://api.menuiserie-surmesure.fr/api';</script>
// Default: '/api' (relative to current domain)
Comportement
Behaviour
| Situation | Résultat |
|---|---|
| API disponible + authentifié | Chargement depuis API, sauvegarde API + localStorage |
| API disponible + non authentifié | Overlay connexion → après connexion, rechargement depuis API |
| API indisponible | Fonctionne intégralement avec localStorage + JSON local |
| 401 de l'API | Déconnexion automatique, overlay de connexion réapparaît |
| Sauvegarde échouée (API down) | Données en sécurité dans localStorage, toast d'avertissement |
| Situation | Result |
|---|---|
| API available + authenticated | Load from API, save to API + localStorage |
| API available + not authenticated | Login overlay → after login, reload from API |
| API unavailable | Works fully with localStorage + local JSON |
| 401 from API | Auto-logout, login overlay reappears |
| Save failed (API down) | Data safe in localStorage, warning toast |
08Architecture
Modules JS
JS Modules
| Fichier | File | Rôle | Role | Export |
|---|---|---|---|---|
api-client.js | Client HTTP avec JWT, CRUD, import/export | HTTP client with JWT, CRUD, import/export | apiClient | |
auth-gate.js | Overlay connexion, vérification rôle, badge utilisateur | Login overlay, role check, user badge | authGate | |
produse-site.js | CRUD produits site, glisser-déposer | Site products CRUD, drag & drop | ProduseSiteManager | |
admin-app.js | Orchestrateur principal, 13 onglets | Main orchestrator, 13 tabs | AdminApp |
09 Dépannage Troubleshooting
"Session expirée — reconnectez-vous"
"Session expired — please reconnect"
Le token JWT a expiré. Reconnectez-vous avec email et mot de passe. Les données locales sont intactes.
The JWT token has expired. Log in again with email and password. Local data is intact.
"Local only (API offline)"
Le backend API ne répond pas. Le panneau fonctionne normalement avec les données locales. Quand l'API revient, cliquez Save pour synchroniser.
The backend API is not responding. The panel works normally with local data. When the API returns, click Save to sync.
"Accès interdit — rôle insuffisant"
"Access denied — insufficient role"
Le compte n'a pas le rôle ADMIN_SALES ou SUPER_ADMIN. Contactez l'administrateur.
The account does not have the ADMIN_SALES or SUPER_ADMIN role. Contact the administrator.
Les données ont disparu après un rafraîchissement
Data disappeared after refresh
Vérifiez que vous êtes authentifié. À la connexion, les données API écrasent localStorage (backend wins). Si l'API avait des données plus anciennes, utilisez Import JSON avec un backup local.
Check you are authenticated. On login, API data overwrites localStorage (backend wins). If the API had older data, use JSON Import with a local backup.
Comment tout réinitialiser ?
How to reset everything?
Cliquez sur le bouton 🔄 Flush dans l'en-tête → confirmez. Le cache localStorage est effacé et les fichiers JSON originaux sont rechargés.
Click the 🔄 Flush button in the header → confirm. The localStorage cache is cleared and the original JSON files are reloaded.
10 Gestion des utilisateurs User Management
L'authentification se fait exclusivement via Google OAuth. Aucun mot de passe n'est stocké dans le système.
Rôles disponibles
SUPER_ADMIN |
Accès total — configuration, utilisateurs, finance, catalogue |
ADMIN_SALES |
Équipe commerciale — commandes, clients, devis |
ADMIN_PRODUCTION |
Production — suivi fabrication, planning |
ADMIN_LOGISTICS |
Logistique — livraisons, transport |
ADMIN_ACCOUNTING |
Comptabilité — factures, paiements |
ADMIN_SUPPORT |
Support client — tickets, SAV |
Ajouter un utilisateur (SUPER_ADMIN uniquement)
- L'utilisateur doit avoir un compte Google (Gmail ou Google Workspace)
- Demandez-lui son adresse email Google
- Appelez l'API pour créer le compte :
POST /api/admin/users { "email": "vendeur@gmail.com", "firstName": "Jean", "lastName": "Dupont", "role": "ADMIN_SALES" } - L'utilisateur se connecte via Connexion avec Google — son compte est automatiquement lié
Modifier le rôle d'un utilisateur
PUT /api/admin/users/{userId}/role
{ "role": "ADMIN_PRODUCTION" }
Désactiver un utilisateur
PUT /api/admin/users/{userId}/active
{ "active": false }
L'utilisateur ne pourra plus se connecter. Son compte n'est pas supprimé.
Authentication is exclusively via Google OAuth. No passwords are stored in the system.
Available Roles
SUPER_ADMIN |
Full access — config, users, finance, catalog |
ADMIN_SALES |
Sales team — orders, clients, quotes |
ADMIN_PRODUCTION |
Production — manufacturing tracking, planning |
ADMIN_LOGISTICS |
Logistics — deliveries, transport |
ADMIN_ACCOUNTING |
Accounting — invoices, payments |
ADMIN_SUPPORT |
Customer support — tickets, after-sales |
Add a user (SUPER_ADMIN only)
- The user must have a Google account (Gmail or Google Workspace)
- Ask them for their Google email address
- Call the API to create the account:
POST /api/admin/users { "email": "salesperson@gmail.com", "firstName": "John", "lastName": "Doe", "role": "ADMIN_SALES" } - The user signs in via Sign in with Google — their account is automatically linked
Change a user's role
PUT /api/admin/users/{userId}/role
{ "role": "ADMIN_PRODUCTION" }
Disable a user
PUT /api/admin/users/{userId}/active
{ "active": false }
The user will no longer be able to sign in. Their account is not deleted.
11 Fichiers & Structure Files & Structure
admin/
├── index.html ← Admin panel
├── guide.html ← This guide (FR/EN)
├── css/
│ └── admin.css ← Styles (auth, products, import)
├── js/
│ ├── admin-app.js ← Main orchestrator (ES module)
│ ├── api-client.js ← API client (JWT auth)
│ ├── auth-gate.js ← Login overlay + user badge
│ └── produse-site.js ← Site products manager (CRUD)
├── images/
└── docs/
└── S2-IMPLEMENTATION.md
Deploy
scp -r admin/ root@83.228.246.186:/var/www/ui.menuiserie-surmesure.fr/admin/