Plateforme de decisions collectives pour Duniter/G1. Backend FastAPI async + PostgreSQL (14 tables, 8 routers, 6 services, moteur de vote avec formule d'inertie WoT/Smith/TechComm). Frontend Nuxt 4 + Nuxt UI v3 + Pinia (9 pages, 5 stores). Infrastructure Docker + Woodpecker CI + Traefik. Documentation technique et utilisateur (15 fichiers). Seed : Licence G1, Engagement Forgeron v2.0.0, 4 protocoles de vote. 30 tests unitaires (formules, mode params, vote nuance) -- tous verts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
101 lines
2.5 KiB
TypeScript
101 lines
2.5 KiB
TypeScript
/**
|
|
* Protocols store: voting protocols and formula configurations.
|
|
*
|
|
* Maps to the backend /api/v1/protocols endpoints.
|
|
*/
|
|
|
|
export interface FormulaConfig {
|
|
id: string
|
|
name: string
|
|
description: string | null
|
|
duration_days: number
|
|
majority_pct: number
|
|
base_exponent: number
|
|
gradient_exponent: number
|
|
constant_base: number
|
|
smith_exponent: number | null
|
|
techcomm_exponent: number | null
|
|
nuanced_min_participants: number | null
|
|
nuanced_threshold_pct: number | null
|
|
created_at: string
|
|
}
|
|
|
|
export interface VotingProtocol {
|
|
id: string
|
|
name: string
|
|
description: string | null
|
|
vote_type: string
|
|
formula_config_id: string
|
|
mode_params: string | null
|
|
is_meta_governed: boolean
|
|
created_at: string
|
|
formula_config: FormulaConfig
|
|
}
|
|
|
|
interface ProtocolsState {
|
|
protocols: VotingProtocol[]
|
|
formulas: FormulaConfig[]
|
|
loading: boolean
|
|
error: string | null
|
|
}
|
|
|
|
export const useProtocolsStore = defineStore('protocols', {
|
|
state: (): ProtocolsState => ({
|
|
protocols: [],
|
|
formulas: [],
|
|
loading: false,
|
|
error: null,
|
|
}),
|
|
|
|
getters: {
|
|
binaryProtocols: (state): VotingProtocol[] => {
|
|
return state.protocols.filter(p => p.vote_type === 'binary')
|
|
},
|
|
nuancedProtocols: (state): VotingProtocol[] => {
|
|
return state.protocols.filter(p => p.vote_type === 'nuanced')
|
|
},
|
|
metaGovernedProtocols: (state): VotingProtocol[] => {
|
|
return state.protocols.filter(p => p.is_meta_governed)
|
|
},
|
|
},
|
|
|
|
actions: {
|
|
/**
|
|
* Fetch all voting protocols with their formula configurations.
|
|
*/
|
|
async fetchProtocols(params?: { vote_type?: string }) {
|
|
this.loading = true
|
|
this.error = null
|
|
|
|
try {
|
|
const { $api } = useApi()
|
|
const query: Record<string, string> = {}
|
|
if (params?.vote_type) query.vote_type = params.vote_type
|
|
|
|
this.protocols = await $api<VotingProtocol[]>('/protocols/', { query })
|
|
} catch (err: any) {
|
|
this.error = err?.data?.detail || err?.message || 'Erreur lors du chargement des protocoles'
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Fetch all formula configurations.
|
|
*/
|
|
async fetchFormulas() {
|
|
this.loading = true
|
|
this.error = null
|
|
|
|
try {
|
|
const { $api } = useApi()
|
|
this.formulas = await $api<FormulaConfig[]>('/protocols/formulas')
|
|
} catch (err: any) {
|
|
this.error = err?.data?.detail || err?.message || 'Erreur lors du chargement des formules'
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
},
|
|
})
|