Version UX Pilot design refs and map them to roadmap plans
Add the 11 UX Pilot design pairs (.png + .html) under docs/design-refs/latest/ and link each to its roadmap item and plan. Record the decision that UX/structure is the reference but the old palette is not — implementation uses the light campaign theme tokens.
|
|
@ -26,6 +26,7 @@ alwaysApply: false
|
|||
- Em 2026-07-17, a Refactor Phase 4A consolidou as dez migrations locais não publicadas de `20260717_*` em `20260718_010733_consolidate_campaign_schema`, mantendo intacta a história rastreada até `20260716_010420_add_campaign_user`; os bancos locais foram reconciliados sem alterar dados de aplicação.
|
||||
- Em 2026-07-18, o follow-up Phase 4C fixou o Playwright em dois workers por padrão, adicionou guardas automáticos de erros do navegador/console/5xx, fortaleceu privacidade HTML+Flight por papel e tornou o login por teclado uma interação real com Enter e cookie verificado.
|
||||
- Em 2026-07-18, a projeção do dashboard omite `supportStatus` ausente por redação de acesso e lança invariante genérico se um valor não-vazio inválido chegar à fronteira; agregação e badge são exaustivos no enum.
|
||||
- Em 2026-07-18, os designs UX Pilot dos próximos ciclos foram versionados em `docs/design-refs/latest/` (11 pares `.png`+`.html`) e mapeados aos itens do roadmap — tabela "Referências de design (UX Pilot)" em `docs/roadmap.md`, com seção "Referência visual (UX Pilot)" em cada plano. Decisão: a UX/estrutura dos designs é a referência; a paleta NÃO — os arquivos vieram na paleta antiga (vermelho escuro/navy/dourado) e toda implementação usa os tokens claros do tema `data-theme='campaign'`. Sem design nesta leva: dobradinha, mapa, demandas, detalhe do plano de ação, opt-in de push e fill-ins.
|
||||
|
||||
## Decisões
|
||||
|
||||
|
|
|
|||
278
docs/design-refs/latest/Apoiador-Ficha.html
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Ficha do Apoiador</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
wa: '#25D366',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
.seg-btn {
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.seg-btn.active {
|
||||
background: #8e0e23;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-28">
|
||||
<!-- Header -->
|
||||
<header id="header" class="bg-primary sticky top-0 z-20 px-4 py-3 flex items-center gap-3">
|
||||
<button class="text-white p-1"><i class="fa-solid fa-arrow-left text-lg"></i></button>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h1 class="text-white font-bold text-sm truncate">Maria das Dores Souza</h1>
|
||||
<p class="text-white/60 text-xs">Apoiadora · Bom Jesus da Lapa</p>
|
||||
</div>
|
||||
<button class="text-white/70 p-1.5"><i class="fa-solid fa-ellipsis-vertical"></i></button>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Avatar + intent badge -->
|
||||
<div
|
||||
class="mx-4 mt-3 mb-3 bg-white border border-gray-200 rounded-2xl shadow-sm p-4 flex items-center gap-4"
|
||||
>
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-6.jpg"
|
||||
class="w-16 h-16 rounded-full object-cover border-2 border-primary/20 flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h2 class="text-base font-bold text-navy">Maria das Dores Souza</h2>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Cadastrada em 10/07/2025 · por João S.</p>
|
||||
<div class="flex items-center gap-2 mt-2">
|
||||
<span class="bg-green-100 text-green-800 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>Certo</span
|
||||
>
|
||||
<span class="text-xs text-gray-400">intenção de voto</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-4 space-y-4">
|
||||
<!-- Contato -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-3">
|
||||
<p class="text-xs font-semibold text-gray-500 uppercase tracking-wide">Dados de contato</p>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2 text-sm text-navy">
|
||||
<i class="fa-solid fa-phone text-gray-400 w-4 text-center"></i>
|
||||
<span>(77) 9 9000-1111</span>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 bg-wa text-white text-xs font-bold px-3 py-1.5 rounded-lg"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-sm"></i> WhatsApp
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 text-sm text-navy border-t border-gray-100 pt-3">
|
||||
<i class="fa-solid fa-location-dot text-gray-400 w-4 text-center"></i>
|
||||
<div>
|
||||
<p class="font-semibold">Bom Jesus da Lapa</p>
|
||||
<p class="text-xs text-gray-500">Bahia · Velho Chico</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Núcleo vinculado -->
|
||||
<div class="flex items-center justify-between border-t border-gray-100 pt-3">
|
||||
<div class="flex items-center gap-2 text-sm text-navy">
|
||||
<i class="fa-solid fa-layer-group text-gray-400 w-4 text-center"></i>
|
||||
<span class="text-primary font-semibold">Quilombo Rio das Rãs</span>
|
||||
</div>
|
||||
<button
|
||||
class="text-xs text-gray-500 border border-gray-200 rounded-lg px-2.5 py-1 hover:border-primary hover:text-primary transition-colors"
|
||||
>
|
||||
Mudar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ══════════════════════════════════════════ -->
|
||||
<!-- LGPD CONSENT BLOCK — visually distinct -->
|
||||
<!-- ══════════════════════════════════════════ -->
|
||||
<div id="lgpd-block" class="bg-blue-50 border-2 border-blue-200 rounded-xl p-4 space-y-3">
|
||||
<div class="flex items-start gap-2">
|
||||
<i class="fa-solid fa-shield text-blue-500 text-base mt-0.5 flex-shrink-0"></i>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-blue-800">Consentimento LGPD</p>
|
||||
<p class="text-xs text-blue-600 mt-0.5">
|
||||
O apoiador deve ter consentido previamente o uso de seus dados para fins eleitorais.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<label class="flex items-start gap-3 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked
|
||||
class="w-5 h-5 mt-0.5 rounded accent-blue-600 flex-shrink-0"
|
||||
/>
|
||||
<p class="text-xs text-blue-800">
|
||||
Confirmo que <strong>Maria das Dores Souza</strong> consentiu o uso de seus dados
|
||||
pessoais para comunicação da campanha de <strong>Jorge Solla</strong>, conforme a
|
||||
<span class="underline cursor-pointer">Política de Privacidade</span>.
|
||||
</p>
|
||||
</label>
|
||||
<p class="text-xs text-blue-500 flex items-center gap-1">
|
||||
<i class="fa-solid fa-circle-info text-xs"></i>
|
||||
Consentimento registrado em 10/07/2025 · Coletor: João Santos
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Intenção de voto — segmented control (gated by LGPD) -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-3">
|
||||
<p class="text-xs font-semibold text-gray-500 uppercase tracking-wide">Intenção de voto</p>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button
|
||||
class="seg-btn active text-xs font-bold py-3 rounded-xl border border-primary bg-primary text-white"
|
||||
>
|
||||
Certo
|
||||
</button>
|
||||
<button
|
||||
class="seg-btn text-xs font-bold py-3 rounded-xl border border-gray-200 text-gray-600 bg-gray-50"
|
||||
>
|
||||
Tende a certo
|
||||
</button>
|
||||
<button
|
||||
class="seg-btn text-xs font-bold py-3 rounded-xl border border-gray-200 text-gray-600 bg-gray-50"
|
||||
>
|
||||
Indeciso
|
||||
</button>
|
||||
<button
|
||||
class="seg-btn text-xs font-bold py-3 rounded-xl border border-gray-200 text-gray-600 bg-gray-50"
|
||||
>
|
||||
Outro
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400">
|
||||
Disponível somente após confirmação do consentimento LGPD
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Kit de compartilhamento -->
|
||||
<div
|
||||
id="kit-compartilhamento"
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-3"
|
||||
>
|
||||
<p
|
||||
class="text-xs font-semibold text-gray-500 uppercase tracking-wide flex items-center gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-share-nodes text-primary text-sm"></i>
|
||||
Kit de compartilhamento
|
||||
</p>
|
||||
<p class="text-xs text-gray-600">
|
||||
Mensagem pronta para <strong>Maria</strong> encaminhar nos próprios contatos.
|
||||
<em>Nunca disparada pela campanha.</em>
|
||||
</p>
|
||||
|
||||
<!-- Ready-made message -->
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-xl p-3">
|
||||
<p class="text-xs text-gray-700 leading-relaxed">
|
||||
"Oi! Tô apoiando <strong>Jorge Solla</strong> para Deputado Federal pela Bahia. Ele tem
|
||||
um histórico de luta pela saúde e pelos direitos da nossa comunidade. Se você ainda não
|
||||
decidiu, vale conhecer o trabalho dele! 🌟 <br />solla.ba"
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Action buttons -->
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button
|
||||
class="flex items-center justify-center gap-2 bg-wa text-white text-xs font-bold py-3 rounded-xl"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-base"></i> Enviar no WhatsApp
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center justify-center gap-2 border border-gray-200 text-navy text-xs font-bold py-3 rounded-xl hover:bg-gray-50"
|
||||
>
|
||||
<i class="fa-solid fa-copy text-sm"></i> Copiar texto
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-100 pt-3">
|
||||
<p class="text-xs text-gray-400 text-center">
|
||||
<i class="fa-solid fa-circle-info text-gray-400 mr-1"></i>
|
||||
A mensagem é enviada pelo celular de <strong>Maria</strong> — não é disparo em massa da
|
||||
campanha
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Remover dados -->
|
||||
<div
|
||||
class="bg-white border border-red-100 rounded-xl shadow-sm p-4 flex items-center justify-between"
|
||||
>
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-red-700">Remover meus dados</p>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Exclui todos os dados desta pessoa do sistema</p>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 border border-red-200 text-red-700 text-xs font-bold px-3 py-2 rounded-lg hover:bg-red-50 transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-trash text-xs"></i> Remover
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom action bar -->
|
||||
<div class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 px-4 py-4 z-20">
|
||||
<button
|
||||
class="w-full bg-primary text-white text-sm font-bold py-3 rounded-xl hover:bg-primary-light transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-floppy-disk"></i> Salvar alterações
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll('.seg-btn').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
document.querySelectorAll('.seg-btn').forEach(function (b) {
|
||||
b.classList.remove('active', 'bg-primary', 'text-white', 'border-primary')
|
||||
b.classList.add('bg-gray-50', 'text-gray-600', 'border-gray-200')
|
||||
})
|
||||
this.classList.add('active', 'bg-primary', 'text-white', 'border-primary')
|
||||
this.classList.remove('bg-gray-50', 'text-gray-600', 'border-gray-200')
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Apoiador-Ficha.png
Normal file
|
After Width: | Height: | Size: 174 KiB |
312
docs/design-refs/latest/Apoiadores-Lista.html
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Apoiadores</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-24">
|
||||
<!-- Header -->
|
||||
<header
|
||||
id="header"
|
||||
class="bg-navy sticky top-0 z-20 px-4 py-3 flex items-center justify-between"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-7 h-7 rounded-full bg-primary flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-star text-white text-xs"></i>
|
||||
</div>
|
||||
<h1 class="text-white font-bold text-sm">Apoiadores</h1>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="relative text-white/70 p-1.5">
|
||||
<i class="fa-solid fa-bell text-base"></i>
|
||||
<span
|
||||
class="absolute top-1 right-1 w-2 h-2 bg-primary rounded-full border border-navy"
|
||||
></span>
|
||||
</button>
|
||||
<button
|
||||
class="bg-white/10 text-white text-xs font-semibold px-3 py-1.5 rounded-lg flex items-center gap-1.5 border border-white/20"
|
||||
>
|
||||
<i class="fa-solid fa-file-arrow-up text-xs"></i> Importar CSV
|
||||
</button>
|
||||
<button
|
||||
class="bg-primary text-white text-xs font-semibold px-3 py-1.5 rounded-lg flex items-center gap-1.5"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xs"></i> Novo
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral · todos os
|
||||
apoiadores
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Summary strip -->
|
||||
<div class="px-4 pt-3 pb-2 grid grid-cols-3 gap-2">
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-3 text-center shadow-sm">
|
||||
<p class="text-2xl font-extrabold text-navy">1.847</p>
|
||||
<p class="text-xs text-gray-500 mt-0.5">total</p>
|
||||
</div>
|
||||
<div class="bg-white border border-green-200 rounded-xl p-3 text-center shadow-sm">
|
||||
<p class="text-2xl font-extrabold text-green-700">1.104</p>
|
||||
<p class="text-xs text-green-600 mt-0.5">Certo + Tende</p>
|
||||
</div>
|
||||
<div class="bg-white border border-amber-200 rounded-xl p-3 text-center shadow-sm">
|
||||
<p class="text-2xl font-extrabold text-amber-700">415</p>
|
||||
<p class="text-xs text-amber-600 mt-0.5">Indecisos</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search + Filters -->
|
||||
<div class="px-4 pt-1 pb-3 space-y-2">
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Buscar por nome, telefone ou município…"
|
||||
class="w-full pl-9 pr-4 py-2.5 text-sm border border-gray-200 rounded-xl bg-white focus:outline-none focus:ring-2 focus:ring-primary/20 text-navy placeholder-gray-300"
|
||||
/>
|
||||
<i
|
||||
class="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"
|
||||
></i>
|
||||
</div>
|
||||
<div class="flex gap-2 overflow-x-auto pb-1">
|
||||
<select
|
||||
class="flex-shrink-0 text-xs border border-gray-200 rounded-lg px-3 py-2 text-navy bg-white focus:outline-none focus:ring-2 focus:ring-primary/20"
|
||||
>
|
||||
<option>Intenção de voto</option>
|
||||
<option>Certo</option>
|
||||
<option>Tende a certo</option>
|
||||
<option>Indeciso</option>
|
||||
<option>Outro</option>
|
||||
</select>
|
||||
<select
|
||||
class="flex-shrink-0 text-xs border border-gray-200 rounded-lg px-3 py-2 text-navy bg-white focus:outline-none"
|
||||
>
|
||||
<option>Território</option>
|
||||
<option>Velho Chico</option>
|
||||
<option>Sertão do São Francisco</option>
|
||||
</select>
|
||||
<select
|
||||
class="flex-shrink-0 text-xs border border-gray-200 rounded-lg px-3 py-2 text-navy bg-white focus:outline-none"
|
||||
>
|
||||
<option>Núcleo</option>
|
||||
<option>Quilombo Rio das Rãs</option>
|
||||
<option>Sindicato Rural Oeste</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- List -->
|
||||
<section id="apoiadores-list" class="px-4 space-y-2">
|
||||
<!-- Item 1 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-6.jpg"
|
||||
class="w-10 h-10 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<p class="font-bold text-navy text-sm truncate">Maria das Dores Souza</p>
|
||||
<span
|
||||
class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>Certo</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Bom Jesus da Lapa · Quilombo Rio das Rãs</p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-gray-500">
|
||||
<span><i class="fa-solid fa-phone text-gray-400 mr-1"></i>(77) 9 9000-1111</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 2 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-8.jpg"
|
||||
class="w-10 h-10 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<p class="font-bold text-navy text-sm truncate">Antônio Carlos Leal</p>
|
||||
<span
|
||||
class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>Tende a certo</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Brumado · Sindicato Rural Oeste</p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-gray-500">
|
||||
<span><i class="fa-solid fa-phone text-gray-400 mr-1"></i>(77) 9 9111-2222</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 3 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-7.jpg"
|
||||
class="w-10 h-10 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<p class="font-bold text-navy text-sm truncate">Joelma Pereira</p>
|
||||
<span
|
||||
class="bg-amber-100 text-amber-800 text-xs font-bold px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>Indeciso</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Feira de Santana · sem núcleo vinculado</p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-gray-500">
|
||||
<span><i class="fa-solid fa-phone text-gray-400 mr-1"></i>(75) 9 8200-3333</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 4 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-9.jpg"
|
||||
class="w-10 h-10 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<p class="font-bold text-navy text-sm truncate">Roberto Bispo</p>
|
||||
<span
|
||||
class="bg-gray-100 text-gray-600 text-xs font-bold px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>Outro</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">
|
||||
Vitória da Conquista · Igreja Batista Central
|
||||
</p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-gray-400 italic">
|
||||
<span>Sem telefone cadastrado</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 5 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-5.jpg"
|
||||
class="w-10 h-10 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<p class="font-bold text-navy text-sm truncate">Simone Oliveira</p>
|
||||
<span
|
||||
class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>Certo</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Caetité · Quilombo Palmares II</p>
|
||||
<div class="flex items-center gap-3 mt-1.5 text-xs text-gray-500">
|
||||
<span><i class="fa-solid fa-phone text-gray-400 mr-1"></i>(77) 9 9444-5555</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination hint -->
|
||||
<p class="text-center text-xs text-gray-400 py-3">
|
||||
Mostrando 5 de 1.847 · <span class="text-primary font-semibold">Carregar mais</span>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- FAB -->
|
||||
<div class="fixed bottom-20 right-4 z-30">
|
||||
<button
|
||||
class="bg-primary text-white w-14 h-14 rounded-full shadow-xl flex items-center justify-center"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Bottom nav -->
|
||||
<nav
|
||||
id="bottom-nav"
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 flex z-20"
|
||||
>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-house text-base"></i>
|
||||
<span class="text-xs mt-0.5">Início</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-layer-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Núcleos</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-primary">
|
||||
<i class="fa-solid fa-user-group text-base"></i>
|
||||
<span class="text-xs mt-0.5 font-semibold">Apoiadores</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-calendar-days text-base"></i>
|
||||
<span class="text-xs mt-0.5">Agenda</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-users text-base"></i>
|
||||
<span class="text-xs mt-0.5">Lideranças</span>
|
||||
</a>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Apoiadores-Lista.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
422
docs/design-refs/latest/Baseline-Eleitoral-2022.html
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Baseline Eleitoral 2022</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
.tab-btn.active {
|
||||
color: #8e0e23;
|
||||
border-bottom: 2px solid #8e0e23;
|
||||
}
|
||||
.tab-btn {
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-24">
|
||||
<!-- Header -->
|
||||
<header
|
||||
id="nucleo-header"
|
||||
class="bg-primary sticky top-0 z-20 px-4 py-3 flex items-center gap-3"
|
||||
>
|
||||
<button class="text-white p-1"><i class="fa-solid fa-arrow-left text-lg"></i></button>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h1 class="text-white font-bold text-sm leading-tight truncate">Quilombo Rio das Rãs</h1>
|
||||
<p class="text-white/60 text-xs truncate">Comunidade · Bom Jesus da Lapa</p>
|
||||
</div>
|
||||
<button class="text-white/70 p-1.5"><i class="fa-solid fa-share-nodes text-lg"></i></button>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-eye text-gold text-xs"></i> Visível para você · Coord. de Núcleo
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- ZE chips + territory -->
|
||||
<div class="px-4 pt-3 pb-2 flex items-center gap-2 flex-wrap">
|
||||
<span class="text-sm text-gray-600">Comunidade · Bom Jesus da Lapa</span>
|
||||
<span class="bg-gray-100 text-gray-600 text-xs font-mono font-semibold px-2 py-1 rounded"
|
||||
>ZE 12</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Vote estimate block -->
|
||||
<div class="mx-4 mt-1 mb-3 bg-white rounded-2xl border border-gray-200 shadow-sm p-4">
|
||||
<p class="text-xs text-gray-500 mb-1 font-medium">Estimativa de votos</p>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-4xl font-extrabold text-primary">1.200</span>
|
||||
<span class="bg-green-100 text-green-800 text-sm font-bold px-3 py-1 rounded-full"
|
||||
>Confirmada</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-1.5">por João S. em 12/07</p>
|
||||
<button
|
||||
class="mt-3 w-full border border-primary text-primary text-sm font-semibold py-2.5 rounded-xl hover:bg-primary-xlight transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-pen-to-square text-xs"></i> Atualizar estimativa
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tabs -->
|
||||
<div class="bg-white border-b border-gray-200 sticky top-14 z-10 overflow-x-auto">
|
||||
<div class="flex whitespace-nowrap px-2">
|
||||
<button class="tab-btn active text-xs font-semibold px-3 py-3">Visão geral</button>
|
||||
<button class="tab-btn text-xs font-semibold px-3 py-3 text-gray-500">Território</button>
|
||||
<button class="tab-btn text-xs font-semibold px-3 py-3 text-gray-500">Eleitorado</button>
|
||||
<button class="tab-btn text-xs font-semibold px-3 py-3 text-gray-500">Lideranças</button>
|
||||
<button class="tab-btn text-xs font-semibold px-3 py-3 text-gray-500">Atualizações</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab content: Visão Geral -->
|
||||
<div class="px-4 py-4 space-y-4">
|
||||
<!-- Strengths (existing block, compacted) -->
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-4">
|
||||
<h3 class="text-sm font-bold text-navy mb-3 flex items-center gap-2">
|
||||
<i class="fa-solid fa-circle-check text-green-500 text-xs"></i> Pontos fortes
|
||||
</h3>
|
||||
<ul class="space-y-1.5">
|
||||
<li class="text-xs text-gray-700 flex gap-2">
|
||||
<span class="text-green-500">•</span>Liderança comunitária consolidada há 15 anos
|
||||
</li>
|
||||
<li class="text-xs text-gray-700 flex gap-2">
|
||||
<span class="text-green-500">•</span>Forte presença em saúde comunitária (ACS)
|
||||
</li>
|
||||
<li class="text-xs text-gray-700 flex gap-2">
|
||||
<span class="text-green-500">•</span>Histórico de votação favorável ao candidato
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- ══════════════════════════════════════════ -->
|
||||
<!-- BASELINE ELEITORAL 2022 — new block -->
|
||||
<!-- ══════════════════════════════════════════ -->
|
||||
<div
|
||||
id="baseline-block"
|
||||
class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden"
|
||||
>
|
||||
<!-- Block header -->
|
||||
<div class="px-4 py-3 border-b border-gray-100 flex items-center justify-between">
|
||||
<h3 class="text-sm font-bold text-navy flex items-center gap-2">
|
||||
<i class="fa-solid fa-chart-bar text-primary text-sm"></i> Baseline eleitoral 2022
|
||||
</h3>
|
||||
<span class="text-xs text-gray-400">Deputado Federal · Bahia</span>
|
||||
</div>
|
||||
|
||||
<!-- Vote rows -->
|
||||
<div class="divide-y divide-gray-50">
|
||||
<!-- Solla — destaque row -->
|
||||
<div class="px-4 py-3.5 bg-primary-xlight border-l-4 border-primary">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-7 h-7 rounded-full bg-primary flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-star text-white text-xs"></i>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-navy">Jorge Solla</p>
|
||||
<p class="text-xs text-primary font-semibold">PT · Dep. Federal</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-lg font-extrabold text-primary">850</p>
|
||||
<p class="text-xs text-gray-500">votos · 2022</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 h-1.5 bg-primary/20 rounded-full overflow-hidden">
|
||||
<div class="h-full bg-primary rounded-full" style="width: 34%"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lula -->
|
||||
<div class="px-4 py-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-7 h-7 rounded-full bg-red-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-person text-red-600 text-xs"></i>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-navy">Lula</p>
|
||||
<p class="text-xs text-gray-500">PT · Presidente (2º turno)</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm font-bold text-navy">1.480</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Jerônimo -->
|
||||
<div class="px-4 py-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-7 h-7 rounded-full bg-red-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-person text-red-600 text-xs"></i>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-navy">Jerônimo Rodrigues</p>
|
||||
<p class="text-xs text-gray-500">PT · Governador</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm font-bold text-navy">1.310</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider: eleitorado stats -->
|
||||
<div class="px-4 py-3 bg-gray-50">
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide mb-2.5">
|
||||
Eleitorado 2022
|
||||
</p>
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-gray-600">Votos válidos</span>
|
||||
<span class="text-xs font-bold text-navy">2.490</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-gray-600">Brancos</span>
|
||||
<span class="text-xs font-bold text-navy">142</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-gray-600">Nulos</span>
|
||||
<span class="text-xs font-bold text-navy">87</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-gray-600">Abstenções</span>
|
||||
<span class="text-xs font-bold text-navy">680</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mais votado aqui -->
|
||||
<div class="px-4 py-3 flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="fa-solid fa-trophy text-amber-400 text-sm flex-shrink-0"></i>
|
||||
<div>
|
||||
<p class="text-xs text-gray-500">Mais votado aqui em 2022</p>
|
||||
<p class="text-sm font-semibold text-navy">Dep. Fulano de Tal (PP)</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm font-bold text-gray-700">2.100</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── INSIGHT LINE — negative scenario ──────── -->
|
||||
<div
|
||||
class="mx-4 mb-4 mt-1 flex items-start gap-2.5 bg-amber-50 border border-amber-200 rounded-xl px-3.5 py-3"
|
||||
>
|
||||
<i
|
||||
class="fa-solid fa-triangle-exclamation text-amber-500 text-base mt-0.5 flex-shrink-0"
|
||||
></i>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-amber-800">Faltam 350 votos para o patamar de 2022</p>
|
||||
<p class="text-xs text-amber-700 mt-0.5">
|
||||
Estimativa atual (1.200) ainda abaixo do resultado de 2022 (850 → meta: 1.200
|
||||
confirmada, mas patamar atingido exige esforço de ativação adicional)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── INSIGHT LINE — positive scenario (alternate, commented) ──
|
||||
<div class="mx-4 mb-4 mt-1 flex items-start gap-2.5 bg-green-50 border border-green-200 rounded-xl px-3.5 py-3">
|
||||
<i class="fa-solid fa-circle-check text-green-500 text-base mt-0.5 flex-shrink-0"></i>
|
||||
<div>
|
||||
<p class="text-sm font-bold text-green-800">Já superamos 2022 em 12%</p>
|
||||
<p class="text-xs text-green-700 mt-0.5">Estimativa de 1.200 supera os 850 votos de 2022 — território em crescimento.</p>
|
||||
</div>
|
||||
</div>
|
||||
──────────────────────────────────────────── -->
|
||||
</div>
|
||||
<!-- end baseline block -->
|
||||
|
||||
<!-- ══════════════════════════════════════════ -->
|
||||
<!-- INSIGHTS PANEL (Priority 3 — preview) -->
|
||||
<!-- ══════════════════════════════════════════ -->
|
||||
<div
|
||||
id="insights-panel"
|
||||
class="bg-white rounded-xl border border-gray-200 shadow-sm p-4 space-y-3"
|
||||
>
|
||||
<h3 class="text-sm font-bold text-navy flex items-center gap-2">
|
||||
<i class="fa-solid fa-lightbulb text-amber-400 text-sm"></i> Insights do território
|
||||
</h3>
|
||||
|
||||
<!-- Insight card 1: conversão -->
|
||||
<div class="flex items-center gap-3 p-2.5 rounded-lg bg-green-50 border border-green-100">
|
||||
<div
|
||||
class="w-8 h-8 rounded-lg bg-green-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-percent text-green-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold text-green-800">
|
||||
Taxa de conversão: 18% do eleitorado apto
|
||||
</p>
|
||||
<p class="text-xs text-green-700 mt-0.5">850 votos / 4.700 eleitores aptos</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Insight card 2: classificação -->
|
||||
<div class="flex items-center gap-3 p-2.5 rounded-lg bg-gray-50 border border-gray-200">
|
||||
<div
|
||||
class="w-8 h-8 rounded-lg bg-green-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-shield text-green-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold text-navy">Território de defesa</p>
|
||||
<p class="text-xs text-gray-600 mt-0.5">Base sólida — prioridade manter engajamento</p>
|
||||
</div>
|
||||
<span
|
||||
class="bg-green-100 text-green-700 text-xs font-bold px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>Defesa</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Insight card 3: alavancagem -->
|
||||
<div class="flex items-center gap-3 p-2.5 rounded-lg bg-blue-50 border border-blue-100">
|
||||
<div
|
||||
class="w-8 h-8 rounded-lg bg-blue-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-link text-blue-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold text-blue-800">Alavancagem da chapa: 22%</p>
|
||||
<p class="text-xs text-blue-700 mt-0.5">Da base Lula/Jerônimo ainda não convertida</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Insight card 4: oportunidade -->
|
||||
<div class="flex items-center gap-3 p-2.5 rounded-lg bg-amber-50 border border-amber-100">
|
||||
<div
|
||||
class="w-8 h-8 rounded-lg bg-amber-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-bullhorn text-amber-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold text-amber-800">Oportunidade de mobilização</p>
|
||||
<p class="text-xs text-amber-700 mt-0.5">
|
||||
142 brancos/nulos + 680 abstenções = 822 votos possíveis
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Insight card 5: mais votado -->
|
||||
<div class="flex items-center gap-3 p-2.5 rounded-lg bg-gray-50 border border-gray-200">
|
||||
<div
|
||||
class="w-8 h-8 rounded-lg bg-gray-100 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-ranking-star text-gray-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold text-navy">Mais votado aqui em 2022: Dep. Fulano (PP)</p>
|
||||
<p class="text-xs text-gray-600 mt-0.5">
|
||||
Solla ficou em 4º lugar · 2.100 votos à frente
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end insights panel -->
|
||||
|
||||
<!-- Status lideranças -->
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-4">
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide mb-3">
|
||||
Status das lideranças
|
||||
</p>
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-2.5 h-2.5 rounded-full bg-green-500"></span> Engajadas
|
||||
</div>
|
||||
<span class="font-bold text-green-700">5</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-2.5 h-2.5 rounded-full bg-gray-400"></span> A abordar
|
||||
</div>
|
||||
<span class="font-bold text-gray-600">4</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-2.5 h-2.5 rounded-full bg-amber-500"></span> Em disputa
|
||||
</div>
|
||||
<span class="font-bold text-amber-700">2</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-2.5 h-2.5 rounded-full bg-red-500"></span> Negativas
|
||||
</div>
|
||||
<span class="font-bold text-red-700">1</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom nav -->
|
||||
<nav
|
||||
id="bottom-nav"
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 flex z-20"
|
||||
>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-house text-base"></i>
|
||||
<span class="text-xs mt-0.5">Início</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-primary">
|
||||
<i class="fa-solid fa-layer-group text-base"></i>
|
||||
<span class="text-xs mt-0.5 font-semibold">Núcleos</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-user-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Apoiadores</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-calendar-days text-base"></i>
|
||||
<span class="text-xs mt-0.5">Agenda</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-users text-base"></i>
|
||||
<span class="text-xs mt-0.5">Lideranças</span>
|
||||
</a>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Baseline-Eleitoral-2022.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
259
docs/design-refs/latest/Compartilhar-Nucleo.html
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Compartilhar Núcleo</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
wa: '#25D366',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-900/60 pb-0" style="min-height: 840px">
|
||||
<!-- Dimmed background — represents nuclei detail screen behind -->
|
||||
<div class="bg-gray-50" style="height: 840px; position: relative">
|
||||
<!-- Blurred header behind -->
|
||||
<header class="bg-primary px-4 py-3 flex items-center gap-3 opacity-40">
|
||||
<button class="text-white p-1"><i class="fa-solid fa-arrow-left text-lg"></i></button>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h1 class="text-white font-bold text-sm truncate">Quilombo Rio das Rãs</h1>
|
||||
<p class="text-white/60 text-xs">Comunidade · Bom Jesus da Lapa</p>
|
||||
</div>
|
||||
<button class="text-white/70 p-1.5"><i class="fa-solid fa-share-nodes text-lg"></i></button>
|
||||
</header>
|
||||
<div class="px-4 pt-3 opacity-30">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-eye text-gold text-xs"></i> Visível para você · Coord. de Núcleo
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Dialog overlay -->
|
||||
<div class="absolute inset-0 bg-black/40 flex items-end" style="z-index: 50">
|
||||
<div
|
||||
id="share-dialog"
|
||||
class="w-full bg-white rounded-t-2xl shadow-2xl"
|
||||
style="max-height: 660px; overflow-y: auto"
|
||||
>
|
||||
<!-- Handle -->
|
||||
<div class="flex justify-center pt-3 pb-1">
|
||||
<div class="w-10 h-1 bg-gray-300 rounded-full"></div>
|
||||
</div>
|
||||
|
||||
<!-- Dialog header -->
|
||||
<div class="px-5 pt-3 pb-4 border-b border-gray-100 flex items-center justify-between">
|
||||
<div>
|
||||
<h2 class="text-base font-bold text-navy">Compartilhar núcleo</h2>
|
||||
<p class="text-xs text-gray-500 mt-0.5">
|
||||
Quilombo Rio das Rãs · envia apenas o link, não concede acesso
|
||||
</p>
|
||||
</div>
|
||||
<button class="text-gray-400 hover:text-navy p-1.5 rounded-lg hover:bg-gray-100">
|
||||
<i class="fa-solid fa-xmark text-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Sections -->
|
||||
<div class="px-5 py-4 space-y-5">
|
||||
<!-- Section: Coordenação Geral -->
|
||||
<div>
|
||||
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-2.5">
|
||||
Com coordenação geral
|
||||
</p>
|
||||
<div class="space-y-2.5">
|
||||
<!-- Person 1 -->
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-2.jpg"
|
||||
class="w-9 h-9 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-navy truncate">Carlos Mendes</p>
|
||||
<p class="text-xs text-gray-500">Coord. Geral</p>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 bg-wa text-white text-xs font-bold px-3 py-2 rounded-xl active:opacity-80 flex-shrink-0"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-base"></i> Abrir
|
||||
</button>
|
||||
</div>
|
||||
<!-- Person 2 -->
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-1.jpg"
|
||||
class="w-9 h-9 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-navy truncate">Ana Ribeiro</p>
|
||||
<p class="text-xs text-gray-500">Coord. Geral</p>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 bg-wa text-white text-xs font-bold px-3 py-2 rounded-xl active:opacity-80 flex-shrink-0"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-base"></i> Abrir
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<div class="border-t border-gray-100"></div>
|
||||
|
||||
<!-- Section: Coordenador do Núcleo -->
|
||||
<div>
|
||||
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-2.5">
|
||||
Com coordenador
|
||||
</p>
|
||||
<div class="space-y-2.5">
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-3.jpg"
|
||||
class="w-9 h-9 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-navy truncate">João Santos</p>
|
||||
<p class="text-xs text-gray-500">Coord. Núcleo</p>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 bg-wa text-white text-xs font-bold px-3 py-2 rounded-xl active:opacity-80 flex-shrink-0"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-base"></i> Abrir
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-5.jpg"
|
||||
class="w-9 h-9 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-navy truncate">Patrícia Lima</p>
|
||||
<p class="text-xs text-gray-500">Coord. Núcleo</p>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 bg-wa text-white text-xs font-bold px-3 py-2 rounded-xl active:opacity-80 flex-shrink-0"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-base"></i> Abrir
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<div class="border-t border-gray-100"></div>
|
||||
|
||||
<!-- Section: Liderança -->
|
||||
<div>
|
||||
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-2.5">
|
||||
Com liderança
|
||||
</p>
|
||||
<div class="space-y-2.5">
|
||||
<div class="flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-6.jpg"
|
||||
class="w-9 h-9 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-navy truncate">Dona Rosa Ferreira</p>
|
||||
<p class="text-xs text-gray-500">Liderança · Engajada</p>
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center gap-1.5 bg-wa text-white text-xs font-bold px-3 py-2 rounded-xl active:opacity-80 flex-shrink-0"
|
||||
>
|
||||
<i class="fa-brands fa-whatsapp text-base"></i> Abrir
|
||||
</button>
|
||||
</div>
|
||||
<!-- No phone — absent -->
|
||||
<!-- (Person without phone simply not shown) -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<div class="border-t border-gray-100"></div>
|
||||
|
||||
<!-- Copy link -->
|
||||
<div>
|
||||
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-2.5">
|
||||
Copiar link
|
||||
</p>
|
||||
<div
|
||||
class="flex items-center gap-2 bg-gray-50 border border-gray-200 rounded-xl px-3 py-2.5"
|
||||
>
|
||||
<i class="fa-solid fa-link text-gray-400 text-sm flex-shrink-0"></i>
|
||||
<p class="text-xs text-gray-600 truncate flex-1">
|
||||
solla.app/nucleos/quilombo-rio-das-ras
|
||||
</p>
|
||||
<button
|
||||
id="copy-btn"
|
||||
onclick="copyLink()"
|
||||
class="flex-shrink-0 bg-navy text-white text-xs font-bold px-3 py-1.5 rounded-lg active:opacity-80"
|
||||
>
|
||||
Copiar
|
||||
</button>
|
||||
</div>
|
||||
<!-- Copied state (hidden by default) -->
|
||||
<div
|
||||
id="copied-msg"
|
||||
class="hidden mt-2 flex items-center gap-1.5 text-green-700 text-xs font-semibold"
|
||||
>
|
||||
<i class="fa-solid fa-check-circle"></i> Link copiado!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom padding -->
|
||||
<div class="h-6"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function copyLink() {
|
||||
document.getElementById('copied-msg').classList.remove('hidden')
|
||||
var btn = document.getElementById('copy-btn')
|
||||
btn.textContent = 'Copiado ✓'
|
||||
btn.classList.add('bg-green-600')
|
||||
btn.classList.remove('bg-navy')
|
||||
setTimeout(function () {
|
||||
document.getElementById('copied-msg').classList.add('hidden')
|
||||
btn.textContent = 'Copiar'
|
||||
btn.classList.remove('bg-green-600')
|
||||
btn.classList.add('bg-navy')
|
||||
}, 2500)
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Compartilhar-Nucleo.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
343
docs/design-refs/latest/Dia-D-GOTV.html
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Dia D – Operação Eleitoral</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
.supporter-btn {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.supporter-btn.votou {
|
||||
background: #dcfce7;
|
||||
border-color: #16a34a;
|
||||
color: #166534;
|
||||
}
|
||||
.supporter-btn.confirmou {
|
||||
background: #dbeafe;
|
||||
border-color: #2563eb;
|
||||
color: #1e40af;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-24">
|
||||
<!-- Header -->
|
||||
<header
|
||||
id="header"
|
||||
class="bg-primary sticky top-0 z-30 px-4 py-3 flex items-center justify-between"
|
||||
>
|
||||
<div>
|
||||
<div class="flex items-center gap-2 mb-0.5">
|
||||
<i class="fa-solid fa-flag text-white/90 text-sm"></i>
|
||||
<h1 class="text-white font-bold text-sm">Dia D — 4 de outubro</h1>
|
||||
</div>
|
||||
<p class="text-white/70 text-xs">
|
||||
Quilombo Rio das Rãs · <span class="font-mono">ZE 12</span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- Sync status -->
|
||||
<div class="flex flex-col items-end gap-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-green-500 text-white text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-wifi text-xs"></i> Sincronizado
|
||||
</span>
|
||||
<p class="text-white/50 text-xs">às 08:42</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Sticky progress header -->
|
||||
<div id="progress-header" class="sticky z-20 bg-navy px-4 py-3" style="top: 60px">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div>
|
||||
<p class="text-white font-bold text-lg leading-none">62% da base</p>
|
||||
<p class="text-white/60 text-xs mt-0.5">1.240 de 2.000 confirmados</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<p class="text-white/80 text-xs">Votaram</p>
|
||||
<p class="text-green-400 font-extrabold text-xl leading-none">830</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Progress bar -->
|
||||
<div class="h-3 bg-white/20 rounded-full overflow-hidden">
|
||||
<div
|
||||
class="h-full rounded-full"
|
||||
style="width: 62%; background: linear-gradient(to right, #22c55e, #86efac)"
|
||||
></div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between mt-1.5 text-xs">
|
||||
<span class="text-white/60">0</span>
|
||||
<span class="text-green-400 font-semibold">62% confirmados vão votar</span>
|
||||
<span class="text-white/60">2.000</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter chips -->
|
||||
<div
|
||||
class="px-4 py-3 flex gap-2 overflow-x-auto bg-white border-b border-gray-200 sticky z-10"
|
||||
style="top: 140px"
|
||||
>
|
||||
<button
|
||||
class="flex-shrink-0 text-xs font-bold px-3 py-1.5 rounded-full border-2 border-primary bg-primary text-white"
|
||||
>
|
||||
Todos (2.000)
|
||||
</button>
|
||||
<button
|
||||
class="flex-shrink-0 text-xs font-semibold px-3 py-1.5 rounded-full border border-gray-200 text-gray-600 hover:border-navy"
|
||||
>
|
||||
Ainda não confirmados (760)
|
||||
</button>
|
||||
<button
|
||||
class="flex-shrink-0 text-xs font-semibold px-3 py-1.5 rounded-full border border-gray-200 text-gray-600 hover:border-navy"
|
||||
>
|
||||
Votaram (830)
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-eye text-gold text-xs"></i> Visão do coordenador · Quilombo Rio das
|
||||
Rãs
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Legend -->
|
||||
<div class="px-4 pt-2 pb-3 flex items-center gap-4 text-xs">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="w-3 h-3 rounded-full bg-gray-200 border border-gray-300"></div>
|
||||
<span class="text-gray-500">Não confirmado</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="w-3 h-3 rounded-full bg-blue-200 border border-blue-400"></div>
|
||||
<span class="text-gray-500">Vai votar</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="w-3 h-3 rounded-full bg-green-400 border border-green-600"></div>
|
||||
<span class="text-gray-500">Votou ✓</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Supporter list — big tap targets -->
|
||||
<section id="supporter-list" class="px-4 space-y-2">
|
||||
<!-- Item: Votou (confirmed voted) -->
|
||||
<div class="bg-green-50 border border-green-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Maria das Dores Souza</p>
|
||||
<p class="text-xs text-gray-500">Seção 42 · ZE 12</p>
|
||||
</div>
|
||||
<button
|
||||
class="supporter-btn votou text-xs font-bold px-4 py-3 rounded-xl border-2 min-w-[90px] text-center"
|
||||
>
|
||||
<i class="fa-solid fa-check-circle mr-1"></i> Votou ✓
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Item: Confirmou que vai votar -->
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Antônio Carlos Leal</p>
|
||||
<p class="text-xs text-gray-500">Seção 42 · ZE 12</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<button
|
||||
class="supporter-btn confirmou text-xs font-bold px-3 py-2 rounded-xl border-2 text-center whitespace-nowrap"
|
||||
>
|
||||
<i class="fa-solid fa-thumbs-up mr-1"></i> Vai votar
|
||||
</button>
|
||||
<button
|
||||
onclick="markVotou(this)"
|
||||
class="text-xs font-bold px-3 py-2 rounded-xl border-2 border-green-400 text-green-700 bg-white text-center whitespace-nowrap hover:bg-green-50"
|
||||
>
|
||||
Confirmar votou
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item: Não confirmado -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Joelma Pereira</p>
|
||||
<p class="text-xs text-gray-500">Seção 38 · ZE 12</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<button
|
||||
onclick="markConfirmou(this)"
|
||||
class="supporter-btn text-xs font-bold px-3 py-2.5 rounded-xl border-2 border-blue-300 text-blue-700 bg-blue-50 text-center whitespace-nowrap hover:bg-blue-100"
|
||||
>
|
||||
Confirmou que vai votar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item: Não confirmado -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Roberto Bispo</p>
|
||||
<p class="text-xs text-gray-500">Seção 38 · ZE 12</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<button
|
||||
onclick="markConfirmou(this)"
|
||||
class="supporter-btn text-xs font-bold px-3 py-2.5 rounded-xl border-2 border-blue-300 text-blue-700 bg-blue-50 text-center whitespace-nowrap hover:bg-blue-100"
|
||||
>
|
||||
Confirmou que vai votar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item: Votou -->
|
||||
<div class="bg-green-50 border border-green-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Simone Oliveira</p>
|
||||
<p class="text-xs text-gray-500">Seção 45 · ZE 12</p>
|
||||
</div>
|
||||
<button
|
||||
class="supporter-btn votou text-xs font-bold px-4 py-3 rounded-xl border-2 min-w-[90px] text-center"
|
||||
>
|
||||
<i class="fa-solid fa-check-circle mr-1"></i> Votou ✓
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Item: Não confirmado -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">José Nascimento</p>
|
||||
<p class="text-xs text-gray-500">Seção 40 · ZE 12</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<button
|
||||
onclick="markConfirmou(this)"
|
||||
class="supporter-btn text-xs font-bold px-3 py-2.5 rounded-xl border-2 border-blue-300 text-blue-700 bg-blue-50 text-center whitespace-nowrap hover:bg-blue-100"
|
||||
>
|
||||
Confirmou que vai votar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item: Não confirmado -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-4 flex items-center gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Ana Paula Ferreira</p>
|
||||
<p class="text-xs text-gray-500">Seção 38 · ZE 12</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<button
|
||||
onclick="markConfirmou(this)"
|
||||
class="supporter-btn text-xs font-bold px-3 py-2.5 rounded-xl border-2 border-blue-300 text-blue-700 bg-blue-50 text-center whitespace-nowrap hover:bg-blue-100"
|
||||
>
|
||||
Confirmou que vai votar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center text-xs text-gray-400 py-3">
|
||||
Mostrando 7 de 2.000 · <span class="text-primary font-semibold">Carregar mais</span>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Offline warning banner (example) -->
|
||||
<div
|
||||
id="offline-banner"
|
||||
class="hidden fixed top-20 left-4 right-4 z-40 bg-amber-50 border border-amber-300 rounded-xl px-4 py-3 flex items-center gap-3 shadow-lg"
|
||||
>
|
||||
<i class="fa-solid fa-wifi-slash text-amber-600 text-lg flex-shrink-0"></i>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold text-amber-800">Sem conexão — modo offline</p>
|
||||
<p class="text-xs text-amber-600">
|
||||
As marcações serão sincronizadas quando a conexão voltar
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="text-xs font-bold text-amber-700 bg-amber-200 px-2 py-0.5 rounded-full flex-shrink-0"
|
||||
>3 pend.</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Bottom nav -->
|
||||
<nav
|
||||
id="bottom-nav"
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 flex z-20"
|
||||
>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-house text-base"></i>
|
||||
<span class="text-xs mt-0.5">Início</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-layer-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Núcleos</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-user-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Apoiadores</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-primary">
|
||||
<i class="fa-solid fa-flag text-base"></i>
|
||||
<span class="text-xs mt-0.5 font-semibold">Dia D</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-users text-base"></i>
|
||||
<span class="text-xs mt-0.5">Lideranças</span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
function markConfirmou(btn) {
|
||||
var row = btn.closest('div.flex.flex-col')
|
||||
row.innerHTML =
|
||||
'<button onclick="markVotou(this)" class="text-xs font-bold px-3 py-2 rounded-xl border-2 border-blue-400 text-blue-700 bg-blue-50 text-center whitespace-nowrap">Confirmou que vai votar</button><button onclick="markVotou(this)" class="text-xs font-bold px-3 py-2 rounded-xl border-2 border-green-400 text-green-700 bg-white text-center whitespace-nowrap hover:bg-green-50">Confirmar votou</button>'
|
||||
var card = btn.closest('.bg-white')
|
||||
if (card) {
|
||||
card.classList.remove('bg-white', 'border-gray-200')
|
||||
card.classList.add('bg-blue-50', 'border-blue-200')
|
||||
}
|
||||
}
|
||||
function markVotou(btn) {
|
||||
var card = btn.closest('[class*="rounded-xl"]')
|
||||
card.classList.remove('bg-blue-50', 'border-blue-200', 'bg-white', 'border-gray-200')
|
||||
card.classList.add('bg-green-50', 'border-green-200')
|
||||
var actionArea = btn.closest('.flex.flex-col') || btn.closest('.flex.items-center.gap-4')
|
||||
var parent = card.querySelector('.flex.flex-col') || card.lastElementChild
|
||||
if (parent)
|
||||
parent.innerHTML =
|
||||
'<button class="supporter-btn votou text-xs font-bold px-4 py-3 rounded-xl border-2 min-w-[90px] text-center"><i class="fa-solid fa-check-circle mr-1"></i> Votou ✓</button>'
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Dia-D-GOTV.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
385
docs/design-refs/latest/Formulario-Territorio.html
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Formulário – Território</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
.chip-remove {
|
||||
cursor: pointer;
|
||||
}
|
||||
.ze-chip {
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-28">
|
||||
<!-- Header -->
|
||||
<header id="header" class="bg-navy sticky top-0 z-20 px-4 py-3 flex items-center gap-3">
|
||||
<button class="text-white p-1"><i class="fa-solid fa-arrow-left text-lg"></i></button>
|
||||
<div class="flex-1">
|
||||
<h1 class="text-white font-bold text-sm">Editar Núcleo</h1>
|
||||
<p class="text-white/60 text-xs">Quilombo Rio das Rãs · Território</p>
|
||||
</div>
|
||||
<button
|
||||
class="text-white/70 text-xs font-semibold px-3 py-1.5 border border-white/30 rounded-lg"
|
||||
>
|
||||
Salvar
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Form -->
|
||||
<form class="px-4 pt-4 space-y-5" onsubmit="return false">
|
||||
<!-- Nome do núcleo -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-4">
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Nome do Núcleo <span class="text-primary">*</span></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
value="Quilombo Rio das Rãs"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 focus:border-primary"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Tipo de território <span class="text-primary">*</span></label
|
||||
>
|
||||
<select
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 bg-white"
|
||||
>
|
||||
<option>Comunidade Quilombola</option>
|
||||
<option>Sindicato</option>
|
||||
<option>Religioso</option>
|
||||
<option>Rural / Assentamento</option>
|
||||
<option>Bairro</option>
|
||||
<option>Outro</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════════════════════ -->
|
||||
<!-- TERRITÓRIO — multi-município block -->
|
||||
<!-- ═══════════════════════════════════════ -->
|
||||
<div
|
||||
id="territorio-block"
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-4"
|
||||
>
|
||||
<h3 class="text-sm font-bold text-navy flex items-center gap-2">
|
||||
<i class="fa-solid fa-map-location-dot text-primary text-sm"></i> Território
|
||||
</h3>
|
||||
|
||||
<!-- Municípios multi-select -->
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Municípios <span class="text-primary">*</span></label
|
||||
>
|
||||
<!-- Selected chips -->
|
||||
<div id="municipios-chips" class="flex flex-wrap gap-2 mb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-navy text-white text-xs font-semibold px-3 py-1.5 rounded-full"
|
||||
>
|
||||
Bom Jesus da Lapa
|
||||
<button
|
||||
type="button"
|
||||
onclick="removeChip(this, 'municipios-chips', 'municipios-count')"
|
||||
class="chip-remove ml-0.5 opacity-70 hover:opacity-100"
|
||||
>
|
||||
<i class="fa-solid fa-xmark text-xs"></i>
|
||||
</button>
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-navy text-white text-xs font-semibold px-3 py-1.5 rounded-full"
|
||||
>
|
||||
Carinhanha
|
||||
<button
|
||||
type="button"
|
||||
onclick="removeChip(this, 'municipios-chips', 'municipios-count')"
|
||||
class="chip-remove ml-0.5 opacity-70 hover:opacity-100"
|
||||
>
|
||||
<i class="fa-solid fa-xmark text-xs"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<!-- Combobox input -->
|
||||
<div class="relative">
|
||||
<input
|
||||
id="municipio-input"
|
||||
type="text"
|
||||
placeholder="Buscar e adicionar município…"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 focus:border-primary pr-10"
|
||||
oninput="showSuggestions(this.value)"
|
||||
/>
|
||||
<i
|
||||
class="fa-solid fa-chevron-down absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs pointer-events-none"
|
||||
></i>
|
||||
<!-- Dropdown suggestions -->
|
||||
<div
|
||||
id="municipio-dropdown"
|
||||
class="hidden absolute left-0 right-0 top-full mt-1 bg-white border border-gray-200 rounded-xl shadow-lg z-30 overflow-hidden"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onclick="addMunicipio('Malhada')"
|
||||
class="w-full text-left px-4 py-3 text-sm text-navy hover:bg-gray-50 border-b border-gray-100"
|
||||
>
|
||||
Malhada
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick="addMunicipio('Igaporã')"
|
||||
class="w-full text-left px-4 py-3 text-sm text-navy hover:bg-gray-50 border-b border-gray-100"
|
||||
>
|
||||
Igaporã
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick="addMunicipio('Serra do Ramalho')"
|
||||
class="w-full text-left px-4 py-3 text-sm text-navy hover:bg-gray-50"
|
||||
>
|
||||
Serra do Ramalho
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-1.5 flex items-center gap-1">
|
||||
<i class="fa-solid fa-circle-info text-blue-400 text-xs"></i>
|
||||
<span id="municipios-count">2 municípios selecionados</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Territórios de Identidade — read-only auto-derived -->
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5">
|
||||
Territórios de Identidade
|
||||
<span class="normal-case font-normal text-gray-400 ml-1"
|
||||
>(preenchido automaticamente)</span
|
||||
>
|
||||
</label>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-800 text-xs font-semibold px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-lock text-amber-400 text-xs"></i> Velho Chico
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-800 text-xs font-semibold px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-lock text-amber-400 text-xs"></i> Sertão do São Francisco
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-1.5">
|
||||
Derivados dos municípios selecionados · não é possível editar
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Bairros — disabled because 2 municípios selected -->
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-400 uppercase tracking-wide mb-1.5"
|
||||
>Bairros</label
|
||||
>
|
||||
<div
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 bg-gray-50 text-gray-400 text-sm flex items-center gap-2 cursor-not-allowed"
|
||||
>
|
||||
<i class="fa-solid fa-ban text-gray-300 text-sm"></i>
|
||||
Selecione municípios primeiro
|
||||
</div>
|
||||
<p class="text-xs text-amber-600 font-semibold mt-1.5 flex items-center gap-1">
|
||||
<i class="fa-solid fa-triangle-exclamation text-xs"></i>
|
||||
Bairros exigem um único município selecionado
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════════════════════ -->
|
||||
<!-- TSE ZONES AUTO-FILL block -->
|
||||
<!-- ═══════════════════════════════════════ -->
|
||||
<div id="tse-zones-block">
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Zonas Eleitorais (TSE)</label
|
||||
>
|
||||
|
||||
<!-- Info caption -->
|
||||
<div
|
||||
class="bg-blue-50 border border-blue-200 rounded-xl px-3 py-2.5 mb-3 flex items-start gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-circle-info text-blue-500 text-sm mt-0.5 flex-shrink-0"></i>
|
||||
<p class="text-xs text-blue-700">
|
||||
Zonas sugeridas pelo cadastro oficial do TSE — confira antes de salvar.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Pre-checked zone chips -->
|
||||
<div class="space-y-2" id="ze-chips">
|
||||
<!-- Suggested + checked -->
|
||||
<label
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 border border-gray-200 rounded-xl cursor-pointer ze-chip"
|
||||
>
|
||||
<input type="checkbox" checked class="w-5 h-5 rounded accent-primary flex-shrink-0" />
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-mono font-bold text-navy text-sm">ZE 12</span>
|
||||
<span
|
||||
class="bg-blue-100 text-blue-700 text-xs font-semibold px-1.5 py-0.5 rounded"
|
||||
>sugerida</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Bom Jesus da Lapa</p>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 border border-gray-200 rounded-xl cursor-pointer ze-chip"
|
||||
>
|
||||
<input type="checkbox" checked class="w-5 h-5 rounded accent-primary flex-shrink-0" />
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-mono font-bold text-navy text-sm">ZE 41</span>
|
||||
<span
|
||||
class="bg-blue-100 text-blue-700 text-xs font-semibold px-1.5 py-0.5 rounded"
|
||||
>sugerida</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Carinhanha</p>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<!-- Unchecked suggestion -->
|
||||
<label
|
||||
class="flex items-center gap-3 p-3 bg-gray-50 border border-gray-200 rounded-xl cursor-pointer ze-chip opacity-60"
|
||||
>
|
||||
<input type="checkbox" class="w-5 h-5 rounded accent-primary flex-shrink-0" />
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-mono font-bold text-navy text-sm">ZE 7</span>
|
||||
<span
|
||||
class="bg-blue-100 text-blue-700 text-xs font-semibold px-1.5 py-0.5 rounded"
|
||||
>sugerida</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Carinhanha (zona adicional)</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Add custom zone -->
|
||||
<button
|
||||
type="button"
|
||||
class="mt-2.5 flex items-center gap-2 text-primary text-xs font-semibold"
|
||||
>
|
||||
<i class="fa-solid fa-plus-circle text-sm"></i> Adicionar zona manualmente
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end território block -->
|
||||
|
||||
<!-- Validation error example -->
|
||||
<div
|
||||
id="validation-error"
|
||||
class="hidden bg-red-50 border border-red-200 rounded-xl p-3 flex items-start gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-circle-xmark text-red-500 text-sm mt-0.5 flex-shrink-0"></i>
|
||||
<p class="text-xs text-red-700">Selecione pelo menos um município para continuar.</p>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Bottom action bar -->
|
||||
<div
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 px-4 py-4 flex gap-3 z-20"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 border border-gray-200 text-navy text-sm font-semibold py-3 rounded-xl hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 bg-primary text-white text-sm font-bold py-3 rounded-xl hover:bg-primary-light transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-floppy-disk text-sm"></i> Salvar território
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showSuggestions(val) {
|
||||
var dd = document.getElementById('municipio-dropdown')
|
||||
dd.classList.toggle('hidden', val.length < 1)
|
||||
}
|
||||
function addMunicipio(name) {
|
||||
document.getElementById('municipio-dropdown').classList.add('hidden')
|
||||
document.getElementById('municipio-input').value = ''
|
||||
var container = document.getElementById('municipios-chips')
|
||||
var chip = document.createElement('span')
|
||||
chip.className =
|
||||
'inline-flex items-center gap-1.5 bg-navy text-white text-xs font-semibold px-3 py-1.5 rounded-full'
|
||||
chip.innerHTML =
|
||||
name +
|
||||
'<button type="button" onclick="removeChip(this,\'municipios-chips\',\'municipios-count\')" class="chip-remove ml-0.5 opacity-70"><i class="fa-solid fa-xmark text-xs"></i></button>'
|
||||
container.appendChild(chip)
|
||||
updateCount()
|
||||
}
|
||||
function removeChip(btn, containerId, countId) {
|
||||
btn.closest('span').remove()
|
||||
updateCount()
|
||||
}
|
||||
function updateCount() {
|
||||
var chips = document.querySelectorAll('#municipios-chips span')
|
||||
var c = document.getElementById('municipios-count')
|
||||
c.textContent =
|
||||
chips.length +
|
||||
' município' +
|
||||
(chips.length !== 1 ? 's' : '') +
|
||||
' selecionado' +
|
||||
(chips.length !== 1 ? 's' : '')
|
||||
}
|
||||
document.addEventListener('click', function (e) {
|
||||
if (!e.target.closest('#municipio-input') && !e.target.closest('#municipio-dropdown')) {
|
||||
document.getElementById('municipio-dropdown').classList.add('hidden')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Formulario-Territorio.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
443
docs/design-refs/latest/Importar-CSV-Apoiadores.html
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Importar CSV – Apoiadores</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 flex">
|
||||
<!-- Sidebar -->
|
||||
<aside id="sidebar" class="w-60 min-h-screen bg-navy flex flex-col fixed top-0 left-0 z-30">
|
||||
<div class="flex items-center gap-3 px-5 py-5 border-b border-white/10">
|
||||
<div class="w-9 h-9 rounded-full bg-primary flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-star text-white text-sm"></i>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-white font-bold text-sm leading-tight">Jorge Solla</p>
|
||||
<p class="text-white/40 text-xs">Bahia · Dep. Federal</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-5 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-primary/20 text-primary-xlight text-xs font-semibold px-3 py-1.5 rounded-full border border-primary/30"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-xs"></i> Coordenação Geral
|
||||
</span>
|
||||
</div>
|
||||
<nav class="flex-1 px-3 py-2 space-y-0.5">
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white text-sm transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-house w-4 text-center"></i> Início
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white text-sm transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-layer-group w-4 text-center"></i> Núcleos
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white text-sm transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-users w-4 text-center"></i> Lideranças
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg bg-primary/20 text-white font-semibold text-sm"
|
||||
>
|
||||
<i class="fa-solid fa-user-group w-4 text-center text-primary-xlight"></i> Apoiadores
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white text-sm transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-calendar-days w-4 text-center"></i> Planos de ação
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white text-sm transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-newspaper w-4 text-center"></i> Atualizações
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white text-sm transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-map w-4 text-center"></i> Territórios
|
||||
</a>
|
||||
</nav>
|
||||
<div class="px-4 py-4 border-t border-white/10 flex items-center gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-2.jpg"
|
||||
class="w-8 h-8 rounded-full object-cover"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-white text-xs font-semibold truncate">Carlos Mendes</p>
|
||||
<p class="text-white/40 text-xs truncate">Coord. Geral</p>
|
||||
</div>
|
||||
<button class="text-white/40 hover:text-white">
|
||||
<i class="fa-solid fa-arrow-right-from-bracket text-xs"></i>
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main -->
|
||||
<main class="ml-60 flex-1">
|
||||
<header
|
||||
id="topbar"
|
||||
class="sticky top-0 z-20 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="text-gray-500 hover:text-navy p-1.5 rounded-lg hover:bg-gray-100">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</button>
|
||||
<div>
|
||||
<h1 class="text-lg font-bold text-navy">Importar apoiadores via CSV</h1>
|
||||
<p class="text-xs text-gray-500">
|
||||
Importe uma planilha para adicionar apoiadores em lote
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button class="relative text-gray-500 hover:text-navy p-2 rounded-lg hover:bg-gray-100">
|
||||
<i class="fa-solid fa-bell text-lg"></i>
|
||||
<span
|
||||
class="absolute top-1.5 right-1.5 w-2 h-2 bg-primary rounded-full border border-white"
|
||||
></span>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<div class="px-8 py-6 max-w-5xl">
|
||||
<!-- Step indicator -->
|
||||
<div id="step-indicator" class="flex items-center gap-0 mb-8">
|
||||
<!-- Step 1 — completed -->
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-8 h-8 rounded-full bg-green-600 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-check text-white text-xs"></i>
|
||||
</div>
|
||||
<span class="text-sm font-semibold text-green-700">Upload do arquivo</span>
|
||||
</div>
|
||||
<div class="flex-1 h-0.5 bg-primary mx-3"></div>
|
||||
<!-- Step 2 — active -->
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-8 h-8 rounded-full bg-primary flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<span class="text-white text-xs font-bold">2</span>
|
||||
</div>
|
||||
<span class="text-sm font-bold text-primary">Conferir prévia</span>
|
||||
</div>
|
||||
<div class="flex-1 h-0.5 bg-gray-200 mx-3"></div>
|
||||
<!-- Step 3 — pending -->
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<span class="text-gray-500 text-xs font-bold">3</span>
|
||||
</div>
|
||||
<span class="text-sm text-gray-400">Confirmação</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── STEP 1: Upload (shown as completed, for reference) ──────── -->
|
||||
<!-- (would be the drag-drop zone — already past) -->
|
||||
|
||||
<!-- ── STEP 2: Preview table ──────────────────────────────────── -->
|
||||
<section id="preview-section" class="space-y-4">
|
||||
<!-- Summary chips -->
|
||||
<div class="flex flex-wrap gap-3 items-center">
|
||||
<div
|
||||
class="flex items-center gap-2 bg-green-50 border border-green-200 text-green-700 text-sm font-semibold px-4 py-2 rounded-xl"
|
||||
>
|
||||
<i class="fa-solid fa-check-circle text-green-600"></i>
|
||||
<span><strong>412</strong> prontos para importar</span>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center gap-2 bg-amber-50 border border-amber-200 text-amber-700 text-sm font-semibold px-4 py-2 rounded-xl"
|
||||
>
|
||||
<i class="fa-solid fa-copy text-amber-600"></i>
|
||||
<span><strong>37</strong> duplicados (pelo telefone)</span>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center gap-2 bg-red-50 border border-red-200 text-red-700 text-sm font-semibold px-4 py-2 rounded-xl"
|
||||
>
|
||||
<i class="fa-solid fa-circle-xmark text-red-600"></i>
|
||||
<span><strong>3</strong> erros</span>
|
||||
</div>
|
||||
<button
|
||||
class="ml-auto text-xs text-primary font-semibold hover:underline flex items-center gap-1"
|
||||
>
|
||||
<i class="fa-solid fa-download"></i> Baixar relatório de erros
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Preview table -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden">
|
||||
<div class="px-5 py-3 border-b border-gray-100 flex items-center justify-between">
|
||||
<p class="text-sm font-semibold text-navy">Prévia — 452 linhas no arquivo</p>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
class="text-xs border border-gray-200 rounded-lg px-3 py-1.5 text-gray-600 hover:border-primary hover:text-primary"
|
||||
>
|
||||
Todos
|
||||
</button>
|
||||
<button
|
||||
class="text-xs border border-gray-200 rounded-lg px-3 py-1.5 text-gray-600 hover:border-primary hover:text-primary bg-red-50 border-red-200 text-red-700"
|
||||
>
|
||||
Só erros
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="bg-gray-50 border-b border-gray-200">
|
||||
<th
|
||||
class="text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wide w-8"
|
||||
>
|
||||
#
|
||||
</th>
|
||||
<th
|
||||
class="text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wide"
|
||||
>
|
||||
Nome
|
||||
</th>
|
||||
<th
|
||||
class="text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wide"
|
||||
>
|
||||
Telefone
|
||||
</th>
|
||||
<th
|
||||
class="text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wide"
|
||||
>
|
||||
Município
|
||||
</th>
|
||||
<th
|
||||
class="text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wide"
|
||||
>
|
||||
Intenção
|
||||
</th>
|
||||
<th
|
||||
class="text-left px-4 py-3 text-xs font-semibold text-gray-500 uppercase tracking-wide"
|
||||
>
|
||||
Status
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
<!-- Row OK -->
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-4 py-3 text-xs text-gray-400">1</td>
|
||||
<td class="px-4 py-3 font-medium text-navy">Maria das Dores Souza</td>
|
||||
<td class="px-4 py-3 text-gray-700">(77) 9 9000-1111</td>
|
||||
<td class="px-4 py-3 text-gray-700">Bom Jesus da Lapa</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Certo</span
|
||||
>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-green-100 text-green-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-check text-xs"></i> ok
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Row OK -->
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-4 py-3 text-xs text-gray-400">2</td>
|
||||
<td class="px-4 py-3 font-medium text-navy">Antônio Carlos Leal</td>
|
||||
<td class="px-4 py-3 text-gray-700">(77) 9 9111-2222</td>
|
||||
<td class="px-4 py-3 text-gray-700">Brumado</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Tende a certo</span
|
||||
>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-green-100 text-green-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-check text-xs"></i> ok
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Row DUPLICADO -->
|
||||
<tr class="hover:bg-amber-50 bg-amber-50/50">
|
||||
<td class="px-4 py-3 text-xs text-gray-400">3</td>
|
||||
<td class="px-4 py-3 font-medium text-navy">Joelma Pereira</td>
|
||||
<td class="px-4 py-3 text-gray-700">(75) 9 8200-3333</td>
|
||||
<td class="px-4 py-3 text-gray-700">Feira de Santana</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="bg-amber-100 text-amber-800 text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Indeciso</span
|
||||
>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-amber-100 text-amber-700 text-xs font-semibold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-copy text-xs"></i> duplicado pelo telefone
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Row ERRO -->
|
||||
<tr class="hover:bg-red-50 bg-red-50/40">
|
||||
<td class="px-4 py-3 text-xs text-gray-400">4</td>
|
||||
<td class="px-4 py-3 font-medium text-navy">Roberto Bispo</td>
|
||||
<td class="px-4 py-3 text-red-600 font-semibold">—</td>
|
||||
<td class="px-4 py-3 text-gray-700">Vitória da Conquista</td>
|
||||
<td class="px-4 py-3"><span class="text-xs text-gray-400 italic">—</span></td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-red-100 text-red-700 text-xs font-semibold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-xmark text-xs"></i> telefone inválido
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Row OK -->
|
||||
<tr class="hover:bg-gray-50">
|
||||
<td class="px-4 py-3 text-xs text-gray-400">5</td>
|
||||
<td class="px-4 py-3 font-medium text-navy">Simone Oliveira</td>
|
||||
<td class="px-4 py-3 text-gray-700">(77) 9 9444-5555</td>
|
||||
<td class="px-4 py-3 text-gray-700">Caetité</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Certo</span
|
||||
>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-green-100 text-green-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-check text-xs"></i> ok
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Row ERRO -->
|
||||
<tr class="hover:bg-red-50 bg-red-50/40">
|
||||
<td class="px-4 py-3 text-xs text-gray-400">6</td>
|
||||
<td class="px-4 py-3 font-medium text-navy">Fernanda Costa</td>
|
||||
<td class="px-4 py-3 text-gray-700">(71) 9 7777-8888</td>
|
||||
<td class="px-4 py-3 text-red-600 font-semibold">Municipio Invalido</td>
|
||||
<td class="px-4 py-3"><span class="text-xs text-gray-400 italic">—</span></td>
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-red-100 text-red-700 text-xs font-semibold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-xmark text-xs"></i> município não reconhecido
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="px-5 py-3 border-t border-gray-100 bg-gray-50 text-xs text-gray-500">
|
||||
Mostrando 6 de 452 linhas ·
|
||||
<span class="text-primary font-semibold cursor-pointer">Ver todas</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action row -->
|
||||
<div class="flex items-center justify-between pt-2">
|
||||
<button
|
||||
class="flex items-center gap-2 text-sm text-gray-600 border border-gray-200 rounded-xl px-4 py-2.5 hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-arrow-left text-xs"></i> Voltar e substituir arquivo
|
||||
</button>
|
||||
<div class="flex items-center gap-3">
|
||||
<p class="text-xs text-gray-500">
|
||||
Serão importados <strong class="text-navy">412 apoiadores</strong> · 37 duplicados
|
||||
ignorados · 3 erros pulados
|
||||
</p>
|
||||
<button
|
||||
class="bg-primary text-white text-sm font-bold px-6 py-2.5 rounded-xl hover:bg-primary-light transition-colors flex items-center gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-file-import"></i> Confirmar importação
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── STEP 3: Confirmation summary (success state shown below — would appear after confirm) ── -->
|
||||
<div
|
||||
id="confirmation-summary"
|
||||
class="bg-green-50 border border-green-200 rounded-xl p-6 text-center mt-4"
|
||||
>
|
||||
<div
|
||||
class="w-14 h-14 rounded-full bg-green-100 flex items-center justify-center mx-auto mb-3"
|
||||
>
|
||||
<i class="fa-solid fa-check-circle text-green-600 text-2xl"></i>
|
||||
</div>
|
||||
<h3 class="text-base font-bold text-green-800 mb-1">Importação concluída!</h3>
|
||||
<p class="text-sm text-green-700 mb-4">
|
||||
<strong>412 importados</strong> · <strong>37 duplicados ignorados</strong> ·
|
||||
<strong>3 erros</strong>
|
||||
</p>
|
||||
<div class="flex items-center justify-center gap-3">
|
||||
<button
|
||||
class="text-sm text-gray-600 border border-gray-200 rounded-xl px-4 py-2 hover:bg-gray-50"
|
||||
>
|
||||
Baixar relatório
|
||||
</button>
|
||||
<button
|
||||
class="bg-primary text-white text-sm font-bold px-5 py-2 rounded-xl hover:bg-primary-light"
|
||||
>
|
||||
Ver apoiadores
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Importar-CSV-Apoiadores.png
Normal file
|
After Width: | Height: | Size: 280 KiB |
450
docs/design-refs/latest/Lista-Nucleos-Overview.html
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Núcleos – Visão Geral</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-24">
|
||||
<!-- Header -->
|
||||
<header
|
||||
id="header"
|
||||
class="bg-navy sticky top-0 z-20 px-4 py-3 flex items-center justify-between"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-7 h-7 rounded-full bg-primary flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-star text-white text-xs"></i>
|
||||
</div>
|
||||
<h1 class="text-white font-bold text-sm">Núcleos Eleitorais</h1>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="relative text-white/70 p-1.5">
|
||||
<i class="fa-solid fa-bell text-base"></i>
|
||||
<span
|
||||
class="absolute top-1 right-1 w-2 h-2 bg-primary rounded-full border border-navy"
|
||||
></span>
|
||||
</button>
|
||||
<button
|
||||
class="bg-primary text-white text-xs font-semibold px-3 py-1.5 rounded-lg flex items-center gap-1.5"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xs"></i> Novo
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral · vê todos os
|
||||
núcleos
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Search + Filter -->
|
||||
<div class="px-4 pt-2 pb-3 space-y-2">
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Buscar núcleo ou zona…"
|
||||
class="w-full pl-9 pr-4 py-2.5 text-sm border border-gray-200 rounded-xl bg-white focus:outline-none focus:ring-2 focus:ring-primary/20 text-navy placeholder-gray-300"
|
||||
/>
|
||||
<i
|
||||
class="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"
|
||||
></i>
|
||||
</div>
|
||||
<!-- Active filter chips -->
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-navy text-white text-xs font-semibold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
Velho Chico
|
||||
<button class="ml-0.5 opacity-70"><i class="fa-solid fa-xmark text-xs"></i></button>
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-navy text-white text-xs font-semibold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
ZE 12 <button class="ml-0.5 opacity-70"><i class="fa-solid fa-xmark text-xs"></i></button>
|
||||
</span>
|
||||
<button class="text-xs text-primary font-semibold">+ Filtros</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ════════════════════════════════ -->
|
||||
<!-- OVERVIEW PANEL -->
|
||||
<!-- ════════════════════════════════ -->
|
||||
<section id="overview-panel" class="px-4 space-y-3 mb-4">
|
||||
<!-- Caption -->
|
||||
<p class="text-xs text-gray-500 flex items-center gap-1.5">
|
||||
<i class="fa-solid fa-filter text-gray-400 text-xs"></i>
|
||||
Mostrando agregados de <strong class="text-navy mx-0.5">14 núcleos</strong> filtrados
|
||||
</p>
|
||||
|
||||
<!-- Estimativa de votos -->
|
||||
<div id="card-estimativa" class="bg-white border border-gray-200 rounded-xl shadow-sm p-4">
|
||||
<div class="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide mb-1">
|
||||
Estimativa de votos
|
||||
</p>
|
||||
<div class="flex items-baseline gap-2">
|
||||
<span class="text-3xl font-extrabold text-navy leading-none">18.740</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-0.5">votos estimados nos 14 núcleos</p>
|
||||
</div>
|
||||
<div
|
||||
class="w-9 h-9 rounded-xl bg-primary-xlight flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-ballot-check text-primary"></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Progress -->
|
||||
<div class="mb-3">
|
||||
<div class="flex items-center justify-between text-xs mb-1">
|
||||
<span class="text-gray-600">Com estimativa confirmada</span>
|
||||
<span class="font-bold text-green-700">71%</span>
|
||||
</div>
|
||||
<div class="h-2 bg-gray-100 rounded-full overflow-hidden">
|
||||
<div class="h-full bg-green-500 rounded-full" style="width: 71%"></div>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-1">10 confirmadas · 4 pendentes</p>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-700 text-xs font-semibold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-clock text-xs"></i> 3 sugestões pendentes
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Cobertura + Baseline 2022 (two-col) -->
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<!-- Cobertura -->
|
||||
<div id="card-cobertura" class="bg-white border border-gray-200 rounded-xl shadow-sm p-3.5">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide">Cobertura</p>
|
||||
<i class="fa-solid fa-user-shield text-blue-500 text-sm"></i>
|
||||
</div>
|
||||
<p class="text-2xl font-extrabold text-navy leading-none mb-1">86%</p>
|
||||
<div class="h-1.5 bg-gray-100 rounded-full overflow-hidden mb-1.5">
|
||||
<div class="h-full bg-blue-500 rounded-full" style="width: 86%"></div>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400">12 de 14 com coordenador</p>
|
||||
</div>
|
||||
<!-- Baseline 2022 -->
|
||||
<div id="card-baseline" class="bg-white border border-gray-200 rounded-xl shadow-sm p-3.5">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide">Baseline 2022</p>
|
||||
<i class="fa-solid fa-chart-line text-primary text-sm"></i>
|
||||
</div>
|
||||
<p class="text-xl font-extrabold text-navy leading-none mb-1">+2.140</p>
|
||||
<p class="text-xs text-gray-400 mb-2">votos acima do patamar</p>
|
||||
<div class="flex flex-col gap-1 text-xs">
|
||||
<span class="text-green-700 font-semibold flex items-center gap-1"
|
||||
><i class="fa-solid fa-arrow-up text-xs"></i> 8 acima</span
|
||||
>
|
||||
<span class="text-amber-600 font-semibold flex items-center gap-1"
|
||||
><i class="fa-solid fa-arrow-down text-xs"></i> 6 abaixo</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Últimas atualizações -->
|
||||
<div id="card-updates" class="bg-white border border-gray-200 rounded-xl shadow-sm p-4">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide">
|
||||
Últimas atualizações
|
||||
</p>
|
||||
<a href="#" class="text-xs text-primary font-semibold">Ver todas</a>
|
||||
</div>
|
||||
<div class="space-y-3">
|
||||
<!-- Row 1 -->
|
||||
<div class="flex items-start gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-3.jpg"
|
||||
class="w-8 h-8 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-0.5">
|
||||
<span
|
||||
class="bg-primary-xlight text-primary text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Semanal</span
|
||||
>
|
||||
<span class="text-xs text-gray-400">há 1 dia</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-700">
|
||||
João S. · <span class="text-primary font-medium">Quilombo Rio das Rãs</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Row 2 -->
|
||||
<div class="flex items-start gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-5.jpg"
|
||||
class="w-8 h-8 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-0.5">
|
||||
<span class="bg-amber-50 text-amber-700 text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Urgente</span
|
||||
>
|
||||
<span class="text-xs text-gray-400">há 2 dias</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-700">
|
||||
Maria L. · <span class="text-primary font-medium">Sindicato Rural Oeste</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Row 3 -->
|
||||
<div class="flex items-start gap-3">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-4.jpg"
|
||||
class="w-8 h-8 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-0.5">
|
||||
<span class="bg-gray-100 text-gray-600 text-xs font-bold px-2 py-0.5 rounded-full"
|
||||
>Nota</span
|
||||
>
|
||||
<span class="text-xs text-gray-400">há 3 dias</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-700">
|
||||
Pedro A. · <span class="text-primary font-medium">Igreja Batista Central</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- end overview panel -->
|
||||
|
||||
<!-- List header -->
|
||||
<div class="px-4 mb-2">
|
||||
<p class="text-xs text-gray-500 font-semibold uppercase tracking-wide">
|
||||
14 núcleos filtrados
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Nuclei list -->
|
||||
<section id="nucleos-list" class="px-4 space-y-2">
|
||||
<!-- Item 1 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Quilombo Rio das Rãs</p>
|
||||
<p class="text-xs text-gray-500">
|
||||
Bom Jesus da Lapa ·
|
||||
<span
|
||||
class="font-mono font-semibold bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded text-xs"
|
||||
>ZE 12</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<span class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full ml-2"
|
||||
>Confirmada</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-4 text-xs text-gray-600">
|
||||
<span><i class="fa-solid fa-users text-gray-400 mr-1"></i>12 lideranças</span>
|
||||
<span><i class="fa-solid fa-ballot-check text-gray-400 mr-1"></i>1.200 votos</span>
|
||||
<span class="text-green-700 font-semibold ml-auto"
|
||||
><i class="fa-solid fa-arrow-up text-xs mr-0.5"></i>+12%</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 2 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Sindicato Rural Oeste</p>
|
||||
<p class="text-xs text-gray-500">
|
||||
Brumado ·
|
||||
<span
|
||||
class="font-mono font-semibold bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded text-xs"
|
||||
>ZE 5</span
|
||||
>
|
||||
<span
|
||||
class="font-mono font-semibold bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded text-xs"
|
||||
>ZE 7</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="bg-amber-100 text-amber-800 text-xs font-bold px-2 py-0.5 rounded-full ml-2 whitespace-nowrap"
|
||||
>Sugestão pend.</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-4 text-xs text-gray-600">
|
||||
<span><i class="fa-solid fa-users text-gray-400 mr-1"></i>16 lideranças</span>
|
||||
<span><i class="fa-solid fa-ballot-check text-gray-400 mr-1"></i>3.400 votos</span>
|
||||
<span class="text-amber-600 font-semibold ml-auto"
|
||||
><i class="fa-solid fa-arrow-down text-xs mr-0.5"></i>−8%</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 3 -->
|
||||
<div
|
||||
class="bg-white border border-amber-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Assentamento Vitória</p>
|
||||
<p class="text-xs text-gray-500">
|
||||
Feira de Santana ·
|
||||
<span
|
||||
class="font-mono font-semibold bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded text-xs"
|
||||
>ZE 5</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<span class="bg-green-100 text-green-800 text-xs font-bold px-2 py-0.5 rounded-full ml-2"
|
||||
>Confirmada</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-4 text-xs text-gray-600">
|
||||
<span><i class="fa-solid fa-users text-gray-400 mr-1"></i>7 lideranças</span>
|
||||
<span><i class="fa-solid fa-ballot-check text-gray-400 mr-1"></i>900 votos</span>
|
||||
<span class="text-amber-600 font-semibold ml-auto flex items-center gap-1"
|
||||
><i class="fa-solid fa-triangle-exclamation text-xs"></i>Sem coord.</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 4 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Igreja Batista Central</p>
|
||||
<p class="text-xs text-gray-500">
|
||||
Vitória da Conquista ·
|
||||
<span
|
||||
class="font-mono font-semibold bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded text-xs"
|
||||
>ZE 8</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="bg-amber-100 text-amber-800 text-xs font-bold px-2 py-0.5 rounded-full ml-2 whitespace-nowrap"
|
||||
>Sugestão pend.</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-4 text-xs text-gray-600">
|
||||
<span><i class="fa-solid fa-users text-gray-400 mr-1"></i>11 lideranças</span>
|
||||
<span><i class="fa-solid fa-ballot-check text-gray-400 mr-1"></i>650 votos</span>
|
||||
<span class="text-amber-600 font-semibold ml-auto"
|
||||
><i class="fa-solid fa-arrow-down text-xs mr-0.5"></i>−5%</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item 5 -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 cursor-pointer active:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-bold text-navy text-sm">Quilombo Palmares II</p>
|
||||
<p class="text-xs text-gray-500">
|
||||
Caetité · <span class="text-gray-400 italic text-xs">sem ZE</span>
|
||||
</p>
|
||||
</div>
|
||||
<span class="bg-gray-100 text-gray-600 text-xs font-bold px-2 py-0.5 rounded-full ml-2"
|
||||
>Sem estimativa</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-4 text-xs text-gray-600">
|
||||
<span><i class="fa-solid fa-users text-gray-400 mr-1"></i>4 lideranças</span>
|
||||
<span><i class="fa-solid fa-ballot-check text-gray-400 mr-1"></i>—</span>
|
||||
<span class="text-amber-600 font-semibold ml-auto flex items-center gap-1"
|
||||
><i class="fa-solid fa-triangle-exclamation text-xs"></i>Sem coord.</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center text-xs text-gray-400 py-3">
|
||||
Mostrando 5 de 14 · <span class="text-primary font-semibold">Ver mais</span>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- FAB -->
|
||||
<div class="fixed bottom-20 right-4 z-30">
|
||||
<button
|
||||
class="bg-primary text-white w-14 h-14 rounded-full shadow-xl flex items-center justify-center"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Bottom nav -->
|
||||
<nav
|
||||
id="bottom-nav"
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 flex z-20"
|
||||
>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-house text-base"></i>
|
||||
<span class="text-xs mt-0.5">Início</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-primary">
|
||||
<i class="fa-solid fa-layer-group text-base"></i>
|
||||
<span class="text-xs mt-0.5 font-semibold">Núcleos</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-user-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Apoiadores</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-calendar-days text-base"></i>
|
||||
<span class="text-xs mt-0.5">Agenda</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-users text-base"></i>
|
||||
<span class="text-xs mt-0.5">Lideranças</span>
|
||||
</a>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Lista-Nucleos-Overview.png
Normal file
|
After Width: | Height: | Size: 184 KiB |
264
docs/design-refs/latest/Notificacoes-PWA.html
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Notificações</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-24" style="min-height: 840px; position: relative">
|
||||
<!-- Background: Inicio Coordenador blurred behind sheet -->
|
||||
<!-- Main screen content (dimmed) -->
|
||||
<div class="opacity-30 pointer-events-none">
|
||||
<header class="bg-navy px-4 py-3 flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div
|
||||
class="w-7 h-7 rounded-full bg-primary flex items-center justify-center flex-shrink-0"
|
||||
>
|
||||
<i class="fa-solid fa-star text-white text-xs"></i>
|
||||
</div>
|
||||
<h1 class="text-white font-bold text-sm">Início</h1>
|
||||
</div>
|
||||
<button class="relative text-white/70 p-1.5">
|
||||
<i class="fa-solid fa-bell text-xl"></i>
|
||||
<span
|
||||
class="absolute top-1 right-1 w-2.5 h-2.5 bg-primary rounded-full border-2 border-navy"
|
||||
></span>
|
||||
</button>
|
||||
</header>
|
||||
<div class="px-4 pt-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral
|
||||
</span>
|
||||
</div>
|
||||
<div class="px-4 pt-4 grid grid-cols-2 gap-3">
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-4 shadow-sm">
|
||||
<p class="text-xs text-gray-500">Núcleos ativos</p>
|
||||
<p class="text-2xl font-extrabold text-navy">47</p>
|
||||
</div>
|
||||
<div class="bg-white border border-gray-200 rounded-xl p-4 shadow-sm">
|
||||
<p class="text-xs text-gray-500">Apoiadores</p>
|
||||
<p class="text-2xl font-extrabold text-navy">1.847</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ════════════════════════════════ -->
|
||||
<!-- NOTIFICATION CENTER SHEET -->
|
||||
<!-- ════════════════════════════════ -->
|
||||
<div class="absolute inset-0 bg-black/40 flex items-end" style="z-index: 50">
|
||||
<div
|
||||
id="notif-sheet"
|
||||
class="w-full bg-white rounded-t-2xl shadow-2xl"
|
||||
style="max-height: 640px; display: flex; flex-direction: column"
|
||||
>
|
||||
<!-- Handle -->
|
||||
<div class="flex justify-center pt-3 pb-0 flex-shrink-0">
|
||||
<div class="w-10 h-1 bg-gray-300 rounded-full"></div>
|
||||
</div>
|
||||
|
||||
<!-- Sheet header -->
|
||||
<div
|
||||
class="px-5 pt-3 pb-3 border-b border-gray-100 flex items-center justify-between flex-shrink-0"
|
||||
>
|
||||
<div>
|
||||
<h2 class="text-base font-bold text-navy">Notificações</h2>
|
||||
<span class="text-xs text-primary font-semibold">4 não lidas</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<button class="text-xs text-primary font-semibold hover:underline">
|
||||
Marcar todas como lidas
|
||||
</button>
|
||||
<button class="text-gray-400 hover:text-navy p-1 rounded-lg">
|
||||
<i class="fa-solid fa-xmark text-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notifications list -->
|
||||
<div class="overflow-y-auto flex-1 divide-y divide-gray-50 px-1">
|
||||
<!-- Unread -->
|
||||
<div
|
||||
class="flex items-start gap-3 px-4 py-4 bg-primary-xlight/40 cursor-pointer active:bg-primary-xlight"
|
||||
>
|
||||
<div
|
||||
class="w-9 h-9 rounded-full bg-amber-100 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
>
|
||||
<i class="fa-solid fa-clock text-amber-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-bold text-navy leading-snug">
|
||||
Estimativa aguardando confirmação — Núcleo Quilombo Rio das Rãs
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 mt-0.5">
|
||||
João Santos sugeriu 1.200 votos · confirme ou ajuste
|
||||
</p>
|
||||
<p class="text-xs text-primary font-semibold mt-1">há 2 horas</p>
|
||||
</div>
|
||||
<div class="w-2 h-2 bg-primary rounded-full flex-shrink-0 mt-2"></div>
|
||||
</div>
|
||||
|
||||
<!-- Unread -->
|
||||
<div
|
||||
class="flex items-start gap-3 px-4 py-4 bg-primary-xlight/40 cursor-pointer active:bg-primary-xlight"
|
||||
>
|
||||
<div
|
||||
class="w-9 h-9 rounded-full bg-green-100 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
>
|
||||
<i class="fa-solid fa-user-plus text-green-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-bold text-navy leading-snug">
|
||||
Novo apoiador cadastrado — Sindicato Rural Oeste
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 mt-0.5">Maria Lima adicionou Antônio Carlos Leal</p>
|
||||
<p class="text-xs text-primary font-semibold mt-1">há 4 horas</p>
|
||||
</div>
|
||||
<div class="w-2 h-2 bg-primary rounded-full flex-shrink-0 mt-2"></div>
|
||||
</div>
|
||||
|
||||
<!-- Unread -->
|
||||
<div
|
||||
class="flex items-start gap-3 px-4 py-4 bg-primary-xlight/40 cursor-pointer active:bg-primary-xlight"
|
||||
>
|
||||
<div
|
||||
class="w-9 h-9 rounded-full bg-blue-100 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
>
|
||||
<i class="fa-solid fa-newspaper text-blue-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-bold text-navy leading-snug">
|
||||
Novo reporte de campo — Igreja Batista Central
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 mt-0.5">
|
||||
Pedro Alves publicou uma atualização urgente
|
||||
</p>
|
||||
<p class="text-xs text-primary font-semibold mt-1">há 1 dia</p>
|
||||
</div>
|
||||
<div class="w-2 h-2 bg-primary rounded-full flex-shrink-0 mt-2"></div>
|
||||
</div>
|
||||
|
||||
<!-- Unread -->
|
||||
<div
|
||||
class="flex items-start gap-3 px-4 py-4 bg-primary-xlight/40 cursor-pointer active:bg-primary-xlight"
|
||||
>
|
||||
<div
|
||||
class="w-9 h-9 rounded-full bg-red-100 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
>
|
||||
<i class="fa-solid fa-calendar-xmark text-red-600 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-bold text-navy leading-snug">
|
||||
Plano de ação precisa de atenção — Comício (Rascunho)
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 mt-0.5">
|
||||
Data ainda não definida · confirme ou cancele
|
||||
</p>
|
||||
<p class="text-xs text-primary font-semibold mt-1">há 2 dias</p>
|
||||
</div>
|
||||
<div class="w-2 h-2 bg-primary rounded-full flex-shrink-0 mt-2"></div>
|
||||
</div>
|
||||
|
||||
<!-- Read -->
|
||||
<div class="flex items-start gap-3 px-4 py-3.5 cursor-pointer active:bg-gray-50">
|
||||
<div
|
||||
class="w-9 h-9 rounded-full bg-gray-100 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
>
|
||||
<i class="fa-solid fa-file-import text-gray-500 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-gray-700 leading-snug">
|
||||
Importação de CSV concluída
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 mt-0.5">
|
||||
412 apoiadores importados · 37 duplicados ignorados
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 mt-1">há 3 dias</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Read -->
|
||||
<div class="flex items-start gap-3 px-4 py-3.5 cursor-pointer active:bg-gray-50">
|
||||
<div
|
||||
class="w-9 h-9 rounded-full bg-gray-100 flex items-center justify-center flex-shrink-0 mt-0.5"
|
||||
>
|
||||
<i class="fa-solid fa-user-shield text-gray-500 text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-gray-700 leading-snug">
|
||||
Bem-vindo ao Solla Campanha!
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 mt-0.5">
|
||||
Seu acesso de Coordenação Geral foi ativado
|
||||
</p>
|
||||
<p class="text-xs text-gray-400 mt-1">há 12 dias</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PWA install prompt inside sheet footer -->
|
||||
<div
|
||||
id="pwa-prompt"
|
||||
class="flex-shrink-0 mx-4 my-3 bg-navy text-white rounded-xl p-3 flex items-center gap-3"
|
||||
>
|
||||
<div class="w-9 h-9 rounded-xl bg-primary flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-mobile-screen text-white text-sm"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-xs font-bold leading-snug">Instale o app da campanha</p>
|
||||
<p class="text-xs text-white/60 mt-0.5">Acesse mais rápido e receba avisos</p>
|
||||
</div>
|
||||
<button class="bg-white text-navy text-xs font-bold px-3 py-1.5 rounded-lg flex-shrink-0">
|
||||
Instalar
|
||||
</button>
|
||||
<button class="text-white/50 p-1 flex-shrink-0">
|
||||
<i class="fa-solid fa-xmark text-xs"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ════════════════════════════════ -->
|
||||
<!-- PUSH OPT-IN SCREEN -->
|
||||
<!-- (shown as a separate card below, for reference) -->
|
||||
<!-- In production this appears on its own route -->
|
||||
<!-- ════════════════════════════════ -->
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Notificacoes-PWA.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
283
docs/design-refs/latest/Novo-Plano-de-Acao.html
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Novo Plano de Ação</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-28">
|
||||
<!-- Header -->
|
||||
<header id="header" class="bg-navy sticky top-0 z-20 px-4 py-3 flex items-center gap-3">
|
||||
<button class="text-white p-1"><i class="fa-solid fa-arrow-left text-lg"></i></button>
|
||||
<div class="flex-1">
|
||||
<h1 class="text-white font-bold text-sm">Novo Plano de Ação</h1>
|
||||
<p class="text-white/60 text-xs">Preencha os dados do evento</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<form class="px-4 pt-4 space-y-4" onsubmit="return false">
|
||||
<!-- Informações básicas -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-4">
|
||||
<h3 class="text-sm font-bold text-navy">Informações básicas</h3>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Título <span class="text-primary">*</span></label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Ex: Caminhada no Centro Histórico"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 focus:border-primary placeholder-gray-300"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Tipo de ação <span class="text-primary">*</span></label
|
||||
>
|
||||
<select
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 bg-white"
|
||||
>
|
||||
<option value="" disabled selected>Selecione o tipo…</option>
|
||||
<option>Caminhada</option>
|
||||
<option>Comício</option>
|
||||
<option>Carreata</option>
|
||||
<option>Panfletagem</option>
|
||||
<option>Porta a porta</option>
|
||||
<option>Reunião de apoio</option>
|
||||
<option>Outro</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Descrição (opcional)</label
|
||||
>
|
||||
<textarea
|
||||
rows="3"
|
||||
placeholder="Contexto, objetivo e observações do plano…"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 focus:border-primary placeholder-gray-300 resize-none"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Data e horário -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-4">
|
||||
<h3 class="text-sm font-bold text-navy">Data e horário</h3>
|
||||
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Data <span class="text-primary">*</span></label
|
||||
>
|
||||
<input
|
||||
type="date"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 bg-white"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Início <span class="text-primary">*</span></label
|
||||
>
|
||||
<input
|
||||
type="time"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Término (opcional)</label
|
||||
>
|
||||
<input
|
||||
type="time"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 bg-white"
|
||||
placeholder="—"
|
||||
/>
|
||||
<p class="text-xs text-gray-400 mt-1">Deixe em branco se a duração for indefinida</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Território (multi-município — same pattern as Territory Form) -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-4">
|
||||
<h3 class="text-sm font-bold text-navy flex items-center gap-2">
|
||||
<i class="fa-solid fa-map-location-dot text-primary text-sm"></i> Território
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Municípios <span class="text-primary">*</span></label
|
||||
>
|
||||
<div class="flex flex-wrap gap-2 mb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-navy text-white text-xs font-semibold px-3 py-1.5 rounded-full"
|
||||
>
|
||||
Bom Jesus da Lapa
|
||||
<button type="button" class="ml-0.5 opacity-70">
|
||||
<i class="fa-solid fa-xmark text-xs"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Buscar município…"
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 focus:border-primary pr-10"
|
||||
/>
|
||||
<i
|
||||
class="fa-solid fa-chevron-down absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs pointer-events-none"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5">
|
||||
Território de identidade
|
||||
<span class="normal-case font-normal text-gray-400 ml-1">(automático)</span>
|
||||
</label>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-800 text-xs font-semibold px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-lock text-amber-400 text-xs"></i> Velho Chico
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pessoas responsáveis -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4 space-y-4">
|
||||
<h3 class="text-sm font-bold text-navy">Pessoas responsáveis</h3>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Coordenadores</label
|
||||
>
|
||||
<!-- Selected person -->
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<img
|
||||
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-3.jpg"
|
||||
class="w-8 h-8 rounded-full object-cover flex-shrink-0"
|
||||
/>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-semibold text-navy truncate">João Santos</p>
|
||||
<p class="text-xs text-gray-500">Coord. Núcleo · Bom Jesus da Lapa</p>
|
||||
</div>
|
||||
<button type="button" class="text-gray-400 hover:text-red-600 p-1.5">
|
||||
<i class="fa-solid fa-xmark text-sm"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center gap-2 text-primary text-xs font-semibold border border-dashed border-primary/40 rounded-xl px-3 py-2 w-full justify-center hover:bg-primary-xlight transition-colors"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xs"></i> Adicionar coordenador
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-gray-100 pt-4">
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-1.5"
|
||||
>Responsável principal <span class="text-primary">*</span></label
|
||||
>
|
||||
<select
|
||||
class="w-full border border-gray-200 rounded-xl px-3 py-3 text-sm text-navy focus:outline-none focus:ring-2 focus:ring-primary/25 bg-white"
|
||||
>
|
||||
<option>João Santos</option>
|
||||
<option>Maria Lima</option>
|
||||
<option>Pedro Alves</option>
|
||||
<option>Carlos Mendes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status inicial -->
|
||||
<div class="bg-white border border-gray-200 rounded-xl shadow-sm p-4">
|
||||
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wide mb-3"
|
||||
>Status inicial</label
|
||||
>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<label
|
||||
class="flex items-center gap-2.5 p-3 border-2 border-primary rounded-xl cursor-pointer bg-primary-xlight"
|
||||
>
|
||||
<input type="radio" name="status" value="planejado" checked class="accent-primary" />
|
||||
<div>
|
||||
<p class="text-xs font-bold text-primary">Planejado</p>
|
||||
<p class="text-xs text-gray-500">Em organização</p>
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
class="flex items-center gap-2.5 p-3 border border-gray-200 rounded-xl cursor-pointer hover:border-gray-300"
|
||||
>
|
||||
<input type="radio" name="status" value="rascunho" class="accent-primary" />
|
||||
<div>
|
||||
<p class="text-xs font-bold text-navy">Rascunho</p>
|
||||
<p class="text-xs text-gray-500">Ainda indefinido</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Bottom action bar -->
|
||||
<div
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 px-4 py-4 flex gap-3 z-20"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 border border-gray-200 text-navy text-sm font-semibold py-3 rounded-xl hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 bg-primary text-white text-sm font-bold py-3 rounded-xl hover:bg-primary-light transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<i class="fa-solid fa-calendar-plus text-sm"></i> Criar plano
|
||||
</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Novo-Plano-de-Acao.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
341
docs/design-refs/latest/Planos-de-Acao.html
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
<!doctype html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<script>
|
||||
window.FontAwesomeConfig = {
|
||||
autoReplaceSvg: 'nest',
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
></script>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Planos de Ação</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
|
||||
/>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#8E0E23',
|
||||
'primary-light': '#B01C35',
|
||||
'primary-xlight': '#F9E8EB',
|
||||
gold: '#C8874B',
|
||||
'gold-light': '#FDF3EC',
|
||||
navy: '#1B2B4B',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
}
|
||||
.filter-tab.active {
|
||||
background: #1b2b4b;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 pb-24">
|
||||
<!-- Header -->
|
||||
<header
|
||||
id="header"
|
||||
class="bg-navy sticky top-0 z-20 px-4 py-3 flex items-center justify-between"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-7 h-7 rounded-full bg-primary flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-star text-white text-xs"></i>
|
||||
</div>
|
||||
<h1 class="text-white font-bold text-sm">Planos de Ação</h1>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="relative text-white/70 p-1.5">
|
||||
<i class="fa-solid fa-bell text-base"></i>
|
||||
<span
|
||||
class="absolute top-1 right-1 w-2 h-2 bg-primary rounded-full border border-navy"
|
||||
></span>
|
||||
</button>
|
||||
<button
|
||||
class="bg-primary text-white text-xs font-semibold px-3 py-1.5 rounded-lg flex items-center gap-1.5"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xs"></i> Novo
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Scope badge -->
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gold-light border border-gold/30 text-xs font-semibold text-navy px-3 py-1.5 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-shield-halved text-gold text-xs"></i> Coordenação Geral
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Filter tabs -->
|
||||
<div class="px-4 pt-3 pb-2 flex gap-2 overflow-x-auto">
|
||||
<button
|
||||
class="filter-tab active flex-shrink-0 text-xs font-semibold px-3 py-1.5 rounded-full border border-navy transition-colors"
|
||||
>
|
||||
Próximos
|
||||
</button>
|
||||
<button
|
||||
class="filter-tab flex-shrink-0 text-xs font-semibold px-3 py-1.5 rounded-full border border-gray-200 text-gray-600 hover:border-navy transition-colors"
|
||||
>
|
||||
Todos
|
||||
</button>
|
||||
<button
|
||||
class="filter-tab flex-shrink-0 text-xs font-semibold px-3 py-1.5 rounded-full border border-gray-200 text-gray-600 hover:border-navy transition-colors"
|
||||
>
|
||||
Realizados
|
||||
</button>
|
||||
<button
|
||||
class="filter-tab flex-shrink-0 text-xs font-semibold px-3 py-1.5 rounded-full border border-gray-200 text-gray-600 hover:border-navy transition-colors"
|
||||
>
|
||||
Rascunhos
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Additional filters -->
|
||||
<div class="px-4 pb-3">
|
||||
<div class="flex gap-2 overflow-x-auto">
|
||||
<select
|
||||
class="flex-shrink-0 text-xs border border-gray-200 rounded-lg px-3 py-2 text-navy bg-white focus:outline-none"
|
||||
>
|
||||
<option>Tipo de ação</option>
|
||||
<option>Caminhada</option>
|
||||
<option>Comício</option>
|
||||
<option>Carreata</option>
|
||||
<option>Panfletagem</option>
|
||||
<option>Porta a porta</option>
|
||||
<option>Reunião de apoio</option>
|
||||
</select>
|
||||
<select
|
||||
class="flex-shrink-0 text-xs border border-gray-200 rounded-lg px-3 py-2 text-navy bg-white focus:outline-none"
|
||||
>
|
||||
<option>Território</option>
|
||||
<option>Velho Chico</option>
|
||||
<option>Sertão do São Francisco</option>
|
||||
</select>
|
||||
<select
|
||||
class="flex-shrink-0 text-xs border border-gray-200 rounded-lg px-3 py-2 text-navy bg-white focus:outline-none"
|
||||
>
|
||||
<option>Status</option>
|
||||
<option>Planejado</option>
|
||||
<option>Confirmado</option>
|
||||
<option>Realizado</option>
|
||||
<option>Cancelado</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Events list -->
|
||||
<section id="events-list" class="px-4 space-y-3">
|
||||
<!-- Event 1: Caminhada — Confirmado -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<!-- Kind + date bar -->
|
||||
<div class="flex items-center justify-between px-4 pt-3 pb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-blue-50 border border-blue-200 text-blue-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-person-walking text-xs"></i> Caminhada
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-green-100 text-green-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-circle-check text-xs"></i> Confirmado
|
||||
</span>
|
||||
</div>
|
||||
<div class="px-4 pb-3">
|
||||
<h3 class="font-bold text-navy text-sm mb-1">Caminhada no Centro Histórico</h3>
|
||||
<div class="flex items-center gap-3 text-xs text-gray-500 mb-2">
|
||||
<span><i class="fa-solid fa-calendar text-gray-400 mr-1"></i>Dom, 3 ago · 08h00</span>
|
||||
<span
|
||||
><i class="fa-solid fa-location-dot text-gray-400 mr-1"></i>Bom Jesus da Lapa</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-800 text-xs font-semibold px-2 py-0.5 rounded-full"
|
||||
>Velho Chico</span
|
||||
>
|
||||
<span class="text-xs text-gray-500">· Resp: João Santos</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 2: Reunião de apoio — Planejado -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center justify-between px-4 pt-3 pb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-purple-50 border border-purple-200 text-purple-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-handshake text-xs"></i> Reunião de apoio
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-blue-100 text-blue-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-clock text-xs"></i> Planejado
|
||||
</span>
|
||||
</div>
|
||||
<div class="px-4 pb-3">
|
||||
<h3 class="font-bold text-navy text-sm mb-1">Reunião com lideranças quilombolas</h3>
|
||||
<div class="flex items-center gap-3 text-xs text-gray-500 mb-2">
|
||||
<span><i class="fa-solid fa-calendar text-gray-400 mr-1"></i>Ter, 5 ago · 18h30</span>
|
||||
<span><i class="fa-solid fa-location-dot text-gray-400 mr-1"></i>Brumado</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-800 text-xs font-semibold px-2 py-0.5 rounded-full"
|
||||
>Sertão do São Francisco</span
|
||||
>
|
||||
<span class="text-xs text-gray-500">· Resp: Maria Lima</span>
|
||||
</div>
|
||||
<!-- Tarefas progress -->
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<div class="flex-1 h-1.5 bg-gray-100 rounded-full overflow-hidden">
|
||||
<div class="h-full bg-primary rounded-full" style="width: 40%"></div>
|
||||
</div>
|
||||
<span class="text-xs text-gray-500">2/5 tarefas</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 3: Porta a porta — Confirmado -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden cursor-pointer active:bg-gray-50"
|
||||
>
|
||||
<div class="flex items-center justify-between px-4 pt-3 pb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-amber-50 border border-amber-200 text-amber-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-door-open text-xs"></i> Porta a porta
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-green-100 text-green-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-circle-check text-xs"></i> Confirmado
|
||||
</span>
|
||||
</div>
|
||||
<div class="px-4 pb-3">
|
||||
<h3 class="font-bold text-navy text-sm mb-1">Porta a porta Bairro Novo</h3>
|
||||
<div class="flex items-center gap-3 text-xs text-gray-500 mb-2">
|
||||
<span><i class="fa-solid fa-calendar text-gray-400 mr-1"></i>Sáb, 9 ago · 09h00</span>
|
||||
<span><i class="fa-solid fa-location-dot text-gray-400 mr-1"></i>Feira de Santana</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1 bg-amber-50 border border-amber-200 text-amber-800 text-xs font-semibold px-2 py-0.5 rounded-full"
|
||||
>Bacia do Jacuípe</span
|
||||
>
|
||||
<span class="text-xs text-gray-500">· Resp: Pedro Alves</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 4: Comício — Rascunho -->
|
||||
<div
|
||||
class="bg-white border border-dashed border-gray-300 rounded-xl shadow-sm overflow-hidden cursor-pointer active:bg-gray-50 opacity-75"
|
||||
>
|
||||
<div class="flex items-center justify-between px-4 pt-3 pb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-red-50 border border-red-200 text-red-700 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-microphone text-xs"></i> Comício
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gray-100 text-gray-500 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-pencil text-xs"></i> Rascunho
|
||||
</span>
|
||||
</div>
|
||||
<div class="px-4 pb-3">
|
||||
<h3 class="font-bold text-navy text-sm mb-1">Comício de encerramento (planejado)</h3>
|
||||
<div class="flex items-center gap-3 text-xs text-gray-400 mb-2">
|
||||
<span><i class="fa-solid fa-calendar text-gray-300 mr-1"></i>Data a definir</span>
|
||||
<span
|
||||
><i class="fa-solid fa-location-dot text-gray-300 mr-1"></i>Vitória da Conquista</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event 5: Panfletagem — Realizado -->
|
||||
<div
|
||||
class="bg-white border border-gray-200 rounded-xl shadow-sm overflow-hidden cursor-pointer active:bg-gray-50 opacity-70"
|
||||
>
|
||||
<div class="flex items-center justify-between px-4 pt-3 pb-2">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gray-100 border border-gray-200 text-gray-600 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-file-alt text-xs"></i> Panfletagem
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 bg-gray-100 text-gray-500 text-xs font-bold px-2.5 py-1 rounded-full"
|
||||
>
|
||||
<i class="fa-solid fa-flag-checkered text-xs"></i> Realizado
|
||||
</span>
|
||||
</div>
|
||||
<div class="px-4 pb-3">
|
||||
<h3 class="font-bold text-gray-600 text-sm mb-1">Panfletagem no mercado municipal</h3>
|
||||
<div class="flex items-center gap-3 text-xs text-gray-400">
|
||||
<span><i class="fa-solid fa-calendar text-gray-300 mr-1"></i>20 jul · Salvador</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-center text-xs text-gray-400 py-3">
|
||||
5 de 23 planos · <span class="text-primary font-semibold">Ver mais</span>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- FAB -->
|
||||
<div class="fixed bottom-20 right-4 z-30">
|
||||
<button
|
||||
class="bg-primary text-white w-14 h-14 rounded-full shadow-xl flex items-center justify-center"
|
||||
>
|
||||
<i class="fa-solid fa-plus text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Bottom nav -->
|
||||
<nav
|
||||
id="bottom-nav"
|
||||
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 flex z-20"
|
||||
>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-house text-base"></i>
|
||||
<span class="text-xs mt-0.5">Início</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-layer-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Núcleos</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-user-group text-base"></i>
|
||||
<span class="text-xs mt-0.5">Apoiadores</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-primary">
|
||||
<i class="fa-solid fa-calendar-days text-base"></i>
|
||||
<span class="text-xs mt-0.5 font-semibold">Agenda</span>
|
||||
</a>
|
||||
<a href="#" class="flex-1 flex flex-col items-center py-3 text-gray-400">
|
||||
<i class="fa-solid fa-users text-base"></i>
|
||||
<span class="text-xs mt-0.5">Lideranças</span>
|
||||
</a>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
BIN
docs/design-refs/latest/Planos-de-Acao.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
|
|
@ -5,6 +5,19 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Baseline-Eleitoral-2022.png`](../design-refs/latest/Baseline-Eleitoral-2022.png) · [`Baseline-Eleitoral-2022.html`](../design-refs/latest/Baseline-Eleitoral-2022.html) — a tela também contém o card "Insights do território", que pertence aos planos de insight separados (ver abaixo).
|
||||
|
||||

|
||||
|
||||
Como usar:
|
||||
|
||||
- **Adotar a estrutura (Fases 2 e 4 deste plano):** bloco "Baseline eleitoral 2022" na aba Visão geral do núcleo com: linha destacada de Solla (votos 2022 + barra), linhas secundárias de Lula (Presidente, 2º turno) e Jerônimo (Governador); sub-bloco "Eleitorado 2022" (válidos, brancos, nulos, abstenções); linha "Mais votado aqui em 2022"; e o alerta âmbar do insight Gap vs 2022 ("Faltam 350 votos para o patamar de 2022" com a conta estimativa vs. resultado). Os quatro estados do gap descritos na Fase 4 seguem esse mesmo formato de alerta (âmbar/verde/informativo).
|
||||
- **Pertence aos planos de insight separados (não implementar junto):** o card "Insights do território" (taxa de conversão, território de defesa, alavancagem da chapa, oportunidade de mobilização, mais votado/ranking) é a referência visual dos cinco planos `insight-*.md` — cada linha do card corresponde a um plano. A arquitetura do componente (`NucleusInsights.tsx`, stack de cards com ícone + veredito de uma linha + número de apoio) deve nascer extensível conforme já previsto.
|
||||
- **Overview da lista:** o bloco compacto "Baseline 2022" da Fase 3 aparece no design [`Lista-Nucleos-Overview.png`](../design-refs/latest/Lista-Nucleos-Overview.png) (gap total + "8 acima · 6 abaixo").
|
||||
- **Ajustar cores:** paleta antiga no HTML/PNG (header vermelho escuro, destaque de Solla em vermelho escuro). Implementar com tokens do tema `campaign`: destaque de Solla pode usar `#C51414` sobre fundo claro; alerta do gap usa o par âmbar (`#FEF3C7`/`#92400E`) ou verde (`#DCFCE7`/`#166534`).
|
||||
|
||||
## Contexto
|
||||
|
||||
Os resultados das eleições passadas são **dados abertos públicos** do TSE (Portal de Dados Abertos, licença Creative Commons Atribuição), disponíveis por **município e zona eleitoral** (e por seção). Hoje o `/campanha` só tem a estimativa manual de votos (sugerir/confirmar); não há referência histórica. A decisão de produto (2026-07-17) é importar os resultados oficiais de 2022 (presidente, governador, dep. federal, dep. estadual) por município+zona e usá-los como **baseline histórico** em três lugares: no detalhe do núcleo, no overview da lista de núcleos (escopado pelos filtros), e em insights automáticos para coordenadores e lideranças.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,27 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos", linha 56)
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Três designs cobrem este plano:
|
||||
|
||||
| Tela | Arquivos |
|
||||
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Lista de apoiadores (`/campanha/apoiadores`) | [`Apoiadores-Lista.png`](../design-refs/latest/Apoiadores-Lista.png) · [`Apoiadores-Lista.html`](../design-refs/latest/Apoiadores-Lista.html) |
|
||||
| Ficha do apoiador | [`Apoiador-Ficha.png`](../design-refs/latest/Apoiador-Ficha.png) · [`Apoiador-Ficha.html`](../design-refs/latest/Apoiador-Ficha.html) |
|
||||
| Import CSV (desktop, wizard 3 passos) | [`Importar-CSV-Apoiadores.png`](../design-refs/latest/Importar-CSV-Apoiadores.png) · [`Importar-CSV-Apoiadores.html`](../design-refs/latest/Importar-CSV-Apoiadores.html) |
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Como usar:
|
||||
|
||||
- **Lista — adotar:** KPIs no topo (total / "Certo + Tende" / "Indecisos"), busca por nome/telefone/município, filtros "Intenção de voto" e "Território", linhas com nome + município + núcleo vinculado (ou "sem núcleo vinculado" — reflete a decisão de núcleo opcional) + badge de intenção + telefone; estado "Sem telefone cadastrado" em itálico; CTAs "Importar CSV" e "+ Novo".
|
||||
- **Ficha — adotar:** é a tela que melhor materializa as decisões LGPD do plano: bloco destacado "Consentimento LGPD" com checkbox nominal, link para a Política de Privacidade e registro "Consentimento registrado em … · Coletor: …" (`consentedAt` + `createdBy`); segmented control de intenção de voto **desabilitado até o consentimento** ("Disponível somente após confirmação do consentimento LGPD" — consentimento destacado, chave `apoiador-intencao-voto`); seção "Kit de compartilhamento" com mensagem pronta, "Enviar no WhatsApp"/"Copiar texto" e a nota "A mensagem é enviada pelo celular de {nome} — não é disparo em massa da campanha" (art. 33 §2º); ação "Remover meus dados" (descadastramento art. 18).
|
||||
- **Import — adotar:** wizard em 3 passos (Upload → Conferir prévia → Confirmação) com chips de contagem ("412 prontos" / "37 duplicados (pelo telefone)" / "3 erros"), tabela de prévia com status por linha (`ok`, `duplicado pelo telefone`, `telefone inválido`, `município não reconhecido`), toggle "Todos | Só erros", "Baixar relatório de erros" e resumo final. Corresponde ao `importSupporters` (dedup por telefone + preview de erros por linha). O sidebar desktop do design mostra a navegação-alvo (Início, Núcleos, Lideranças, Apoiadores, Planos de ação, Atualizações, Territórios) — usar como referência do shell desktop, mas só adicionar entradas de domínios que existirem.
|
||||
- **Ajustar cores:** paleta antiga (navy/vermelho escuro) no HTML/PNG; implementar com tokens do tema `campaign` (sidebar clara `#FAFAF9`, primário `#C51414`, badges de intenção com os pares pastel claros). Avatares com foto viram iniciais; "solla.ba" no kit é placeholder — a URL real vem de `NEXT_PUBLIC_SITE_URL`.
|
||||
|
||||
## Contexto
|
||||
|
||||
Hoje a campanha só cadastra pessoas via `leadership` — a junção única `Contact`↔núcleo que carrega status de apoio, vínculo com `campaignUser` (acesso ao app) e consentimento. Não existe base nominal de apoiadores "comuns": eleitores que declaram apoio mas não são lideranças engajadas com acesso à plataforma. O roadmap pede explicitamente o cadastro nominal em massa via `Contact` + junção, **sem nunca criar uma collection "pessoa/apoiador" paralela** (decisão travada no AGENTS.md, espelhada por `Signature`/`Subscription`).
|
||||
|
|
|
|||
|
|
@ -5,6 +5,19 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos", linha 51)
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Compartilhar-Nucleo.png`](../design-refs/latest/Compartilhar-Nucleo.png) · [`Compartilhar-Nucleo.html`](../design-refs/latest/Compartilhar-Nucleo.html)
|
||||
|
||||

|
||||
|
||||
Como usar:
|
||||
|
||||
- **Adotar a estrutura:** bottom sheet no mobile com título "Compartilhar núcleo", subtítulo reforçando "envia apenas o link, não concede acesso" (copy que materializa a decisão travada), três seções de destinatários ("Com coordenação geral", "Com coordenador", "Com liderança" — nome + papel + botão verde "Abrir" com ícone WhatsApp) e a seção "Copiar link" com a URL canônica truncada + botão "Copiar".
|
||||
- **Ajuste em relação ao plano:** o plano especifica `Dialog` central (como `LeadershipInviteDialog`); o design mostra bottom sheet. Adotar o padrão responsivo já usado no painel de lideranças (Sheet/Drawer no mobile, Dialog no desktop) — a estrutura interna do design vale para ambos.
|
||||
- **Lembrar das regras que o design não mostra:** ocultar a seção "Com liderança" para o papel `lideranca`; ocultar destinatários sem telefone; ocultar seções vazias; estado "copiado" após o clique.
|
||||
- **Ajustar cores:** paleta antiga no HTML/PNG (header vermelho escuro, navy). Implementar com os tokens do tema `campaign` e componentes `src/components/ui`; avatares com foto viram iniciais.
|
||||
|
||||
## Contexto
|
||||
|
||||
Hoje o detalhe do núcleo (`/campanha/nucleos/[slug]`) só tem ações de escrita (Editar, Nova liderança, Nova atualização, Arquivar). Não existe um caminho rápido para um usuário da campanha mandar o link daquele núcleo a outra pessoa do mesmo núcleo. A decisão de produto (2026-07-17) é adicionar um botão **Compartilhar** que oferece quatro destinos: coordenação geral, coordenador, liderança ou copiar link. Para os três primeiros, abre o WhatsApp via `wa.me` com o telefone do destinatário — o mesmo padrão já usado pelos convites, **sem WhatsApp Business API**.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,25 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos", linha 54)
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Dois designs cobrem este plano:
|
||||
|
||||
| Tela | Arquivos |
|
||||
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Lista de planos (`/campanha/planos`) | [`Planos-de-Acao.png`](../design-refs/latest/Planos-de-Acao.png) · [`Planos-de-Acao.html`](../design-refs/latest/Planos-de-Acao.html) |
|
||||
| Form novo plano | [`Novo-Plano-de-Acao.png`](../design-refs/latest/Novo-Plano-de-Acao.png) · [`Novo-Plano-de-Acao.html`](../design-refs/latest/Novo-Plano-de-Acao.html) |
|
||||
|
||||

|
||||

|
||||
|
||||
Como usar:
|
||||
|
||||
- **Lista — adotar:** tabs de janela/status ("Próximos" default, "Todos", "Realizados", "Rascunhos"), filtros "Tipo de ação" e "Território", cards com badge de `kind` (Caminhada, Reunião de apoio, Porta a porta, Comício, Panfletagem — cada tipo com cor própria clara), badge de `status` (Confirmado verde, Planejado azul, Rascunho outline, Realizado cinza), data/hora + município, chip do Território de Identidade, "Resp: {nome}" e barra de progresso de tarefas ("2/5 tarefas"). O card de rascunho com "Data a definir" esmaecido é um bom estado para `startAt` pendente em rascunho — mas atenção: o plano define `startAt` obrigatório; se rascunho puder ficar sem data, registrar em "Questões em aberto".
|
||||
- **Form — adotar:** seções "Informações básicas" (título, tipo, descrição opcional), "Data e horário" (data + início obrigatórios, término opcional com helper "Deixe em branco se a duração for indefinida"), "Território" (municípios multi-chip + território derivado automático — mesmo padrão de [`Formulario-Territorio.png`](../design-refs/latest/Formulario-Territorio.png), confirmando que o bloco nasce no modelo multi-município), "Pessoas responsáveis" (coordenadores com "+ Adicionar", responsável principal) e "Status inicial" (Planejado | Rascunho como radio cards).
|
||||
- **Falta desenhar (não bloqueia):** o detalhe do plano com tabs "Visão geral / Tarefas / Atualizações" não veio nesta leva — seguir o padrão `NucleusTabNav` do detalhe do núcleo; o checklist de tarefas pode reusar o formato de linhas do design da lista.
|
||||
- **Ajustar cores:** paleta antiga no HTML/PNG; implementar com tokens do tema `campaign`. A entrada "Agenda" do bottom nav só entra quando este domínio existir.
|
||||
|
||||
## Contexto
|
||||
|
||||
O roadmap lista "Eventos / presença e agenda de mobilização" como próximo ciclo da vertical `/campanha` (plano-arquitetura §4). Hoje a campanha só modela território (núcleo) e reporte (atualização); não há como planejar, escalar e acompanhar ações de campo — caminhadas, comícios, carreatas, panfletagens, reuniões de apoio, lançamentos, convenções, atos, entrevistas — nem ver o que vem a seguir.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Baseline-Eleitoral-2022.png`](../design-refs/latest/Baseline-Eleitoral-2022.png) — card "Insights do território", linha "Alavancagem da chapa: 22% · Da base Lula/Jerônimo ainda não convertida". Implementar como um card do stack `NucleusInsights.tsx` ([baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), com os tokens claros do tema `campaign` em vez da paleta antiga do HTML/PNG.
|
||||
|
||||
## Contexto
|
||||
|
||||
Solla apoia a chapa principal do PT (Lula para presidente, Jerônimo para governador, ambos nº 13). Os votos que Lula e Jerônimo receberam em 2022 numa geografia são o **teto natural do PT** no local — um piso de simpatia partidária que a candidatura de Solla pode capturar como dobradinha. Com o baseline TSE 2022 (ver [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), podemos medir quanto da base da chapa a estimativa do núcleo já captura e quanto ainda falta — meta implícita de alavancagem.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Baseline-Eleitoral-2022.png`](../design-refs/latest/Baseline-Eleitoral-2022.png) — card "Insights do território", linha "Território de defesa · Base sólida — prioridade: manter engajamento" com chip de classificação à direita (`Defesa` em verde). Os quatro estados usam pares de badge do tema `campaign`: defesa = verde, ataque = contorno vermelho, indecisa = âmbar, perdida = cinza. Implementar como um card do stack `NucleusInsights.tsx` ([baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), ajustando a paleta antiga do HTML/PNG para os tokens claros.
|
||||
|
||||
## Contexto
|
||||
|
||||
A literatura de territorialização eleitoral (Politipédia AVM, OPUS, Seja Eleito) classifica cada território em quatro zonas operacionais — **defesa** (voto histórico favorável, meta: manter), **ataque** (desfavorável mas relevante, meta: virar/reduzir margem), **indecisa** (pulverizada, baixa rejeição, meta: consolidar) e **perdida** (desfavorável e elástica, meta: minimizar perda) — para alocar esforço de forma proporcional ao retorno. Hoje o `/campanha` não classifica núcleos; com o baseline TSE 2022 (ver [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)) podemos derivar uma primeira classificação a partir do histórico.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Baseline-Eleitoral-2022.png`](../design-refs/latest/Baseline-Eleitoral-2022.png) — card "Insights do território", linha "Mais votado aqui em 2022: Dep. Fulano (PP) · Solla ficou em 4º lugar · 2.100 votos à frente"; a linha "Mais votado aqui em 2022" do bloco de baseline também alimenta este insight. Implementar como um card do stack `NucleusInsights.tsx` ([baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), com os tokens claros do tema `campaign` em vez da paleta antiga do HTML/PNG.
|
||||
|
||||
## Contexto
|
||||
|
||||
Saber onde Solla foi bem é só metade; a outra é saber **quem o superou localmente** e por quanto. O baseline TSE 2022 (ver [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)) guarda o conjunto completo de candidatos por geografia, com flag de eleito — podemos dizer, por núcleo, quem foi o mais votado para deputado federal ali em 2022, qual a margem sobre Solla, e em que colocação Solla ficou. É inteligência competitiva: onde há adversário forte a desmontar e onde Solla já é o referencial.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Baseline-Eleitoral-2022.png`](../design-refs/latest/Baseline-Eleitoral-2022.png) — card "Insights do território", linha "Oportunidade de mobilização: 142 brancos/nulos + 680 abstenções = 822 votos possíveis". Implementar como um card do stack `NucleusInsights.tsx` ([baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), com os tokens claros do tema `campaign` em vez da paleta antiga do HTML/PNG.
|
||||
|
||||
## Contexto
|
||||
|
||||
Em 2022, parte significativa dos eleitores aptos de cada geografia não gerou voto útil: **abstenções** (não compareceu), **votos em branco** e **votos nulos** (compareceu mas não votou em candidato válido). Esses eleitores são potencial de mobilização — gente que, bem engajada, pode virar voto. O baseline TSE 2022 (ver [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)) traz `electionTally.abstencoes`, `votosBranco` e `votosNulo` por município+zona; hoje o `/campanha` não os usa.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Baseline-Eleitoral-2022.png`](../design-refs/latest/Baseline-Eleitoral-2022.png) — card "Insights do território", primeira linha: "Taxa de conversão: 18% do eleitorado apto · 850 votos / 4.700 eleitores aptos" (ícone + veredito de uma linha + números de apoio). Implementar como um card do stack `NucleusInsights.tsx` (arquitetura definida em [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), com os tokens claros do tema `campaign` em vez da paleta antiga do HTML/PNG.
|
||||
|
||||
## Contexto
|
||||
|
||||
Com o baseline TSE 2022 importado (ver [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md)), temos `electionTally.aptos` (eleitores aptos) por município+zona. A estimativa confirmada do núcleo (`confirmedVoteEstimate`) hoje só é comparada com o voto histórico de Solla (Gap vs 2022). Falta medir a estimativa contra o **tamanho do eleitorado apto** da geografia — ou seja, qual % do eleitorado potencial da zona a estimativa representa. É o indicador que separa "reduto consolidado" de "oportunidade de crescimento", segundo a literatura de estratégia eleitoral.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,18 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Notificacoes-PWA.png`](../design-refs/latest/Notificacoes-PWA.png) · [`Notificacoes-PWA.html`](../design-refs/latest/Notificacoes-PWA.html) — **compartilhado com [pwa-campanha.md](pwa-campanha.md)** (o banner de instalação no rodapé pertence àquele plano).
|
||||
|
||||

|
||||
|
||||
Como usar (parte deste plano — o sino):
|
||||
|
||||
- **Adotar a estrutura:** sino no header com contagem; bottom sheet "Notificações" com "4 não lidas", ação "Marcar todas como lidas", itens com ícone por tipo de evento, título com o núcleo/entidade ("Estimativa aguardando confirmação — Núcleo Quilombo Rio das Rãs"), linha de detalhe (autor + ação), data relativa e ponto de não lida. Os quatro tipos exemplificados (estimativa aguardando confirmação, novo apoiador, novo reporte de campo, plano de ação precisa de atenção) são um bom ponto de partida para o enum `type` da collection `Notification` — dois deles dependem dos domínios C2/C3 existirem.
|
||||
- **Falta desenhar (não bloqueia):** a tela de opt-in de push com o checkbox de consentimento LGPD (`campanha-notificacoes-push`) e a nota de limitação do iOS — seguir o padrão do bloco "Consentimento LGPD" da [`Apoiador-Ficha.png`](../design-refs/latest/Apoiador-Ficha.png).
|
||||
- **Ajustar cores:** paleta antiga no HTML/PNG; implementar com tokens do tema `campaign` e componentes `Sheet`/`Drawer` existentes.
|
||||
|
||||
## Contexto
|
||||
|
||||
Coordenadores e lideranças precisam ser avisados de eventos da campanha (convite aceito, novo `nucleusUpdate`, estimativa aguardando confirmação) sem depender só do canal de WhatsApp. Este plano cobre dois canais de notificação dentro da vertical `/campanha`:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,18 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos", linha 50)
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Lista-Nucleos-Overview.png`](../design-refs/latest/Lista-Nucleos-Overview.png) · [`Lista-Nucleos-Overview.html`](../design-refs/latest/Lista-Nucleos-Overview.html)
|
||||
|
||||

|
||||
|
||||
Como usar:
|
||||
|
||||
- **Adotar a estrutura:** header → busca → chips de filtro ativos → caption "Mostrando agregados de 14 núcleos filtrados" → blocos de overview → lista. O bloco "Estimativa de votos" (total grande + barra de "% com estimativa confirmada" + badge "3 sugestões pendentes") e os blocos compactos "Cobertura" e "Últimas atualizações" (autor, badge de tipo, data relativa, núcleo, "Ver todas") correspondem exatamente aos objetivos deste plano.
|
||||
- **Fora deste plano:** o bloco "Baseline 2022" que aparece no design é a Fase 3 de [baseline-eleitoral-tse.md](baseline-eleitoral-tse.md) — só ganha UI quando aquele plano for implementado (mantém-se a decisão "sem UI órfã"). O bottom nav com "Apoiadores" e "Agenda" antecipa os domínios C2/C3; as entradas só entram quando existirem.
|
||||
- **Ajustar cores e código:** o HTML/PNG usa a paleta antiga (vermelho escuro `#8E0E23`, navy `#1B2B4B`, dourado `#C8874B`) e Tailwind via CDN. Implementar com os componentes shadcn existentes (`src/components/ui`) e os tokens do tema `data-theme='campaign'` (`src/app/(frontend)/styles.css`): fundo branco, primário `#C51414`, superfícies neutras claras. O header navy do design vira o shell claro atual; avatares com foto viram avatares de iniciais (padrão do app).
|
||||
|
||||
## Contexto
|
||||
|
||||
Hoje `/campanha/nucleos` é só cabeçalho + filtros + lista paginada (25/página). Não há agregados: o usuário precisa varrer a lista (ou ir ao dashboard `/campanha`) para sentir quanto daquela seleção tem estimativa confirmada, quantos votos somam, ou quais foram os últimos reportes. O dashboard geral já calcula esses agregados, mas para **todos** os núcleos ativos — não respeita os filtros de território/cobertura/estimativa da lista.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,17 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos", linha 62)
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Notificacoes-PWA.png`](../design-refs/latest/Notificacoes-PWA.png) · [`Notificacoes-PWA.html`](../design-refs/latest/Notificacoes-PWA.html) — **compartilhado com [notifications.md](notifications.md)** (a central de notificações pertence àquele plano).
|
||||
|
||||

|
||||
|
||||
Como usar (parte deste plano — o banner de instalação no rodapé):
|
||||
|
||||
- **Adotar o conteúdo:** banner fixo inferior com ícone do app, título "Instale o app da campanha", subtítulo "Acesse mais rápido e receba avisos", botão "Instalar" e X de dispensa — exatamente o `InstallPwaToast` da seção "Toast de instalação" (Android chama `deferredPrompt.prompt()`; iOS abre o passo a passo no Drawer; X grava `sessionStorage`).
|
||||
- **Ajuste:** o plano implementa isso via `<Toaster>` (sonner) já montado, não como barra fixa custom — usar o design como referência de conteúdo/hierarquia, não de posicionamento exato. Cores do design (navy) viram os tokens claros do tema `campaign`.
|
||||
|
||||
## Contexto
|
||||
|
||||
A vertical `/campanha` é a ferramenta de campo da campanha: coordenadores e lideranças acessam o app pelo celular, muitas vezes em locais com conexão instável. Transformar `/campanha` em um PWA instalável (com ícone na tela inicial, splash e capacidade offline básica) melhora a experiência de campo e desbloqueia o push web no iOS (que só recebe push com o PWA instalado — ver [plans/notifications.md](./notifications.md)).
|
||||
|
|
|
|||
|
|
@ -5,6 +5,19 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Formulario-Territorio.png`](../design-refs/latest/Formulario-Territorio.png) · [`Formulario-Territorio.html`](../design-refs/latest/Formulario-Territorio.html) — **compartilhado com [zonas-por-municipio.md](zonas-por-municipio.md)** (a mesma tela cobre os dois planos).
|
||||
|
||||

|
||||
|
||||
Como usar (parte deste plano — bloco Território):
|
||||
|
||||
- **Adotar a estrutura:** "Municípios" como combobox multi-seleção com chips removíveis + contagem "2 municípios selecionados"; "Territórios de Identidade" como chips derivados somente leitura com cadeado e legenda "Derivados dos municípios selecionados · não é possível editar" (materializa a regra 3 — `regions` rederivado no servidor); "Bairros" desabilitado com placeholder "Selecione municípios primeiro" e o aviso "Bairros exigem um único município selecionado" (regra 5).
|
||||
- **Divergência a resolver na implementação:** no design o campo de bairros aparece desabilitado com 2 municípios e o aviso âmbar simultaneamente; a regra é: habilitar bairros somente com exatamente 1 município e limpar bairros ao passar para >1 (mostrar o aviso como helper text, não como erro).
|
||||
- **Fora deste plano:** a seção "Zonas Eleitorais (TSE)" com chips "sugerida" pertence a [zonas-por-municipio.md](zonas-por-municipio.md).
|
||||
- **Ajustar cores:** paleta antiga no HTML/PNG. Implementar com `StrictCombobox`/`NucleusTerritoryFields` existentes e os tokens do tema `campaign` (chips neutros claros; chips de município selecionado não precisam ser navy).
|
||||
|
||||
## Contexto
|
||||
|
||||
Hoje o território do Núcleo Eleitoral é modelado com campos **single-valued** em `src/collections/ElectoralNucleus.ts`:
|
||||
|
|
|
|||
|
|
@ -5,6 +5,19 @@ Atualizado em: 2026-07-17
|
|||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (seção "Campanha → Próximos ciclos")
|
||||
Responsável: —
|
||||
|
||||
## Referência visual (UX Pilot)
|
||||
|
||||
Design: [`Formulario-Territorio.png`](../design-refs/latest/Formulario-Territorio.png) · [`Formulario-Territorio.html`](../design-refs/latest/Formulario-Territorio.html) — **compartilhado com [territorio-multi-municipio-bairro.md](territorio-multi-municipio-bairro.md)** (a mesma tela cobre os dois planos).
|
||||
|
||||

|
||||
|
||||
Como usar (parte deste plano — seção "Zonas Eleitorais (TSE)"):
|
||||
|
||||
- **Adotar a estrutura:** banner informativo "Zonas sugeridas pelo cadastro oficial do TSE — confira antes de salvar", lista de zonas como linhas com checkbox + número ("ZE 12"), badge "sugerida" e o município de origem como legenda — bom formato para o modo multi-município (união das zonas, cada uma rastreável ao município).
|
||||
- **Divergências a resolver na implementação:** o design mostra checkboxes editáveis e um link "Adicionar zona manualmente" para todos os casos; o plano define 4 modos — no modo 1 (municípios sem bairro) as zonas são **somente leitura** (sem checkbox, sem adicionar manual); checkbox/edição vale para os modos 2 e 3 (restrito ao conjunto permitido); entrada manual livre só no modo 4. Usar o visual das linhas do design, trocando checkbox por badge estático no modo read-only.
|
||||
- **Manter do design:** a zona desmarcada "ZE 7 (zona adicional)" ilustra bem o modo 2/3 (subconjunto permitido).
|
||||
- **Ajustar cores:** paleta antiga no HTML/PNG; implementar com `TseZoneInput` + tokens do tema `campaign` (chips TSE `#F1F3F5`/`#3F4854`).
|
||||
|
||||
## Contexto
|
||||
|
||||
Hoje o campo **Zonas TSE** do formulário do núcleo (`TseZoneInput` em `src/components/campaign/TseZoneInput.tsx`) é sempre de preenchimento manual livre: o usuário digita números de 1 a 999, separados por vírgula/espaço/Enter, e o servidor só valida unicidade e intervalo (`parseTseZoneNumbers` em `src/utilities/nucleusUi.ts`, `validateNucleusTerritoryAndZones` em `src/collections/ElectoralNucleus.ts`, `validateGeographyAndZones` em `src/lib/schemas/nucleus.ts`). Não há nenhuma relação entre o município selecionado e as zonas informadas — o usuário precisa saber (ou adivinhar) quais zonas cobrem aquele município.
|
||||
|
|
|
|||
|
|
@ -48,6 +48,26 @@ O MVP de Núcleos está **entregue em código** (ondas 1–8 + refactors; commit
|
|||
|
||||
MVP de território + reporte implementado e enviado (ondas 1–8 + refactors de composição/infra/fixtures): auth isolada `campaignUser` (`geral` / `coordenador` / `lideranca`), núcleos com slug canônico, designação de coordenador, lideranças, estimativas sugerir/confirmar com versão UUID, atualizações semanais, convites WhatsApp (`wa.me`, hash, uso único), dashboard e hardening. Território atual ainda é `region`/`city`/`neighborhood` unitários; multi-município permanece no item A1. Detalhes: [`.cursor/rules/projects/nucleos-eleitorais.mdc`](../.cursor/rules/projects/nucleos-eleitorais.mdc).
|
||||
|
||||
### Referências de design (UX Pilot, 2026-07-18)
|
||||
|
||||
Os designs gerados pelo UX Pilot para os próximos ciclos estão em [`docs/design-refs/latest/`](design-refs/latest/) (pares `.png` + `.html` com o mesmo nome). **A UX/estrutura é a referência a seguir; a paleta não é** — os arquivos usam a paleta antiga (vermelho escuro `#8E0E23`, navy `#1B2B4B`, dourado `#C8874B`); toda implementação usa os tokens claros do tema `data-theme='campaign'` (`src/app/(frontend)/styles.css`: fundo branco, primário `#C51414`, superfícies neutras). Cada plano detalha o uso na sua seção "Referência visual (UX Pilot)".
|
||||
|
||||
| Item do roadmap | Design | Plano com instruções |
|
||||
| ------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| B1 Overview da lista de núcleos | `Lista-Nucleos-Overview` | [overview-lista-nucleos.md](plans/overview-lista-nucleos.md) |
|
||||
| C1 Compartilhar página | `Compartilhar-Nucleo` | [compartilhar-pagina.md](plans/compartilhar-pagina.md) |
|
||||
| A1 Território multi-município/bairro | `Formulario-Territorio` (bloco Território) | [territorio-multi-municipio-bairro.md](plans/territorio-multi-municipio-bairro.md) |
|
||||
| A2 Zonas TSE por município | `Formulario-Territorio` (seção Zonas TSE) | [zonas-por-municipio.md](plans/zonas-por-municipio.md) |
|
||||
| A3/A4 Baseline TSE 2022 + Gap vs 2022 | `Baseline-Eleitoral-2022` (+ bloco "Baseline 2022" em `Lista-Nucleos-Overview`) | [baseline-eleitoral-tse.md](plans/baseline-eleitoral-tse.md) |
|
||||
| A5 Insights (5 planos) | `Baseline-Eleitoral-2022` (card "Insights do território", uma linha por insight) | [conversão](plans/insight-taxa-conversao.md) · [classificação](plans/insight-classificacao-territorial.md) · [alavancagem](plans/insight-alavancagem-chapa.md) · [mobilização](plans/insight-mobilizacao-brancos-nulos.md) · [competitiva](plans/insight-inteligencia-competitiva.md) |
|
||||
| C2 Cadastro nominal de apoiadores | `Apoiadores-Lista`, `Apoiador-Ficha`, `Importar-CSV-Apoiadores` | [cadastro-nominal-apoiadores.md](plans/cadastro-nominal-apoiadores.md) |
|
||||
| C3 Eventos / agenda de mobilização | `Planos-de-Acao`, `Novo-Plano-de-Acao` | [eventos-agenda-mobilizacao.md](plans/eventos-agenda-mobilizacao.md) |
|
||||
| D2 Notificações (sino) | `Notificacoes-PWA` (central de notificações) | [notifications.md](plans/notifications.md) |
|
||||
| D1 PWA `/campanha` | `Notificacoes-PWA` (banner "Instale o app da campanha") | [pwa-campanha.md](plans/pwa-campanha.md) |
|
||||
| C5 Operação dia D / GOTV | `Dia-D-GOTV` | sem plano ainda — o design é a primeira materialização do item (check-off de apoiadores por seção/zona, progresso "62% da base", filtro "Ainda não confirmados", estado "Sincronizado" offline-tolerante) |
|
||||
|
||||
**Sem design nesta leva** (encomendar na próxima rodada ou desenhar na implementação): A6 dobradinha 2026, B2/B3/B4 mapa da Bahia, C4 demandas, fill-ins (visitados recentemente, listas globais, reset de senha). O detalhe do plano de ação (tabs Visão geral/Tarefas/Atualizações) e a tela de opt-in de push também não vieram — os planos correspondentes indicam o padrão a seguir.
|
||||
|
||||
### Grafo de dependências
|
||||
|
||||
Setas cheias = dependência dura; tracejadas = dependência suave (melhora, não bloqueia).
|
||||
|
|
@ -149,7 +169,7 @@ Itens sem seta de entrada (**paralelizáveis a qualquer momento**): A1, A3, B1,
|
|||
| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| 15 | A6 Insight dobradinha 2026 | [detalhes](plans/insight-dobradinha-2026.md) | A4 + TSE publicar candidaturas 2026 (externo, após 15/08) + taxonomia de alinhamento (produto) |
|
||||
| 16 | B4 Camada de zonas TSE no mapa | ciclo seguinte do [plano do mapa](plans/mapa-bahia-geometrias.md) | A2 + B3 |
|
||||
| 17 | C5 **Operação dia D / GOTV** _(item proposto nesta revisão — validar com produto)_: confirmação de comparecimento da base nominal em 04/10 (lista de apoiadores por núcleo/zona com marcação "confirmou que vai votar / votou", visão de cobertura para a coordenação). É o uso final da base construída em C2; a literatura de campanha trata a mobilização do dia como onde eleições apertadas se decidem. Sem plano ainda. | — | C2 |
|
||||
| 17 | C5 **Operação dia D / GOTV** _(item proposto nesta revisão — validar com produto)_: confirmação de comparecimento da base nominal em 04/10 (lista de apoiadores por núcleo/zona com marcação "confirmou que vai votar / votou", visão de cobertura para a coordenação). É o uso final da base construída em C2; a literatura de campanha trata a mobilização do dia como onde eleições apertadas se decidem. Sem plano ainda. | design: [`Dia-D-GOTV`](design-refs/latest/Dia-D-GOTV.png) | C2 |
|
||||
| 18 | Congelamento: a partir de ~20/09, só correção de bug e dados; nada de migration arriscada perto do dia D. | — | — |
|
||||
|
||||
**Fill-ins (qualquer janela, quando houver folga; nenhum bloqueia nada):**
|
||||
|
|
|
|||