Ajuste Layout, Dashboard Terapeuta, Timeline, Suporte técnico, Documentação e FAQ
This commit is contained in:
@@ -3,13 +3,13 @@ import { useLayout } from '@/layout/composables/layout'
|
||||
import { computed, onMounted, onBeforeUnmount, provide, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import AppFooter from './AppFooter.vue'
|
||||
import AppSidebar from './AppSidebar.vue'
|
||||
import AppTopbar from './AppTopbar.vue'
|
||||
import AppRail from './AppRail.vue'
|
||||
import AppRailPanel from './AppRailPanel.vue'
|
||||
import AppRailTopbar from './AppRailTopbar.vue'
|
||||
import AjudaDrawer from '@/components/AjudaDrawer.vue'
|
||||
import AppFooter from './AppFooter.vue'
|
||||
import AppSidebar from './AppSidebar.vue'
|
||||
import AppTopbar from './AppTopbar.vue'
|
||||
import AppRail from './AppRail.vue'
|
||||
import AppRailPanel from './AppRailPanel.vue'
|
||||
import AppRailSidebar from './AppRailSidebar.vue'
|
||||
import AjudaDrawer from '@/components/AjudaDrawer.vue'
|
||||
|
||||
import { fetchDocsForPath, useAjuda } from '@/composables/useAjuda'
|
||||
|
||||
@@ -27,7 +27,6 @@ import { useTenantFeaturesStore } from '@/stores/tenantFeaturesStore'
|
||||
const route = useRoute()
|
||||
const { layoutConfig, layoutState, hideMobileMenu, isDesktop } = useLayout()
|
||||
|
||||
// ✅ área do layout definida por rota (shell único)
|
||||
const layoutArea = computed(() => route.meta?.area || null)
|
||||
provide('layoutArea', layoutArea)
|
||||
|
||||
@@ -60,10 +59,8 @@ async function revalidateAfterSessionRefresh () {
|
||||
if (!tenantStore.loaded && !tenantStore.loading) {
|
||||
await tenantStore.loadSessionAndTenant()
|
||||
}
|
||||
|
||||
const tid = getTenantId()
|
||||
if (!tid) return
|
||||
|
||||
await Promise.allSettled([
|
||||
entitlementsStore.loadForTenant?.(tid, { force: true }),
|
||||
tf.fetchForTenant?.(tid, { force: true })
|
||||
@@ -74,20 +71,16 @@ async function revalidateAfterSessionRefresh () {
|
||||
}
|
||||
|
||||
function onSessionRefreshed () {
|
||||
// ✅ Só revalidar tenantStore/entitlements em áreas TENANT.
|
||||
// Em /portal e /account isso causa vazamento de contexto e troca de menu.
|
||||
const p = String(route.path || '')
|
||||
const isTenantArea =
|
||||
p.startsWith('/admin') ||
|
||||
p.startsWith('/therapist') ||
|
||||
p.startsWith('/supervisor') ||
|
||||
p.startsWith('/saas')
|
||||
|
||||
if (!isTenantArea) return
|
||||
revalidateAfterSessionRefresh()
|
||||
}
|
||||
|
||||
// Dispara busca de docs de ajuda sempre que a rota muda
|
||||
watch(() => route.path, (path) => fetchDocsForPath(path), { immediate: true })
|
||||
|
||||
onMounted(() => {
|
||||
@@ -100,18 +93,19 @@ onBeforeUnmount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- ══ Fullscreen: setup wizard (sem sidebar/topbar/footer) ══ -->
|
||||
<!-- ══ Fullscreen ══ -->
|
||||
<template v-if="route.meta?.fullscreen">
|
||||
<router-view />
|
||||
<Toast />
|
||||
</template>
|
||||
|
||||
<!-- ══ Layout 2: Rail + Painel + Main (full-width) ══════════ -->
|
||||
<template v-else-if="layoutConfig.variant === 'rail' && isDesktop()">
|
||||
<!-- ══ Layout Rail ══ -->
|
||||
<template v-else-if="layoutConfig.variant === 'rail'">
|
||||
<div class="l2-root">
|
||||
<!-- Rail de ícones: oculto em mobile (≤ 1200px) via CSS -->
|
||||
<AppRail />
|
||||
<div class="l2-body">
|
||||
<AppRailTopbar />
|
||||
<AppTopbar />
|
||||
<div class="l2-content">
|
||||
<AppRailPanel />
|
||||
<div class="l2-main" :style="ajudaPushStyle">
|
||||
@@ -120,11 +114,19 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Sidebar mobile exclusiva do Rail -->
|
||||
<AppRailSidebar />
|
||||
<!-- Overlay escuro ao abrir sidebar mobile -->
|
||||
<div
|
||||
v-if="layoutState.mobileMenuActive"
|
||||
class="l2-mobile-overlay"
|
||||
@click="hideMobileMenu"
|
||||
/>
|
||||
<AjudaDrawer />
|
||||
<Toast />
|
||||
</template>
|
||||
|
||||
<!-- ══ Layout 1: Clássico ═══════════════════════════════════ -->
|
||||
<!-- ══ Layout Clássico melhorado ══ -->
|
||||
<template v-else>
|
||||
<div class="layout-wrapper" :class="containerClass">
|
||||
<AppTopbar />
|
||||
@@ -142,8 +144,62 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* ──────────────────────────────────────────────
|
||||
LAYOUT CLÁSSICO — ajustes globais (não scoped)
|
||||
para sobrescrever o tema PrimeVue/Sakai
|
||||
────────────────────────────────────────────── */
|
||||
|
||||
/* ── Sidebar — sempre abaixo da topbar fixed (56px) ────────
|
||||
z-index: 999 para flutuar sobre o conteúdo em overlay.
|
||||
Topbar (z-index 1000) fica sempre acessível acima da sidebar. */
|
||||
.layout-sidebar {
|
||||
position: fixed !important;
|
||||
top: 56px !important;
|
||||
left: 0 !important;
|
||||
height: calc(100vh - 56px) !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 0 !important;
|
||||
box-shadow: 2px 0 6px rgba(0,0,0,.06) !important;
|
||||
border-right: 1px solid var(--surface-border) !important;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* ── Topbar no layout Clássico — sempre tela toda, acima da sidebar */
|
||||
.layout-wrapper .rail-topbar {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
/* ── Conteúdo — margem esquerda por modo ───────────────────
|
||||
Static ativo : afasta da sidebar
|
||||
Static inativo: sem margem
|
||||
Overlay : sem margem (sidebar flutua sobre o conteúdo) */
|
||||
.layout-main-container {
|
||||
margin-left: 20rem !important;
|
||||
padding-left: 0 !important;
|
||||
padding-top: 56px !important;
|
||||
}
|
||||
.layout-overlay .layout-main-container,
|
||||
.layout-static-inactive .layout-main-container {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.layout-main-container {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Overlay: hambúrguer sempre visível ─────────────────────
|
||||
Em overlay a sidebar não ocupa espaço fixo — o botão precisa
|
||||
estar disponível em qualquer largura de tela. */
|
||||
.layout-overlay .rail-topbar__hamburger {
|
||||
display: grid !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
/* ─── Layout 2 ───────────────────────────────────────────── */
|
||||
/* ─── Layout Rail (inalterado) ────────────────── */
|
||||
.l2-root {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
@@ -152,7 +208,6 @@ onBeforeUnmount(() => {
|
||||
background: var(--surface-ground);
|
||||
}
|
||||
|
||||
/* Coluna direita do rail: topbar + conteúdo */
|
||||
.l2-body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
@@ -160,9 +215,9 @@ onBeforeUnmount(() => {
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
padding-top: 56px; /* compensa a topbar fixed */
|
||||
}
|
||||
|
||||
/* Linha: painel lateral + main */
|
||||
.l2-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
@@ -170,13 +225,35 @@ onBeforeUnmount(() => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Área de conteúdo principal */
|
||||
.l2-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
/* Headers sticky no Rail colam no topo do scroll container (já abaixo da topbar) */
|
||||
--layout-sticky-top: 0px;
|
||||
}
|
||||
|
||||
/* Rail de ícones: oculto em mobile */
|
||||
@media (max-width: 1200px) {
|
||||
.l2-root :deep(.rail) {
|
||||
display: none;
|
||||
}
|
||||
/* Painel lateral: também oculto em mobile (substituído pelo AppRailSidebar) */
|
||||
.l2-content :deep(.rp) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Overlay escuro ao abrir sidebar mobile no Rail */
|
||||
.l2-mobile-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
z-index: 98;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user