<!--
|--------------------------------------------------------------------------
| Agência PSI — SaaS / Segurança (A#20 rev2)
|--------------------------------------------------------------------------
| Painel saas_admin para configurar a defesa em camadas e ver telemetria.
|
| Tabela: saas_security_config (singleton)
| Logs:   public_submission_attempts (genérico, todos endpoints)
| Estado: submission_rate_limits (IPs com contadores e bloqueios)
|--------------------------------------------------------------------------
-->
<script setup>
import { ref, onMounted, computed } from 'vue';
import { supabase } from '@/lib/supabase/client';

import InputNumber from 'primevue/inputnumber';
import ToggleSwitch from 'primevue/toggleswitch';
import Button from 'primevue/button';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import Tag from 'primevue/tag';
import Accordion from 'primevue/accordion';
import AccordionPanel from 'primevue/accordionpanel';
import AccordionHeader from 'primevue/accordionheader';
import AccordionContent from 'primevue/accordioncontent';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';

const toast = useToast();
const confirm = useConfirm();

const helpOpen = ref(true); // accordion abre fechado depois da primeira leitura

const cfg = ref(null);
const cfgLoading = ref(false);
const cfgSaving = ref(false);

const stats = ref({ total24h: 0, blocked24h: 0, success24h: 0, captcha24h: 0 });
const recentAttempts = ref([]);
const blockedIps = ref([]);
const dataLoading = ref(false);

async function loadConfig() {
    cfgLoading.value = true;
    try {
        const { data, error } = await supabase.from('saas_security_config').select('*').eq('id', true).maybeSingle();
        if (error) throw error;
        cfg.value = data || null;
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'falha config', life: 4000 });
    } finally {
        cfgLoading.value = false;
    }
}

async function saveConfig() {
    if (!cfg.value) return;
    cfgSaving.value = true;
    try {
        const payload = {
            honeypot_enabled: cfg.value.honeypot_enabled,
            rate_limit_enabled: cfg.value.rate_limit_enabled,
            rate_limit_window_min: cfg.value.rate_limit_window_min,
            rate_limit_max_attempts: cfg.value.rate_limit_max_attempts,
            captcha_after_failures: cfg.value.captcha_after_failures,
            captcha_required_globally: cfg.value.captcha_required_globally,
            block_duration_min: cfg.value.block_duration_min,
            captcha_required_window_min: cfg.value.captcha_required_window_min
        };
        const { error } = await supabase.from('saas_security_config').update(payload).eq('id', true);
        if (error) throw error;
        toast.add({ severity: 'success', summary: 'Salvo', detail: 'Configuração atualizada.', life: 2500 });
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'falha ao salvar', life: 4000 });
    } finally {
        cfgSaving.value = false;
    }
}

async function loadDashboard() {
    dataLoading.value = true;
    try {
        const since = new Date(Date.now() - 24 * 3600 * 1000).toISOString();

        const [{ data: attempts, error: e1 }, { data: blocked, error: e2 }] = await Promise.all([
            supabase
                .from('public_submission_attempts')
                .select('id, endpoint, ip_hash, success, blocked_by, error_code, error_msg, user_agent, created_at')
                .gte('created_at', since)
                .order('created_at', { ascending: false })
                .limit(100),
            supabase
                .from('submission_rate_limits')
                .select('*')
                .order('last_attempt_at', { ascending: false })
                .limit(50)
        ]);

        if (e1) throw e1;
        if (e2) throw e2;

        recentAttempts.value = attempts || [];
        blockedIps.value = blocked || [];

        const total = (attempts || []).length;
        const success = (attempts || []).filter((a) => a.success).length;
        const blockedC = (attempts || []).filter((a) => !a.success && a.blocked_by && a.blocked_by !== 'rpc').length;
        const captchaC = (attempts || []).filter((a) => a.blocked_by === 'captcha').length;

        stats.value = { total24h: total, blocked24h: blockedC, success24h: success, captcha24h: captchaC };
    } catch (e) {
        toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'falha dashboard', life: 4000 });
    } finally {
        dataLoading.value = false;
    }
}

