mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-15 10:43:07 +00:00
* deploy: limpeza pós-deploy do build cache e tags locais antigas (INF3/F2) O deploy compila no homeserver e acumulava build cache + tags locais antigas no disco raiz (incidente 19/08: 45G de cache). Após o smoke: docker builder prune -f + remoção das tags locais teqo-1313 exceto o SHA em uso (best-effort, registry preserva o rollback). * feat(S9): captura de novidades da campanha na home pública (form + CTA do hero) Seção 'Receba as novidades da campanha' acima do rodapé: nome + WhatsApp obrigatórios, e-mail/estado/cidade/comentário opcionais, toggle pré-selecionado 'Quero fazer parte do time' gravado como subscription.campaignLevel (time|esporadico). CTA secundário do hero vira o atalho (#novidades, scroll suave). Contact + Subscription em withPayloadTransaction com consentimento novo fail-closed por chave estável 'campanha-novidades' — nada é gravado sem o texto aprovado no admin. Migration 20260819_192605 (state de contact nullable + coluna campaign_level). Impl plan, changelog, int + e2e. * plans(C141,C143,C142): permissões granulares por assessor + responsáveis de demanda + UI por perfil * plans(C141,C143,C142): permissões granulares por assessor + responsáveis de demanda + UI por perfil * feat(S8): seção 'Nossa história' na home — vídeo da trajetória embutido do YouTube (Closes #91) * docs(S8): resolução do conflito com S9 (história → newsletter) + nota do guard e2e dev-only * feat(S10): pixel do Meta na página pública de campanha (campo admin em SiteSettings + PageView na home + Lead no sucesso da captura) Campo tracking.facebookPixelId no global SiteSettings (mesma validação/normalização do precedente Petition, regra centralizada em facebookPixel.ts); home (grupo (home)) injeta o base code + PageView quando o ID está configurado (fail-closed) e o CampaignNewsletterForm dispara exatamente um Lead no sucesso do S9. Migration 20260819_213947_add_site_settings_facebook_pixel_id. Closes #94 * refactor(S10): simplify pass — Lead wiring unit-tested e raças de estado compartilhado do e2e resolvidas e2e: stub hermético de connect.facebook.net no guard compartilhado (specs paralelos renderizam a home com o pixel); advisory lock no Postgres serializando o login do usuário de teste (Payload perde sessão em login concorrente read-modify-write — classe documentada no webauthn); seedTestUser vira create-if-missing (sem janela de usuário ausente nem reset de senha); Lead do form protegido do catch de erro (tracking nunca falha uma captura commitada); descrição do campo compartilhada; unidade nova campaignNewsletterLead cobre exatamente um Lead no sucesso. * feat(C141): perfis de permissão por assessor — Visão × Edição configuráveis, enforcement fail-closed (Closes #105) * chore(C141): regenera changelog agregado após rebase com S10 * plans(C144): options write-scoped para formulários de escrita pós-C141 --------- Co-authored-by: Francisco Solla <admin@solla.dev>
322 lines
14 KiB
HTML
322 lines
14 KiB
HTML
<!doctype html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
|
<title>UI draft — Perfis de permissão por assessor</title>
|
|
</head>
|
|
<body class="bg-zinc-950 text-zinc-100 antialiased">
|
|
<main class="mx-auto max-w-6xl p-8">
|
|
<p class="text-sm text-zinc-400">
|
|
Coordenador/candidato define por assessor o que ele vê (Tudo | Carteira) e o que ele pode
|
|
editar (Tudo | Carteira | Somente leitura) — cenas: lista com coluna Permissão + editor,
|
|
mobile, detalhe do assessor.
|
|
</p>
|
|
|
|
<!-- Cena 1: lista desktop com editor aberto numa linha -->
|
|
<section data-shot="desktop" class="mt-6 overflow-hidden rounded-xl border border-zinc-800">
|
|
<div
|
|
class="flex items-center justify-between border-b border-zinc-200 bg-zinc-100 px-6 py-4"
|
|
>
|
|
<div>
|
|
<div class="h-5 w-44 rounded bg-zinc-500"></div>
|
|
<div class="mt-1 h-2 w-64 rounded bg-zinc-400"></div>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<div
|
|
class="h-9 w-44 rounded-full border border-zinc-300 bg-white px-3 text-sm text-zinc-500"
|
|
>
|
|
Buscar assessor…
|
|
</div>
|
|
<div
|
|
class="inline-flex h-9 items-center rounded-lg bg-red-600 px-4 text-sm font-extrabold text-white"
|
|
>
|
|
+ Novo assessor
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-zinc-100 px-6 pb-6">
|
|
<!-- tabela -->
|
|
<div class="overflow-hidden rounded-lg border border-zinc-200 bg-white">
|
|
<div
|
|
class="grid grid-cols-[1.3fr_1.7fr_1.1fr_1.7fr_1.5fr] gap-2 border-b border-zinc-200 bg-zinc-50 px-4 py-2 text-xs font-bold text-zinc-500"
|
|
>
|
|
<div>Nome</div>
|
|
<div>E-mail</div>
|
|
<div>Celular</div>
|
|
<div>Municípios</div>
|
|
<div>Permissão</div>
|
|
</div>
|
|
<div
|
|
class="grid grid-cols-[1.3fr_1.7fr_1.1fr_1.7fr_1.5fr] items-center gap-2 border-b border-zinc-100 px-4 py-3 text-sm"
|
|
>
|
|
<div class="font-semibold text-zinc-900">Nome do assessor</div>
|
|
<div class="text-zinc-600">assessor@exemplo.org</div>
|
|
<div class="text-zinc-600">(71) 90000-0000</div>
|
|
<div class="flex flex-wrap gap-1">
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-xs text-zinc-700"
|
|
>Salvador (19)</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-xs text-zinc-700"
|
|
>Feira de Santana</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-xs text-zinc-700">+3</span>
|
|
</div>
|
|
<div>
|
|
<span class="rounded bg-zinc-300 px-2 py-0.5 text-xs font-bold text-zinc-800"
|
|
>Carteira · Edita carteira</span
|
|
>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="grid grid-cols-[1.3fr_1.7fr_1.1fr_1.7fr_1.5fr] items-center gap-2 border-b border-zinc-100 px-4 py-3 text-sm"
|
|
>
|
|
<div class="font-semibold text-zinc-900">Outra assessora</div>
|
|
<div class="text-zinc-600">outra@exemplo.org</div>
|
|
<div class="text-zinc-600">(71) 90000-0001</div>
|
|
<div class="flex flex-wrap gap-1">
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-xs text-zinc-700"
|
|
>Camaçari</span
|
|
>
|
|
</div>
|
|
<div>
|
|
<span class="rounded bg-zinc-300 px-2 py-0.5 text-xs font-bold text-zinc-800"
|
|
>Tudo · Somente leitura</span
|
|
>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="relative grid grid-cols-[1.3fr_1.7fr_1.1fr_1.7fr_1.5fr] items-center gap-2 bg-zinc-50 px-4 py-3 text-sm pb-[28rem]"
|
|
>
|
|
<div class="font-semibold text-zinc-900">Assessora de campo</div>
|
|
<div class="text-zinc-600">campo@exemplo.org</div>
|
|
<div class="text-zinc-600">(71) 90000-0002</div>
|
|
<div class="flex flex-wrap gap-1">
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-xs text-zinc-700">Ilhéus</span>
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-xs text-zinc-700">Itabuna</span>
|
|
</div>
|
|
<div>
|
|
<span class="rounded bg-zinc-300 px-2 py-0.5 text-xs font-bold text-zinc-800"
|
|
>Carteira · Edita carteira</span
|
|
>
|
|
</div>
|
|
|
|
<!-- popover editor -->
|
|
<div
|
|
class="absolute left-4 top-6 z-10 w-80 rounded-lg border border-zinc-200 bg-white p-4 shadow-xl"
|
|
>
|
|
<div class="text-sm font-bold text-zinc-900">Permissão da conta</div>
|
|
<div class="mt-1 text-xs text-zinc-500">Vale para todas as telas do /campanha.</div>
|
|
|
|
<div class="mt-4">
|
|
<div class="text-xs font-bold text-zinc-700">Visão</div>
|
|
<div
|
|
class="mt-1 flex h-9 items-center justify-between rounded-md border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-800"
|
|
>
|
|
Carteira — municípios que administra
|
|
<span class="text-xs text-zinc-400">▾</span>
|
|
</div>
|
|
<div class="mt-1 text-[11px] text-zinc-500">
|
|
Tudo: enxerga todos os municípios e lideranças.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<div class="text-xs font-bold text-zinc-700">Edição</div>
|
|
<div
|
|
class="mt-1 flex h-9 items-center justify-between rounded-md border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-800"
|
|
>
|
|
Carteira — edita só o que administra
|
|
<span class="text-xs text-zinc-400">▾</span>
|
|
</div>
|
|
<div class="mt-1 text-[11px] text-zinc-500">
|
|
Somente leitura: nenhum controle de edição em lugar nenhum.
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="mt-4 rounded-md bg-zinc-100 px-3 py-2 text-[11px] leading-relaxed text-zinc-600"
|
|
>
|
|
Demandas seguem regra própria: só quem é responsável pela demanda (e
|
|
candidato/coordenador) a vê — mesmo com visão "Tudo".
|
|
</div>
|
|
|
|
<div class="mt-4 flex justify-end gap-2">
|
|
<div
|
|
class="inline-flex h-9 items-center rounded-lg border border-zinc-300 px-4 text-sm font-bold text-zinc-700"
|
|
>
|
|
Cancelar
|
|
</div>
|
|
<div
|
|
class="inline-flex h-9 items-center rounded-lg bg-red-600 px-4 text-sm font-extrabold text-white"
|
|
>
|
|
Salvar
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-3 text-xs text-zinc-500">
|
|
Padrão de contas novas: Carteira · Edita carteira (comportamento atual). Alterações
|
|
valem na hora — ninguém precisa reenviar senha.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Cena 2: mobile — lista em cards -->
|
|
<section
|
|
data-shot="mobile"
|
|
class="mt-6 w-[390px] overflow-hidden rounded-xl border border-zinc-800"
|
|
>
|
|
<div class="bg-zinc-100 p-4">
|
|
<div class="flex items-center justify-between">
|
|
<div class="h-5 w-36 rounded bg-zinc-500"></div>
|
|
<div
|
|
class="inline-flex h-9 items-center rounded-lg bg-red-600 px-4 text-sm font-extrabold text-white"
|
|
>
|
|
+ Novo
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="mt-3 h-9 w-full rounded-full border border-zinc-300 bg-white px-3 text-sm text-zinc-500"
|
|
>
|
|
Buscar assessor…
|
|
</div>
|
|
|
|
<div class="mt-3 rounded-lg border border-zinc-200 bg-white p-3">
|
|
<div class="flex items-start justify-between gap-2">
|
|
<div class="min-w-0 truncate font-semibold text-zinc-900">Nome do assessor</div>
|
|
<span
|
|
class="shrink-0 rounded bg-zinc-300 px-2 py-0.5 text-[11px] font-bold text-zinc-800"
|
|
>Carteira · Edita</span
|
|
>
|
|
</div>
|
|
<div class="mt-1 text-xs text-zinc-600">assessor@exemplo.org · (71) 90000-0000</div>
|
|
<div class="mt-2 flex flex-wrap gap-1">
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-[11px] text-zinc-700"
|
|
>Salvador (19)</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-[11px] text-zinc-700"
|
|
>Feira de Santana</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-[11px] text-zinc-700">+3</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-2 rounded-lg border border-zinc-200 bg-white p-3">
|
|
<div class="flex items-start justify-between gap-2">
|
|
<div class="min-w-0 truncate font-semibold text-zinc-900">Outra assessora</div>
|
|
<span
|
|
class="shrink-0 rounded bg-zinc-300 px-2 py-0.5 text-[11px] font-bold text-zinc-800"
|
|
>Tudo · Só leitura</span
|
|
>
|
|
</div>
|
|
<div class="mt-1 text-xs text-zinc-600">outra@exemplo.org · (71) 90000-0001</div>
|
|
<div class="mt-2 flex flex-wrap gap-1">
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-[11px] text-zinc-700"
|
|
>Camaçari</span
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-2 rounded-lg border border-zinc-200 bg-white p-3">
|
|
<div class="flex items-start justify-between gap-2">
|
|
<div class="min-w-0 truncate font-semibold text-zinc-900">Assessora de campo</div>
|
|
<span
|
|
class="shrink-0 rounded bg-zinc-300 px-2 py-0.5 text-[11px] font-bold text-zinc-800"
|
|
>Carteira · Edita</span
|
|
>
|
|
</div>
|
|
<div class="mt-1 text-xs text-zinc-600">campo@exemplo.org · (71) 90000-0002</div>
|
|
<div class="mt-2 flex flex-wrap gap-1">
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-[11px] text-zinc-700"
|
|
>Ilhéus</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-1.5 py-0.5 text-[11px] text-zinc-700"
|
|
>Itabuna</span
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Cena 3: detalhe do assessor com seção de permissão -->
|
|
<section data-shot="detalhe" class="mt-6 overflow-hidden rounded-xl border border-zinc-800">
|
|
<div class="bg-zinc-100 px-8 py-6">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="h-10 w-10 rounded-full bg-zinc-400"></div>
|
|
<div>
|
|
<div class="text-lg font-bold text-zinc-900">Nome do assessor</div>
|
|
<div class="text-sm text-zinc-500">assessor@exemplo.org · (71) 90000-0000</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="rounded-lg border border-zinc-300 bg-white px-4 py-2 text-sm font-bold text-zinc-700"
|
|
>
|
|
Enviar link de redefinição de senha
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6 grid grid-cols-1 gap-4 lg:grid-cols-2">
|
|
<div class="rounded-lg border border-zinc-200 bg-white p-5">
|
|
<div class="text-sm font-bold text-zinc-900">Permissão da conta</div>
|
|
<div class="mt-3">
|
|
<div class="text-xs font-bold text-zinc-700">Visão</div>
|
|
<div
|
|
class="mt-1 flex h-9 items-center justify-between rounded-md border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-800"
|
|
>
|
|
Carteira — municípios que administra
|
|
<span class="text-xs text-zinc-400">▾</span>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3">
|
|
<div class="text-xs font-bold text-zinc-700">Edição</div>
|
|
<div
|
|
class="mt-1 flex h-9 items-center justify-between rounded-md border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-800"
|
|
>
|
|
Carteira — edita só o que administra
|
|
<span class="text-xs text-zinc-400">▾</span>
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="mt-3 rounded-md bg-zinc-100 px-3 py-2 text-[11px] leading-relaxed text-zinc-600"
|
|
>
|
|
Demandas ficam sempre limitadas aos municípios de responsabilidade. Decisões de
|
|
coordenação (nível de envolvimento, contas, demandas escaladas) continuam restritas
|
|
a coordenador e candidato.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rounded-lg border border-zinc-200 bg-white p-5">
|
|
<div class="text-sm font-bold text-zinc-900">Municípios administrados</div>
|
|
<div class="mt-3 flex flex-wrap gap-1.5">
|
|
<span class="rounded bg-zinc-200 px-2 py-1 text-xs text-zinc-700"
|
|
>Salvador (19)</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-2 py-1 text-xs text-zinc-700"
|
|
>Feira de Santana</span
|
|
>
|
|
<span class="rounded bg-zinc-200 px-2 py-1 text-xs text-zinc-700">Camaçari</span>
|
|
<span class="rounded bg-zinc-200 px-2 py-1 text-xs text-zinc-700">Ilhéus</span>
|
|
<span class="rounded bg-zinc-200 px-2 py-1 text-xs text-zinc-700">Itabuna</span>
|
|
<span
|
|
class="inline-flex h-6 items-center rounded bg-zinc-100 px-2 text-xs text-zinc-500"
|
|
>+8</span
|
|
>
|
|
</div>
|
|
<div
|
|
class="mt-3 h-9 w-full rounded-md border border-zinc-300 bg-zinc-50 px-3 text-sm text-zinc-500"
|
|
>
|
|
Adicionar município…
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|