From 3ba9c43ce30ec2f0f4e2f240c2cc2f40f7c832fc Mon Sep 17 00:00:00 2001
From: Yvv
Date: Fri, 24 Apr 2026 05:29:13 +0200
Subject: [PATCH] =?UTF-8?q?Mandat=20:=20wizard=20cr=C3=A9ation=204=20?=
=?UTF-8?q?=C3=A9tapes=20+=20bo=C3=AEte=20=C3=A0=20outils=20=C3=A9lection?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Mandate model : champ origin (contexte/déclencheur) + migration
- MandateCreate schema : origin, starts_at, ends_at
- mandates/new.vue : wizard complet
· Étape 1 : type · nom · origine · description · durée (relative ou dates)
· Étape 2 : auto-désignation (ratification) ou désignation collective
· Étape 3 : boîte à outils — sans/avec candidature, 6 modalités,
paramètres configurables (durée, quorum, seuil, slider+input)
· Étape 4 : récap + génération automatique des étapes du mandat
- Tous les boutons "Nouveau mandat" pointent vers /mandates/new
- decisions/new.vue : "Demander un mandat" → /mandates/new
Co-Authored-By: Claude Sonnet 4.6
---
...24_1000-d91a3c7f8b02_add_mandate_origin.py | 24 +
backend/app/models/mandate.py | 1 +
backend/app/schemas/mandate.py | 5 +
frontend/app/pages/decisions/new.vue | 2 +-
frontend/app/pages/mandates/index.vue | 10 +-
frontend/app/pages/mandates/new.vue | 1007 +++++++++++++++++
frontend/app/stores/mandates.ts | 2 +
7 files changed, 1045 insertions(+), 6 deletions(-)
create mode 100644 backend/alembic/versions/2026_04_24_1000-d91a3c7f8b02_add_mandate_origin.py
create mode 100644 frontend/app/pages/mandates/new.vue
diff --git a/backend/alembic/versions/2026_04_24_1000-d91a3c7f8b02_add_mandate_origin.py b/backend/alembic/versions/2026_04_24_1000-d91a3c7f8b02_add_mandate_origin.py
new file mode 100644
index 0000000..fde9331
--- /dev/null
+++ b/backend/alembic/versions/2026_04_24_1000-d91a3c7f8b02_add_mandate_origin.py
@@ -0,0 +1,24 @@
+"""Add origin column to mandates table.
+
+Revision ID: d91a3c7f8b02
+Revises: c4e812fb3a01
+Create Date: 2026-04-24 10:00:00.000000
+"""
+
+from __future__ import annotations
+
+import sqlalchemy as sa
+from alembic import op
+
+revision = "d91a3c7f8b02"
+down_revision = "c4e812fb3a01"
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ op.add_column("mandates", sa.Column("origin", sa.Text(), nullable=True))
+
+
+def downgrade() -> None:
+ op.drop_column("mandates", "origin")
diff --git a/backend/app/models/mandate.py b/backend/app/models/mandate.py
index 3afbf88..c3c677b 100644
--- a/backend/app/models/mandate.py
+++ b/backend/app/models/mandate.py
@@ -12,6 +12,7 @@ class Mandate(Base):
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
title: Mapped[str] = mapped_column(String(256), nullable=False)
+ origin: Mapped[str | None] = mapped_column(Text) # contexte / déclencheur du mandat
description: Mapped[str | None] = mapped_column(Text)
mandate_type: Mapped[str] = mapped_column(String(64), nullable=False) # techcomm, smith, custom
status: Mapped[str] = mapped_column(String(32), default="draft") # draft, candidacy, voting, active, reporting, completed, revoked
diff --git a/backend/app/schemas/mandate.py b/backend/app/schemas/mandate.py
index dac3881..e801f6e 100644
--- a/backend/app/schemas/mandate.py
+++ b/backend/app/schemas/mandate.py
@@ -46,9 +46,12 @@ class MandateCreate(BaseModel):
"""Payload for creating a new mandate."""
title: str = Field(..., min_length=1, max_length=256)
+ origin: str | None = None
description: str | None = None
mandate_type: str = Field(..., max_length=64, description="techcomm, smith, custom")
decision_id: UUID | None = None
+ starts_at: datetime | None = None
+ ends_at: datetime | None = None
class MandateUpdate(BaseModel):
@@ -73,6 +76,7 @@ class MandateOut(BaseModel):
id: UUID
title: str
+ origin: str | None = None
description: str | None = None
mandate_type: str
status: str
@@ -92,6 +96,7 @@ class MandateAdvanceOut(BaseModel):
id: UUID
title: str
+ origin: str | None = None
description: str | None = None
mandate_type: str
status: str
diff --git a/frontend/app/pages/decisions/new.vue b/frontend/app/pages/decisions/new.vue
index b658d91..cefdec8 100644
--- a/frontend/app/pages/decisions/new.vue
+++ b/frontend/app/pages/decisions/new.vue
@@ -353,7 +353,7 @@ const confidenceLabel: Record = {
Aucun mandat actif pour l'espace de travail sélectionné.
-
+
Demander un mandat
diff --git a/frontend/app/pages/mandates/index.vue b/frontend/app/pages/mandates/index.vue
index a8c1b1d..affb139 100644
--- a/frontend/app/pages/mandates/index.vue
+++ b/frontend/app/pages/mandates/index.vue
@@ -154,14 +154,14 @@ async function handleCreate() {
{{ opt.label }}
-
+
@@ -199,11 +199,11 @@ async function handleCreate() {
e === 'create' && (showCreateModal = true)"
+ @action="e => e === 'create' && navigateTo('/mandates/new')"
/>
diff --git a/frontend/app/pages/mandates/new.vue b/frontend/app/pages/mandates/new.vue
new file mode 100644
index 0000000..062977d
--- /dev/null
+++ b/frontend/app/pages/mandates/new.vue
@@ -0,0 +1,1007 @@
+
+
+
+
+
+
+
+
+
+ Mandats
+
+
+
+
+ 1 Infos
+ ›
+ 2 Nomination
+ ›
+ 3 Modalités
+ ›
+ {{ nominationCase === 'election' ? '4' : '3' }} Récap
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Paramètres du vote de ratification
+
+
+
+
+
+ jours
+
+
+
+
+
+
+
+ %
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ m.title }}
+
{{ m.desc }}
+
+
+
+
+
+
+
+
+
+ Recommandé
+
+
{{ m.recommendedReason }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Mandat
+
{{ title }}
+
Origine : {{ origin }}
+
{{ description }}
+
+
+ {{ durationLabel }}
+
+
+
+ {{ MANDATE_TYPE_OPTIONS.find(o => o.value === mandateType)?.label }}
+
+
+
+
+
+
Nomination
+
+ {{ nominationCase === 'self' ? 'Auto-désignation avec ratification' : `Élection — ${MODALITIES.find(m => m.id === selectedModalityId)?.title ?? ''}` }}
+
+
+ Durée : {{ selfParams.duration_days }}j · Quorum : {{ selfParams.quorum_pct }}% · Seuil : {{ selfParams.majority_pct }}%
+
+
+
+
+
+
Étapes générées ({{ stepsToCreate.length }})
+
+ -
+ {{ i + 1 }}
+
+
{{ s.title }}
+
{{ s.description }}
+
+
+
+
+
+
+
{{ submitError }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/app/stores/mandates.ts b/frontend/app/stores/mandates.ts
index 59c1bd6..99ba9d1 100644
--- a/frontend/app/stores/mandates.ts
+++ b/frontend/app/stores/mandates.ts
@@ -20,6 +20,7 @@ export interface MandateStep {
export interface Mandate {
id: string
title: string
+ origin: string | null
description: string | null
mandate_type: string
status: string
@@ -34,6 +35,7 @@ export interface Mandate {
export interface MandateCreate {
title: string
+ origin?: string | null
description?: string | null
mandate_type: string
decision_id?: string | null