MelissaMenu: label Conta + remove modo escuro + preset migra pra Personalizar

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-05-07 10:37:05 -03:00
parent 27b5bbed6f
commit 63340d1226
+46 -132
View File
@@ -25,7 +25,8 @@ import { supabase } from '@/lib/supabase/client';
import { useRoleGuard } from '@/composables/useRoleGuard';
import { useLayout } from '@/layout/composables/layout';
import { useUserSettingsPersistence } from '@/composables/useUserSettingsPersistence';
import { primaryColors, surfaces, presetOptions, applyThemeEngine } from '@/theme/theme.options';
import { primaryColors, surfaces, applyThemeEngine } from '@/theme/theme.options';
import { MELISSA_CONFIG_GRUPOS } from './composables/melissaConfigGrupos.js';
const props = defineProps({
secaoAtiva: { type: String, default: null }
@@ -35,7 +36,7 @@ const emit = defineEmits(['select', 'close']);
const router = useRouter();
const { role } = useRoleGuard();
const { layoutConfig, toggleDarkMode, isDarkTheme } = useLayout();
const { layoutConfig, isDarkTheme } = useLayout();
const { queuePatch } = useUserSettingsPersistence();
// ── Catálogo de categorias ────────────────────────────────────
@@ -146,29 +147,25 @@ const CATEGORIAS = [
label: 'Configurações',
icon: 'pi pi-cog',
color: '#94a3b8',
groups: [
{
title: 'Layout Melissa',
items: [
// Sem `route` — emit('select', 'aparencia') abre página interna do Melissa
{ key: 'aparencia', label: 'Layout Melissa', icon: 'pi pi-palette' }
]
},
{
title: 'Agenda',
items: [
{ key: 'cfg-agenda', label: 'Agenda', icon: 'pi pi-calendar', route: { name: 'ConfiguracoesAgenda' } },
{ key: 'cfg-agendador', label: 'Agendador externo', icon: 'pi pi-link', route: { name: 'ConfiguracoesAgendador' } }
]
},
{
title: 'WhatsApp',
items: [
{ key: 'cfg-wa', label: 'Canal de WhatsApp', icon: 'pi pi-whatsapp', route: { name: 'ConfiguracoesWhatsapp' } },
{ key: 'cfg-wa-templates', label: 'Templates', icon: 'pi pi-file-edit', route: { name: 'ConfiguracoesWhatsappTemplates' } }
]
}
]
// Groups derivados do MELISSA_CONFIG_GRUPOS (fonte unica em
// composables/melissaConfigGrupos.js). Items SEM `route` —
// emit('select', key) dispara abrirSecao no MelissaLayout, que
// navega pra /melissa/<slug> e renderiza a pagina nativa
// (perfil/plano/etc) ou o MelissaConfiguracoes (cfg-* embeds).
//
// Grupo 'conta' filtrado: Meu Perfil/Plano/Negocio/Seguranca ja
// aparecem como atalhos fixos no rodape do mm-side, nao precisa
// duplicar aqui.
groups: MELISSA_CONFIG_GRUPOS
.filter((g) => g.key !== 'conta')
.map((g) => ({
title: g.label,
items: g.items.map((i) => ({
key: i.key,
label: i.label,
icon: i.icon
}))
}))
}
];
@@ -323,21 +320,6 @@ function goPlano() { emit('select', 'plano'); emit('close'); }
function goNegocio() { emit('select', 'negocio'); emit('close'); }
function goSeguranca() { emit('select', 'seguranca'); emit('close'); }
async function toggleDarkAndPersist() {
try {
toggleDarkMode();
// requestAnimationFrame pra garantir que a classe já foi aplicada
await new Promise((r) => requestAnimationFrame(r));
const after = document.documentElement.classList.contains('app-dark');
const theme_mode = after ? 'dark' : 'light';
try { localStorage.setItem('ui_theme_mode', theme_mode); } catch {}
await queuePatch({ theme_mode }, { flushNow: true });
} catch (e) {
// eslint-disable-next-line no-console
console.warn('[MelissaMenu] toggleDark falhou:', e);
}
}
// ── Cores do Tema (embutido no aside, não em popover externo) ──
const themeViewActive = ref(false);
@@ -371,14 +353,6 @@ function setSurface(s) {
saveThemeToStorage();
}
function setPreset(p) {
if (!p || p === layoutConfig.preset) return;
layoutConfig.preset = p;
applyThemeEngine(layoutConfig);
queuePatch?.({ preset: p });
saveThemeToStorage();
}
function surfaceIsActive(s) {
if (layoutConfig.surface) return layoutConfig.surface === s.name;
// fallback default por mode
@@ -478,6 +452,10 @@ async function sair() {
<div class="mm-side__foot">
<!-- Itens grudados acima do usuário -->
<div class="mm-foot-actions">
<!-- Bloco "Conta": sempre visivel no rodape. Os mesmos
atalhos sao filtrados do aside direito quando a
categoria Configuracoes esta ativa, pra nao duplicar. -->
<div class="mm-foot-label">Conta</div>
<button
class="mm-foot-item"
:class="{ 'is-active': props.secaoAtiva === 'perfil' }"
@@ -506,20 +484,6 @@ async function sair() {
>
<i class="pi pi-shield" /><span>Segurança</span>
</button>
<button
class="mm-foot-item"
:class="{ 'is-active': isDarkTheme }"
:aria-pressed="isDarkTheme"
@click="toggleDarkAndPersist"
>
<i :class="isDarkTheme ? 'pi pi-sun' : 'pi pi-moon'" />
<span>Modo escuro</span>
<span
class="mm-toggle"
:class="{ 'is-on': isDarkTheme }"
aria-hidden="true"
/>
</button>
<button
class="mm-foot-item"
:class="{ 'is-active': themeViewActive }"
@@ -600,22 +564,10 @@ async function sair() {
</div>
</div>
<div class="mm-theme__group">
<div class="mm-theme__title">Preset</div>
<div class="mm-theme__presets">
<button
v-for="p in presetOptions"
:key="p"
type="button"
class="mm-theme__preset"
:class="{ 'is-active': layoutConfig.preset === p }"
@click="setPreset(p)"
>{{ p }}</button>
</div>
</div>
<div class="mm-theme__hint">
Mudanças se aplicam ao app inteiro e ficam salvas no seu perfil.
Para escolher o <strong>preset</strong> (Aura / Lara / Nora), use o
<i class="pi pi-cog" /> Personalizar no canto superior direito.
</div>
<!-- Cards informativos (sem interação ainda) -->
@@ -988,6 +940,14 @@ async function sair() {
padding-bottom: 6px;
border-bottom: 1px solid var(--m-border);
}
.mm-foot-label {
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--m-text-faint);
font-size: 0.62rem;
font-weight: 600;
padding: 4px 10px 4px;
}
.mm-foot-item {
width: 100%;
display: flex;
@@ -1037,35 +997,6 @@ async function sair() {
border-radius: 999px;
}
/* Switch on/off (modo escuro) — usa as cores do tema */
.mm-toggle {
flex: none !important;
width: 32px;
height: 18px;
background: var(--m-border-strong, var(--m-border));
border-radius: 999px;
position: relative;
transition: background-color 200ms ease;
}
.mm-toggle::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 14px;
height: 14px;
border-radius: 50%;
background: white;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
transition: transform 200ms ease;
}
.mm-toggle.is-on {
background: var(--p-primary-color);
}
.mm-toggle.is-on::after {
transform: translateX(14px);
}
/* User row */
.mm-user {
display: flex;
@@ -1347,39 +1278,22 @@ async function sair() {
box-shadow: 0 0 0 2px var(--m-bg-soft-hover);
transform: scale(1.08);
}
.mm-theme__presets {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.mm-theme__preset {
background: var(--m-bg-soft);
border: 1px solid var(--m-border);
color: var(--m-text);
padding: 5px 11px;
border-radius: 8px;
font-size: 0.72rem;
font-family: inherit;
text-transform: capitalize;
cursor: pointer;
transition: all 140ms ease;
}
.mm-theme__preset:hover {
background: var(--m-bg-soft-hover);
color: var(--m-text);
}
.mm-theme__preset.is-active {
background: var(--m-border-strong);
border-color: var(--m-border-strong);
color: var(--m-text);
}
.mm-theme__hint {
font-size: 0.7rem;
color: var(--m-text-faint);
line-height: 1.4;
line-height: 1.5;
padding-top: 6px;
border-top: 1px solid var(--m-border);
}
.mm-theme__hint strong {
color: var(--m-text-muted);
font-weight: 600;
}
.mm-theme__hint i {
color: var(--m-text-muted);
font-size: 0.72rem;
margin: 0 2px;
}
/* ─── Info cards (descritivos, sem interação ainda) ─────── */
.mm-info-card {