Sistema de Apoio ao Processo Legislativo
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

88 lines
3.3 KiB

// frontend/src/__apps/painel/store/painelStore.js
//
// Store Pinia do painel. Substitui o store Vuex inline: um único ponto de
// entrada (`applyData`), alimentado pelo payload normalizado a partir do
// full-snapshot broadcast do backend (sapl/painel/views.py::
// build_dados_painel()) — não há mais eventos incrementais
// (`vote.update`/`stopwatch.update`); qualquer mudança de estado é
// republicada como um novo snapshot completo.
import { defineStore } from 'pinia'
import { DEFAULT_STATE, normalizePainelData } from '../ws/normalizePainel'
function deepClone (x) {
return JSON.parse(JSON.stringify(x))
}
export const usePainelStore = defineStore('painel', {
state: () => deepClone(DEFAULT_STATE),
getters: {
canRender: (s) => !!(s.sessao_aberta && s.painel_aberto),
// Getters usados pelo app `votacao` (apuração ao vivo a partir dos votos).
totalVotos: (s) => {
const totals = [
{ tipo: 'Sim', total: 0 },
{ tipo: 'Não', total: 0 },
{ tipo: 'Abstenção', total: 0 },
{ tipo: 'Não Votou', total: 0 }
]
s.parlamentares.forEach((p) => {
if (p.voto) {
const entry = totals.find((t) => t.tipo === p.voto)
if (entry) entry.total++
}
})
return totals
},
numPresentes: (s) => s.parlamentares.length,
totalVotados: (s) =>
s.parlamentares.filter((p) => p.voto && p.voto !== 'Não Votou').length
},
actions: {
// Aplica o payload completo (`type: "data"`) do WebSocket.
applyData (raw) {
const next = normalizePainelData(raw)
// flags simples
this.sessao_aberta = next.sessao_aberta
this.painel_aberto = next.painel_aberto
this.mostrar_voto = next.mostrar_voto
this.message = next.message
this.cronometro_ativo = next.cronometro_ativo
// objeto aninhado: patch (preserva reatividade dos campos)
Object.assign(this.sessao, next.sessao)
// cronômetros: só start/stop/reset explícitos (ver Cronometro.vue/
// CronometroList.vue) reagem a mudança de valor — nunca a um toggle
// por broadcast, que dispara em qualquer voto/matéria aberta, não só
// em ações de cronômetro.
this.cronometro_discurso = next.cronometro_discurso
this.cronometro_aparte = next.cronometro_aparte
this.cronometro_ordem = next.cronometro_ordem
this.cronometro_consideracoes = next.cronometro_consideracoes
this.registro_aberto = next.registro_aberto
// arrays: trocar referência (voto já vem aplicado por parlamentar
// dentro de next.parlamentares — get_votos() no backend já inlina o
// voto de cada presente, não há mais um mapa separado a reaplicar)
this.parlamentares = next.parlamentares
this.oradores = next.oradores
// objetos grandes: substituir
this.materia = next.materia
this.resultado = next.resultado
// tipos de resultado (app votacao): nunca vem no broadcast do
// WebSocket (ver GAP 3 do plano de merge) — só sobrescreve quando o
// payload realmente traz a lista, preservando o valor populado uma
// vez a partir do contexto inicial renderizado pelo Django.
if (next.tipos_resultado && next.tipos_resultado.length) {
this.tipos_resultado = next.tipos_resultado
}
}
}
})