KPI's na lista de beneficiários

This commit is contained in:
Duarte
2026-06-07 20:34:15 +01:00
parent ac75e55f50
commit 356947a113
3 changed files with 294 additions and 86 deletions
+1
View File
@@ -23,6 +23,7 @@ vite.config.js.timestamp-*
vite.config.ts.timestamp-* vite.config.ts.timestamp-*
# SQLite # SQLite
*.db *.db
*.db.*
# Persistent local data / uploads # Persistent local data / uploads
/data/ /data/
BIN
View File
Binary file not shown.
+291 -84
View File
@@ -1,20 +1,20 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/state'; import { page } from "$app/state";
import { enhance } from '$app/forms'; import { enhance } from "$app/forms";
let { data, form } = $props(); let { data, form } = $props();
let syncing = $state(false); let syncing = $state(false);
let sortBy = $state<'number' | 'name' | 'householdSize'>('number'); let sortBy = $state<"number" | "name" | "householdSize">("number");
let sortOrder = $state<'asc' | 'desc'>('asc'); let sortOrder = $state<"asc" | "desc">("asc");
function toggleSort(field: 'number' | 'name' | 'householdSize') { function toggleSort(field: "number" | "name" | "householdSize") {
if (sortBy === field) { if (sortBy === field) {
sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; sortOrder = sortOrder === "asc" ? "desc" : "asc";
} else { } else {
sortBy = field; sortBy = field;
sortOrder = 'asc'; sortOrder = "asc";
} }
} }
@@ -27,20 +27,19 @@
if (valA === null || valA === undefined) return 1; if (valA === null || valA === undefined) return 1;
if (valB === null || valB === undefined) return -1; if (valB === null || valB === undefined) return -1;
if (typeof valA === 'string' && typeof valB === 'string') { if (typeof valA === "string" && typeof valB === "string") {
return sortOrder === 'asc' return sortOrder === "asc"
? valA.localeCompare(valB, 'pt-PT') ? valA.localeCompare(valB, "pt-PT")
: valB.localeCompare(valA, 'pt-PT'); : valB.localeCompare(valA, "pt-PT");
} else { } else {
return sortOrder === 'asc' return sortOrder === "asc"
? (valA as number) - (valB as number) ? (valA as number) - (valB as number)
: (valB as number) - (valA as number); : (valB as number) - (valA as number);
} }
}); });
}); });
const successMessage = $derived(page.url.searchParams.get('success')); const successMessage = $derived(page.url.searchParams.get("success"));
</script> </script>
<svelte:head> <svelte:head>
@@ -49,9 +48,21 @@
<div class="container py-4"> <div class="container py-4">
{#if successMessage} {#if successMessage}
<div class="alert alert-success border-0 shadow-sm rounded-3 d-flex align-items-center gap-2 mb-4" role="alert"> <div
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-check-circle-fill text-success" viewBox="0 0 16 16"> class="alert alert-success border-0 shadow-sm rounded-3 d-flex align-items-center gap-2 mb-4"
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/> role="alert"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-check-circle-fill text-success"
viewBox="0 0 16 16"
>
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"
/>
</svg> </svg>
<div> <div>
{successMessage} {successMessage}
@@ -60,9 +71,21 @@
{/if} {/if}
{#if form?.success} {#if form?.success}
<div class="alert alert-success border-0 shadow-sm rounded-3 d-flex align-items-center gap-2 mb-4" role="alert"> <div
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-check-circle-fill text-success" viewBox="0 0 16 16"> class="alert alert-success border-0 shadow-sm rounded-3 d-flex align-items-center gap-2 mb-4"
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/> role="alert"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-check-circle-fill text-success"
viewBox="0 0 16 16"
>
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"
/>
</svg> </svg>
<div> <div>
Sincronização concluída com sucesso! {form.count} beneficiários atualizados/importados. Sincronização concluída com sucesso! {form.count} beneficiários atualizados/importados.
@@ -71,9 +94,21 @@
{/if} {/if}
{#if form?.error} {#if form?.error}
<div class="alert alert-danger border-0 shadow-sm rounded-3 d-flex align-items-center gap-2 mb-4" role="alert"> <div
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-exclamation-triangle-fill text-danger" viewBox="0 0 16 16"> class="alert alert-danger border-0 shadow-sm rounded-3 d-flex align-items-center gap-2 mb-4"
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/> role="alert"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-exclamation-triangle-fill text-danger"
viewBox="0 0 16 16"
>
<path
d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"
/>
</svg> </svg>
<div> <div>
{form.error} {form.error}
@@ -81,32 +116,78 @@
</div> </div>
{/if} {/if}
<div class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center gap-3 mb-4"> <div
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center gap-3 mb-4"
>
<div> <div>
<h2 class="fw-bold text-dark mb-1">Beneficiários</h2> <h2 class="fw-bold text-dark mb-1">Beneficiários</h2>
<p class="text-muted mb-0">Gerir a listagem de beneficiários e agregados familiares</p> <p class="text-muted mb-0">
Gerir a listagem de beneficiários e agregados familiares
</p>
</div> </div>
<div class="d-flex gap-2"> <div class="d-flex gap-2">
{#if data.user?.role === 'admin'} {#if data.user?.role === "admin"}
<form method="POST" action="?/sync" use:enhance={() => { <form
syncing = true; method="POST"
return async ({ update }) => { action="?/sync"
await update(); use:enhance={() => {
syncing = false; syncing = true;
}; return async ({ update }) => {
}} onsubmit={(e) => { if (!confirm('Tem a certeza que deseja sincronizar os beneficiários com o Odoo?')) e.preventDefault(); }}> await update();
<button type="submit" class="btn btn-outline-sync btn-lg d-flex align-items-center gap-2 rounded-3 shadow-sm" disabled={syncing}> syncing = false;
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-repeat {syncing ? 'spin' : ''}" viewBox="0 0 16 16"> };
<path d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"/> }}
<path fill-rule="evenodd" d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"/> onsubmit={(e) => {
if (
!confirm(
"Tem a certeza que deseja sincronizar os beneficiários com o Odoo?",
)
)
e.preventDefault();
}}
>
<button
type="submit"
class="btn btn-outline-sync btn-lg d-flex align-items-center gap-2 rounded-3 shadow-sm"
disabled={syncing}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-arrow-repeat {syncing ? 'spin' : ''}"
viewBox="0 0 16 16"
>
<path
d="M11.534 7h3.932a.25.25 0 0 1 .192.41l-1.966 2.36a.25.25 0 0 1-.384 0l-1.966-2.36a.25.25 0 0 1 .192-.41zm-11 2h3.932a.25.25 0 0 0 .192-.41L2.692 6.23a.25.25 0 0 0-.384 0L.342 8.59A.25.25 0 0 0 .534 9z"
/>
<path
fill-rule="evenodd"
d="M8 3c-1.552 0-2.94.707-3.857 1.818a.5.5 0 1 1-.771-.636A6.002 6.002 0 0 1 13.917 7H12.9A5.002 5.002 0 0 0 8 3zM3.1 9a5.002 5.002 0 0 0 8.757 2.182.5.5 0 1 1 .771.636A6.002 6.002 0 0 1 2.083 9H3.1z"
/>
</svg> </svg>
{syncing ? 'A sincronizar...' : 'Sincronizar Odoo'} {syncing ? "A sincronizar..." : "Sincronizar Odoo"}
</button> </button>
</form> </form>
{/if} {/if}
<a href="/admin/beneficiarios/novo" class="btn btn-success btn-lg d-flex align-items-center gap-2 rounded-3 shadow-sm border-0" style="background-color: var(--refood-primary, #FCB515);"> <a
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-plus-lg" viewBox="0 0 16 16"> href="/admin/beneficiarios/novo"
<path fill-rule="evenodd" d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2"/> class="btn btn-success btn-lg d-flex align-items-center gap-2 rounded-3 shadow-sm border-0"
style="background-color: var(--refood-primary, #FCB515);"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-plus-lg"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2"
/>
</svg> </svg>
Novo Beneficiário Novo Beneficiário
</a> </a>
@@ -116,33 +197,84 @@
<!-- Indicadores/Estatísticas --> <!-- Indicadores/Estatísticas -->
<div class="row g-3 mb-4"> <div class="row g-3 mb-4">
<div class="col-12 col-sm-6"> <div class="col-12 col-sm-6">
<div class="card border-0 shadow-sm rounded-4 p-3 bg-white h-100 d-flex flex-row align-items-center gap-3"> <div
<div class="stats-icon rounded-3 p-3 d-flex align-items-center justify-content-center" style="background-color: rgba(44, 86, 46, 0.1); color: #2c562e; width: 60px; height: 60px; flex-shrink: 0;"> class="card border-0 shadow-sm rounded-4 p-3 bg-white h-100 d-flex flex-row align-items-center gap-3"
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" class="bi bi-house-door-fill" viewBox="0 0 16 16"> >
<path d="M6.5 14.5v-3.507c0-.31.25-.56.56-.56h2c.31 0 .56.25.56.56v3.507c0 .31-.25.56-.56.56H7.06a.56.56 0 0 1-.56-.56"/> <div
<path d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/> class="stats-icon rounded-3 p-3 d-flex align-items-center justify-content-center"
<path d="M8 .757 1.01 6.855a.5.5 0 0 0-.01.768l.66.583a.5.5 0 0 0 .702-.055L8 2.501l5.64 5.65a.5.5 0 0 0 .702.054l.66-.583a.5.5 0 0 0-.01-.767L8 .757z"/> style="background-color: rgba(44, 86, 46, 0.1); color: #2c562e; width: 60px; height: 60px; flex-shrink: 0;"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
fill="currentColor"
class="bi bi-house-door-fill"
viewBox="0 0 16 16"
>
<path
d="M6.5 14.5v-3.507c0-.31.25-.56.56-.56h2c.31 0 .56.25.56.56v3.507c0 .31-.25.56-.56.56H7.06a.56.56 0 0 1-.56-.56"
/>
<path
d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"
/>
<path
d="M8 .757 1.01 6.855a.5.5 0 0 0-.01.768l.66.583a.5.5 0 0 0 .702-.055L8 2.501l5.64 5.65a.5.5 0 0 0 .702.054l.66-.583a.5.5 0 0 0-.01-.767L8 .757z"
/>
</svg> </svg>
</div> </div>
<div> <div>
<span class="text-secondary small fw-semibold d-block text-uppercase" style="letter-spacing: 0.05em; font-size: 0.75rem;">Famílias</span> <span
<span class="fs-2 fw-bold text-dark lh-1">{data.totalFamilies}</span> class="text-secondary small fw-semibold d-block text-uppercase"
<span class="text-muted small d-block mt-1" style="font-size: 0.75rem;">Número de famílias (IsParent=true)</span> style="letter-spacing: 0.05em; font-size: 0.75rem;"
>Famílias</span
>
<span class="fs-2 fw-bold text-dark lh-1"
>{data.totalFamilies}</span
>
<span
class="text-muted small d-block mt-1"
style="font-size: 0.75rem;">Número de famílias</span
>
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 col-sm-6"> <div class="col-12 col-sm-6">
<div class="card border-0 shadow-sm rounded-4 p-3 bg-white h-100 d-flex flex-row align-items-center gap-3"> <div
<div class="stats-icon rounded-3 p-3 d-flex align-items-center justify-content-center" style="background-color: rgba(252, 181, 21, 0.15); color: #b78104; width: 60px; height: 60px; flex-shrink: 0;"> class="card border-0 shadow-sm rounded-4 p-3 bg-white h-100 d-flex flex-row align-items-center gap-3"
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" class="bi bi-people-fill" viewBox="0 0 16 16"> >
<path d="M7 14s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1zm4-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6m-5.784 6A2.24 2.24 0 0 1 5 13c0-1.355.68-2.75 1.936-3.72A6.3 6.3 0 0 0 5 9c-4 0-5 3-5 4s1 1 1 1zM4.5 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5"/> <div
class="stats-icon rounded-3 p-3 d-flex align-items-center justify-content-center"
style="background-color: rgba(252, 181, 21, 0.15); color: #b78104; width: 60px; height: 60px; flex-shrink: 0;"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
fill="currentColor"
class="bi bi-people-fill"
viewBox="0 0 16 16"
>
<path
d="M7 14s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1zm4-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6m-5.784 6A2.24 2.24 0 0 1 5 13c0-1.355.68-2.75 1.936-3.72A6.3 6.3 0 0 0 5 9c-4 0-5 3-5 4s1 1 1 1zM4.5 8a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5"
/>
</svg> </svg>
</div> </div>
<div> <div>
<span class="text-secondary small fw-semibold d-block text-uppercase" style="letter-spacing: 0.05em; font-size: 0.75rem;">Total de Beneficiários</span> <span
<span class="fs-2 fw-bold text-dark lh-1">{data.totalBeneficiaries}</span> class="text-secondary small fw-semibold d-block text-uppercase"
<span class="text-muted small d-block mt-1" style="font-size: 0.75rem;">Todos os registos na base de dados</span> style="letter-spacing: 0.05em; font-size: 0.75rem;"
>Total de Beneficiários</span
>
<span class="fs-2 fw-bold text-dark lh-1"
>{data.totalBeneficiaries}</span
>
<span
class="text-muted small d-block mt-1"
style="font-size: 0.75rem;"
>Todos os registos na base de dados</span
>
</div> </div>
</div> </div>
</div> </div>
@@ -151,7 +283,11 @@
<div class="card border-0 shadow-sm rounded-4 p-3 mb-4 bg-white"> <div class="card border-0 shadow-sm rounded-4 p-3 mb-4 bg-white">
<form method="GET" class="row g-3 align-items-end"> <form method="GET" class="row g-3 align-items-end">
<div class="col-md-6 col-lg-7"> <div class="col-md-6 col-lg-7">
<label for="search" class="form-label fw-semibold text-secondary small">Pesquisar</label> <label
for="search"
class="form-label fw-semibold text-secondary small"
>Pesquisar</label
>
<input <input
type="text" type="text"
name="search" name="search"
@@ -163,8 +299,17 @@
</div> </div>
<div class="col-md-3 col-lg-3"> <div class="col-md-3 col-lg-3">
<label for="status" class="form-label fw-semibold text-secondary small">Estado</label> <label
<select name="status" id="status" value={data.status} class="form-select rounded-3 border-2"> for="status"
class="form-label fw-semibold text-secondary small"
>Estado</label
>
<select
name="status"
id="status"
value={data.status}
class="form-select rounded-3 border-2"
>
<option value="todos">Todos</option> <option value="todos">Todos</option>
<option value="ativo">Ativo</option> <option value="ativo">Ativo</option>
<option value="inativo">Inativo</option> <option value="inativo">Inativo</option>
@@ -172,7 +317,11 @@
</div> </div>
<div class="col-md-3 col-lg-2 d-grid"> <div class="col-md-3 col-lg-2 d-grid">
<button type="submit" class="btn btn-primary rounded-3 fw-semibold border-0 py-2" style="background-color: #2c562e;"> <button
type="submit"
class="btn btn-primary rounded-3 fw-semibold border-0 py-2"
style="background-color: #2c562e;"
>
Filtrar Filtrar
</button> </button>
</div> </div>
@@ -180,50 +329,88 @@
</div> </div>
<div class="card border-0 shadow-sm rounded-4 overflow-hidden bg-white"> <div class="card border-0 shadow-sm rounded-4 overflow-hidden bg-white">
<div class="card-header border-0 bg-light py-3 px-4 d-flex justify-content-between align-items-center flex-wrap gap-2"> <div
class="card-header border-0 bg-light py-3 px-4 d-flex justify-content-between align-items-center flex-wrap gap-2"
>
<h5 class="fw-bold text-dark mb-0">Lista de Beneficiários</h5> <h5 class="fw-bold text-dark mb-0">Lista de Beneficiários</h5>
</div> </div>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover align-middle mb-0"> <table class="table table-hover align-middle mb-0">
<thead class="table-light text-secondary fw-semibold"> <thead class="table-light text-secondary fw-semibold">
<tr> <tr>
<th class="px-4 py-3 sortable-header" style="width: 120px;" onclick={() => toggleSort('number')}> <th
<div class="d-flex align-items-center gap-1 select-none"> class="px-4 py-3 sortable-header"
style="width: 120px;"
onclick={() => toggleSort("number")}
>
<div
class="d-flex align-items-center gap-1 select-none"
>
Número Número
{#if sortBy === 'number'} {#if sortBy === "number"}
<span class="sort-arrow">{sortOrder === 'asc' ? '▲' : '▼'}</span> <span class="sort-arrow"
>{sortOrder === "asc" ? "▲" : "▼"}</span
>
{/if} {/if}
</div> </div>
</th> </th>
<th class="py-3 sortable-header" onclick={() => toggleSort('name')}> <th
<div class="d-flex align-items-center gap-1 select-none"> class="py-3 sortable-header"
onclick={() => toggleSort("name")}
>
<div
class="d-flex align-items-center gap-1 select-none"
>
Nome Nome
{#if sortBy === 'name'} {#if sortBy === "name"}
<span class="sort-arrow">{sortOrder === 'asc' ? '▲' : '▼'}</span> <span class="sort-arrow"
>{sortOrder === "asc" ? "▲" : "▼"}</span
>
{/if} {/if}
</div> </div>
</th> </th>
<th class="py-3">Contacto</th> <th class="py-3">Contacto</th>
<th class="py-3 text-center sortable-header" style="width: 120px;" onclick={() => toggleSort('householdSize')}> <th
<div class="d-flex align-items-center justify-content-center gap-1 select-none"> class="py-3 text-center sortable-header"
style="width: 120px;"
onclick={() => toggleSort("householdSize")}
>
<div
class="d-flex align-items-center justify-content-center gap-1 select-none"
>
Agregado Agregado
{#if sortBy === 'householdSize'} {#if sortBy === "householdSize"}
<span class="sort-arrow">{sortOrder === 'asc' ? '▲' : '▼'}</span> <span class="sort-arrow"
>{sortOrder === "asc" ? "▲" : "▼"}</span
>
{/if} {/if}
</div> </div>
</th> </th>
<th class="py-3" style="width: 120px;">Estado</th> <th class="py-3" style="width: 120px;">Estado</th>
<th class="px-4 py-3 text-end" style="width: 120px;">Ações</th> <th class="px-4 py-3 text-end" style="width: 120px;"
>Ações</th
>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#if sortedBeneficiaries.length === 0} {#if sortedBeneficiaries.length === 0}
<tr> <tr>
<td colspan="6" class="text-center py-5 text-muted"> <td colspan="6" class="text-center py-5 text-muted">
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="currentColor" class="bi bi-people mb-2 text-black-50" viewBox="0 0 16 16"> <svg
<path d="M15 14s1 0 1-1-1-4-5-4-5 3-5 4 1 1 1 1zm-7.978-1L7 12.996c.001-.264.167-1.03.76-1.72C8.312 10.629 9.282 10 11 10c1.717 0 2.687.63 3.24 1.276.593.69.758 1.457.76 1.72l-.008.002-.014.002zM11 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4m3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0M6.936 9.28a6 6 0 0 0-1.23-.247A7 7 0 0 0 5 9c-4 0-5 3-5 4q0 1 2 1h4.216A2.24 2.24 0 0 1 5 13c0-1.01.377-2.042 1.09-2.904.243-.294.526-.569.846-.816M4.92 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4m3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0"/> xmlns="http://www.w3.org/2000/svg"
width="40"
height="40"
fill="currentColor"
class="bi bi-people mb-2 text-black-50"
viewBox="0 0 16 16"
>
<path
d="M15 14s1 0 1-1-1-4-5-4-5 3-5 4 1 1 1 1zm-7.978-1L7 12.996c.001-.264.167-1.03.76-1.72C8.312 10.629 9.282 10 11 10c1.717 0 2.687.63 3.24 1.276.593.69.758 1.457.76 1.72l-.008.002-.014.002zM11 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4m3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0M6.936 9.28a6 6 0 0 0-1.23-.247A7 7 0 0 0 5 9c-4 0-5 3-5 4q0 1 2 1h4.216A2.24 2.24 0 0 1 5 13c0-1.01.377-2.042 1.09-2.904.243-.294.526-.569.846-.816M4.92 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4m3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0"
/>
</svg> </svg>
<p class="mb-0">Nenhum beneficiário encontrado.</p> <p class="mb-0">
Nenhum beneficiário encontrado.
</p>
</td> </td>
</tr> </tr>
{:else} {:else}
@@ -242,16 +429,36 @@
{beneficiary.householdSize} {beneficiary.householdSize}
</td> </td>
<td> <td>
{#if beneficiary.status === 'ativo'} {#if beneficiary.status === "ativo"}
<span class="badge bg-success-subtle text-success px-2.5 py-1.5 rounded-pill border border-success-subtle text-uppercase fw-semibold" style="font-size: 0.7rem;">Ativo</span> <span
class="badge bg-success-subtle text-success px-2.5 py-1.5 rounded-pill border border-success-subtle text-uppercase fw-semibold"
style="font-size: 0.7rem;"
>Ativo</span
>
{:else} {:else}
<span class="badge bg-danger-subtle text-danger px-2.5 py-1.5 rounded-pill border border-danger-subtle text-uppercase fw-semibold" style="font-size: 0.7rem;">Inativo</span> <span
class="badge bg-danger-subtle text-danger px-2.5 py-1.5 rounded-pill border border-danger-subtle text-uppercase fw-semibold"
style="font-size: 0.7rem;"
>Inativo</span
>
{/if} {/if}
</td> </td>
<td class="px-4 text-end"> <td class="px-4 text-end">
<a href="/admin/beneficiarios/{beneficiary.id}" class="btn btn-sm btn-outline-secondary rounded-2 px-2.5 py-1 d-inline-flex align-items-center gap-1.5"> <a
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16"> href="/admin/beneficiarios/{beneficiary.id}"
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325"/> class="btn btn-sm btn-outline-secondary rounded-2 px-2.5 py-1 d-inline-flex align-items-center gap-1.5"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
fill="currentColor"
class="bi bi-pencil"
viewBox="0 0 16 16"
>
<path
d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325"
/>
</svg> </svg>
Editar Editar
</a> </a>