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:
@@ -25,7 +25,8 @@ import { supabase } from '@/lib/supabase/client';
|
|||||||
import { useRoleGuard } from '@/composables/useRoleGuard';
|
import { useRoleGuard } from '@/composables/useRoleGuard';
|
||||||
import { useLayout } from '@/layout/composables/layout';
|
import { useLayout } from '@/layout/composables/layout';
|
||||||
import { useUserSettingsPersistence } from '@/composables/useUserSettingsPersistence';
|
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({
|
const props = defineProps({
|
||||||
secaoAtiva: { type: String, default: null }
|
secaoAtiva: { type: String, default: null }
|
||||||
@@ -35,7 +36,7 @@ const emit = defineEmits(['select', 'close']);
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { role } = useRoleGuard();
|
const { role } = useRoleGuard();
|
||||||
const { layoutConfig, toggleDarkMode, isDarkTheme } = useLayout();
|
const { layoutConfig, isDarkTheme } = useLayout();
|
||||||
const { queuePatch } = useUserSettingsPersistence();
|
const { queuePatch } = useUserSettingsPersistence();
|
||||||
|
|
||||||
// ── Catálogo de categorias ────────────────────────────────────
|
// ── Catálogo de categorias ────────────────────────────────────
|
||||||
@@ -146,29 +147,25 @@ const CATEGORIAS = [
|
|||||||
label: 'Configurações',
|
label: 'Configurações',
|
||||||
icon: 'pi pi-cog',
|
icon: 'pi pi-cog',
|
||||||
color: '#94a3b8',
|
color: '#94a3b8',
|
||||||
groups: [
|
// Groups derivados do MELISSA_CONFIG_GRUPOS (fonte unica em
|
||||||
{
|
// composables/melissaConfigGrupos.js). Items SEM `route` —
|
||||||
title: 'Layout Melissa',
|
// emit('select', key) dispara abrirSecao no MelissaLayout, que
|
||||||
items: [
|
// navega pra /melissa/<slug> e renderiza a pagina nativa
|
||||||
// Sem `route` — emit('select', 'aparencia') abre página interna do Melissa
|
// (perfil/plano/etc) ou o MelissaConfiguracoes (cfg-* embeds).
|
||||||
{ key: 'aparencia', label: 'Layout Melissa', icon: 'pi pi-palette' }
|
//
|
||||||
]
|
// Grupo 'conta' filtrado: Meu Perfil/Plano/Negocio/Seguranca ja
|
||||||
},
|
// aparecem como atalhos fixos no rodape do mm-side, nao precisa
|
||||||
{
|
// duplicar aqui.
|
||||||
title: 'Agenda',
|
groups: MELISSA_CONFIG_GRUPOS
|
||||||
items: [
|
.filter((g) => g.key !== 'conta')
|
||||||
{ key: 'cfg-agenda', label: 'Agenda', icon: 'pi pi-calendar', route: { name: 'ConfiguracoesAgenda' } },
|
.map((g) => ({
|
||||||
{ key: 'cfg-agendador', label: 'Agendador externo', icon: 'pi pi-link', route: { name: 'ConfiguracoesAgendador' } }
|
title: g.label,
|
||||||
]
|
items: g.items.map((i) => ({
|
||||||
},
|
key: i.key,
|
||||||
{
|
label: i.label,
|
||||||
title: 'WhatsApp',
|
icon: i.icon
|
||||||
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' } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -323,21 +320,6 @@ function goPlano() { emit('select', 'plano'); emit('close'); }
|
|||||||
function goNegocio() { emit('select', 'negocio'); emit('close'); }
|
function goNegocio() { emit('select', 'negocio'); emit('close'); }
|
||||||
function goSeguranca() { emit('select', 'seguranca'); 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) ──
|
// ── Cores do Tema (embutido no aside, não em popover externo) ──
|
||||||
const themeViewActive = ref(false);
|
const themeViewActive = ref(false);
|
||||||
|
|
||||||
@@ -371,14 +353,6 @@ function setSurface(s) {
|
|||||||
saveThemeToStorage();
|
saveThemeToStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setPreset(p) {
|
|
||||||
if (!p || p === layoutConfig.preset) return;
|
|
||||||
layoutConfig.preset = p;
|
|
||||||
applyThemeEngine(layoutConfig);
|
|
||||||
queuePatch?.({ preset: p });
|
|
||||||
saveThemeToStorage();
|
|
||||||
}
|
|
||||||
|
|
||||||
function surfaceIsActive(s) {
|
function surfaceIsActive(s) {
|
||||||
if (layoutConfig.surface) return layoutConfig.surface === s.name;
|
if (layoutConfig.surface) return layoutConfig.surface === s.name;
|
||||||
// fallback default por mode
|
// fallback default por mode
|
||||||
@@ -478,6 +452,10 @@ async function sair() {
|
|||||||
<div class="mm-side__foot">
|
<div class="mm-side__foot">
|
||||||
<!-- Itens grudados acima do usuário -->
|
<!-- Itens grudados acima do usuário -->
|
||||||
<div class="mm-foot-actions">
|
<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
|
<button
|
||||||
class="mm-foot-item"
|
class="mm-foot-item"
|
||||||
:class="{ 'is-active': props.secaoAtiva === 'perfil' }"
|
:class="{ 'is-active': props.secaoAtiva === 'perfil' }"
|
||||||
@@ -506,20 +484,6 @@ async function sair() {
|
|||||||
>
|
>
|
||||||
<i class="pi pi-shield" /><span>Segurança</span>
|
<i class="pi pi-shield" /><span>Segurança</span>
|
||||||
</button>
|
</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
|
<button
|
||||||
class="mm-foot-item"
|
class="mm-foot-item"
|
||||||
:class="{ 'is-active': themeViewActive }"
|
:class="{ 'is-active': themeViewActive }"
|
||||||
@@ -600,22 +564,10 @@ async function sair() {
|
|||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="mm-theme__hint">
|
||||||
Mudanças se aplicam ao app inteiro e ficam salvas no seu perfil.
|
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>
|
</div>
|
||||||
|
|
||||||
<!-- Cards informativos (sem interação ainda) -->
|
<!-- Cards informativos (sem interação ainda) -->
|
||||||
@@ -988,6 +940,14 @@ async function sair() {
|
|||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
border-bottom: 1px solid var(--m-border);
|
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 {
|
.mm-foot-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1037,35 +997,6 @@ async function sair() {
|
|||||||
border-radius: 999px;
|
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 */
|
/* User row */
|
||||||
.mm-user {
|
.mm-user {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1347,39 +1278,22 @@ async function sair() {
|
|||||||
box-shadow: 0 0 0 2px var(--m-bg-soft-hover);
|
box-shadow: 0 0 0 2px var(--m-bg-soft-hover);
|
||||||
transform: scale(1.08);
|
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 {
|
.mm-theme__hint {
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
color: var(--m-text-faint);
|
color: var(--m-text-faint);
|
||||||
line-height: 1.4;
|
line-height: 1.5;
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
border-top: 1px solid var(--m-border);
|
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) ─────── */
|
/* ─── Info cards (descritivos, sem interação ainda) ─────── */
|
||||||
.mm-info-card {
|
.mm-info-card {
|
||||||
|
|||||||
Reference in New Issue
Block a user