Boîtes à outils enrichies : ContextMapper, SocioElection, WorkflowMilestones

- ContextMapper : 4 questions contexte → méthode de décision optimale
  (advice process Laloux, vote inertiel WoT, consentement sociocratique, Smith…)
- SocioElection : guide élection sociocratique 6 étapes + advice process + clarté de rôle
- WorkflowMilestones : 11 jalons de protocole (7 essentiels), durées recommandées, principes Ostrom
- WorkspaceSelector : sélecteur de collectif multi-site dans le header
- SectionLayout : toolbox en USlideover droit sur mobile, sidebar sticky desktop
- Décisions : ContextMapper intégré + guide consentement
- Mandats : SocioElection intégré + cycle de mandat
- Documents : guide inertie 4 niveaux + structure + IPFS
- Protocoles : WorkflowMilestones + protocole élection sociocratique ajouté
- Renommage projet Glibredecision → libreDecision (dossier + sources)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-03-17 00:13:08 +01:00
parent 316d205593
commit 290548703d
29 changed files with 4174 additions and 168 deletions

View File

@@ -11,6 +11,41 @@ const documents = useDocumentsStore()
const protocols = useProtocolsStore()
const auth = useAuthStore()
const inertiaLevels = [
{
id: 'light',
name: 'Léger',
color: 'teal',
params: 'B=0.05, G=0.1',
desc: 'Modification facile. Majorité simple suffit avec bonne participation.',
example: 'Clarifications rédactionnelles, notes de bas de page.',
},
{
id: 'standard',
name: 'Standard',
color: 'accent',
params: 'B=0.1, G=0.2',
desc: 'Seuil adaptatif standard. La formule g1vote dans son paramétrage habituel.',
example: 'Articles de fond, engagements opérationnels.',
},
{
id: 'strong',
name: 'Fort',
color: 'secondary',
params: 'B=0.15, G=0.3',
desc: 'Forte résistance. Faible participation → quasi-unanimité requise.',
example: 'Principes fondateurs, formules de vote, critères WoT.',
},
{
id: 'very-strong',
name: 'Très fort',
color: 'error',
params: 'B=0.2, G=0.4',
desc: 'Protection maximale. Seule une forte mobilisation peut modifier.',
example: 'Clause de licence, identité du projet, droits des membres.',
},
]
const activeStatus = ref<string | null>(null)
const searchQuery = ref('')
const sortBy = ref<'date' | 'title' | 'status'>('date')
@@ -251,25 +286,55 @@ async function createDocument() {
<!-- Toolbox sidebar -->
<template #toolbox>
<!-- Inertia guide -->
<div class="toolbox-block">
<div class="toolbox-block__head">
<UIcon name="i-lucide-sliders-horizontal" />
<span>Niveaux d'inertie</span>
</div>
<div class="inertia-guide">
<div v-for="level in inertiaLevels" :key="level.id" class="inertia-level">
<div class="inertia-level__header">
<span class="inertia-level__name" :class="`inertia-level__name--${level.color}`">
{{ level.name }}
</span>
<span class="inertia-level__params">{{ level.params }}</span>
</div>
<p class="inertia-level__desc">{{ level.desc }}</p>
<p class="inertia-level__example">{{ level.example }}</p>
</div>
</div>
<NuxtLink to="/protocols/formulas" class="toolbox-link-btn">
<UIcon name="i-lucide-calculator" />
Simuler les formules
</NuxtLink>
</div>
<!-- Structure document -->
<ToolboxVignette
title="Modules"
:bullets="['Structurer en sections et clauses', 'Vote indépendant par clause']"
:actions="[
{ label: 'Voir', icon: 'i-lucide-puzzle', emit: 'modules' },
title="Structure d'un document"
:bullets="[
'Items = clauses individuelles',
'Sections = groupes thématiques',
'Chaque clause : vote indépendant',
'Genesis block : traçabilité d\'origine',
]"
/>
<ToolboxVignette
title="Votes permanents"
:bullets="['Chaque clause est modifiable', 'Seuil adaptatif WoT']"
:actions="[
{ label: 'Formules', icon: 'i-lucide-calculator', to: '/protocols/formulas', primary: true },
{ label: 'Nouveau doc', icon: 'i-lucide-file-plus', emit: 'new', primary: true },
]"
@action="e => e === 'new' && openNewDocModal()"
/>
<!-- Sanctuaire -->
<ToolboxVignette
title="Inertie de remplacement"
:bullets="['4 niveaux de difficulté', 'Protège les textes fondamentaux']"
title="Sanctuaire IPFS"
:bullets="[
'Document adopté → archivé on-chain',
'Hash IPFS + system.remark Duniter',
'Immuable, vérifiable, décentralisé',
]"
:actions="[
{ label: 'Simuler', icon: 'i-lucide-sliders-horizontal', to: '/protocols/formulas', primary: true },
{ label: 'Sanctuaire', icon: 'i-lucide-archive', to: '/sanctuary', primary: true },
]"
/>
</template>
@@ -469,18 +534,104 @@ async function createDocument() {
}
}
.toolbox-section-title {
font-size: 0.8125rem;
font-weight: 700;
color: var(--mood-text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 0.25rem;
/* Toolbox blocks */
.toolbox-block {
background: var(--mood-accent-soft);
border-radius: 14px;
padding: 0.875rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.toolbox-empty-text {
.toolbox-block__head {
display: flex;
align-items: center;
gap: 0.375rem;
font-size: 0.8125rem;
font-weight: 800;
color: var(--mood-accent);
text-transform: uppercase;
letter-spacing: 0.04em;
}
/* Inertia guide */
.inertia-guide {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.inertia-level {
background: var(--mood-surface);
border-radius: 10px;
padding: 0.625rem 0.75rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.inertia-level__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
}
.inertia-level__name {
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.inertia-level__name--teal { color: var(--mood-success); }
.inertia-level__name--accent { color: var(--mood-accent); }
.inertia-level__name--secondary { color: var(--mood-secondary, var(--mood-accent)); }
.inertia-level__name--error { color: var(--mood-error); }
.inertia-level__params {
font-size: 0.6875rem;
font-family: ui-monospace, SFMono-Regular, monospace;
color: var(--mood-text-muted);
background: var(--mood-accent-soft);
padding: 1px 6px;
border-radius: 8px;
}
.inertia-level__desc {
font-size: 0.75rem;
color: var(--mood-text-muted);
margin: 0;
line-height: 1.5;
}
.inertia-level__example {
font-size: 0.6875rem;
color: var(--mood-text-muted);
margin: 0;
font-style: italic;
opacity: 0.8;
}
.toolbox-link-btn {
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.5rem 0.875rem;
font-size: 0.8125rem;
font-weight: 700;
color: var(--mood-accent-text);
background: var(--mood-accent);
border-radius: 20px;
text-decoration: none;
cursor: pointer;
align-self: flex-start;
transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.toolbox-link-btn:hover {
transform: translateY(-1px);
box-shadow: 0 3px 10px var(--mood-shadow);
}
/* --- Modern search / sort / action --- */