Backend: - Sessions de vote : list, close, tally, threshold details, auto-expiration - Protocoles : update, simulate, meta-gouvernance, formulas CRUD - Service vote enrichi : close_session, get_threshold_details, nuanced breakdown - Schemas : ThresholdDetailOut, VoteResultOut, FormulaSimulationRequest/Result - WebSocket broadcast sur chaque vote + fermeture session - 25 nouveaux tests (threshold details, close, nuanced, simulation) Frontend: - 5 composants vote : VoteBinary, VoteNuanced, ThresholdGauge, FormulaDisplay, VoteHistory - 3 composants protocoles : ProtocolPicker, FormulaEditor, ModeParamsDisplay - Simulateur de formules interactif (page /protocols/formulas) - Page detail protocole (/protocols/[id]) - Composable useWebSocket (live updates) - Composable useVoteFormula (calcul client-side reactif) - Integration KaTeX pour rendu LaTeX des formules Documentation: - API reference : 8 nouveaux endpoints documentes - Formules : tables d'inertie, parametres detailles, simulation API - Guide vote : vote binaire/nuance, jauge, historique, simulateur, meta-gouvernance 55 tests passes (+ 1 skipped), 126 fichiers total. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
65 lines
1.6 KiB
Vue
65 lines
1.6 KiB
Vue
<script setup lang="ts">
|
|
/**
|
|
* Dropdown/select to pick a voting protocol.
|
|
*
|
|
* Fetches protocols from the store and renders them in a USelect
|
|
* with protocol name, mode params, and vote type badge.
|
|
*/
|
|
import type { VotingProtocol } from '~/stores/protocols'
|
|
|
|
const props = defineProps<{
|
|
modelValue: string | null
|
|
voteType?: string
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
'update:modelValue': [value: string | null]
|
|
}>()
|
|
|
|
const protocols = useProtocolsStore()
|
|
|
|
onMounted(async () => {
|
|
if (protocols.protocols.length === 0) {
|
|
await protocols.fetchProtocols(props.voteType ? { vote_type: props.voteType } : undefined)
|
|
}
|
|
})
|
|
|
|
const filteredProtocols = computed(() => {
|
|
if (!props.voteType) return protocols.protocols
|
|
return protocols.protocols.filter(p => p.vote_type === props.voteType)
|
|
})
|
|
|
|
const options = computed(() => {
|
|
return filteredProtocols.value.map(p => ({
|
|
label: buildLabel(p),
|
|
value: p.id,
|
|
}))
|
|
})
|
|
|
|
function buildLabel(p: VotingProtocol): string {
|
|
const typeLabel = p.vote_type === 'binary' ? 'Binaire' : 'Nuance'
|
|
const params = p.mode_params ? ` [${p.mode_params}]` : ''
|
|
return `${p.name} - ${typeLabel}${params}`
|
|
}
|
|
|
|
function onSelect(value: string) {
|
|
emit('update:modelValue', value || null)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<USelect
|
|
:model-value="modelValue ?? undefined"
|
|
:items="options"
|
|
placeholder="Selectionnez un protocole..."
|
|
:loading="protocols.loading"
|
|
value-key="value"
|
|
@update:model-value="onSelect"
|
|
/>
|
|
<p v-if="protocols.error" class="text-xs text-red-500 mt-1">
|
|
{{ protocols.error }}
|
|
</p>
|
|
</div>
|
|
</template>
|