/** * Decisions store: decision processes and their steps. * * Maps to the backend /api/v1/decisions endpoints. */ export interface DecisionStep { id: string decision_id: string step_order: number step_type: string title: string | null description: string | null status: string vote_session_id: string | null outcome: string | null created_at: string } export interface Decision { id: string title: string description: string | null context: string | null decision_type: string status: string voting_protocol_id: string | null created_by_id: string | null created_at: string updated_at: string steps: DecisionStep[] } export interface DecisionCreate { title: string description?: string | null context?: string | null decision_type: string voting_protocol_id?: string | null } export interface DecisionUpdate { title?: string description?: string | null context?: string | null decision_type?: string voting_protocol_id?: string | null } export interface DecisionStepCreate { step_type: string title?: string | null description?: string | null } interface DecisionsState { list: Decision[] current: Decision | null loading: boolean error: string | null } export const useDecisionsStore = defineStore('decisions', { state: (): DecisionsState => ({ list: [], current: null, loading: false, error: null, }), getters: { byStatus: (state) => { return (status: string) => state.list.filter(d => d.status === status) }, activeDecisions: (state): Decision[] => { return state.list.filter(d => d.status === 'draft' || d.status === 'qualification' || d.status === 'review' || d.status === 'voting', ) }, completedDecisions: (state): Decision[] => { return state.list.filter(d => d.status === 'executed' || d.status === 'closed') }, }, actions: { /** * Fetch all decisions with optional filters. */ async fetchAll(params?: { decision_type?: string; status?: string }) { this.loading = true this.error = null try { const { $api } = useApi() const query: Record = {} if (params?.decision_type) query.decision_type = params.decision_type if (params?.status) query.status = params.status this.list = await $api('/decisions/', { query }) } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors du chargement des decisions' } finally { this.loading = false } }, /** * Fetch a single decision by ID with all its steps. */ async fetchById(id: string) { this.loading = true this.error = null try { const { $api } = useApi() this.current = await $api(`/decisions/${id}`) } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Decision introuvable' } finally { this.loading = false } }, /** * Create a new decision. */ async create(payload: DecisionCreate) { this.loading = true this.error = null try { const { $api } = useApi() const decision = await $api('/decisions/', { method: 'POST', body: payload, }) this.list.unshift(decision) return decision } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de la creation de la decision' throw err } finally { this.loading = false } }, /** * Update an existing decision. */ async update(id: string, data: DecisionUpdate) { this.error = null try { const { $api } = useApi() const updated = await $api(`/decisions/${id}`, { method: 'PUT', body: data, }) if (this.current?.id === id) this.current = updated const idx = this.list.findIndex(d => d.id === id) if (idx >= 0) this.list[idx] = updated return updated } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de la mise a jour de la decision' throw err } }, /** * Delete a decision. */ async delete(id: string) { this.error = null try { const { $api } = useApi() await $api(`/decisions/${id}`, { method: 'DELETE' }) this.list = this.list.filter(d => d.id !== id) if (this.current?.id === id) this.current = null } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de la suppression de la decision' throw err } }, /** * Advance the decision to the next step in its workflow. */ async advance(id: string) { this.error = null try { const { $api } = useApi() const updated = await $api(`/decisions/${id}/advance`, { method: 'POST', }) if (this.current?.id === id) this.current = updated const idx = this.list.findIndex(d => d.id === id) if (idx >= 0) this.list[idx] = updated return updated } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de l\'avancement de la decision' throw err } }, /** * Add a step to a decision. */ async addStep(id: string, step: DecisionStepCreate) { this.error = null try { const { $api } = useApi() const newStep = await $api(`/decisions/${id}/steps`, { method: 'POST', body: step, }) if (this.current?.id === id) { this.current.steps.push(newStep) } return newStep } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de l\'ajout de l\'etape' throw err } }, /** * Create a vote session for a specific step. */ async createVoteSession(decisionId: string, stepId: string) { this.error = null try { const { $api } = useApi() const result = await $api(`/decisions/${decisionId}/steps/${stepId}/create-vote-session`, { method: 'POST', }) // Refresh decision to get updated step with vote_session_id await this.fetchById(decisionId) return result } catch (err: any) { this.error = err?.data?.detail || err?.message || 'Erreur lors de la creation de la session de vote' throw err } }, /** * Clear the current decision. */ clearCurrent() { this.current = null }, }, })