All checks were successful
Dev Build & Deploy Portal / build-deploy (push) Successful in 2m29s
161 lines
7.3 KiB
Vue
161 lines
7.3 KiB
Vue
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { portalService } from '@/services/portalService'
|
|
|
|
definePageMeta({
|
|
layout: 'portal',
|
|
middleware: 'auth',
|
|
})
|
|
|
|
// ─── MOCKS APRESENTAÇÃO — remover antes do deploy ─────────────────────────
|
|
const MOCK_ATIVO = true
|
|
const CERTIDOES_MOCK = [
|
|
{
|
|
id: 1,
|
|
tipo: 'Certidão Negativa de Débitos',
|
|
numero: '2024/0042',
|
|
dataEmissao: '2024-03-10',
|
|
dataValidade: '2025-03-10',
|
|
status: 'ATIVA',
|
|
},
|
|
{
|
|
id: 2,
|
|
tipo: 'Certidão de Regularidade Fiscal',
|
|
numero: '2023/0187',
|
|
dataEmissao: '2023-06-15',
|
|
dataValidade: '2024-06-15',
|
|
status: 'VENCIDA',
|
|
},
|
|
]
|
|
// ──────────────────────────────────────────────────────────────────────────
|
|
|
|
const router = useRouter()
|
|
const certidoes = ref([])
|
|
const carregando = ref(true)
|
|
const carregandoPdf = ref(null)
|
|
const mensagemErro = ref('')
|
|
|
|
onMounted(carregar)
|
|
|
|
async function carregar() {
|
|
carregando.value = true
|
|
mensagemErro.value = ''
|
|
try {
|
|
const res = await portalService.getCertidoes()
|
|
certidoes.value = res.data ?? []
|
|
if (MOCK_ATIVO && certidoes.value.length === 0) {
|
|
certidoes.value = CERTIDOES_MOCK
|
|
}
|
|
} catch (e) {
|
|
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar as certidões.'
|
|
if (MOCK_ATIVO) {
|
|
certidoes.value = CERTIDOES_MOCK
|
|
mensagemErro.value = ''
|
|
}
|
|
} finally {
|
|
carregando.value = false
|
|
}
|
|
}
|
|
|
|
async function reemitir(cert) {
|
|
carregandoPdf.value = cert.id
|
|
try {
|
|
const buf = await portalService.reemitirCertidao(cert.id)
|
|
const url = URL.createObjectURL(new Blob([buf], { type: 'application/pdf' }))
|
|
const a = document.createElement('a')
|
|
a.href = url
|
|
a.download = `certidao-${cert.numero}.pdf`
|
|
a.click()
|
|
URL.revokeObjectURL(url)
|
|
} catch {
|
|
mensagemErro.value = 'Erro ao reemitir a certidão.'
|
|
} finally {
|
|
carregandoPdf.value = null
|
|
}
|
|
}
|
|
|
|
const statusMap = {
|
|
ATIVA: { label: 'Ativa', classe: 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-400' },
|
|
VENCIDA: { label: 'Vencida', classe: 'bg-slate-100 dark:bg-slate-700 text-slate-500 dark:text-slate-400' },
|
|
CANCELADA: { label: 'Cancelada', classe: 'bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-400' },
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="space-y-6">
|
|
<div class="flex items-center justify-between gap-4 flex-wrap">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-slate-800 dark:text-slate-100">Certidões</h1>
|
|
<p class="text-sm text-slate-500 dark:text-slate-400 mt-0.5">Suas certidões emitidas e disponíveis para reemissão.</p>
|
|
</div>
|
|
<Button label="Nova certidão" icon="pi pi-plus" size="small" @click="router.push('/servicos/certidao?from=portal')" />
|
|
</div>
|
|
|
|
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden">
|
|
|
|
<div v-if="carregando" class="divide-y divide-slate-100 dark:divide-slate-700">
|
|
<div v-for="i in 4" :key="i" class="p-5 flex items-center gap-4">
|
|
<div class="flex-1 space-y-2">
|
|
<div class="h-3.5 bg-slate-200 dark:bg-slate-700 rounded animate-pulse w-2/5" />
|
|
<div class="h-3 bg-slate-200 dark:bg-slate-700 rounded animate-pulse w-1/4" />
|
|
</div>
|
|
<div class="h-6 bg-slate-200 dark:bg-slate-700 rounded-full animate-pulse w-14" />
|
|
<div class="h-8 bg-slate-200 dark:bg-slate-700 rounded-lg animate-pulse w-24" />
|
|
</div>
|
|
</div>
|
|
|
|
<div v-else-if="mensagemErro" class="p-8 text-center">
|
|
<p class="text-sm text-slate-600 dark:text-slate-300">{{ mensagemErro }}</p>
|
|
<Button label="Tentar novamente" severity="secondary" size="small" class="mt-4" @click="carregar" />
|
|
</div>
|
|
|
|
<div v-else-if="certidoes.length === 0" class="p-12 text-center">
|
|
<i class="pi pi-file text-slate-300 dark:text-slate-600 text-4xl mb-3 block" aria-hidden="true" />
|
|
<p class="font-semibold text-slate-700 dark:text-slate-200">Nenhuma certidão emitida</p>
|
|
<p class="text-sm text-slate-400 dark:text-slate-500 mt-1 mb-4">Emita sua primeira certidão pelo portal público.</p>
|
|
<Button label="Emitir certidão" size="small" @click="router.push('/servicos/certidao?from=portal')" />
|
|
</div>
|
|
|
|
<div v-else>
|
|
<div class="flex items-center gap-4 px-5 py-3 bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700 text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">
|
|
<span class="flex-1">Certidão</span>
|
|
<span class="hidden sm:block w-28 text-right">Emissão</span>
|
|
<span class="hidden sm:block w-28 text-right">Validade</span>
|
|
<span class="w-20 text-center">Status</span>
|
|
<span class="w-24" />
|
|
</div>
|
|
<div class="divide-y divide-slate-100 dark:divide-slate-700">
|
|
<div
|
|
v-for="cert in certidoes"
|
|
:key="cert.id"
|
|
class="flex items-center gap-4 px-5 py-4 hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors"
|
|
>
|
|
<div class="flex-1 min-w-0">
|
|
<p class="text-sm font-semibold text-slate-800 dark:text-slate-100 truncate">{{ cert.tipo }}</p>
|
|
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Nº {{ cert.numero }}</p>
|
|
</div>
|
|
<p class="hidden sm:block text-sm text-slate-500 dark:text-slate-400 w-28 text-right">{{ cert.dataEmissao }}</p>
|
|
<p class="hidden sm:block text-sm text-slate-500 dark:text-slate-400 w-28 text-right">{{ cert.dataValidade }}</p>
|
|
<div class="w-20 flex justify-center">
|
|
<span :class="['text-xs font-semibold px-2 py-1 rounded-full', statusMap[cert.status]?.classe ?? 'bg-slate-100 text-slate-500']">
|
|
{{ statusMap[cert.status]?.label ?? cert.status }}
|
|
</span>
|
|
</div>
|
|
<div class="w-24 flex justify-end">
|
|
<Button
|
|
icon="pi pi-download"
|
|
label="PDF"
|
|
size="small"
|
|
outlined
|
|
:loading="carregandoPdf === cert.id"
|
|
:disabled="cert.status === 'CANCELADA' || !!carregandoPdf"
|
|
@click="reemitir(cert)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|