function blockedSeverity(by) {
    return ({
        honeypot: 'info',
        rate_limit: 'warn',
        captcha: 'warn',
        validation: 'secondary',
        rpc: 'danger'
    })[by] || 'secondary';
}

function fmtRelative(ts) {
    if (!ts) return '—';
    const diff = (Date.now() - new Date(ts).getTime()) / 1000;
    if (diff < 60) return `${Math.floor(diff)}s atrás`;
    if (diff < 3600) return `${Math.floor(diff / 60)}min atrás`;
    if (diff < 86400) return `${Math.floor(diff / 3600)}h atrás`;
    return new Date(ts).toLocaleString('pt-BR');
}

const ipsCurrentlyBlocked = computed(() => {
    const now = Date.now();
    return blockedIps.value.filter((r) => r.blocked_until && new Date(r.blocked_until).getTime() > now);
});

const ipsRequiringCaptcha = computed(() => {
    const now = Date.now();
    return blockedIps.value.filter((r) => r.requires_captcha_until && new Date(r.requires_captcha_until).getTime() > now);
});

async function clearRateLimit(row) {
    confirm.require({
        message: `Limpar rate limit de ${row.ip_hash.slice(0, 8)}… em ${row.endpoint}?`,
        header: 'Limpar bloqueio',
        icon: 'pi pi-question-circle',
        accept: async () => {
            try {
                const { error } = await supabase.from('submission_rate_limits').delete().eq('ip_hash', row.ip_hash).eq('endpoint', row.endpoint);
                if (error) throw error;
                toast.add({ severity: 'success', summary: 'Ok', detail: 'Bloqueio limpo.', life: 2500 });
                await loadDashboard();
            } catch (e) {
                toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'falha', life: 4000 });
            }
        }
    });
}

onMounted(async () => {
    await Promise.all([loadConfig(), loadDashboard()]);
});
</script>

