All checks were successful
Dev Build & Deploy Portal / build-deploy (push) Successful in 2m44s
Remove página, navegação e chamadas de API de alvarás do portal do contribuinte. Co-authored-by: Cursor <cursoragent@cursor.com>
192 lines
8.7 KiB
Vue
192 lines
8.7 KiB
Vue
<script setup>
|
|
import { ref } from 'vue'
|
|
import { useAuth } from '@/composables/useAuth'
|
|
import { usePrefeituraStore } from '@/stores/prefeituraStore'
|
|
|
|
const { nomeUsuario, logout } = useAuth()
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const prefeitura = usePrefeituraStore()
|
|
|
|
const menuAberto = ref(false)
|
|
|
|
const navItems = [
|
|
{ path: '/portal/painel', label: 'Painel', icon: 'pi-home' },
|
|
{ path: '/portal/debitos', label: 'Débitos', icon: 'pi-receipt' },
|
|
{ path: '/portal/taxas', label: 'Taxas', icon: 'pi-file-export' },
|
|
{ path: '/portal/certidoes', label: 'Certidões', icon: 'pi-file-check' },
|
|
{ path: '/portal/pagamentos', label: 'Pagamentos', icon: 'pi-credit-card' },
|
|
{ path: '/portal/dados', label: 'Dados Cadastrais', icon: 'pi-user' },
|
|
]
|
|
|
|
function navegar(path) {
|
|
menuAberto.value = false
|
|
router.push(path)
|
|
}
|
|
|
|
function sair() {
|
|
menuAberto.value = false
|
|
logout()
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<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">
|
|
<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
|
|
to="/portal/painel"
|
|
class="flex items-center gap-2.5 min-w-0 flex-shrink-0"
|
|
aria-label="Ir para o painel principal"
|
|
>
|
|
<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" />
|
|
</div>
|
|
<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>
|
|
|
|
<!-- Nav desktop -->
|
|
<nav aria-label="Menu do contribuinte" class="hidden md:flex items-center gap-1 flex-1 justify-center">
|
|
<NuxtLink
|
|
v-for="item in navItems"
|
|
:key="item.path"
|
|
:to="item.path"
|
|
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"
|
|
:aria-current="route.path === item.path ? 'page' : undefined"
|
|
>
|
|
{{ item.label }}
|
|
</NuxtLink>
|
|
</nav>
|
|
|
|
<!-- Ações desktop -->
|
|
<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 }}
|
|
</span>
|
|
<Button
|
|
label="Sair"
|
|
severity="secondary"
|
|
size="small"
|
|
icon="pi pi-sign-out"
|
|
outlined
|
|
aria-label="Sair do portal"
|
|
@click="sair"
|
|
/>
|
|
</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>
|
|
</header>
|
|
|
|
<!-- 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 />
|
|
</main>
|
|
|
|
<AppFooter />
|
|
</div>
|
|
</template>
|