From 9d4cb5b9968694729beee09c36484c94b51c2063 Mon Sep 17 00:00:00 2001 From: Junior Date: Sat, 14 Mar 2026 15:38:44 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20tela=20de=20cadastro=20/register=20e=20?= =?UTF-8?q?configura=C3=A7=C3=B5es=20com=20perfil=20completo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - register.vue: cadastro PF/PJ com nome fantasia, razão social, CPF/CNPJ, slug - auto-gera slug a partir do nome fantasia - toggle PF/PJ muda label dos campos dinamicamente - configuracoes.vue: exibe e edita todos os campos do perfil do tenant - auth.global.ts: /register liberado sem autenticação - login.vue: link para /register + remove erro duplicado Co-Authored-By: Claude Sonnet 4.6 --- front-end/app/middleware/auth.global.ts | 6 +- front-end/app/pages/login.vue | 6 + front-end/app/pages/register.vue | 176 ++++++++++++++++++ front-end/app/pages/sistema/configuracoes.vue | 57 +++++- 4 files changed, 236 insertions(+), 9 deletions(-) create mode 100644 front-end/app/pages/register.vue diff --git a/front-end/app/middleware/auth.global.ts b/front-end/app/middleware/auth.global.ts index 25fbf2b..6d90e1e 100644 --- a/front-end/app/middleware/auth.global.ts +++ b/front-end/app/middleware/auth.global.ts @@ -1,9 +1,11 @@ +const PUBLIC_ROUTES = ['/login', '/register'] + export default defineNuxtRouteMiddleware((to) => { const { isAuthenticated } = useAuth() - if (!isAuthenticated.value && to.path !== '/login') { + if (!isAuthenticated.value && !PUBLIC_ROUTES.includes(to.path)) { return navigateTo('/login') } - if (isAuthenticated.value && to.path === '/login') { + if (isAuthenticated.value && PUBLIC_ROUTES.includes(to.path)) { return navigateTo('/') } }) diff --git a/front-end/app/pages/login.vue b/front-end/app/pages/login.vue index 0680764..d7b0491 100644 --- a/front-end/app/pages/login.vue +++ b/front-end/app/pages/login.vue @@ -75,6 +75,10 @@ async function handleSubmit() { > Entrar + + @@ -99,4 +103,6 @@ async function handleSubmit() { background: linear-gradient(135deg, #667eea, #764ba2) !important; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); } +.register-link { text-align: center; font-size: 13px; color: #64748b; margin-top: 16px; } +.register-link a { color: #667eea; font-weight: 600; text-decoration: none; } diff --git a/front-end/app/pages/register.vue b/front-end/app/pages/register.vue new file mode 100644 index 0000000..01dfa23 --- /dev/null +++ b/front-end/app/pages/register.vue @@ -0,0 +1,176 @@ + + + + + + diff --git a/front-end/app/pages/sistema/configuracoes.vue b/front-end/app/pages/sistema/configuracoes.vue index 7a40b8f..72a16c9 100644 --- a/front-end/app/pages/sistema/configuracoes.vue +++ b/front-end/app/pages/sistema/configuracoes.vue @@ -6,6 +6,9 @@ interface ApiTenant { ID: string Slug: string Name: string + LegalName: string + DocumentType: string + Document: string Plan: string MaxUsers: number IsActive: boolean @@ -15,19 +18,35 @@ const { data: tenant, refresh } = await useAsyncData('tenant-me', () => apiFetch('/tenant/me') ) -const nome = ref(tenant.value?.Name ?? '') +const form = reactive({ + name: tenant.value?.Name ?? '', + legalName: tenant.value?.LegalName ?? '', + documentType: tenant.value?.DocumentType ?? 'pj', + document: tenant.value?.Document ?? '', +}) + const saving = ref(false) const saved = ref(false) async function salvar() { saving.value = true saved.value = false - await apiFetch('/tenant/me', { method: 'PUT', body: { name: nome.value } }) + await apiFetch('/tenant/me', { + method: 'PUT', + body: { + name: form.name, + legal_name: form.legalName, + document_type: form.documentType, + document: form.document, + }, + }) await refresh() saving.value = false saved.value = true setTimeout(() => { saved.value = false }, 3000) } + +const documentLabel = computed(() => form.documentType === 'pj' ? 'CNPJ' : 'CPF')