diff --git a/manifest.json b/manifest.json
index 47b79b4..043e752 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Planification",
- "version": "2026.5.23",
+ "version": "2026.5.24",
"description": "Vue claire et rapide du planning des techniciens EasyVista. Regroupe interventions et réservations par tech, affiche horaires, contact, lieu, catégorie et statut en un coup d'œil.",
"browser_specific_settings": {
"gecko": {
diff --git a/viewer.css b/viewer.css
index d8cf538..502b56f 100644
--- a/viewer.css
+++ b/viewer.css
@@ -842,6 +842,17 @@ html, body {
background: var(--bg-hover);
}
+/* v2026.5.29 : highlight visible sur les rows .intervention-v2 quand on
+ survole le segment timeline correspondant (ou que l'user survole la row) */
+.intervention-v2.highlight {
+ background: var(--accent-soft);
+ outline: 2px solid var(--accent);
+ outline-offset: -2px;
+ box-shadow: 0 0 0 3px var(--accent-soft);
+ z-index: 2;
+ position: relative;
+}
+
/* ==========================================================================
Interventions — layout v2 (heures verticales)
========================================================================== */
@@ -1832,15 +1843,17 @@ body.modal-open {
overflow: hidden;
}
-/* v4.2.9 : pied de page discret en bas à droite — affiche auteur + date + version */
+/* v4.2.9 : pied de page discret en bas à droite — affiche auteur + date + version
+ v2026.5.29 : agrandi + plus contrasté */
.app-footer {
position: fixed;
- right: 8px;
- bottom: 4px;
- font-size: 10px;
- color: var(--text-faint, #8892a0);
- opacity: 0.55;
- pointer-events: none; /* ne capture pas les clics */
+ right: 10px;
+ bottom: 6px;
+ font-size: 13px;
+ font-weight: 500;
+ color: var(--text-muted);
+ opacity: 0.85;
+ pointer-events: none;
user-select: none;
font-variant-numeric: tabular-nums;
letter-spacing: 0.2px;
diff --git a/viewer.js b/viewer.js
index 6073863..77c04af 100644
--- a/viewer.js
+++ b/viewer.js
@@ -502,7 +502,13 @@ function toggleUserNamePopup() {
popup.innerHTML = "";
const nameEl = document.createElement("div");
nameEl.className = "user-name-popup-name";
- nameEl.textContent = state.currentUser.name;
+ if (state.currentUser && state.currentUser.name) {
+ nameEl.textContent = state.currentUser.name;
+ } else {
+ nameEl.textContent = "Utilisateur inconnu";
+ nameEl.style.fontStyle = "italic";
+ nameEl.style.color = "var(--text-muted)";
+ }
popup.appendChild(nameEl);
const sessEl = document.createElement("div");
@@ -511,6 +517,36 @@ function toggleUserNamePopup() {
_renderUserPopupSessionLine(sessEl);
popup.appendChild(sessEl);
+ // v2026.5.25 : bouton Paramètres (remplace les 5 clics sur le titre)
+ // v2026.5.32 : bouton "Vue" pour basculer Vue classique ↔ Vue horizontale
+ const viewBtn = document.createElement("button");
+ viewBtn.type = "button";
+ viewBtn.className = "user-name-popup-settings";
+ const currentView = _getCurrentView();
+ viewBtn.innerHTML = '⊞ Vue : '
+ + (currentView === "horizontal" ? "Horizontale" : "Classique");
+ viewBtn.title = "Changer la disposition du planning";
+ viewBtn.addEventListener("click", (e) => {
+ e.stopPropagation();
+ hideUserNamePopup();
+ _toggleView();
+ });
+ popup.appendChild(viewBtn);
+
+ const settingsBtn = document.createElement("button");
+ settingsBtn.type = "button";
+ settingsBtn.className = "user-name-popup-settings";
+ settingsBtn.innerHTML = '⚙ Paramètres';
+ settingsBtn.title = "Ouvrir les paramètres d'administration";
+ settingsBtn.addEventListener("click", (e) => {
+ e.stopPropagation();
+ hideUserNamePopup();
+ if (typeof showAdminPanel === "function") {
+ showAdminPanel();
+ }
+ });
+ popup.appendChild(settingsBtn);
+
popup.classList.remove("hidden");
badge.classList.add("open");
// Positionne juste en dessous de la pastille
@@ -984,20 +1020,49 @@ function initAppFooter() {
document.body.appendChild(el);
}
+// v2026.5.32 : bascule entre Vue classique (cards) et Vue horizontale (rows)
+// Persisté dans localStorage (clé : "view_mode"). Défaut : "classic".
+const VIEW_MODE_KEY = "view_mode";
+
+function _getCurrentView() {
+ try {
+ const v = localStorage.getItem(VIEW_MODE_KEY);
+ return v === "horizontal" ? "horizontal" : "classic";
+ } catch (e) {
+ return "classic";
+ }
+}
+
+function _setCurrentView(mode) {
+ try {
+ localStorage.setItem(VIEW_MODE_KEY, mode === "horizontal" ? "horizontal" : "classic");
+ } catch (e) {}
+ _applyViewMode();
+}
+
+function _toggleView() {
+ const current = _getCurrentView();
+ const next = current === "horizontal" ? "classic" : "horizontal";
+ _setCurrentView(next);
+}
+
+function _applyViewMode() {
+ const mode = _getCurrentView();
+ document.documentElement.classList.remove("view-classic", "view-horizontal");
+ document.documentElement.classList.add("view-" + mode);
+}
+
// v5.0.0 : horloge HH:MM au milieu de la topbar. Mise à jour toutes les 30s
// (les secondes ne sont pas affichées donc pas besoin d'un tick plus rapide).
+// v2026.5.27 : date courte "Jeudi 23.04.26" sur la même ligne que l'heure,
+// séparées par un gros point "•", même taille que l'heure.
function initAppClock() {
const el = document.getElementById("app-clock");
if (!el) return;
const dateEl = document.getElementById("app-clock-date");
const timeEl = document.getElementById("app-clock-time");
- // v2026.5.16 : format "Mardi 21 avril 2026"
const JOURS = ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"];
- const MOIS = [
- "janvier", "février", "mars", "avril", "mai", "juin",
- "juillet", "août", "septembre", "octobre", "novembre", "décembre"
- ];
let lastDateStr = "";
const tick = () => {
@@ -1008,13 +1073,13 @@ function initAppClock() {
if (timeEl) timeEl.textContent = timeStr;
else el.textContent = timeStr; // fallback si ancien markup
- // Date complète : actualisée seulement si elle a changé (évite reflow inutile)
+ // Date courte : "Jeudi 23.04.26"
if (dateEl) {
const jour = JOURS[d.getDay()];
- const num = d.getDate();
- const mois = MOIS[d.getMonth()];
- const annee = d.getFullYear();
- const dateStr = `${jour} ${num} ${mois} ${annee}`;
+ const dd = String(d.getDate()).padStart(2, "0");
+ const mm = String(d.getMonth() + 1).padStart(2, "0");
+ const yy = String(d.getFullYear()).slice(-2);
+ const dateStr = `${jour} ${dd}.${mm}.${yy}`;
if (dateStr !== lastDateStr) {
dateEl.textContent = dateStr;
lastDateStr = dateStr;