fix(marketing): restaurer visibilité 12 fonctions dans 'Comment ça marche'
L'abstraction en 4 catégories (commit 8a7650f) cachait les 13 modes
derrière des regroupements ; l'utilisateur ne VOYAIT plus les 6 boutons
features originaux et percevait que des fonctions avaient disparu.
Refonte v2 :
- Bottom tab bar : 6 boutons FEATURES originaux 1-6 (Trans/Diari/Lang/Exp/Users/Part) — visibles, cliquables
- Right panel : grid 3×4 = 12 boutons FEATURES 1-12 (IA mode 0 reste accessible via Brain card)
- Mobile pills : 12 features scrollables horizontalement
- Auto-cycle : 1→12 skip 0, 1100ms each (~13s cycle complet)
- Manual click : isManual 4500ms reset puis reprend auto
- SUPPRESSION : CATEGORIES array + activeCategory state + handleCategorySelect + sub-mode dots indicator
- AJOUT : featureGridLabel() pour labels compacts (Recording/Recherche IA/Résumés/Intégrations/Audit trail/Conformité)
Préservé : phone shell statique, palette brand stricte b1/b2/b3, IA Mistral
card inchangée, 13 templates de modes (0-12) intacts, eyebrow brand-navy noir,
WCAG aria-labels + aria-pressed, prefers-reduced-motion guard.
Test adapté : assert featureGridLabel + 12 fonctions + labels grid.
This commit is contained in:
@@ -480,8 +480,8 @@
|
|||||||
{# Stats row #}
|
{# Stats row #}
|
||||||
<div class="flex flex-wrap items-center justify-center gap-x-8 gap-y-3 text-brand-navy">
|
<div class="flex flex-wrap items-center justify-center gap-x-8 gap-y-3 text-brand-navy">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="text-2xl font-black grad-text">4</span>
|
<span class="text-2xl font-black grad-text">12</span>
|
||||||
<span class="text-xs font-medium text-brand-navy/60 uppercase tracking-wider">catégories · 6 modules</span>
|
<span class="text-xs font-medium text-brand-navy/60 uppercase tracking-wider">fonctions · modules</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-px h-6 bg-brand-navy/15 hidden sm:block" aria-hidden="true"></div>
|
<div class="w-px h-6 bg-brand-navy/15 hidden sm:block" aria-hidden="true"></div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -1200,34 +1200,27 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# BOTTOM : 4 catégories tabs (Capture / IA / Distribution / Gouvernance) + sub-mode dots + Auto pill — hauteur fixe 90px #}
|
{# BOTTOM : 6 boutons feature originaux (Trans / Diari / Lang / Exp / Users / Part) + Auto pill — hauteur fixe 90px #}
|
||||||
<div class="relative flex flex-col items-center justify-center gap-1 z-10 flex-shrink-0"
|
<div class="relative flex flex-col items-center justify-center gap-1.5 z-10 flex-shrink-0"
|
||||||
style="height: 90px; border-top: 1px solid rgba(255,255,255,0.06); background: linear-gradient(180deg, transparent, rgba(0,0,0,0.32));">
|
style="height: 90px; border-top: 1px solid rgba(255,255,255,0.06); background: linear-gradient(180deg, transparent, rgba(0,0,0,0.32));">
|
||||||
{# Sub-mode dots indicator (shows position within active category) #}
|
|
||||||
<div class="flex items-center gap-1" style="height:6px;" aria-hidden="true">
|
|
||||||
<template x-for="(sm, di) in CATEGORIES[activeCategory].submodes" :key="di">
|
|
||||||
<span class="block rounded-full"
|
|
||||||
:style="`width:${sm === selectedFeature ? '10px' : '4px'};height:4px;background:${sm === selectedFeature ? CATEGORIES[activeCategory].color : 'rgba(255,255,255,0.20)'};transition:width 0.2s, background 0.2s;`"></span>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# 4 catégories tabs #}
|
{# 6 boutons features originaux (FEATURES indexes 1-6) — visible bottom tab bar #}
|
||||||
<div class="flex items-end gap-1">
|
<div class="flex items-end gap-1.5 justify-center">
|
||||||
<template x-for="(cat, ci) in CATEGORIES" :key="ci">
|
<template x-for="i in [1,2,3,4,5,6]" :key="i">
|
||||||
<button type="button" @click="handleCategorySelect(ci)"
|
<button type="button" @click="handleManualSelect(i)"
|
||||||
class="dictia-feat-btn dictia-cat-btn outline-none cursor-pointer focus-visible:ring-2 focus-visible:ring-white/40 flex flex-col items-center justify-end relative"
|
class="dictia-feat-btn outline-none cursor-pointer focus-visible:ring-2 focus-visible:ring-white/40 flex flex-col items-center justify-end relative"
|
||||||
style="width:54px;height:42px;border:none;padding:4px 0 6px;background:transparent;"
|
style="width:34px;height:42px;border:none;padding:4px 0 6px;background:transparent;"
|
||||||
:aria-pressed="activeCategory === ci ? 'true' : 'false'"
|
:aria-pressed="selectedFeature === i ? 'true' : 'false'"
|
||||||
:aria-label="`Catégorie : ${cat.title}`">
|
:aria-label="`Fonction : ${FEATURES[i].title}`">
|
||||||
<span :style="`color: ${activeCategory === ci ? cat.color : 'rgba(255,255,255,0.30)'}; transition: color 0.2s, transform 0.15s, filter 0.2s; filter: ${activeCategory === ci ? 'drop-shadow(0 0 6px ' + cat.color + 'CC)' : 'none'}; transform: scale(${activeCategory === ci ? 1.15 : 1}); display: inline-block;`">
|
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.40)'}; transition: color 0.2s, transform 0.15s, filter 0.2s; filter: ${selectedFeature === i ? 'drop-shadow(0 0 6px ' + FEATURES[i].color + 'CC)' : 'none'}; transform: scale(${selectedFeature === i ? 1.15 : 1}); display: inline-block;`">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;" aria-hidden="true" x-html="cat.iconPath"></svg>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-[9px] font-mono font-bold mt-0.5 leading-none uppercase tracking-wider"
|
<span class="text-[9px] font-mono font-bold mt-0.5 leading-none uppercase tracking-wider"
|
||||||
:style="`color: ${activeCategory === ci ? cat.color : 'rgba(255,255,255,0.40)'};`"
|
:style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.55)'};`"
|
||||||
x-text="cat.short"></span>
|
x-text="featureShortLabel(i)"></span>
|
||||||
{# Tab indicator bottom border 2px #}
|
{# Tab indicator bottom border 2px #}
|
||||||
<span x-show="activeCategory === ci" class="absolute" aria-hidden="true"
|
<span x-show="selectedFeature === i" class="absolute" aria-hidden="true"
|
||||||
:style="`bottom: 0; left: 6px; right: 6px; height: 2px; background: ${cat.color}; border-radius: 1px; box-shadow: 0 0 8px ${cat.color};`"></span>
|
:style="`bottom: 0; left: 4px; right: 4px; height: 2px; background: ${FEATURES[i].color}; border-radius: 1px; box-shadow: 0 0 8px ${FEATURES[i].color};`"></span>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -1286,35 +1279,41 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Mobile : pills catégories horizontales scrollables #}
|
{# Mobile : pills features horizontales scrollables (12 fonctions, indexes 1-12) #}
|
||||||
<div class="lg:hidden w-full overflow-x-auto dictia-hide-scrollbar" style="scrollbar-width:none;">
|
<div class="lg:hidden w-full overflow-x-auto dictia-hide-scrollbar" style="scrollbar-width:none;">
|
||||||
<div class="flex gap-2 px-1 pb-1" style="width:max-content;">
|
<div class="flex gap-2 px-1 pb-1" style="width:max-content;">
|
||||||
<template x-for="(cat, ci) in CATEGORIES" :key="ci">
|
<template x-for="i in [1,2,3,4,5,6,7,8,9,10,11,12]" :key="i">
|
||||||
<button type="button" @click="handleCategorySelect(ci)"
|
<button type="button" @click="handleManualSelect(i)"
|
||||||
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-full shrink-0 transition-all focus-visible:ring-2 focus-visible:ring-brand-b1"
|
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-full shrink-0 transition-all focus-visible:ring-2 focus-visible:ring-brand-b1"
|
||||||
:style="`border: 1px solid ${activeCategory === ci ? cat.color + '70' : 'rgba(0,0,0,0.10)'}; background-color: ${activeCategory === ci ? cat.color + '18' : 'rgba(0,0,0,0.04)'}; outline: none;`">
|
:style="`border: 1px solid ${selectedFeature === i ? FEATURES[i].color + '70' : 'rgba(0,0,0,0.10)'}; background-color: ${selectedFeature === i ? FEATURES[i].color + '18' : 'rgba(0,0,0,0.04)'}; outline: none;`"
|
||||||
<span :style="`color: ${activeCategory === ci ? cat.color : 'rgba(0,0,0,0.40)'}; transition: color 0.2s;`">
|
:aria-pressed="selectedFeature === i ? 'true' : 'false'"
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:12px;height:12px;" aria-hidden="true" x-html="cat.iconPath"></svg>
|
:aria-label="`Fonction : ${FEATURES[i].title}`">
|
||||||
|
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(0,0,0,0.40)'}; transition: color 0.2s;`">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:12px;height:12px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-[11px] font-bold whitespace-nowrap"
|
<span class="text-[11px] font-bold whitespace-nowrap"
|
||||||
:style="`color: ${activeCategory === ci ? cat.color : 'rgba(0,0,0,0.50)'};`"
|
:style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(0,0,0,0.50)'};`"
|
||||||
x-text="cat.title"></span>
|
x-text="FEATURES[i].title"></span>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# ─────────── ZONE RIGHT : IA Mistral premium card + grid 6 features ─────────── #}
|
{# ─────────── ZONE RIGHT : IA Mistral premium card + grid 12 features ─────────── #}
|
||||||
<div class="flex flex-col gap-3 w-full lg:w-[320px] flex-shrink-0 relative z-10">
|
<div class="flex flex-col gap-3 w-full lg:w-[320px] flex-shrink-0 relative z-10">
|
||||||
|
|
||||||
{# Eyebrow + title — alignés sur le système typo #}
|
{# Eyebrow + title — alignés sur le système typo #}
|
||||||
<div class="mb-1 flex items-center gap-2">
|
<div class="mb-1 flex items-center justify-between gap-2">
|
||||||
<span class="block w-1 h-6 rounded-full" style="background:linear-gradient(180deg,#06b6d4,#c026d3);" aria-hidden="true"></span>
|
<div class="flex items-center gap-2">
|
||||||
<div>
|
<span class="block w-1 h-6 rounded-full" style="background:linear-gradient(180deg,#06b6d4,#c026d3);" aria-hidden="true"></span>
|
||||||
<p class="text-xs font-mono font-bold uppercase tracking-widest text-brand-b3">4 catégories · 12 sous-modes</p>
|
<div>
|
||||||
<p class="font-bold text-lg leading-snug text-brand-navy">Le moteur IA local</p>
|
<p class="text-xs font-mono font-bold uppercase tracking-widest text-brand-b3">Fonctions clés</p>
|
||||||
|
<p class="font-bold text-lg leading-snug text-brand-navy">Le moteur IA local</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="text-[10px] font-mono font-bold px-2 py-0.5 rounded-full text-brand-b3 whitespace-nowrap"
|
||||||
|
style="background-color:rgba(192,38,211,0.10);border:1px solid rgba(192,38,211,0.25);">12 fonctions</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# IA Mistral 7B premium card — couleurs brand-b3 (fuchsia officiel) #}
|
{# IA Mistral 7B premium card — couleurs brand-b3 (fuchsia officiel) #}
|
||||||
@@ -1410,32 +1409,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Category grid 2×2 — 4 catégories avec sous-modes affichés dessous (architecture lisible) #}
|
{# Feature grid 3×4 — 12 fonctions (FEATURES indexes 1-12, IA mode 0 accessible via Brain card ci-dessus) #}
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-3 gap-2">
|
||||||
<template x-for="(cat, ci) in CATEGORIES" :key="ci">
|
<template x-for="i in [1,2,3,4,5,6,7,8,9,10,11,12]" :key="i">
|
||||||
<button type="button" @click="handleCategorySelect(ci)"
|
<button type="button" @click="handleManualSelect(i)"
|
||||||
class="flex flex-col items-start gap-2 rounded-xl py-3 px-3 outline-none transition-all focus-visible:ring-2 focus-visible:ring-white/40 text-left"
|
class="flex flex-col items-center gap-1.5 rounded-xl py-2.5 px-2 outline-none transition-all focus-visible:ring-2 focus-visible:ring-white/40 text-center"
|
||||||
:style="`border: 1px solid ${activeCategory === ci ? cat.color + '70' : 'rgba(255,255,255,0.10)'}; background-color: ${activeCategory === ci ? 'rgba(8,12,24,0.95)' : 'rgba(8,12,24,0.85)'}; box-shadow: ${activeCategory === ci ? '0 0 16px ' + cat.color + '40, inset 0 0 16px ' + cat.color + '20' : 'none'}; cursor: pointer;`"
|
:style="`border: 1px solid ${selectedFeature === i ? FEATURES[i].color + '70' : 'rgba(255,255,255,0.10)'}; background-color: ${selectedFeature === i ? 'rgba(8,12,24,0.95)' : 'rgba(8,12,24,0.85)'}; box-shadow: ${selectedFeature === i ? '0 0 16px ' + FEATURES[i].color + '40, inset 0 0 16px ' + FEATURES[i].color + '20' : 'none'}; cursor: pointer; min-height:64px;`"
|
||||||
:aria-pressed="activeCategory === ci ? 'true' : 'false'"
|
:aria-pressed="selectedFeature === i ? 'true' : 'false'"
|
||||||
:aria-label="`Catégorie : ${cat.title}`">
|
:aria-label="`Fonction : ${FEATURES[i].title}`">
|
||||||
<div class="flex items-center gap-2 w-full">
|
<span :style="`color: ${selectedFeature === i ? FEATURES[i].color : 'rgba(255,255,255,0.55)'}; filter: ${selectedFeature === i ? 'drop-shadow(0 0 6px ' + FEATURES[i].color + 'BB)' : 'none'}; transition: all 0.2s; transform: scale(${selectedFeature === i ? 1.15 : 1}); display:inline-block;`">
|
||||||
<span :style="`color: ${activeCategory === ci ? cat.color : 'rgba(255,255,255,0.55)'}; filter: ${activeCategory === ci ? 'drop-shadow(0 0 6px ' + cat.color + 'BB)' : 'none'}; transition: all 0.2s; display:inline-block;`">
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;" aria-hidden="true" x-html="featureIconPath(i)"></svg>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;" aria-hidden="true" x-html="cat.iconPath"></svg>
|
</span>
|
||||||
</span>
|
<span class="text-[10px] font-bold leading-tight w-full truncate"
|
||||||
<span class="text-[11px] font-bold leading-tight flex-1"
|
:style="`color: ${selectedFeature === i ? 'rgba(255,255,255,0.98)' : 'rgba(255,255,255,0.85)'};`"
|
||||||
:style="`color: ${activeCategory === ci ? 'rgba(255,255,255,0.98)' : 'rgba(255,255,255,0.85)'};`"
|
x-text="featureGridLabel(i)"></span>
|
||||||
x-text="cat.title"></span>
|
|
||||||
</div>
|
|
||||||
<p class="text-[10px] font-mono leading-snug w-full"
|
|
||||||
:style="`color: ${activeCategory === ci ? cat.color + 'EE' : 'rgba(255,255,255,0.55)'};`"
|
|
||||||
x-text="cat.subtitle"></p>
|
|
||||||
{# Mini sous-modes dots dans la card #}
|
|
||||||
<div class="flex items-center gap-0.5 mt-auto" aria-hidden="true">
|
|
||||||
<template x-for="(sm, si) in cat.submodes" :key="si">
|
|
||||||
<span class="block rounded-full"
|
|
||||||
:style="`width:${activeCategory === ci && sm === selectedFeature ? '8px' : '3px'};height:3px;background:${activeCategory === ci ? (sm === selectedFeature ? cat.color : cat.color + '55') : 'rgba(255,255,255,0.15)'};transition:all 0.2s;`"></span>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -1445,11 +1432,11 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Alpine logic — dictiaDashboard + 4 catégories × 12 sous-modes (refonte stratégique 2026-04-29) #}
|
{# Alpine logic — dictiaDashboard : 12 fonctions visibles (1-12) + IA accessible via Brain card (refonte 2026-04-29) #}
|
||||||
<script>
|
<script>
|
||||||
function dictiaDashboard() {
|
function dictiaDashboard() {
|
||||||
return {
|
return {
|
||||||
/* FEATURES indexes (0-12) — même structure que v1 (0=IA, 1-6=existants), nouveaux 7-12 ajoutés */
|
/* FEATURES indexes (0-12) — IA mode 0 accessible via Brain card; 1-6 = originaux, 7-12 = nouveaux */
|
||||||
FEATURES: [
|
FEATURES: [
|
||||||
{ idx: 0, title: 'IA intégrée', subtitle: "Résumé, actions, Q&R", color: '#c026d3', badge: 'Mistral 7B' }, /* brand-b3 */
|
{ idx: 0, title: 'IA intégrée', subtitle: "Résumé, actions, Q&R", color: '#c026d3', badge: 'Mistral 7B' }, /* brand-b3 */
|
||||||
{ idx: 1, title: 'Transcription', subtitle: 'Parole → texte en temps réel', color: '#06b6d4', badge: 'Whisper AI' }, /* brand-b2 */
|
{ idx: 1, title: 'Transcription', subtitle: 'Parole → texte en temps réel', color: '#06b6d4', badge: 'Whisper AI' }, /* brand-b2 */
|
||||||
@@ -1466,43 +1453,7 @@
|
|||||||
{ idx: 11, title: 'Audit trail', subtitle: 'Traçabilité Loi 25 immutable', color: '#2563eb', badge: 'Loi 25' }, /* brand-b1 */
|
{ idx: 11, title: 'Audit trail', subtitle: 'Traçabilité Loi 25 immutable', color: '#2563eb', badge: 'Loi 25' }, /* brand-b1 */
|
||||||
{ idx: 12, title: 'Conformité', subtitle: '9 ordres pros · EFVP CAI', color: '#c026d3', badge: 'MCN' } /* brand-b3 */
|
{ idx: 12, title: 'Conformité', subtitle: '9 ordres pros · EFVP CAI', color: '#c026d3', badge: 'MCN' } /* brand-b3 */
|
||||||
],
|
],
|
||||||
/* CATEGORIES : 4 regroupements logiques. Chaque catégorie a ses sous-modes (ids des FEATURES). */
|
|
||||||
CATEGORIES: [
|
|
||||||
{
|
|
||||||
title: 'Capture',
|
|
||||||
short: 'Capture',
|
|
||||||
subtitle: 'Audio in : upload, recording, recherche',
|
|
||||||
color: '#06b6d4', /* brand-b2 cyan */
|
|
||||||
submodes: [1, 7, 8], /* Transcription (upload), Recording live, Recherche sémantique */
|
|
||||||
iconPath: '<rect x="9" y="2" width="6" height="12" rx="3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/>'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Transformation IA',
|
|
||||||
short: 'IA',
|
|
||||||
subtitle: 'Diarisation, langues, résumés, Q&R',
|
|
||||||
color: '#2563eb', /* brand-b1 blue */
|
|
||||||
submodes: [2, 3, 9, 0], /* Diarisation, Langues, Résumé+actions, Chat IA */
|
|
||||||
iconPath: '<path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z"/>'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Distribution',
|
|
||||||
short: 'Distrib',
|
|
||||||
subtitle: 'Exports, intégrations, partage',
|
|
||||||
color: '#c026d3', /* brand-b3 fuchsia */
|
|
||||||
submodes: [4, 10, 6, 5], /* Exports, Intégrations, Partage, Users */
|
|
||||||
iconPath: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Gouvernance',
|
|
||||||
short: 'Gouv',
|
|
||||||
subtitle: 'Audit, Loi 25, AGPL, ordres pros',
|
|
||||||
color: '#2563eb', /* brand-b1 blue (sobre, institutionnel) */
|
|
||||||
submodes: [11, 12], /* Audit trail, Conformité Loi 25 */
|
|
||||||
iconPath: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="M9 12l2 2 4-4"/>'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
selectedFeature: 1,
|
selectedFeature: 1,
|
||||||
activeCategory: 0,
|
|
||||||
isManual: false,
|
isManual: false,
|
||||||
autoCycleTimer: null,
|
autoCycleTimer: null,
|
||||||
manualResetTimer: null,
|
manualResetTimer: null,
|
||||||
@@ -1512,42 +1463,19 @@
|
|||||||
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
this.startAutoCycle();
|
this.startAutoCycle();
|
||||||
},
|
},
|
||||||
/* Auto-cycle logic : avance dans les sous-modes de la catégorie active toutes les 1100ms.
|
/* Auto-cycle logic : avance 1→12 (skip 0=IA mode, accessible via Brain card), 1100ms each.
|
||||||
Quand on atteint le dernier sous-mode → switch catégorie suivante (boucle 0→1→2→3→0). */
|
Cycle complet : 12 features × 1100ms ≈ 13.2s puis recommence à 1. */
|
||||||
startAutoCycle() {
|
startAutoCycle() {
|
||||||
if (this.autoCycleTimer) clearInterval(this.autoCycleTimer);
|
if (this.autoCycleTimer) clearInterval(this.autoCycleTimer);
|
||||||
this.autoCycleTimer = setInterval(() => {
|
this.autoCycleTimer = setInterval(() => {
|
||||||
const cat = this.CATEGORIES[this.activeCategory];
|
/* Avance 1→2→...→12, puis retour à 1 (skip 0=IA) */
|
||||||
const currentIdx = cat.submodes.indexOf(this.selectedFeature);
|
this.selectedFeature = this.selectedFeature >= 12 ? 1 : this.selectedFeature + 1;
|
||||||
if (currentIdx < cat.submodes.length - 1) {
|
if (this.selectedFeature === 0) this.selectedFeature = 1;
|
||||||
/* Avance dans la catégorie courante */
|
|
||||||
this.selectedFeature = cat.submodes[currentIdx + 1];
|
|
||||||
} else {
|
|
||||||
/* Fin de catégorie → passe à la suivante */
|
|
||||||
this.activeCategory = (this.activeCategory + 1) % this.CATEGORIES.length;
|
|
||||||
this.selectedFeature = this.CATEGORIES[this.activeCategory].submodes[0];
|
|
||||||
}
|
|
||||||
}, 1100);
|
}, 1100);
|
||||||
},
|
},
|
||||||
/* Click manuel sur un sous-mode (compatibilité 6 boutons originaux) */
|
/* Click manuel sur un bouton feature : sélectionne ce mode + freeze auto 4500ms */
|
||||||
handleManualSelect(i) {
|
handleManualSelect(i) {
|
||||||
this.selectedFeature = i;
|
this.selectedFeature = i;
|
||||||
/* Trouve la catégorie qui contient ce sous-mode */
|
|
||||||
for (let ci = 0; ci < this.CATEGORIES.length; ci++) {
|
|
||||||
if (this.CATEGORIES[ci].submodes.includes(i)) { this.activeCategory = ci; break; }
|
|
||||||
}
|
|
||||||
this.isManual = true;
|
|
||||||
if (this.autoCycleTimer) { clearInterval(this.autoCycleTimer); this.autoCycleTimer = null; }
|
|
||||||
if (this.manualResetTimer) clearTimeout(this.manualResetTimer);
|
|
||||||
this.manualResetTimer = setTimeout(() => {
|
|
||||||
this.isManual = false;
|
|
||||||
this.startAutoCycle();
|
|
||||||
}, 4500);
|
|
||||||
},
|
|
||||||
/* Click manuel sur une catégorie : sélectionne son premier sous-mode */
|
|
||||||
handleCategorySelect(ci) {
|
|
||||||
this.activeCategory = ci;
|
|
||||||
this.selectedFeature = this.CATEGORIES[ci].submodes[0];
|
|
||||||
this.isManual = true;
|
this.isManual = true;
|
||||||
if (this.autoCycleTimer) { clearInterval(this.autoCycleTimer); this.autoCycleTimer = null; }
|
if (this.autoCycleTimer) { clearInterval(this.autoCycleTimer); this.autoCycleTimer = null; }
|
||||||
if (this.manualResetTimer) clearTimeout(this.manualResetTimer);
|
if (this.manualResetTimer) clearTimeout(this.manualResetTimer);
|
||||||
@@ -1578,6 +1506,15 @@
|
|||||||
const labels = { 1: 'Trans', 2: 'Diari', 3: 'Lang', 4: 'Exp', 5: 'Users', 6: 'Part',
|
const labels = { 1: 'Trans', 2: 'Diari', 3: 'Lang', 4: 'Exp', 5: 'Users', 6: 'Part',
|
||||||
7: 'Rec', 8: 'Search', 9: 'Résu', 10: 'Hub', 11: 'Audit', 12: 'Conf' };
|
7: 'Rec', 8: 'Search', 9: 'Résu', 10: 'Hub', 11: 'Audit', 12: 'Conf' };
|
||||||
return labels[i] || '';
|
return labels[i] || '';
|
||||||
|
},
|
||||||
|
/* Labels compacts pour la grid 3×4 du right panel (raccourcis pour ne pas tronquer) */
|
||||||
|
featureGridLabel(i) {
|
||||||
|
const labels = {
|
||||||
|
1: 'Transcription', 2: 'Diarisation', 3: '99+ langues', 4: 'Exports',
|
||||||
|
5: 'Utilisateurs', 6: 'Partage', 7: 'Recording', 8: 'Recherche IA',
|
||||||
|
9: 'Résumés', 10: 'Intégrations', 11: 'Audit trail', 12: 'Conformité'
|
||||||
|
};
|
||||||
|
return labels[i] || '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,12 +192,13 @@ def test_fonctionnalites_how_it_works_reactor_section():
|
|||||||
assert 'handleManualSelect' in body, "Missing manual select handler"
|
assert 'handleManualSelect' in body, "Missing manual select handler"
|
||||||
assert '1100' in body, "Missing 1100ms sub-mode cycle interval (refonte 2026-04-29)"
|
assert '1100' in body, "Missing 1100ms sub-mode cycle interval (refonte 2026-04-29)"
|
||||||
assert '4500' in body, "Missing 4500ms manual reset timer"
|
assert '4500' in body, "Missing 4500ms manual reset timer"
|
||||||
# Refonte 2026-04-29 : 4 catégories × 12 sous-modes
|
# Refonte 2026-04-29 (v2) : 12 fonctions visibles directement (1-12), IA mode 0 via Brain card.
|
||||||
assert 'CATEGORIES' in body, "Missing CATEGORIES array (refonte 4 catégories)"
|
# Bottom tab bar = 6 boutons originaux (Trans/Diari/Lang/Exp/Users/Part) ; right panel grid = 12 features.
|
||||||
assert 'activeCategory' in body, "Missing activeCategory state"
|
assert 'featureGridLabel' in body, "Missing featureGridLabel (right grid 12 buttons)"
|
||||||
assert 'handleCategorySelect' in body, "Missing category click handler"
|
assert '12 fonctions' in body, "Missing '12 fonctions' badge in right panel header"
|
||||||
for cat_title in ['Capture', 'Transformation IA', 'Distribution', 'Gouvernance']:
|
# Labels compacts grid right panel
|
||||||
assert cat_title in body, f"Missing category : {cat_title}"
|
for grid_label in ['Recording', 'Recherche IA', 'Résumés', 'Intégrations', 'Audit trail', 'Conformité']:
|
||||||
|
assert grid_label in body, f"Missing right grid label : {grid_label}"
|
||||||
# Nouveaux modes 7-12
|
# Nouveaux modes 7-12
|
||||||
assert 'recModeData' in body, "Missing Mode 7 (Recording live)"
|
assert 'recModeData' in body, "Missing Mode 7 (Recording live)"
|
||||||
assert 'searchModeData' in body, "Missing Mode 8 (Recherche sémantique)"
|
assert 'searchModeData' in body, "Missing Mode 8 (Recherche sémantique)"
|
||||||
@@ -273,9 +274,9 @@ def test_fonctionnalites_how_it_works_reactor_section():
|
|||||||
assert 'dictia-bg-orbs' in body, "Missing floating orbs"
|
assert 'dictia-bg-orbs' in body, "Missing floating orbs"
|
||||||
assert 'dictia-connecting-line' in body, "Missing connecting line phone↔IA"
|
assert 'dictia-connecting-line' in body, "Missing connecting line phone↔IA"
|
||||||
|
|
||||||
# Stats row in section header (refonte 2026-04-29 : 4 catégories · 6 modules)
|
# Stats row in section header (refonte v2 2026-04-29 : 12 fonctions visibles)
|
||||||
assert 'modules' in body, "Missing stats row 'modules'"
|
assert 'modules' in body, "Missing stats row 'modules'"
|
||||||
assert 'catégories' in body, "Missing stats row 'catégories' (refonte)"
|
assert 'fonctions' in body, "Missing stats row 'fonctions' (refonte v2)"
|
||||||
assert 'cloud' in body, "Missing stats row 'cloud'"
|
assert 'cloud' in body, "Missing stats row 'cloud'"
|
||||||
assert 'Voir une démo' in body, "Missing demo CTA link"
|
assert 'Voir une démo' in body, "Missing demo CTA link"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user