mirror of
https://github.com/R0m1k3/Presencia.git
synced 2026-10-11 17:27:42 +02:00
Reprend la maquette Presencia.dc.html sur l'application réelle : thème clair chaud à accent vert forêt, navigation latérale groupée par rôle et tableau de bord, en conservant l'intégralité du fonctionnel existant. Frontend - Écran de connexion en deux panneaux (argumentaire + formulaire). - Tableau de bord par rôle : compteurs du mois et liste « à faire maintenant » (sociétés prêtes à valider, cadres en retard, saisie à compléter), plus l'état du mois par société côté admin. - Planning : saisie rapide au pinceau, trois affichages (grille, compact, liste), sélecteur avec raccourcis clavier (1–4, ⌫, ↵ pour appliquer à la journée), barre d'état de verrouillage, « Tout effacer ». - Nouvelle vue Historique pour les cadres (totaux par mois et statut). - Validation & export : barre de progression et compteurs de demi-journées par cadre. - Mobile : liste verticale, navigation en barre basse, cibles 44 px. Backend - GET /api/validations/overview — état de toutes les sociétés d'un mois. - GET /api/attendance/history — totaux par mois et par statut. - DELETE /api/attendance/month — effacement d'un mois (mêmes verrous). - Compteur de demi-journées saisies par cadre dans /validations/company. Polices et icônes servies localement (Inter, sous-ensemble de 18 icônes Phosphor) au lieu de Google Fonts et unpkg : l'application ne fait plus aucune requête externe au chargement. Vérifié de bout en bout via la vraie configuration nginx : 62 contrôles Playwright (desktop et mobile), tous passants, sur base réinitialisée et rejoués deux fois pour garantir le déterminisme.
294 lines
12 KiB
HTML
294 lines
12 KiB
HTML
<!doctype html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>Presencia — Gestion des présences</title>
|
||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='22' fill='%233f6b54'/%3E%3C/svg%3E" />
|
||
<link rel="stylesheet" href="css/inter.css" />
|
||
<link rel="stylesheet" href="css/styles.css" />
|
||
<link rel="stylesheet" href="css/presencia.css" />
|
||
<link rel="stylesheet" href="css/phosphor.css" />
|
||
<link rel="stylesheet" href="css/app.css" />
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ══════════════ LOGIN ══════════════ -->
|
||
<section id="view-login" class="login-split">
|
||
<div class="login-pitch">
|
||
<div class="brand-row">
|
||
<span class="brand-mark"></span>
|
||
<span class="brand-name">Presencia</span>
|
||
</div>
|
||
<div class="login-pitch-copy">
|
||
<h1>Les présences,<br />sans le tableur.</h1>
|
||
<p class="text-muted">Saisie par demi-journée, validation en deux temps, export mensuel par société. Chaque cadre remplit son mois en moins de deux minutes.</p>
|
||
</div>
|
||
<div class="login-pitch-feet">
|
||
<span>Validation cadre puis administrateur</span>
|
||
<span>Export PDF & Excel</span>
|
||
</div>
|
||
</div>
|
||
<div class="login-formside">
|
||
<form id="login-form" class="login-form" autocomplete="on">
|
||
<div>
|
||
<h3>Connexion</h3>
|
||
<p class="login-lede">Accès réservé — les comptes sont créés par un administrateur.</p>
|
||
</div>
|
||
<div class="field">
|
||
<label for="login-email">Adresse e-mail</label>
|
||
<input class="input" id="login-email" type="email" required autocomplete="username" placeholder="vous@societe.com" />
|
||
</div>
|
||
<div class="field">
|
||
<label for="login-password">Mot de passe</label>
|
||
<input class="input" id="login-password" type="password" required autocomplete="current-password" placeholder="••••••••" />
|
||
</div>
|
||
<div id="login-error" class="login-error" hidden></div>
|
||
<button type="submit" class="btn btn-primary btn-block">Se connecter</button>
|
||
</form>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ══════════════ APP ══════════════ -->
|
||
<div id="app" class="shell" hidden>
|
||
<aside class="side">
|
||
<div class="side-brand">
|
||
<span class="brand-mark small"></span>
|
||
<span class="brand-name small">Presencia</span>
|
||
</div>
|
||
<nav id="side-nav"></nav>
|
||
<div class="side-foot">
|
||
<div class="side-user">
|
||
<span id="user-initials" class="avatar"></span>
|
||
<span class="side-user-text">
|
||
<span id="user-name" class="side-user-name"></span>
|
||
<span id="user-meta" class="side-user-meta"></span>
|
||
</span>
|
||
</div>
|
||
<button id="logout-btn" class="navitem"><i class="ni-ico ph ph-sign-out"></i><span>Déconnexion</span></button>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="content">
|
||
<div class="mobile-only mobile-head">
|
||
<span class="brand-mark tiny"></span>
|
||
<span id="screen-title" class="mobile-title"></span>
|
||
<button id="logout-btn-mobile" class="chipbtn">Quitter</button>
|
||
</div>
|
||
|
||
<!-- ─── DASHBOARD ─── -->
|
||
<section id="view-dashboard" class="view stack-20">
|
||
<div>
|
||
<h3 id="dash-greeting"></h3>
|
||
<p id="dash-subtitle" class="lede"></p>
|
||
</div>
|
||
<div id="dash-tiles" class="tile-grid"></div>
|
||
<div class="stack-8">
|
||
<h6>À faire maintenant</h6>
|
||
<div id="dash-actions" class="stack-6"></div>
|
||
</div>
|
||
<div id="dash-company-block" class="stack-8" hidden>
|
||
<h6>État du mois par société</h6>
|
||
<div class="card table-card">
|
||
<table class="table">
|
||
<thead><tr><th>Société</th><th>Cadres validés</th><th>Statut</th><th></th></tr></thead>
|
||
<tbody id="dash-company-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── PLANNING ─── -->
|
||
<section id="view-planning" class="view stack-14" hidden>
|
||
<div class="planning-head">
|
||
<div class="planning-head-title">
|
||
<button id="back-to-plannings" class="btn btn-ghost back-link" hidden>← Tous les plannings</button>
|
||
<h3 id="planning-title"></h3>
|
||
<p id="planning-subtitle" class="lede"></p>
|
||
</div>
|
||
<div class="month-nav">
|
||
<button id="prev-month" class="btn btn-secondary btn-icon" aria-label="Mois précédent"><i class="ph ph-caret-left"></i></button>
|
||
<span id="month-label" class="month-label"></span>
|
||
<button id="next-month" class="btn btn-secondary btn-icon" aria-label="Mois suivant"><i class="ph ph-caret-right"></i></button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="lockbar">
|
||
<i id="lock-icon" class="ph ph-pencil-simple-line lockbar-icon"></i>
|
||
<span class="lockbar-text">
|
||
<span id="lock-title" class="lockbar-title"></span>
|
||
<span id="lock-detail" class="lockbar-detail"></span>
|
||
</span>
|
||
<span class="lockbar-actions">
|
||
<button id="reopen-month-btn" class="btn btn-secondary" hidden>Réouvrir le mois</button>
|
||
<button id="validate-month-btn" class="btn btn-primary" hidden>Valider mon mois</button>
|
||
</span>
|
||
</div>
|
||
|
||
<div class="toolrow">
|
||
<span class="toolrow-label">Saisie rapide</span>
|
||
<div id="brush-options" class="toolrow-items"></div>
|
||
</div>
|
||
|
||
<div class="toolrow">
|
||
<div id="view-options" class="toolrow-items"></div>
|
||
<span class="toolrow-right">
|
||
<button id="fill-workdays-btn" class="btn btn-secondary">Remplir les jours ouvrés</button>
|
||
<button id="clear-month-btn" class="btn btn-secondary">Tout effacer</button>
|
||
</span>
|
||
</div>
|
||
|
||
<div id="brush-hint" class="brush-hint"></div>
|
||
|
||
<div id="planning-view" class="pv-grid">
|
||
<div class="cal-head">
|
||
<span>Lun</span><span>Mar</span><span>Mer</span><span>Jeu</span><span>Ven</span><span>Sam</span><span>Dim</span>
|
||
</div>
|
||
<div id="cal-grid" class="cal-grid"></div>
|
||
</div>
|
||
|
||
<div id="planning-summary" class="summary-row"></div>
|
||
</section>
|
||
|
||
<!-- ─── PLANNINGS (admin) ─── -->
|
||
<section id="view-plannings" class="view stack-14" hidden>
|
||
<div>
|
||
<h3>Plannings des cadres</h3>
|
||
<p id="plannings-subtitle" class="lede"></p>
|
||
</div>
|
||
<div class="filter-bar">
|
||
<span class="field">
|
||
<label for="pl-co">Société</label>
|
||
<select class="input" id="pl-co"><option value="all">Toutes les sociétés</option></select>
|
||
</span>
|
||
<span class="field">
|
||
<label for="pl-q">Rechercher un cadre</label>
|
||
<input class="input" id="pl-q" placeholder="Nom ou e-mail" />
|
||
</span>
|
||
</div>
|
||
<div id="cadre-rows" class="stack-6"></div>
|
||
</section>
|
||
|
||
<!-- ─── VALIDATION & EXPORT (admin) ─── -->
|
||
<section id="view-validation" class="view stack-14" hidden>
|
||
<div>
|
||
<h3>Validation & export</h3>
|
||
<p class="lede">Une société se valide quand tous ses cadres ont validé leur mois.</p>
|
||
</div>
|
||
<div class="filter-bar">
|
||
<span class="field">
|
||
<label for="va-co">Société</label>
|
||
<select class="input" id="va-co"></select>
|
||
</span>
|
||
<span class="field">
|
||
<label for="va-mo">Mois</label>
|
||
<select class="input" id="va-mo"></select>
|
||
</span>
|
||
</div>
|
||
|
||
<div class="card validation-card">
|
||
<div class="validation-head">
|
||
<span class="validation-head-text">
|
||
<span id="validation-company-name" class="validation-company"></span>
|
||
<span id="validation-status-text" class="validation-status"></span>
|
||
</span>
|
||
<span class="validation-head-actions">
|
||
<button id="export-pdf-btn" class="btn btn-secondary"><i class="ph ph-file-pdf"></i>PDF</button>
|
||
<button id="export-excel-btn" class="btn btn-secondary"><i class="ph ph-file-xls"></i>Excel</button>
|
||
<button id="validate-company-btn" class="btn btn-primary">Valider la société</button>
|
||
</span>
|
||
</div>
|
||
<div class="progress"><span id="validation-progress" class="progress-bar"></span></div>
|
||
<table class="table">
|
||
<thead><tr><th>Cadre</th><th>Demi-journées</th><th>Statut</th><th></th></tr></thead>
|
||
<tbody id="validation-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── COMPANIES (admin) ─── -->
|
||
<section id="view-companies" class="view stack-14" hidden>
|
||
<div class="page-head">
|
||
<div>
|
||
<h3>Sociétés</h3>
|
||
<p id="companies-count" class="lede"></p>
|
||
</div>
|
||
<button id="add-company-btn" class="btn btn-primary"><i class="ph ph-plus"></i>Nouvelle société</button>
|
||
</div>
|
||
<div class="card table-card">
|
||
<table class="table">
|
||
<thead><tr><th>Nom</th><th>Cadres actifs</th><th>Créée le</th><th></th></tr></thead>
|
||
<tbody id="companies-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── USERS (admin) ─── -->
|
||
<section id="view-users" class="view stack-14" hidden>
|
||
<div class="page-head">
|
||
<div>
|
||
<h3>Utilisateurs</h3>
|
||
<p class="lede">Aucune inscription publique — les comptes sont créés ici.</p>
|
||
</div>
|
||
<button id="add-user-btn" class="btn btn-primary"><i class="ph ph-plus"></i>Nouvel utilisateur</button>
|
||
</div>
|
||
<div class="filter-bar">
|
||
<span class="field">
|
||
<label for="us-co">Société</label>
|
||
<select class="input" id="us-co"><option value="all">Toutes les sociétés</option></select>
|
||
</span>
|
||
<span class="field">
|
||
<label for="us-q">Rechercher</label>
|
||
<input class="input" id="us-q" placeholder="Nom ou e-mail" />
|
||
</span>
|
||
</div>
|
||
<div class="card table-card">
|
||
<table class="table">
|
||
<thead><tr><th>Nom</th><th>E-mail</th><th>Rôle</th><th>Société</th><th>Statut</th><th></th></tr></thead>
|
||
<tbody id="users-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ─── HISTORY ─── -->
|
||
<section id="view-history" class="view stack-14" hidden>
|
||
<div>
|
||
<h3>Historique</h3>
|
||
<p class="lede">Vos mois saisis et leurs totaux.</p>
|
||
</div>
|
||
<div class="card table-card">
|
||
<table class="table">
|
||
<thead><tr><th>Mois</th><th>Présent</th><th>Non-présent</th><th>Congé</th><th>RTT</th><th>Statut</th><th></th></tr></thead>
|
||
<tbody id="history-rows"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<nav id="mobile-nav" class="mobile-only mobile-nav"></nav>
|
||
</div>
|
||
|
||
<!-- ══════════════ POPOVER ══════════════ -->
|
||
<div id="pop-backdrop" class="pop-backdrop" hidden></div>
|
||
<div id="pop" class="pop" hidden>
|
||
<div class="pop-head">
|
||
<span id="pop-title" class="pop-title"></span>
|
||
<span class="pop-hint">1–4 au clavier</span>
|
||
</div>
|
||
<div id="pop-options"></div>
|
||
<button id="pop-clear" class="pop-opt pop-opt-muted"><i class="dot st-none"></i>Effacer<span class="kbd">⌫</span></button>
|
||
<button id="pop-whole-day" class="pop-opt"><i class="ph ph-arrows-out-line-horizontal pop-ico"></i>Appliquer à la journée<span class="kbd">↵</span></button>
|
||
</div>
|
||
|
||
<!-- ══════════════ DIALOG ══════════════ -->
|
||
<div id="dialog-backdrop" class="dialog-backdrop" hidden>
|
||
<div id="dialog" class="dialog"></div>
|
||
</div>
|
||
|
||
<!-- ══════════════ TOAST ══════════════ -->
|
||
<div id="toast" class="toast" hidden></div>
|
||
|
||
<script src="js/app.js"></script>
|
||
</body>
|
||
</html>
|