developer #4
@ -1,44 +1,82 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
import { useAuth } from '@/composables/useAuth'
|
import { useAuth } from '@/composables/useAuth'
|
||||||
|
import { usePrefeituraStore } from '@/stores/prefeituraStore'
|
||||||
|
|
||||||
const { nomeUsuario, logout } = useAuth()
|
const { nomeUsuario, logout } = useAuth()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const prefeitura = usePrefeituraStore()
|
||||||
|
|
||||||
|
const menuAberto = ref(false)
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ path: '/portal/painel', label: 'Painel' },
|
{ path: '/portal/painel', label: 'Painel', icon: 'pi-home' },
|
||||||
{ path: '/portal/debitos', label: 'Débitos' },
|
{ path: '/portal/debitos', label: 'Débitos', icon: 'pi-receipt' },
|
||||||
{ path: '/portal/certidoes', label: 'Certidões' },
|
{ path: '/portal/certidoes', label: 'Certidões', icon: 'pi-file-check' },
|
||||||
{ path: '/portal/alvaras', label: 'Alvarás' },
|
{ path: '/portal/alvaras', label: 'Alvarás', icon: 'pi-briefcase' },
|
||||||
{ path: '/portal/pagamentos', label: 'Pagamentos' },
|
{ path: '/portal/pagamentos', label: 'Pagamentos', icon: 'pi-credit-card' },
|
||||||
{ path: '/portal/dados', label: 'Dados Cadastrais' },
|
{ path: '/portal/dados', label: 'Dados Cadastrais', icon: 'pi-user' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
function navegar(path) {
|
||||||
|
menuAberto.value = false
|
||||||
|
router.push(path)
|
||||||
|
}
|
||||||
|
|
||||||
function sair() {
|
function sair() {
|
||||||
|
menuAberto.value = false
|
||||||
logout()
|
logout()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex flex-col bg-slate-50 dark:bg-slate-950">
|
<div class="min-h-screen flex flex-col bg-slate-50 dark:bg-slate-950">
|
||||||
|
|
||||||
<header class="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-700 sticky top-0 z-40" role="banner">
|
<header class="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-700 sticky top-0 z-40" role="banner">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center gap-3">
|
||||||
|
|
||||||
|
<!-- Hambúrguer — mobile only -->
|
||||||
|
<button
|
||||||
|
class="md:hidden flex items-center justify-center w-9 h-9 rounded-lg text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors flex-shrink-0"
|
||||||
|
aria-label="Abrir menu de navegação"
|
||||||
|
aria-expanded="menuAberto"
|
||||||
|
aria-controls="mobile-drawer"
|
||||||
|
@click="menuAberto = true"
|
||||||
|
>
|
||||||
|
<i class="pi pi-bars text-base" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Logo + título -->
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="/portal/painel"
|
to="/portal/painel"
|
||||||
class="flex items-center gap-3"
|
class="flex items-center gap-2.5 min-w-0 flex-shrink-0"
|
||||||
aria-label="Ir para o painel principal"
|
aria-label="Ir para o painel principal"
|
||||||
>
|
>
|
||||||
<div class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center">
|
<img
|
||||||
|
v-if="prefeitura.pathLogo"
|
||||||
|
:src="prefeitura.pathLogo"
|
||||||
|
:alt="prefeitura.nomePrefeitura ?? 'Logo do município'"
|
||||||
|
class="h-8 w-auto object-contain flex-shrink-0"
|
||||||
|
/>
|
||||||
|
<div v-else class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center flex-shrink-0">
|
||||||
<i class="pi pi-building text-white text-sm" aria-hidden="true" />
|
<i class="pi pi-building text-white text-sm" aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
<span class="font-semibold text-slate-800 dark:text-slate-100">Portal do Contribuinte</span>
|
<div class="flex flex-col leading-tight min-w-0">
|
||||||
|
<span class="font-semibold text-slate-800 dark:text-slate-100 text-sm truncate">Portal do Contribuinte</span>
|
||||||
|
<span v-if="prefeitura.nomePrefeitura" class="text-xs text-slate-400 dark:text-slate-500 truncate hidden sm:block">
|
||||||
|
{{ prefeitura.nomePrefeitura }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<nav aria-label="Menu do contribuinte" class="hidden md:flex items-center gap-1">
|
<!-- Nav desktop -->
|
||||||
|
<nav aria-label="Menu do contribuinte" class="hidden md:flex items-center gap-1 flex-1 justify-center">
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-for="item in navItems"
|
v-for="item in navItems"
|
||||||
:key="item.path"
|
:key="item.path"
|
||||||
:to="item.path"
|
:to="item.path"
|
||||||
class="px-4 py-2 rounded-lg text-sm text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-100 transition-colors"
|
class="px-3 py-2 rounded-lg text-sm text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-100 transition-colors whitespace-nowrap"
|
||||||
active-class="bg-primary/10 text-primary font-semibold"
|
active-class="bg-primary/10 text-primary font-semibold"
|
||||||
:aria-current="route.path === item.path ? 'page' : undefined"
|
:aria-current="route.path === item.path ? 'page' : undefined"
|
||||||
>
|
>
|
||||||
@ -46,8 +84,9 @@ function sair() {
|
|||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="flex items-center gap-3">
|
<!-- Ações desktop -->
|
||||||
<span class="hidden sm:block text-sm text-slate-600 dark:text-slate-300" aria-live="polite">
|
<div class="hidden md:flex items-center gap-3 flex-shrink-0 ml-auto">
|
||||||
|
<span class="text-sm text-slate-600 dark:text-slate-300 truncate max-w-40" aria-live="polite">
|
||||||
{{ nomeUsuario }}
|
{{ nomeUsuario }}
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<Button
|
||||||
@ -60,10 +99,90 @@ function sair() {
|
|||||||
@click="sair"
|
@click="sair"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Ícone de usuário — mobile only, fica à direita -->
|
||||||
|
<button
|
||||||
|
class="md:hidden ml-auto flex items-center justify-center w-9 h-9 rounded-full bg-primary/10 dark:bg-primary/20 text-primary flex-shrink-0"
|
||||||
|
aria-label="Opções do usuário"
|
||||||
|
@click="menuAberto = true"
|
||||||
|
>
|
||||||
|
<i class="pi pi-user text-sm" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="main-content" tabindex="-1" class="flex-1 max-w-7xl mx-auto w-full px-4 sm:px-6 lg:px-8 py-8 outline-none">
|
<!-- Drawer mobile -->
|
||||||
|
<Drawer
|
||||||
|
id="mobile-drawer"
|
||||||
|
v-model:visible="menuAberto"
|
||||||
|
position="left"
|
||||||
|
:style="{ width: '17rem' }"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-2.5">
|
||||||
|
<img
|
||||||
|
v-if="prefeitura.pathLogo"
|
||||||
|
:src="prefeitura.pathLogo"
|
||||||
|
:alt="prefeitura.nomePrefeitura ?? 'Logo do município'"
|
||||||
|
class="h-7 w-auto object-contain"
|
||||||
|
/>
|
||||||
|
<div v-else class="w-7 h-7 bg-primary rounded-lg flex items-center justify-center">
|
||||||
|
<i class="pi pi-building text-white text-xs" aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col leading-tight min-w-0">
|
||||||
|
<span class="font-semibold text-slate-800 dark:text-slate-100 text-sm">Portal</span>
|
||||||
|
<span v-if="prefeitura.nomePrefeitura" class="text-xs text-slate-400 dark:text-slate-500 truncate">
|
||||||
|
{{ prefeitura.nomePrefeitura }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="flex flex-col h-full -mx-4 px-2">
|
||||||
|
|
||||||
|
<!-- Info do usuário -->
|
||||||
|
<div class="px-2 pb-4 mb-3 border-b border-slate-200 dark:border-slate-700">
|
||||||
|
<p class="text-xs text-slate-400 dark:text-slate-500 uppercase tracking-wide mb-0.5">Logado como</p>
|
||||||
|
<p class="text-sm font-semibold text-slate-800 dark:text-slate-100 truncate">{{ nomeUsuario }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Links de navegação -->
|
||||||
|
<nav class="flex flex-col gap-0.5 flex-1" aria-label="Menu de navegação mobile">
|
||||||
|
<button
|
||||||
|
v-for="item in navItems"
|
||||||
|
:key="item.path"
|
||||||
|
class="flex items-center gap-3 w-full px-3 py-3 rounded-xl text-sm font-medium transition-colors text-left"
|
||||||
|
:class="route.path === item.path
|
||||||
|
? 'bg-primary/10 dark:bg-primary/15 text-primary'
|
||||||
|
: 'text-slate-600 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800'"
|
||||||
|
:aria-current="route.path === item.path ? 'page' : undefined"
|
||||||
|
@click="navegar(item.path)"
|
||||||
|
>
|
||||||
|
<i :class="['pi', item.icon, 'text-base w-5 text-center flex-shrink-0']" aria-hidden="true" />
|
||||||
|
{{ item.label }}
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Sair -->
|
||||||
|
<div class="pt-3 mt-3 border-t border-slate-200 dark:border-slate-700">
|
||||||
|
<button
|
||||||
|
class="flex items-center gap-3 w-full px-3 py-3 rounded-xl text-sm font-medium text-slate-600 dark:text-slate-300 hover:bg-red-50 dark:hover:bg-red-900/20 hover:text-red-600 dark:hover:text-red-400 transition-colors"
|
||||||
|
@click="sair"
|
||||||
|
>
|
||||||
|
<i class="pi pi-sign-out text-base w-5 text-center flex-shrink-0" aria-hidden="true" />
|
||||||
|
Sair do portal
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
|
||||||
|
<main
|
||||||
|
id="main-content"
|
||||||
|
tabindex="-1"
|
||||||
|
class="flex-1 max-w-7xl mx-auto w-full px-4 sm:px-6 lg:px-8 py-6 sm:py-8 outline-none"
|
||||||
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
5
src/pages/entrar.vue
Normal file
5
src/pages/entrar.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<script setup>
|
||||||
|
const { isAuthenticated } = useAuth()
|
||||||
|
|
||||||
|
await navigateTo(isAuthenticated.value ? '/portal/painel' : '/', { replace: true })
|
||||||
|
</script>
|
||||||
@ -7,11 +7,49 @@ definePageMeta({
|
|||||||
middleware: 'auth',
|
middleware: 'auth',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ─── MOCKS APRESENTAÇÃO — remover antes do deploy ─────────────────────────
|
||||||
|
const MOCK_ATIVO = true
|
||||||
|
const ALVARAS_MOCK = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
tipo: 'Alvará de Funcionamento',
|
||||||
|
numero: 'ALV-2024/0051',
|
||||||
|
status: 'EM_ANALISE',
|
||||||
|
etapas: [
|
||||||
|
{ nome: 'Protocolo', concluida: true, atual: false },
|
||||||
|
{ nome: 'Pagamento', concluida: true, atual: false },
|
||||||
|
{ nome: 'Análise', concluida: false, atual: true },
|
||||||
|
{ nome: 'Emissão', concluida: false, atual: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
tipo: 'Licença Sanitária',
|
||||||
|
numero: 'ALV-2023/0198',
|
||||||
|
status: 'DEFERIDO',
|
||||||
|
etapas: [
|
||||||
|
{ nome: 'Protocolo', concluida: true, atual: false },
|
||||||
|
{ nome: 'Pagamento', concluida: true, atual: false },
|
||||||
|
{ nome: 'Análise', concluida: true, atual: false },
|
||||||
|
{ nome: 'Emissão', concluida: true, atual: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
const alvaras = ref([])
|
const alvaras = ref([])
|
||||||
const carregando = ref(true)
|
const carregando = ref(true)
|
||||||
const mensagemErro = ref('')
|
const mensagemErro = ref('')
|
||||||
const filtroStatus = ref(null)
|
const filtroStatus = ref(null)
|
||||||
|
|
||||||
|
const situacaoMap = {
|
||||||
|
EM_ANALISE: 0,
|
||||||
|
AGUARDANDO_DOCUMENTOS: 1,
|
||||||
|
DEFERIDO: 2,
|
||||||
|
INDEFERIDO: 3,
|
||||||
|
CANCELADO: 4,
|
||||||
|
}
|
||||||
|
|
||||||
const statusOptions = [
|
const statusOptions = [
|
||||||
{ value: 'EM_ANALISE', label: 'Em análise' },
|
{ value: 'EM_ANALISE', label: 'Em análise' },
|
||||||
{ value: 'AGUARDANDO_DOCUMENTOS', label: 'Aguardando documentos' },
|
{ value: 'AGUARDANDO_DOCUMENTOS', label: 'Aguardando documentos' },
|
||||||
@ -34,11 +72,26 @@ async function carregar() {
|
|||||||
carregando.value = true
|
carregando.value = true
|
||||||
mensagemErro.value = ''
|
mensagemErro.value = ''
|
||||||
try {
|
try {
|
||||||
const params = filtroStatus.value ? { status: filtroStatus.value } : {}
|
const params = filtroStatus.value
|
||||||
|
? { situacao: situacaoMap[filtroStatus.value] }
|
||||||
|
: {}
|
||||||
const res = await portalService.getAlvaras(params)
|
const res = await portalService.getAlvaras(params)
|
||||||
alvaras.value = res.data?.content ?? []
|
alvaras.value = res.data ?? []
|
||||||
|
if (MOCK_ATIVO && alvaras.value.length === 0) {
|
||||||
|
const mockFiltrado = filtroStatus.value
|
||||||
|
? ALVARAS_MOCK.filter(a => a.status === filtroStatus.value)
|
||||||
|
: ALVARAS_MOCK
|
||||||
|
alvaras.value = mockFiltrado
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar os alvarás.'
|
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar os alvarás.'
|
||||||
|
if (MOCK_ATIVO) {
|
||||||
|
const mockFiltrado = filtroStatus.value
|
||||||
|
? ALVARAS_MOCK.filter(a => a.status === filtroStatus.value)
|
||||||
|
: ALVARAS_MOCK
|
||||||
|
alvaras.value = mockFiltrado
|
||||||
|
mensagemErro.value = ''
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
carregando.value = false
|
carregando.value = false
|
||||||
}
|
}
|
||||||
@ -102,7 +155,7 @@ async function carregar() {
|
|||||||
<div class="flex items-start justify-between gap-4 mb-2">
|
<div class="flex items-start justify-between gap-4 mb-2">
|
||||||
<div>
|
<div>
|
||||||
<p class="font-semibold text-slate-800 dark:text-slate-100 text-sm">{{ alv.tipo }}</p>
|
<p class="font-semibold text-slate-800 dark:text-slate-100 text-sm">{{ alv.tipo }}</p>
|
||||||
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Processo nº {{ alv.numeroProcesso }}</p>
|
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Processo nº {{ alv.numero }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2 flex-shrink-0">
|
<div class="flex items-center gap-2 flex-shrink-0">
|
||||||
<i :class="['pi', statusMap[alv.status]?.icone ?? 'pi-circle', 'text-xs', statusMap[alv.status]?.classe?.split(' ').find(c => c.startsWith('text'))]" aria-hidden="true" />
|
<i :class="['pi', statusMap[alv.status]?.icone ?? 'pi-circle', 'text-xs', statusMap[alv.status]?.classe?.split(' ').find(c => c.startsWith('text'))]" aria-hidden="true" />
|
||||||
@ -135,10 +188,6 @@ async function carregar() {
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p v-if="alv.ultimaAtualizacao" class="text-xs text-slate-400 dark:text-slate-500 mt-3">
|
|
||||||
Última atualização: {{ alv.ultimaAtualizacao }}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,6 +7,28 @@ definePageMeta({
|
|||||||
middleware: 'auth',
|
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 router = useRouter()
|
||||||
const certidoes = ref([])
|
const certidoes = ref([])
|
||||||
const carregando = ref(true)
|
const carregando = ref(true)
|
||||||
@ -20,9 +42,16 @@ async function carregar() {
|
|||||||
mensagemErro.value = ''
|
mensagemErro.value = ''
|
||||||
try {
|
try {
|
||||||
const res = await portalService.getCertidoes()
|
const res = await portalService.getCertidoes()
|
||||||
certidoes.value = res.data?.content ?? []
|
certidoes.value = res.data ?? []
|
||||||
|
if (MOCK_ATIVO && certidoes.value.length === 0) {
|
||||||
|
certidoes.value = CERTIDOES_MOCK
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar as certidões.'
|
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar as certidões.'
|
||||||
|
if (MOCK_ATIVO) {
|
||||||
|
certidoes.value = CERTIDOES_MOCK
|
||||||
|
mensagemErro.value = ''
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
carregando.value = false
|
carregando.value = false
|
||||||
}
|
}
|
||||||
@ -59,7 +88,7 @@ const statusMap = {
|
|||||||
<h1 class="text-2xl font-bold text-slate-800 dark:text-slate-100">Certidões</h1>
|
<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>
|
<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>
|
</div>
|
||||||
<Button label="Nova certidão" icon="pi pi-plus" size="small" @click="router.push('/servicos/certidao')" />
|
<Button label="Nova certidão" icon="pi pi-plus" size="small" @click="router.push('/servicos/certidao?from=portal')" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden">
|
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||||
@ -84,7 +113,7 @@ const statusMap = {
|
|||||||
<i class="pi pi-file text-slate-300 dark:text-slate-600 text-4xl mb-3 block" aria-hidden="true" />
|
<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="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>
|
<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')" />
|
<Button label="Emitir certidão" size="small" @click="router.push('/servicos/certidao?from=portal')" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
|||||||
@ -113,13 +113,13 @@ function formatarTelefone(e) {
|
|||||||
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-6">
|
<div class="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-6">
|
||||||
<p class="text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-wide mb-4">Endereço</p>
|
<p class="text-xs font-bold text-slate-500 dark:text-slate-400 uppercase tracking-wide mb-4">Endereço</p>
|
||||||
<p class="text-sm text-slate-800 dark:text-slate-100">
|
<p class="text-sm text-slate-800 dark:text-slate-100">
|
||||||
{{ dados.endereco?.logradouro }}, {{ dados.endereco?.numero }}
|
{{ dados.logradouro }}, {{ dados.numero }}
|
||||||
<template v-if="dados.endereco?.complemento"> — {{ dados.endereco.complemento }}</template>
|
<template v-if="dados.complemento"> — {{ dados.complemento }}</template>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-sm text-slate-600 dark:text-slate-300 mt-0.5">
|
<p class="text-sm text-slate-600 dark:text-slate-300 mt-0.5">
|
||||||
{{ dados.endereco?.bairro }} — {{ dados.endereco?.cidade }}/{{ dados.endereco?.uf }}
|
{{ dados.bairro }}<template v-if="dados.cidade"> — {{ dados.cidade }}</template>/{{ dados.uf }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs text-slate-400 dark:text-slate-500 mt-1">CEP: {{ dados.endereco?.cep }}</p>
|
<p class="text-xs text-slate-400 dark:text-slate-500 mt-1">CEP: {{ dados.cep }}</p>
|
||||||
<p class="text-xs text-slate-400 dark:text-slate-500 mt-3">
|
<p class="text-xs text-slate-400 dark:text-slate-500 mt-3">
|
||||||
Para alterar o endereço, compareça ao setor de atendimento da Prefeitura.
|
Para alterar o endereço, compareça ao setor de atendimento da Prefeitura.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -34,7 +34,7 @@ async function carregar() {
|
|||||||
if (filtroTipo.value) params.tipo = filtroTipo.value
|
if (filtroTipo.value) params.tipo = filtroTipo.value
|
||||||
if (filtroStatus.value) params.status = filtroStatus.value
|
if (filtroStatus.value) params.status = filtroStatus.value
|
||||||
const res = await portalService.getDebitos(params)
|
const res = await portalService.getDebitos(params)
|
||||||
debitos.value = res.data?.content ?? []
|
debitos.value = res.data ?? []
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar os débitos.'
|
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar os débitos.'
|
||||||
} finally {
|
} finally {
|
||||||
@ -52,8 +52,11 @@ async function emitirGuia(debito) {
|
|||||||
a.download = `guia-${debito.id}.pdf`
|
a.download = `guia-${debito.id}.pdf`
|
||||||
a.click()
|
a.click()
|
||||||
URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
} catch {
|
} catch (e) {
|
||||||
mensagemErro.value = 'Erro ao gerar a guia. Tente novamente.'
|
const status = e?.status ?? e?.response?.status
|
||||||
|
mensagemErro.value = status === 501
|
||||||
|
? 'Emissão de guia em configuração. Procure a prefeitura para geração manual.'
|
||||||
|
: 'Erro ao gerar a guia. Tente novamente.'
|
||||||
} finally {
|
} finally {
|
||||||
carregandoGuia.value = null
|
carregandoGuia.value = null
|
||||||
}
|
}
|
||||||
@ -84,6 +87,19 @@ function limparFiltros() {
|
|||||||
filtroStatus.value = null
|
filtroStatus.value = null
|
||||||
carregar()
|
carregar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tituloDebito(d) {
|
||||||
|
if (d.tipo && d.referencia) return `${d.tipo} — ${d.referencia}`
|
||||||
|
if (d.tipo) return d.tipo
|
||||||
|
return d.descricao ?? 'Débito'
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatarData(iso) {
|
||||||
|
if (!iso) return '—'
|
||||||
|
const partes = String(iso).split('-')
|
||||||
|
if (partes.length !== 3) return iso
|
||||||
|
return `${partes[2]}/${partes[1]}/${partes[0]}`
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -174,10 +190,11 @@ function limparFiltros() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
<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">
|
<!-- Cabeçalho — apenas desktop -->
|
||||||
|
<div class="hidden sm: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">
|
||||||
<Checkbox :binary="true" @change="toggleTodos($event.target.checked)" />
|
<Checkbox :binary="true" @change="toggleTodos($event.target.checked)" />
|
||||||
<span class="flex-1">Descrição</span>
|
<span class="flex-1">Descrição</span>
|
||||||
<span class="hidden sm:block w-28 text-right">Vencimento</span>
|
<span class="w-28 text-right">Vencimento</span>
|
||||||
<span class="w-28 text-right">Valor</span>
|
<span class="w-28 text-right">Valor</span>
|
||||||
<span class="w-20 text-center">Status</span>
|
<span class="w-20 text-center">Status</span>
|
||||||
<span class="w-28" />
|
<span class="w-28" />
|
||||||
@ -187,43 +204,78 @@ function limparFiltros() {
|
|||||||
<div
|
<div
|
||||||
v-for="debito in debitos"
|
v-for="debito in debitos"
|
||||||
:key="debito.id"
|
:key="debito.id"
|
||||||
class="flex items-center gap-4 px-5 py-4 hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors"
|
class="hover:bg-slate-50 dark:hover:bg-slate-700/30 transition-colors"
|
||||||
>
|
>
|
||||||
<Checkbox v-model="debito._selecionado" :binary="true" />
|
<!-- MOBILE -->
|
||||||
|
<div class="sm:hidden p-4 space-y-3">
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex items-start gap-3">
|
||||||
<p class="text-sm font-semibold text-slate-800 dark:text-slate-100 truncate">{{ debito.descricao }}</p>
|
<Checkbox v-model="debito._selecionado" :binary="true" class="mt-0.5 shrink-0" />
|
||||||
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">{{ debito.tipo }} · Ref: {{ debito.referencia }}</p>
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="text-sm font-bold text-slate-800 dark:text-slate-100 leading-snug">{{ tituloDebito(debito) }}</p>
|
||||||
|
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Nº {{ debito.descricao }}</p>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
:class="['text-xs font-semibold px-2 py-1 rounded-full whitespace-nowrap shrink-0', statusClasse[debito.status] ?? 'bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300']"
|
||||||
|
>
|
||||||
|
{{ statusLabel[debito.status] ?? debito.status }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-end justify-between pl-7">
|
||||||
|
<div>
|
||||||
|
<p class="text-xs text-slate-400 dark:text-slate-500">Vence em {{ formatarData(debito.vencimento) }}</p>
|
||||||
|
<p class="text-base font-bold text-slate-800 dark:text-slate-100 mt-0.5">{{ formatarMoeda(debito.valorAtualizado ?? debito.valor) }}</p>
|
||||||
|
<p v-if="debito.valorAtualizado > debito.valor" class="text-xs text-slate-400 line-through">{{ formatarMoeda(debito.valor) }}</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
icon="pi pi-download"
|
||||||
|
label="Emitir guia"
|
||||||
|
size="small"
|
||||||
|
outlined
|
||||||
|
:loading="carregandoGuia === debito.id"
|
||||||
|
:disabled="!!carregandoGuia"
|
||||||
|
@click="emitirGuia(debito)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="hidden sm:block text-sm text-slate-500 dark:text-slate-400 w-28 text-right whitespace-nowrap">
|
<!-- DESKTOP -->
|
||||||
{{ debito.vencimento }}
|
<div class="hidden sm:flex items-center gap-4 px-5 py-4">
|
||||||
</p>
|
<Checkbox v-model="debito._selecionado" :binary="true" />
|
||||||
|
|
||||||
<div class="w-28 text-right">
|
<div class="flex-1 min-w-0">
|
||||||
<p class="text-sm font-bold text-slate-800 dark:text-slate-100">{{ formatarMoeda(debito.valorAtualizado ?? debito.valor) }}</p>
|
<p class="text-sm font-semibold text-slate-800 dark:text-slate-100 truncate">{{ tituloDebito(debito) }}</p>
|
||||||
<p v-if="debito.valorAtualizado > debito.valor" class="text-xs text-slate-400 line-through">{{ formatarMoeda(debito.valor) }}</p>
|
<p class="text-xs text-slate-400 dark:text-slate-500 mt-0.5">Nº {{ debito.descricao }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-20 flex justify-center">
|
<p class="text-sm text-slate-500 dark:text-slate-400 w-28 text-right whitespace-nowrap">
|
||||||
<span
|
{{ formatarData(debito.vencimento) }}
|
||||||
:class="['text-xs font-semibold px-2 py-1 rounded-full whitespace-nowrap', statusClasse[debito.status] ?? 'bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300']"
|
</p>
|
||||||
>
|
|
||||||
{{ statusLabel[debito.status] ?? debito.status }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="w-28 flex justify-end">
|
<div class="w-28 text-right">
|
||||||
<Button
|
<p class="text-sm font-bold text-slate-800 dark:text-slate-100">{{ formatarMoeda(debito.valorAtualizado ?? debito.valor) }}</p>
|
||||||
label="Emitir guia"
|
<p v-if="debito.valorAtualizado > debito.valor" class="text-xs text-slate-400 line-through">{{ formatarMoeda(debito.valor) }}</p>
|
||||||
icon="pi pi-download"
|
</div>
|
||||||
size="small"
|
|
||||||
outlined
|
<div class="w-20 flex justify-center">
|
||||||
class="whitespace-nowrap"
|
<span
|
||||||
:loading="carregandoGuia === debito.id"
|
:class="['text-xs font-semibold px-2 py-1 rounded-full whitespace-nowrap', statusClasse[debito.status] ?? 'bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300']"
|
||||||
:disabled="!!carregandoGuia"
|
>
|
||||||
@click="emitirGuia(debito)"
|
{{ statusLabel[debito.status] ?? debito.status }}
|
||||||
/>
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-28 flex justify-end">
|
||||||
|
<Button
|
||||||
|
label="Emitir guia"
|
||||||
|
icon="pi pi-download"
|
||||||
|
size="small"
|
||||||
|
outlined
|
||||||
|
class="whitespace-nowrap"
|
||||||
|
:loading="carregandoGuia === debito.id"
|
||||||
|
:disabled="!!carregandoGuia"
|
||||||
|
@click="emitirGuia(debito)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,6 +7,36 @@ definePageMeta({
|
|||||||
middleware: 'auth',
|
middleware: 'auth',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ─── MOCKS APRESENTAÇÃO — remover antes do deploy ─────────────────────────
|
||||||
|
const MOCK_ATIVO = true
|
||||||
|
const PAGAMENTOS_MOCK = [
|
||||||
|
{
|
||||||
|
id: 101,
|
||||||
|
descricao: 'IPTU 2024 — Parcela 1/3',
|
||||||
|
referencia: '202401',
|
||||||
|
dataPagamento: '2024-02-05',
|
||||||
|
formaPagamento: 'BOLETO',
|
||||||
|
valor: 382.50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 102,
|
||||||
|
descricao: 'Taxa de Licença de Funcionamento',
|
||||||
|
referencia: '202403',
|
||||||
|
dataPagamento: '2024-03-20',
|
||||||
|
formaPagamento: 'PIX',
|
||||||
|
valor: 215.00,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 103,
|
||||||
|
descricao: 'ISSQN 2023 — 4º Trimestre',
|
||||||
|
referencia: '202312',
|
||||||
|
dataPagamento: '2024-01-10',
|
||||||
|
formaPagamento: 'BOLETO',
|
||||||
|
valor: 540.00,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
const pagamentos = ref([])
|
const pagamentos = ref([])
|
||||||
const carregando = ref(true)
|
const carregando = ref(true)
|
||||||
const carregandoComprovante = ref(null)
|
const carregandoComprovante = ref(null)
|
||||||
@ -22,9 +52,16 @@ async function carregar() {
|
|||||||
mensagemErro.value = ''
|
mensagemErro.value = ''
|
||||||
try {
|
try {
|
||||||
const res = await portalService.getPagamentos({ ano: filtroAno.value })
|
const res = await portalService.getPagamentos({ ano: filtroAno.value })
|
||||||
pagamentos.value = res.data?.content ?? []
|
pagamentos.value = res.data ?? []
|
||||||
|
if (MOCK_ATIVO && pagamentos.value.length === 0) {
|
||||||
|
pagamentos.value = PAGAMENTOS_MOCK
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar os pagamentos.'
|
mensagemErro.value = e?.data?.description ?? 'Não foi possível carregar os pagamentos.'
|
||||||
|
if (MOCK_ATIVO) {
|
||||||
|
pagamentos.value = PAGAMENTOS_MOCK
|
||||||
|
mensagemErro.value = ''
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
carregando.value = false
|
carregando.value = false
|
||||||
}
|
}
|
||||||
@ -56,6 +93,8 @@ const formaPagMap = {
|
|||||||
PIX: { label: 'Pix', icone: 'pi-qrcode' },
|
PIX: { label: 'Pix', icone: 'pi-qrcode' },
|
||||||
CARTAO: { label: 'Cartão', icone: 'pi-credit-card' },
|
CARTAO: { label: 'Cartão', icone: 'pi-credit-card' },
|
||||||
TRANSFERENCIA: { label: 'Transferência', icone: 'pi-arrow-right-arrow-left' },
|
TRANSFERENCIA: { label: 'Transferência', icone: 'pi-arrow-right-arrow-left' },
|
||||||
|
GUIA: { label: 'Guia', icone: 'pi-file' },
|
||||||
|
DIRETO: { label: 'Direto', icone: 'pi-check' },
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useAuth } from '@/composables/useAuth'
|
import { useAuth } from '@/composables/useAuth'
|
||||||
import { portalService } from '@/services/portalService'
|
import { portalService } from '@/services/portalService'
|
||||||
|
import { usePrefeituraStore } from '@/stores/prefeituraStore'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: 'portal',
|
layout: 'portal',
|
||||||
@ -9,6 +10,7 @@ definePageMeta({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { nomeUsuario } = useAuth()
|
const { nomeUsuario } = useAuth()
|
||||||
|
const prefeitura = usePrefeituraStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const resumo = ref(null)
|
const resumo = ref(null)
|
||||||
@ -53,11 +55,22 @@ const iconeAtividade = {
|
|||||||
<template>
|
<template>
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
|
|
||||||
<div>
|
<div class="flex items-center justify-between gap-4 flex-wrap">
|
||||||
<h1 class="text-2xl font-bold text-slate-800 dark:text-slate-100">
|
<div>
|
||||||
Olá, {{ nomeUsuario || 'Contribuinte' }} 👋
|
<p v-if="prefeitura.nomePrefeitura" class="text-xs font-semibold text-primary/70 dark:text-primary/50 uppercase tracking-widest mb-1">
|
||||||
</h1>
|
{{ prefeitura.nomePrefeitura }}
|
||||||
<p class="text-slate-500 dark:text-slate-400 mt-1">Bem-vindo ao seu painel de gestão fiscal.</p>
|
</p>
|
||||||
|
<h1 class="text-2xl font-bold text-slate-800 dark:text-slate-100">
|
||||||
|
Olá, {{ nomeUsuario || 'Contribuinte' }} 👋
|
||||||
|
</h1>
|
||||||
|
<p class="text-slate-500 dark:text-slate-400 mt-1">Bem-vindo ao seu painel de gestão fiscal.</p>
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
v-if="prefeitura.pathLogo"
|
||||||
|
:src="prefeitura.pathLogo"
|
||||||
|
:alt="prefeitura.nomePrefeitura ?? 'Logo do município'"
|
||||||
|
class="h-14 w-auto object-contain opacity-80 dark:opacity-60"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
|
|||||||
@ -144,7 +144,7 @@ async function solicitar() {
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="text-center py-4">
|
<div class="text-center py-4">
|
||||||
<div class="w-16 h-16 bg-emerald-100 dark:bg-emerald-900/30 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
<div class="w-16 h-16 bg-emerald-100 dark:bg-emerald-900/30 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||||
<i class="pi pi-envelope-open text-emerald-600 dark:text-emerald-400 text-3xl" aria-hidden="true" />
|
<i class="pi pi-check-circle text-emerald-600 dark:text-emerald-400 text-3xl" aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
<h2 class="text-lg font-bold text-slate-800 dark:text-slate-100 mb-2">E-mail enviado!</h2>
|
<h2 class="text-lg font-bold text-slate-800 dark:text-slate-100 mb-2">E-mail enviado!</h2>
|
||||||
<p class="text-sm text-slate-500 dark:text-slate-400">
|
<p class="text-sm text-slate-500 dark:text-slate-400">
|
||||||
@ -159,7 +159,7 @@ async function solicitar() {
|
|||||||
icon="pi pi-sign-in"
|
icon="pi pi-sign-in"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
size="large"
|
size="large"
|
||||||
@click="router.push('/entrar')"
|
@click="router.push('/')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,16 @@ import { useAuth } from '@/composables/useAuth'
|
|||||||
import { certidaoService } from '@/services/certidaoService'
|
import { certidaoService } from '@/services/certidaoService'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
const { isAuthenticated, documento: docUsuarioLogado, nomeUsuario } = useAuth()
|
const { isAuthenticated, documento: docUsuarioLogado, nomeUsuario } = useAuth()
|
||||||
|
|
||||||
|
const voltarPara = computed(() =>
|
||||||
|
route.query.from === 'portal' ? '/portal/certidoes' : '/servicos'
|
||||||
|
)
|
||||||
|
const labelVoltar = computed(() =>
|
||||||
|
route.query.from === 'portal' ? 'Voltar às certidões' : 'Voltar aos serviços'
|
||||||
|
)
|
||||||
|
|
||||||
const documento = ref(isAuthenticated.value ? docUsuarioLogado.value : '')
|
const documento = ref(isAuthenticated.value ? docUsuarioLogado.value : '')
|
||||||
const tipoCertidao = ref('negativa')
|
const tipoCertidao = ref('negativa')
|
||||||
const etapa = ref('formulario')
|
const etapa = ref('formulario')
|
||||||
@ -70,10 +78,10 @@ function reiniciar() {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200 transition-colors mb-8 py-1"
|
class="inline-flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200 transition-colors mb-8 py-1"
|
||||||
@click="router.push('/servicos')"
|
@click="router.push(voltarPara)"
|
||||||
>
|
>
|
||||||
<i class="pi pi-arrow-left text-xs" aria-hidden="true" />
|
<i class="pi pi-arrow-left text-xs" aria-hidden="true" />
|
||||||
Voltar aos serviços
|
{{ labelVoltar }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="flex items-center gap-4 mb-8">
|
<div class="flex items-center gap-4 mb-8">
|
||||||
|
|||||||
@ -4,8 +4,16 @@ import { useAuth } from '@/composables/useAuth'
|
|||||||
import { iptuService } from '@/services/iptuService'
|
import { iptuService } from '@/services/iptuService'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
const { isAuthenticated, documento: docUsuarioLogado, nomeUsuario } = useAuth()
|
const { isAuthenticated, documento: docUsuarioLogado, nomeUsuario } = useAuth()
|
||||||
|
|
||||||
|
const voltarPara = computed(() =>
|
||||||
|
route.query.from === 'portal' ? '/portal/debitos' : '/servicos'
|
||||||
|
)
|
||||||
|
const labelVoltar = computed(() =>
|
||||||
|
route.query.from === 'portal' ? 'Voltar aos débitos' : 'Voltar aos serviços'
|
||||||
|
)
|
||||||
|
|
||||||
const modoConsulta = ref('documento')
|
const modoConsulta = ref('documento')
|
||||||
const documento = ref(isAuthenticated.value ? docUsuarioLogado.value : '')
|
const documento = ref(isAuthenticated.value ? docUsuarioLogado.value : '')
|
||||||
const inscricao = ref('')
|
const inscricao = ref('')
|
||||||
@ -92,10 +100,10 @@ function formatarMoeda(valor) {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="inline-flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200 transition-colors mb-8 py-1"
|
class="inline-flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200 transition-colors mb-8 py-1"
|
||||||
@click="router.push('/servicos')"
|
@click="router.push(voltarPara)"
|
||||||
>
|
>
|
||||||
<i class="pi pi-arrow-left text-xs" aria-hidden="true" />
|
<i class="pi pi-arrow-left text-xs" aria-hidden="true" />
|
||||||
Voltar aos serviços
|
{{ labelVoltar }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="flex items-center gap-4 mb-8">
|
<div class="flex items-center gap-4 mb-8">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user