Accents FR, architecture modulaire, protocoles opérationnels

- Fix accents manquants dans 7 pages UI (décisions, boîte à outils, etc.)
- Titres accueil enrichis : Décisions structurantes, Documents de référence,
  Mandats et nominations, Protocoles et fonctionnement
- Retrait Embarquement Forgeron du seed (n'est pas une Decision)
- 2 protocoles opérationnels dans Protocoles : Embarquement Forgeron
  (lié à l'Acte d'engagement) + Soumission Runtime Upgrade (lié à la
  Décision Runtime Upgrade) avec timeline et liens croisés signalétiques
- Décision Runtime Upgrade : badge on-chain + lien protocole + contexte
- Document [slug] : lien protocole dans la section Qualification

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-03-03 07:05:55 +01:00
parent c19c1aa55e
commit 8201e73d7c
8 changed files with 328 additions and 221 deletions

View File

@@ -3,7 +3,7 @@
* Decisions — page index.
*
* Utilise SectionLayout avec status filters, recherche, tri,
* et sidebar "Boite a outils" affichant les protocoles de vote.
* et sidebar "Boîte à outils" affichant les protocoles de vote.
*/
const decisions = useDecisionsStore()
const protocols = useProtocolsStore()
@@ -28,7 +28,7 @@ onMounted(async () => {
/** Status filter pills with counts. */
const statuses = computed(() => [
{ id: 'draft', label: 'En prepa', count: decisions.list.filter(d => d.status === 'draft').length },
{ id: 'draft', label: 'En prépa', count: decisions.list.filter(d => d.status === 'draft').length },
{ id: 'voting', label: 'En vote', count: decisions.list.filter(d => d.status === 'voting' || d.status === 'qualification' || d.status === 'review').length },
{ id: 'executed', label: 'En vigueur', count: decisions.list.filter(d => d.status === 'executed').length },
{ id: 'closed', label: 'Clos', count: decisions.list.filter(d => d.status === 'closed').length },
@@ -97,8 +97,8 @@ function formatDate(dateStr: string): string {
<template>
<SectionLayout
title="Decisions"
subtitle="Processus de decision collectifs"
title="Décisions"
subtitle="Processus de décision collectifs"
:statuses="statuses"
:active-status="activeStatus"
@update:active-status="activeStatus = $event"
@@ -111,7 +111,7 @@ function formatDate(dateStr: string): string {
v-model="searchQuery"
type="text"
class="search-field__input"
placeholder="Rechercher une decision..."
placeholder="Rechercher une décision..."
/>
</div>
<select v-model="sortBy" class="sort-select">
@@ -149,7 +149,7 @@ function formatDate(dateStr: string): string {
style="color: var(--mood-text-muted);"
>
<UIcon name="i-lucide-scale" class="text-4xl mb-3 block mx-auto" />
<p>Aucune decision trouvee</p>
<p>Aucune décision trouvée</p>
<p v-if="searchQuery || activeStatus" class="text-sm mt-1">
Essayez de modifier vos filtres
</p>
@@ -179,15 +179,33 @@ function formatDate(dateStr: string): string {
<span class="decision-card__type-badge">
{{ typeLabel(decision.decision_type) }}
</span>
<span
v-if="decision.decision_type === 'runtime_upgrade'"
class="decision-card__onchain-badge"
>
<UIcon name="i-lucide-link" class="text-xs" />
on-chain
</span>
<span class="decision-card__steps">
<UIcon name="i-lucide-layers" class="text-xs" />
{{ decision.steps.length }} etape{{ decision.steps.length !== 1 ? 's' : '' }}
{{ decision.steps.length }} étape{{ decision.steps.length !== 1 ? 's' : '' }}
</span>
<span class="decision-card__date">
<UIcon name="i-lucide-clock" class="text-xs" />
{{ formatDate(decision.created_at) }}
</span>
</div>
<!-- Protocol link for runtime_upgrade -->
<NuxtLink
v-if="decision.decision_type === 'runtime_upgrade'"
to="/protocols"
class="decision-card__protocol-link"
@click.stop
>
<UIcon name="i-lucide-git-branch" class="text-xs" />
<span>Protocole : Soumission Runtime Upgrade</span>
<UIcon name="i-lucide-arrow-right" class="text-xs" />
</NuxtLink>
</div>
</div>
</template>
@@ -196,21 +214,21 @@ function formatDate(dateStr: string): string {
<template #toolbox>
<ToolboxVignette
title="Vote majoritaire WoT"
:bullets="['Seuil adaptatif a la participation', 'Formule g1vote inertielle']"
:bullets="['Seuil adaptatif à la participation', 'Formule g1vote inertielle']"
:actions="[
{ label: 'Simuler', icon: 'i-lucide-calculator', to: '/protocols/formulas', primary: true },
]"
/>
<ToolboxVignette
title="Vote nuance"
:bullets="['6 niveaux de preference', 'Seuil de satisfaction 80%']"
title="Vote nuancé"
:bullets="['6 niveaux de préférence', 'Seuil de satisfaction 80%']"
:actions="[
{ label: 'Voir', icon: 'i-lucide-bar-chart-3', emit: 'nuance' },
]"
/>
<ToolboxVignette
title="Mandature"
:bullets="['Election en binome', 'Transparence et revocation']"
:bullets="['Élection en binôme', 'Transparence et révocation']"
:actions="[
{ label: 'Mandats', icon: 'i-lucide-user-check', to: '/mandates', primary: true },
]"
@@ -337,6 +355,40 @@ function formatDate(dateStr: string): string {
color: var(--mood-accent);
}
.decision-card__onchain-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
font-size: 0.625rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
padding: 3px 8px;
border-radius: 20px;
background: color-mix(in srgb, var(--mood-success) 15%, transparent);
color: var(--mood-success);
}
.decision-card__protocol-link {
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.375rem 0.75rem;
font-size: 0.75rem;
font-weight: 600;
border-radius: 20px;
text-decoration: none;
background: color-mix(in srgb, var(--mood-tertiary, var(--mood-accent)) 10%, transparent);
color: var(--mood-tertiary, var(--mood-accent));
transition: transform 0.12s ease, box-shadow 0.12s ease;
width: fit-content;
}
.decision-card__protocol-link:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px var(--mood-shadow);
}
/* --- Modern search / sort / action --- */
.search-field {
flex: 1;