<template>
    <div class="flex flex-col gap-4 p-4">
        <!-- Header -->
        <div class="cfg-subheader">
            <div class="cfg-subheader__icon"><i class="pi pi-shield" /></div>
            <div class="min-w-0 flex-1">
                <div class="cfg-subheader__title">Segurança — defesa contra bots</div>
                <div class="cfg-subheader__sub">Configuração da defesa em camadas para endpoints públicos (cadastro de paciente, signup, agendador).</div>
            </div>
        </div>

        <!-- Card explicativo (colapsável) -->
        <div class="rounded-md border border-indigo-400/30 bg-indigo-400/5">
            <Accordion :value="helpOpen ? '0' : null" @update:value="(v) => helpOpen = (v === '0')">
                <AccordionPanel value="0">
                    <AccordionHeader>
                        <div class="flex items-center gap-2">
                            <i class="pi pi-info-circle text-indigo-400" />
                            <span class="font-semibold">Como funciona — guia de uso</span>
                        </div>
                    </AccordionHeader>
                    <AccordionContent>
                        <div class="flex flex-col gap-5 text-[0.92rem] leading-relaxed">

                            <!-- ── Visão geral ── -->
                            <section>
                                <div class="font-semibold text-[1rem] mb-2">
                                    <i class="pi pi-shield mr-2 text-emerald-400" />
                                    Visão geral
                                </div>
                                <p class="text-[var(--text-color-secondary)]">
                                    Toda submissão na página pública (cadastro de paciente externo) passa por <b>5 camadas em ordem</b>. Se qualquer uma rejeitar, o submit é bloqueado e logado.
                                    O design prioriza <b>zero fricção pro paciente legítimo</b> — captcha visível só aparece quando o sistema desconfia.
                                </p>
                                <ol class="list-decimal pl-6 mt-3 space-y-1.5 text-[var(--text-color-secondary)]">
                                    <li><b>Honeypot</b> — campo invisível que humano nunca vê. Bot scraper preenche tudo e cai aqui. <span class="opacity-70">(zero fricção)</span></li>
                                    <li><b>Validação básica</b> — payload obrigatório, token presente.</li>
                                    <li><b>Rate limit por IP</b> — N tentativas por janela de tempo, do mesmo IP+endpoint. Excedeu, bloqueia por X min.</li>
                                    <li><b>Math captcha condicional</b> — só ativa se o IP teve N falhas recentes. Mostra "Quanto é 7+4?".</li>
                                    <li><b>RPC do intake</b> — só executa se passou pelas camadas 1-4. Validação final dos dados.</li>
                                </ol>
                            </section>

                            <!-- ── Cada controle ── -->
                            <section>
                                <div class="font-semibold text-[1rem] mb-2">
                                    <i class="pi pi-sliders-h mr-2 text-amber-400" />
                                    O que cada controle faz
                                </div>
                                <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Honeypot</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Toggle que liga/desliga o campo invisível. Default <b>ON</b>. Praticamente sem custo, mantenha sempre ligado.</div>
                                    </div>
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Rate limit</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Toggle mestre. Se desligar, ninguém é bloqueado por excesso. Default <b>ON</b>.</div>
                                    </div>
                                    <div class="rounded-md border border-rose-400/40 p-3">
                                        <div class="font-medium text-rose-300">Modo paranoid</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">
                                            Liga: <b>todo submit exige captcha</b>, mesmo IPs novos. Use SÓ sob ataque ativo (você verá centenas de tentativas no dashboard).
                                            Pacientes legítimos vão precisar resolver math toda vez. Lembre de desligar quando passar.
                                        </div>
                                    </div>
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Janela (min)</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Período de medição. Default <b>10</b>. Tentativas mais antigas que isso são esquecidas.</div>
                                    </div>
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Máx tentativas na janela</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Quantos submits do mesmo IP toleramos antes de bloquear. Default <b>5</b>. Aumentar se for ambiente compartilhado (ex: WiFi de clínica com vários terapeutas).</div>
                                    </div>
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Falhas até captcha</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Após N <b>falhas</b> (não tentativas), o IP passa a precisar resolver math. Default <b>3</b>. Mais baixo = mais paranoico.</div>
                                    </div>
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Duração do bloqueio</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Quanto tempo o IP fica bloqueado depois de exceder o máximo. Default <b>30 min</b>.</div>
                                    </div>
                                    <div class="rounded-md border border-[var(--surface-border)] p-3">
                                        <div class="font-medium">Janela do captcha condicional</div>
                                        <div class="text-xs text-[var(--text-color-secondary)] mt-1">Por quanto tempo o IP suspeito continua precisando de captcha após disparar. Default <b>60 min</b>.</div>
                                    </div>
                                </div>
                            </section>

                            <!-- ── Como testar local ── -->
                            <section>
                                <div class="font-semibold text-[1rem] mb-2">
                                    <i class="pi pi-desktop mr-2 text-cyan-400" />
                                    Como testar localmente
                                </div>
                                <ol class="list-decimal pl-6 space-y-2 text-[var(--text-color-secondary)]">
                                    <li>
                                        Suba a edge function:
                                        <pre class="mt-1 p-2 rounded bg-black/30 font-mono text-xs overflow-x-auto">npx supabase functions serve submit-patient-intake</pre>
                                    </li>
                                    <li>
                                        Logue como terapeuta, gere um link de cadastro de paciente em
                                        <span class="font-mono text-xs">/admin/clinic/intake</span>, copie o link.
                                    </li>
                                    <li>
                                        Abra o link em uma <b>aba anônima</b> (pra simular paciente). Preencha e envie. Caminho feliz: zero fricção, vai cair em <span class="font-mono text-xs">patient_intake_requests</span>.
                                    </li>
                                    <li>
                                        Pra simular bot: abra DevTools → Console e dispare 4 submits inválidos:
                                        <pre class="mt-1 p-2 rounded bg-black/30 font-mono text-xs overflow-x-auto">for (let i=0; i&lt;4; i++) {
  await fetch('http://127.0.0.1:54321/functions/v1/submit-patient-intake', {
    method: 'POST',
    headers: {'content-type':'application/json', apikey: '&lt;ANON_KEY&gt;'},
    body: JSON.stringify({ token: 'ruim', payload: {} })
  })
}</pre>
                                    </li>
                                    <li>Recarregue esta tela: você verá o IP listado em <b>"IPs ativos"</b> com tag amarela <b>"exige captcha"</b>. Próximo submit do mesmo IP terá o math captcha visível.</li>
                                    <li>Pra simular bloqueio total: faça 6+ tentativas. IP fica com tag vermelha <b>"bloqueado"</b> por 30 min. Botão <i class="pi pi-eraser" /> remove o bloqueio manualmente.</li>
                                </ol>
                            </section>

                            <!-- ── Como testar online ── -->
                            <section>
                                <div class="font-semibold text-[1rem] mb-2">
                                    <i class="pi pi-cloud mr-2 text-emerald-400" />
                                    Como testar em produção
                                </div>
                                <ol class="list-decimal pl-6 space-y-2 text-[var(--text-color-secondary)]">
                                    <li>
                                        Deploy da edge function:
                                        <pre class="mt-1 p-2 rounded bg-black/30 font-mono text-xs overflow-x-auto">npx supabase functions deploy submit-patient-intake</pre>
                                    </li>
                                    <li>Sem configuração de chave externa — defesa é 100% self-hosted, funciona já após o deploy.</li>
                                    <li>
                                        Crie um link de teste no painel de terapeuta. Acesse de um celular (rede 4G — IP diferente do WiFi) para simular paciente real.
                                    </li>
                                    <li>Tente fluxo correto + tente abusar (4 submits errados). Volte aqui pra ver os logs em <b>"Tentativas recentes"</b>.</li>
                                    <li>Se notar IP brasileiro legítimo sendo bloqueado falsamente, aumente <b>"Máx tentativas na janela"</b> ou diminua <b>"Falhas até captcha"</b>.</li>
                                </ol>
                            </section>

                            <!-- ── Quando usar paranoid ── -->
                            <section>
                                <div class="font-semibold text-[1rem] mb-2">
                                    <i class="pi pi-exclamation-triangle mr-2 text-rose-400" />
                                    Quando ligar o modo paranoid
                                </div>
                                <p class="text-[var(--text-color-secondary)]">
                                    Use SÓ se você ver no dashboard <b>centenas de tentativas/hora</b> de IPs distintos (ataque distribuído real).
                                    Como cada paciente legítimo vai ter que resolver math toda vez, é fricção alta — só vale se a alternativa for floods de cadastro fake.
                                </p>
                                <p class="text-[var(--text-color-secondary)] mt-2">
                                    <b>Lembre de desligar</b> quando o ataque cessar (24-48h depois normalmente). Defina lembrete.
                                </p>
                            </section>

                            <!-- ── O que NÃO protege ── -->
                            <section>
                                <div class="font-semibold text-[1rem] mb-2">
                                    <i class="pi pi-info-circle mr-2 text-amber-400" />
                                    Limitações honestas
                                </div>
                                <ul class="list-disc pl-6 space-y-1 text-[var(--text-color-secondary)]">
                                    <li>Bot <b>dedicado</b> com proxy rotativo + LLM resolvendo math <b>passa</b>. Mas o custo do ataque sobe muito.</li>
                                    <li>Vários pacientes na mesma rede (clínica com WiFi compartilhado) podem disparar rate limit. Se acontecer, ajuste o slider.</li>
                                    <li>Math captcha não é acessível pra todos (deficiência cognitiva, dislexia severa). Se for crítico, diminua <b>"Falhas até captcha"</b> alto pra maior tolerância.</li>
                                    <li>Logs em <span class="font-mono text-xs">public_submission_attempts</span> crescem indefinidamente. Configure cron de limpeza após 30-90 dias.</li>
                                </ul>
                            </section>

                        </div>
                    </AccordionContent>
                </AccordionPanel>
            </Accordion>
        </div>

        <!-- KPIs -->
        <div class="grid grid-cols-2 md:grid-cols-4 gap-3">
            <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-4">
                <div class="text-xs text-[var(--text-color-secondary)]">Submits 24h</div>
                <div class="text-2xl font-bold mt-1">{{ stats.total24h }}</div>
            </div>
            <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-4">
                <div class="text-xs text-[var(--text-color-secondary)]">Bem-sucedidos</div>
                <div class="text-2xl font-bold mt-1 text-emerald-500">{{ stats.success24h }}</div>
            </div>
            <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-4">
                <div class="text-xs text-[var(--text-color-secondary)]">Bloqueados (bot)</div>
                <div class="text-2xl font-bold mt-1 text-amber-500">{{ stats.blocked24h }}</div>
            </div>
            <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-4">
                <div class="text-xs text-[var(--text-color-secondary)]">Captchas barrados</div>
                <div class="text-2xl font-bold mt-1 text-rose-500">{{ stats.captcha24h }}</div>
            </div>
        </div>

        <!-- Configuração -->
        <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
            <div class="font-semibold mb-4">Configuração global</div>

            <div v-if="cfg" class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div class="flex items-center justify-between gap-3 rounded-md border border-[var(--surface-border)] p-3">
                    <div>
                        <div class="text-sm font-medium">Honeypot</div>
                        <div class="text-xs text-[var(--text-color-secondary)]">Campo invisível que bots preenchem.</div>
                    </div>
                    <ToggleSwitch v-model="cfg.honeypot_enabled" />
                </div>

                <div class="flex items-center justify-between gap-3 rounded-md border border-[var(--surface-border)] p-3">
                    <div>
                        <div class="text-sm font-medium">Rate limit</div>
                        <div class="text-xs text-[var(--text-color-secondary)]">Limite de submits por IP por janela.</div>
                    </div>
                    <ToggleSwitch v-model="cfg.rate_limit_enabled" />
                </div>

                <div class="flex items-center justify-between gap-3 rounded-md border border-rose-400/40 bg-rose-400/5 p-3 md:col-span-2">
                    <div>
                        <div class="text-sm font-medium text-rose-300">Modo paranoid</div>
                        <div class="text-xs text-[var(--text-color-secondary)]">Liga: TODO submit exige captcha, mesmo IP novo. Use só sob ataque ativo.</div>
                    </div>
                    <ToggleSwitch v-model="cfg.captcha_required_globally" />
                </div>

                <div>
                    <label class="text-xs text-[var(--text-color-secondary)]">Janela (min)</label>
                    <InputNumber v-model="cfg.rate_limit_window_min" :min="1" :max="1440" class="w-full mt-1" />
                </div>
                <div>
                    <label class="text-xs text-[var(--text-color-secondary)]">Máx tentativas na janela</label>
                    <InputNumber v-model="cfg.rate_limit_max_attempts" :min="1" :max="100" class="w-full mt-1" />
                </div>
                <div>
                    <label class="text-xs text-[var(--text-color-secondary)]">Falhas até exigir captcha</label>
                    <InputNumber v-model="cfg.captcha_after_failures" :min="1" :max="20" class="w-full mt-1" />
                </div>
                <div>
                    <label class="text-xs text-[var(--text-color-secondary)]">Duração do bloqueio (min)</label>
                    <InputNumber v-model="cfg.block_duration_min" :min="1" :max="1440" class="w-full mt-1" />
                </div>
                <div>
                    <label class="text-xs text-[var(--text-color-secondary)]">Janela do captcha condicional (min)</label>
                    <InputNumber v-model="cfg.captcha_required_window_min" :min="1" :max="1440" class="w-full mt-1" />
                </div>
            </div>

            <div class="mt-4 flex items-center justify-end gap-2">
                <Button label="Recarregar" icon="pi pi-refresh" outlined @click="loadConfig" :disabled="cfgSaving" />
                <Button label="Salvar" icon="pi pi-check" @click="saveConfig" :loading="cfgSaving" :disabled="!cfg" />
            </div>
        </div>

        <!-- IPs em estado ativo -->
        <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
            <div class="flex items-center justify-between mb-3">
                <div class="font-semibold">IPs ativos (rate limit)</div>
                <div class="text-xs text-[var(--text-color-secondary)]">
                    {{ ipsCurrentlyBlocked.length }} bloqueados · {{ ipsRequiringCaptcha.length }} exigindo captcha
                </div>
            </div>

            <DataTable :value="blockedIps" :loading="dataLoading" size="small" stripedRows responsiveLayout="scroll">
                <Column header="IP">
                    <template #body="{ data }">
                        <span class="font-mono text-xs">{{ data.ip_hash?.slice(0, 12) }}…</span>
                    </template>
                </Column>
                <Column field="endpoint" header="Endpoint" />
                <Column header="Tentativas" style="width: 8rem">
                    <template #body="{ data }">
                        {{ data.fail_count }}/{{ data.attempt_count }}
                    </template>
                </Column>
                <Column header="Estado">
                    <template #body="{ data }">
                        <Tag v-if="data.blocked_until && new Date(data.blocked_until) > new Date()" value="bloqueado" severity="danger" />
                        <Tag v-else-if="data.requires_captcha_until && new Date(data.requires_captcha_until) > new Date()" value="exige captcha" severity="warn" />
                        <Tag v-else value="ok" severity="success" />
                    </template>
                </Column>
                <Column header="Última">
                    <template #body="{ data }">
                        <span class="text-xs">{{ fmtRelative(data.last_attempt_at) }}</span>
                    </template>
                </Column>
                <Column header="Ações" style="width: 8rem">
                    <template #body="{ data }">
                        <Button icon="pi pi-eraser" text size="small" @click="clearRateLimit(data)" v-tooltip.top="'Limpar bloqueio'" />
                    </template>
                </Column>
            </DataTable>
        </div>

        <!-- Tentativas recentes -->
        <div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
            <div class="flex items-center justify-between mb-3">
                <div class="font-semibold">Tentativas recentes (24h)</div>
                <Button icon="pi pi-refresh" text size="small" @click="loadDashboard" :loading="dataLoading" />
            </div>

            <DataTable :value="recentAttempts" :loading="dataLoading" size="small" stripedRows responsiveLayout="scroll" :paginator="true" :rows="20">
                <Column header="Quando">
                    <template #body="{ data }">
                        <span class="text-xs">{{ fmtRelative(data.created_at) }}</span>
                    </template>
                </Column>
                <Column field="endpoint" header="Endpoint" />
                <Column header="IP">
                    <template #body="{ data }">
                        <span class="font-mono text-xs opacity-70">{{ data.ip_hash?.slice(0, 8) || '—' }}</span>
                    </template>
                </Column>
                <Column header="Estado" style="width: 9rem">
                    <template #body="{ data }">
                        <Tag v-if="data.success" value="ok" severity="success" />
                        <Tag v-else :value="data.blocked_by || 'erro'" :severity="blockedSeverity(data.blocked_by)" />
                    </template>
                </Column>
                <Column field="error_code" header="Motivo">
                    <template #body="{ data }">
                        <span class="text-xs">{{ data.error_code || '—' }}</span>
                    </template>
                </Column>
            </DataTable>
        </div>
    </div>
</template>
