Adicionada compressão Brotli/Gzip, auto-import de Vue e PrimeVue, e análise visual do bundle para otimização de produção e Remove AppLayout duplicado de cada área (therapist, admin, configuracoes, account, supervisor, billing, features) e consolida sob um único pai no router/index.js. Adiciona RouterPassthrough para grupos de rota sem layout intermediário. Remove debug ativo (console.trace em router.push e queries Supabase em todo watch de rota) que degradava performance para todos os usuários.
This commit is contained in:
+4
-114
@@ -19,7 +19,6 @@ import { onMounted, watch } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { supabase } from '@/lib/supabase/client';
|
||||
import { useTenantStore } from '@/stores/tenantStore';
|
||||
import { useEntitlementsStore } from '@/stores/entitlementsStore';
|
||||
import { fetchDocsForPath } from '@/composables/useAjuda';
|
||||
|
||||
import AjudaDrawer from '@/components/AjudaDrawer.vue';
|
||||
@@ -28,25 +27,14 @@ import AppOfflineOverlay from '@/components/AppOfflineOverlay.vue';
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const tenantStore = useTenantStore();
|
||||
const entStore = useEntitlementsStore();
|
||||
|
||||
function isTenantArea(path = '') {
|
||||
return path.startsWith('/admin') || path.startsWith('/therapist');
|
||||
}
|
||||
|
||||
function isPortalArea(path = '') {
|
||||
return path.startsWith('/portal');
|
||||
}
|
||||
|
||||
function isSaasArea(path = '') {
|
||||
return path.startsWith('/saas');
|
||||
return path.startsWith('/admin') || path.startsWith('/therapist') || path.startsWith('/configuracoes');
|
||||
}
|
||||
|
||||
// ── Setup Wizard redirect ────────────────────────────────────────
|
||||
async function checkSetupWizard() {
|
||||
// Só verifica em área de tenant
|
||||
if (!isTenantArea(route.path)) return;
|
||||
// Não redireciona se já está no setup
|
||||
if (route.path.includes('/setup')) return;
|
||||
|
||||
const uid = tenantStore.user?.id;
|
||||
@@ -56,7 +44,6 @@ async function checkSetupWizard() {
|
||||
|
||||
if (!data) return;
|
||||
|
||||
// Determina o kind do tenant ativo para saber qual flag checar
|
||||
const activeMembership = tenantStore.memberships?.find((m) => m.id === tenantStore.activeTenantId);
|
||||
const kind = activeMembership?.kind ?? tenantStore.activeRole ?? '';
|
||||
const isClinic = kind.startsWith('clinic');
|
||||
@@ -68,113 +55,16 @@ async function checkSetupWizard() {
|
||||
}
|
||||
}
|
||||
|
||||
async function debugSnapshot(label = 'snapshot') {
|
||||
console.group(`🧭 [APP DEBUG] ${label}`);
|
||||
try {
|
||||
// 0) rota + meta
|
||||
console.log('route.fullPath:', route.fullPath);
|
||||
console.log('route.path:', route.path);
|
||||
console.log('route.name:', route.name);
|
||||
console.log('route.meta:', route.meta);
|
||||
|
||||
// 1) storage
|
||||
console.groupCollapsed('📦 Storage');
|
||||
console.log('localStorage.tenant_id:', localStorage.getItem('tenant_id'));
|
||||
console.log('localStorage.currentTenantId:', localStorage.getItem('currentTenantId'));
|
||||
console.log('localStorage.tenant:', localStorage.getItem('tenant'));
|
||||
console.log('sessionStorage.redirect_after_login:', sessionStorage.getItem('redirect_after_login'));
|
||||
console.log('sessionStorage.intended_area:', sessionStorage.getItem('intended_area'));
|
||||
console.groupEnd();
|
||||
|
||||
// 2) sessão auth (fonte real)
|
||||
const { data: authData, error: authErr } = await supabase.auth.getUser();
|
||||
if (authErr) console.warn('[auth.getUser] error:', authErr);
|
||||
const user = authData?.user || null;
|
||||
console.log('auth.user:', user ? { id: user.id, email: user.email } : null);
|
||||
|
||||
// 3) profiles.role (identidade global)
|
||||
let profileRole = null;
|
||||
if (user?.id) {
|
||||
const { data: profile, error: pErr } = await supabase.from('profiles').select('role').eq('id', user.id).single();
|
||||
|
||||
if (pErr) console.warn('[profiles] error:', pErr);
|
||||
profileRole = profile?.role || null;
|
||||
}
|
||||
console.log('profiles.role (global):', profileRole);
|
||||
|
||||
// 4) memberships via RPC (fonte de verdade do tenantStore)
|
||||
let rpcTenants = null;
|
||||
if (user?.id) {
|
||||
const { data: rpcData, error: rpcErr } = await supabase.rpc('my_tenants');
|
||||
if (rpcErr) console.warn('[rpc my_tenants] error:', rpcErr);
|
||||
rpcTenants = rpcData ?? null;
|
||||
}
|
||||
console.log('rpc.my_tenants():', rpcTenants);
|
||||
|
||||
// 5) stores (sempre logar)
|
||||
console.groupCollapsed('🏪 Stores (before optional loads)');
|
||||
console.log('tenantStore.activeTenantId:', tenantStore.activeTenantId);
|
||||
console.log('tenantStore.activeRole:', tenantStore.activeRole);
|
||||
console.log('tenantStore.memberships:', tenantStore.memberships);
|
||||
console.log('entStore.loaded:', entStore.loaded);
|
||||
console.log('entStore.tenantId:', entStore.activeTenantId || entStore.tenantId);
|
||||
console.groupEnd();
|
||||
|
||||
// 6) IMPORTANTÍSSIMO: não carregar tenant fora da área tenant
|
||||
const path = route.path || '';
|
||||
|
||||
if (isTenantArea(path)) {
|
||||
console.log('✅ Tenant area detected → will loadSessionAndTenant + entitlements');
|
||||
await tenantStore.loadSessionAndTenant();
|
||||
|
||||
if (tenantStore.activeTenantId) {
|
||||
await entStore.loadForTenant(tenantStore.activeTenantId);
|
||||
}
|
||||
|
||||
console.groupCollapsed('🏪 Stores (after tenant loads)');
|
||||
console.log('tenantStore.activeTenantId:', tenantStore.activeTenantId);
|
||||
console.log('tenantStore.activeRole:', tenantStore.activeRole);
|
||||
console.log('tenantStore.memberships:', tenantStore.memberships);
|
||||
console.log("entStore.can('online_scheduling.manage'):", entStore.can?.('online_scheduling.manage'));
|
||||
console.groupEnd();
|
||||
|
||||
// Redireciona para o wizard se setup não foi concluído
|
||||
await checkSetupWizard();
|
||||
} else if (isPortalArea(path)) {
|
||||
console.log('🟣 Portal area detected → SKIP tenantStore.loadSessionAndTenant()');
|
||||
} else if (isSaasArea(path)) {
|
||||
console.log('🟠 SaaS area detected → SKIP tenantStore.loadSessionAndTenant()');
|
||||
} else {
|
||||
console.log('⚪ Other/public area detected → SKIP tenantStore.loadSessionAndTenant()');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[APP DEBUG] snapshot error:', e);
|
||||
} finally {
|
||||
console.groupEnd();
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 🔥 PRIMEIRO LOG — TENANT ID BRUTO (mantive sua ideia)
|
||||
console.log('[SEU_TENANT_ID]', localStorage.getItem('tenant_id'));
|
||||
|
||||
// snapshot inicial
|
||||
await debugSnapshot('mounted');
|
||||
|
||||
// Carrega docs de ajuda para a rota inicial
|
||||
onMounted(() => {
|
||||
fetchDocsForPath(route.path);
|
||||
});
|
||||
|
||||
// snapshot a cada navegação (isso é o que vai te salvar)
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
async (to, from) => {
|
||||
await debugSnapshot(`route change: ${from} -> ${to}`);
|
||||
// Atualiza docs de ajuda ao navegar
|
||||
() => {
|
||||
fetchDocsForPath(route.path);
|
||||
// Verifica setup sempre que entrar em área tenant
|
||||
if (isTenantArea(route.path) && tenantStore.loaded) {
|
||||
await checkSetupWizard();
|
||||
checkSetupWizard();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user