Automatiza destinatarios de assembleias
This commit is contained in:
@@ -20,7 +20,7 @@ async function safeLoad(section,fn){try{await fn()}catch(e){document.querySelect
|
||||
async function load(){try{const d=await Api.get(`/api/condominios/${id}`);document.querySelector('#header').innerHTML=`<h2>${d.condominio.nome}</h2><p>${d.condominio.endereco||''}</p><div class="cards"><div class="stat">Sindico<strong>${d.sindico_atual?.contato_nome||'-'}</strong></div><div class="stat">Assembleias futuras<strong>${d.assembleias_futuras||0}</strong></div><div class="stat">Avisos ativos<strong>${d.avisos_ativos||0}</strong></div></div>`;await safeLoad('contatos',loadContatos);await safeLoad('avisos',loadFuncionariosVinculados);await safeLoad('avisos',loadExtras);await safeLoad('espacos',loadEspacos);await safeLoad('assembleias',loadAssembleias);await safeLoad('documentos',loadDocs);await safeLoad('avisos',loadAvisos)}catch(e){Util.toast(e.message,true)}}
|
||||
async function loadContatos(){const d=await Api.get(`/api/condominios/${id}/contatos`);contatos=d.contatos||[];document.querySelector('#contatos').innerHTML=`<h2>Contatos</h2><form id="contato-form" class="grid cols"><div class="field"><label>Nome</label><input name="nome" required></div><div class="field"><label>Telefone</label><input name="telefone"></div><div class="field"><label>E-mail</label><input name="email"></div><div class="field"><label>Tipo</label><select name="tipo"><option value="sindico">Sindico</option><option value="subsindico">Subsindico</option><option value="conselheiro">Conselheiro</option></select></div><button class="btn">Cadastrar</button></form><div class="table-wrap"><table><thead><tr><th>Nome</th><th>Tipo</th><th>Telefone</th><th>Email</th></tr></thead><tbody>${contatos.map(c=>`<tr><td>${c.contato_nome}</td><td>${c.tipo}</td><td>${c.contato_telefone||''}</td><td>${c.contato_email||''}</td></tr>`).join('')}</tbody></table></div>`;document.querySelector('#contato-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/contatos/vincular`,Util.formData(e.target));Util.toast('Contato salvo');loadContatos()}catch(err){Util.toast(err.message,true)}}}
|
||||
async function loadEspacos(){const d=await Api.get(`/api/condominios/${id}/espacos-comuns`);document.querySelector('#espacos').innerHTML=`<h2>Espacos comuns</h2><form id="espaco-form" class="grid cols"><div class="field"><label>Nome</label><input name="nome" required></div><div class="field"><label>Valor centavos</label><input name="valor_utilizacao_centavos" type="number"></div><div class="field"><label>Indice</label><input name="indice_correcao"></div><div class="field"><label>Descricao</label><input name="descricao"></div><button class="btn">Cadastrar</button></form><div class="table-wrap"><table><thead><tr><th>Nome</th><th>Valor</th><th>Indice</th><th>Descricao</th></tr></thead><tbody>${(d.espacos||[]).map(x=>`<tr><td>${x.nome}</td><td>${Util.money(x.valor_utilizacao_centavos)}</td><td>${x.indice_correcao||''}</td><td>${x.descricao||''}</td></tr>`).join('')}</tbody></table></div>`;document.querySelector('#espaco-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/espacos-comuns`,Util.formData(e.target));Util.toast('Espaco salvo');loadEspacos()}catch(err){Util.toast(err.message,true)}}}
|
||||
async function loadAssembleias(){const d=await Api.get(`/api/condominios/${id}/assembleias`);const destContatos=contatos.map(c=>`<label><input type="checkbox" name="dest" value="contato:${c.contato_id}" checked> ${c.contato_nome} (${c.tipo})</label>`).join('');const destFuncionarios=funcionariosVinculados.map(f=>`<label><input type="checkbox" name="dest" value="funcionario:${f.funcionario_id||f.id}" checked> ${f.nome} (funcionario)</label>`).join('');const dest=[destContatos,destFuncionarios].filter(Boolean).join('')||'<p>Nenhum membro cadastrado.</p>';document.querySelector('#assembleias').innerHTML=`<div class="section-head"><h2>Assembleias</h2><button class="icon-btn calendar-open" type="button" onclick="abrirCalendarioAssembleias()" title="Calendário de assembleias" aria-label="Calendário de assembleias"></button></div><form id="ass-form" class="grid cols"><div class="field"><label>Tipo</label><input name="tipo" required></div><div class="field"><label>Data e hora</label><input name="data_hora" type="datetime-local" required></div><div class="field"><label>Local</label><input name="local"></div><div class="field"><label>Pauta</label><input name="pauta"></div><div class="field"><label>Membros notificados</label><div class="check-list">${dest}</div></div><button class="btn">Cadastrar</button></form><div class="table-wrap"><table><thead><tr><th>Tipo</th><th>Data</th><th>Local</th><th>Status</th></tr></thead><tbody>${(d.assembleias||[]).map(a=>`<tr><td>${a.tipo}</td><td>${Util.date(a.data_hora)}</td><td>${a.local||''}</td><td>${Util.badge(a.status)}</td></tr>`).join('')}</tbody></table></div>`;document.querySelector('#ass-form').onsubmit=async e=>{e.preventDefault();const f=e.target,b=Util.formData(f);b.destinatarios=[...f.querySelectorAll('input[name=dest]:checked')].map(x=>{const [tipo,did]=x.value.split(':');return{tipo_destinatario:tipo,id:Number(did)}});try{await Api.post(`/api/condominios/${id}/assembleias`,b);Util.toast('Assembleia salva');loadAssembleias();load()}catch(err){Util.toast(err.message,true)}}}
|
||||
async function loadAssembleias(){const d=await Api.get(`/api/condominios/${id}/assembleias`);document.querySelector('#assembleias').innerHTML=`<div class="section-head"><h2>Assembleias</h2><button class="icon-btn calendar-open" type="button" onclick="abrirCalendarioAssembleias()" title="Calendário de assembleias" aria-label="Calendário de assembleias"></button></div><form id="ass-form" class="grid cols"><div class="field"><label>Tipo</label><input name="tipo" required></div><div class="field"><label>Data e hora</label><input name="data_hora" type="datetime-local" required></div><div class="field"><label>Local</label><input name="local"></div><div class="field"><label>Pauta</label><input name="pauta"></div><button class="btn">Cadastrar</button></form><div class="table-wrap"><table><thead><tr><th>Tipo</th><th>Data</th><th>Local</th><th>Status</th></tr></thead><tbody>${(d.assembleias||[]).map(a=>`<tr><td>${a.tipo}</td><td>${Util.date(a.data_hora)}</td><td>${a.local||''}</td><td>${Util.badge(a.status)}</td></tr>`).join('')}</tbody></table></div>`;document.querySelector('#ass-form').onsubmit=async e=>{e.preventDefault();try{await Api.post(`/api/condominios/${id}/assembleias`,Util.formData(e.target));Util.toast('Assembleia salva');loadAssembleias();load()}catch(err){Util.toast(err.message,true)}}}
|
||||
async function loadFuncionariosVinculados(){const d=await Api.get(`/api/condominios/${id}/funcionarios-vinculados`);funcionariosVinculados=d.funcionarios||[]}
|
||||
async function loadExtras(){const d=await Api.get(`/api/extras`);extras=(d.extras||[]).filter(x=>x.status==='ativo')}
|
||||
async function loadDocs(){const d=await Api.get(`/api/condominios/${id}/documentos`);docs=d.documentos||[];document.querySelector('#documentos').innerHTML=`<h2>Documentos</h2><form id="doc-form" class="row"><div class="field"><label>Tipo</label><input name="tipo"></div><div class="field"><label>Arquivo</label><input name="arquivo" type="file" required></div><button class="btn">Enviar</button></form><div class="table-wrap"><table><thead><tr><th>ID</th><th>Arquivo</th><th>Tipo</th><th>Download</th></tr></thead><tbody>${docs.map(d=>`<tr><td>${d.id}</td><td>${d.nome_arquivo}</td><td>${d.tipo||''}</td><td><a href="/api/documentos/${d.id}/download">Baixar</a></td></tr>`).join('')}</tbody></table></div>`;document.querySelector('#doc-form').onsubmit=async e=>{e.preventDefault();const fd=new FormData(e.target);try{await Api.post(`/api/condominios/${id}/documentos`,fd);Util.toast('Documento enviado');loadDocs()}catch(err){Util.toast(err.message,true)}}}
|
||||
|
||||
@@ -3,6 +3,4 @@
|
||||
.success-message{display:inline-block;margin:0 0 10px;padding:10px 12px;border:1px solid #bbf7d0;border-radius:8px;background:#dcfce7;color:var(--ok);font-weight:700}
|
||||
.section-head{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:14px}.section-head h2{margin:0}.icon-btn{position:relative;width:42px;height:42px;border:1px solid var(--line);border-radius:6px;background:#fff;cursor:pointer;display:inline-grid;place-items:center}.icon-btn:hover{border-color:var(--brand);background:#eef8fb}.calendar-open::before{content:"";width:20px;height:18px;border:2px solid var(--brand);border-radius:3px;box-shadow:inset 0 5px 0 #e8f3f7;position:relative}.calendar-open::after{content:"";position:absolute;width:12px;height:2px;background:var(--brand);transform:translateY(-7px)}.calendar-modal{width:min(1120px,100%)}.calendar-layout{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:18px}.calendar-toolbar{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}.calendar-toolbar strong{text-transform:capitalize}.calendar-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));border:1px solid var(--line);border-radius:8px;overflow:hidden;background:#fff}.calendar-weekday{padding:10px;background:#f8fafc;color:var(--muted);font-size:12px;font-weight:700;text-align:center;border-bottom:1px solid var(--line)}.calendar-day{min-height:86px;border:0;border-right:1px solid var(--line);border-bottom:1px solid var(--line);background:#fff;padding:8px;text-align:left;color:var(--text);cursor:pointer;position:relative}.calendar-day:nth-child(7n+7){border-right:0}.calendar-day.other{background:#f8fafc;color:#98a2b3}.calendar-day.busy{background:#fff7ed}.calendar-day.busy span{font-weight:700;color:var(--warn)}.calendar-day.today{box-shadow:inset 0 0 0 2px var(--brand)}.calendar-day.selected{background:#e8f3f7}.calendar-day b{position:absolute;right:8px;bottom:8px;background:var(--brand);color:#fff;border-radius:999px;padding:2px 7px;font-size:12px}.calendar-side{border:1px solid var(--line);border-radius:8px;padding:14px;background:#fff;min-height:420px}.calendar-side h3{margin:0 0 12px}.calendar-event{border:1px solid var(--line);border-radius:8px;padding:10px;margin-bottom:10px;display:grid;gap:6px}.calendar-event span{font-size:13px}.calendar-event p{margin:0;color:var(--muted);font-size:13px}@media(max-width:900px){.calendar-layout{grid-template-columns:1fr}.calendar-day{min-height:64px}.calendar-side{min-height:auto}}
|
||||
|
||||
.check-list{display:grid;gap:8px;max-height:150px;overflow:auto;border:1px solid var(--line);border-radius:6px;padding:10px;background:#fff}.check-list label{display:flex;align-items:center;gap:8px;color:var(--text)}.check-list input{width:auto}
|
||||
|
||||
@media(max-width:520px){.content{padding:12px}h1{font-size:22px}h2{font-size:17px}.panel{padding:12px;border-radius:6px}.login-page{padding:16px}.login-box{padding:20px}.modal{padding:8px;align-items:start}.modal-panel{max-height:calc(100vh - 16px);padding:14px}.modal-head{align-items:flex-start}.modal-head .btn{width:auto}.calendar-grid{font-size:12px}.calendar-weekday{padding:8px 4px}.calendar-day{min-height:54px;padding:5px}.calendar-day b{right:4px;bottom:4px;padding:1px 5px}.calendar-toolbar .btn{width:auto}.section-head{align-items:flex-start}.icon-btn{width:40px;min-width:40px}.cond-item{display:grid;grid-template-columns:1fr;align-items:stretch}.cond-item .btn{width:100%}}
|
||||
|
||||
Reference in New Issue
Block a user