diff --git a/src/main/webapp/cliente/assembleias.html b/src/main/webapp/cliente/assembleias.html
index a31bc78..9f70ef5 100644
--- a/src/main/webapp/cliente/assembleias.html
+++ b/src/main/webapp/cliente/assembleias.html
@@ -1 +1 @@
-
AssembleiaAssembleia
Responsáveis pela assembleia
| Nome | WhatsApp | E-mail | Dias disponíveis | Status | Ações |
|---|
+AssembleiaAssembleia
Responsáveis pela assembleia
| Nome | WhatsApp | E-mail | Dias disponíveis | Status | Ações |
|---|
diff --git a/src/main/webapp/cliente/assembleias.js b/src/main/webapp/cliente/assembleias.js
index c0d0b2e..ed41749 100644
--- a/src/main/webapp/cliente/assembleias.js
+++ b/src/main/webapp/cliente/assembleias.js
@@ -1,12 +1,15 @@
const rows=document.querySelector('#rows'),responsaveisRows=document.querySelector('#responsaveis-rows'),modal=document.querySelector('#responsavel-modal'),modalTitle=document.querySelector('#responsavel-modal-title'),modalBody=document.querySelector('#responsavel-modal-body');
let assembleias=[],responsaveis=[];
const diasNomes=['Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado'];
+let calMonth=new Date();
function esc(v){return String(v??'').replace(/[&<>'"]/g,c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c]))}
function termo(){return document.querySelector('#assembleia-search-input')?.value.trim().toLowerCase()||''}
function contem(q,...vals){return !q||vals.some(v=>String(v??'').toLowerCase().includes(q))}
function destinatariosLabel(a){return (a.destinatarios||[]).map(x=>x.nome+' ('+x.tipo+')').join(', ')||'-'}
function diasLabel(v){return String(v||'').split(',').filter(x=>x!=='').map(x=>diasNomes[Number(x)]||x).join(', ')||'-'}
+function dateKey(v){const d=new Date(v);if(Number.isNaN(d.getTime()))return'';const pad=n=>String(n).padStart(2,'0');return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate())}
+function monthLabel(d){return d.toLocaleDateString('pt-BR',{month:'long',year:'numeric'})}
function formHtml(r={}){
const dias=new Set(String(r.dias_semana||'').split(','));
return ``;
@@ -17,6 +20,8 @@ function renderAssembleias(){
const lista=assembleias.filter(a=>contem(q,a.condominio_nome,a.tipo,a.data_hora,a.local,a.status,destinatariosLabel(a)));
rows.innerHTML=lista.map(a=>`| ${esc(a.condominio_nome||'-')} | ${esc(a.tipo)} | ${Util.date(a.data_hora)} | ${esc(a.local||'')} | ${Util.badge(a.status)} | ${esc(destinatariosLabel(a))} | Abrir |
`).join('')||'| Nenhuma assembleia encontrada. |
';
}
+function ensureCalendarModal(){let m=document.querySelector('#assembleia-calendar-modal');if(m)return m;document.body.insertAdjacentHTML('beforeend','Calendário de assembleias
');return document.querySelector('#assembleia-calendar-modal')}
+function renderCalendarioAssembleias(selected){ensureCalendarModal();const title=document.querySelector('#calendar-title'),grid=document.querySelector('#calendar-grid');title.textContent=monthLabel(calMonth);const y=calMonth.getFullYear(),m=calMonth.getMonth(),start=new Date(y,m,1-new Date(y,m,1).getDay()),todayKey=dateKey(new Date());let html=['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'].map(x=>''+x+'
').join('');for(let i=0;i<42;i++){const d=new Date(start);d.setDate(start.getDate()+i);const key=dateKey(d),items=assembleias.filter(a=>dateKey(a.data_hora)===key),classes=['calendar-day'];if(d.getMonth()!==m)classes.push('other');if(items.length)classes.push('busy');if(key===todayKey)classes.push('today');html+=''}grid.innerHTML=html;grid.querySelectorAll('.calendar-day').forEach(btn=>btn.onclick=()=>selecionarDiaCalendario(btn.dataset.date));if(selected)selecionarDiaCalendario(selected,false)}
async function load(){
try{
@@ -60,6 +65,10 @@ window.alternarBuscaAssembleias=()=>{
strip.classList.toggle('hidden');
if(!strip.classList.contains('hidden'))input.focus();
};
+window.abrirCalendarioAssembleias=async()=>{try{if(!assembleias.length)await load();calMonth=new Date();ensureCalendarModal().classList.remove('hidden');renderCalendarioAssembleias()}catch(e){Util.toast(e.message,true)}};
+window.fecharCalendarioAssembleias=()=>document.querySelector('#assembleia-calendar-modal')?.classList.add('hidden');
+window.mudarMesCalendario=delta=>{calMonth=new Date(calMonth.getFullYear(),calMonth.getMonth()+delta,1);renderCalendarioAssembleias()};
+window.selecionarDiaCalendario=(key,mark=true)=>{if(mark)document.querySelectorAll('.calendar-day').forEach(x=>x.classList.toggle('selected',x.dataset.date===key));const list=document.querySelector('#calendar-day-list'),title=document.querySelector('#calendar-day-title'),items=assembleias.filter(a=>dateKey(a.data_hora)===key);const [yy,mm,dd]=key.split('-');title.textContent=dd+'/'+mm+'/'+yy;if(!items.length){list.innerHTML='Nenhuma assembleia agendada neste dia.
';return;}list.innerHTML=items.map(a=>''+esc(a.condominio_nome||'-')+''+Util.date(a.data_hora)+''+esc(a.tipo)+' - '+esc(a.local||'-')+''+esc(destinatariosLabel(a))+'
Abrir condomínio ').join('')};
window.abrirNovoResponsavel=()=>abrirResponsavel({});
window.editarResponsavel=id=>{const r=responsaveis.find(x=>Number(x.id)===Number(id));if(r)abrirResponsavel(r)};
window.fecharResponsavelModal=()=>{modal.classList.add('hidden');modalBody.innerHTML=''};