+ Menu Hover no Layout Rail, Twilio, Sms, Email, Templates, LNovo Layout Configurações
This commit is contained in:
@@ -208,9 +208,9 @@ onMounted(async () => {
|
||||
</div>
|
||||
|
||||
<!-- Linha 1: icon + título + botão -->
|
||||
<div class="relative z-[1] flex items-center gap-3">
|
||||
<div class="relative z-1 flex items-center gap-3">
|
||||
<div class="flex items-center gap-2.5 flex-1 min-w-0">
|
||||
<div class="cfg-subheader__icon grid place-items-center w-10 h-10 rounded-md flex-shrink-0" style="background: color-mix(in srgb, #10b981 15%, transparent); color: #059669">
|
||||
<div class="cfg-subheader__icon grid place-items-center w-10 h-10 rounded-md shrink-0" style="background: color-mix(in srgb, #10b981 15%, transparent); color: #059669">
|
||||
<i class="pi pi-wallet text-lg" />
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
@@ -218,13 +218,13 @@ onMounted(async () => {
|
||||
<div class="text-[0.78rem] text-[var(--text-color-secondary)] mt-0.5">Resumo e visão geral do período</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 flex-shrink-0">
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<Button label="Ver lançamentos" icon="pi pi-list" severity="secondary" outlined class="rounded-full hidden sm:flex" @click="goToLancamentos" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Linha 2: quick stats -->
|
||||
<div class="relative z-[1] mt-2.5">
|
||||
<div class="relative z-1 mt-2.5">
|
||||
<template v-if="summaryLoading">
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-2.5">
|
||||
<div v-for="n in 4" :key="n" class="flex flex-col gap-1.5 px-4 py-2.5 rounded-md border border-[var(--surface-border)]">
|
||||
@@ -249,7 +249,7 @@ onMounted(async () => {
|
||||
<div class="flex flex-col gap-0.5 px-4 py-2.5 rounded-md border border-amber-500/25 bg-amber-500/5">
|
||||
<div class="text-[1.35rem] font-bold leading-none text-amber-500">{{ fmtBRL(totalPendente) }}</div>
|
||||
<div class="flex items-center gap-1.5 text-[0.7rem] text-amber-600/80 font-semibold">
|
||||
<span class="h-1.5 w-1.5 rounded-full bg-amber-400 animate-pulse flex-shrink-0" />
|
||||
<span class="h-1.5 w-1.5 rounded-full bg-amber-400 animate-pulse shrink-0" />
|
||||
Pendente
|
||||
</div>
|
||||
</div>
|
||||
@@ -281,7 +281,7 @@ onMounted(async () => {
|
||||
═══════════════════════════════════════ -->
|
||||
<section class="dash-card rounded-md">
|
||||
<div class="dash-card__head gap-2.5 p-2.5">
|
||||
<i class="pi pi-chart-bar cfg-subheader__icon w-10 h-10 rounded-md flex-shrink-0" />
|
||||
<i class="pi pi-chart-bar cfg-subheader__icon w-10 h-10 rounded-md shrink-0" />
|
||||
<div>
|
||||
<div class="font-bold tracking-tight text-[var(--text-color-secondary)]">Receita × Despesa</div>
|
||||
<div class="dash-card__sub">Comparativo dos últimos 6 meses</div>
|
||||
@@ -303,7 +303,7 @@ onMounted(async () => {
|
||||
═══════════════════════════════════════ -->
|
||||
<section class="dash-card rounded-md">
|
||||
<div class="dash-card__head gap-2.5 p-2.5">
|
||||
<i class="pi pi-calendar cfg-subheader__icon w-10 h-10 rounded-md flex-shrink-0" />
|
||||
<i class="pi pi-calendar cfg-subheader__icon w-10 h-10 rounded-md shrink-0" />
|
||||
<div>
|
||||
<div class="font-bold tracking-tight text-[var(--text-color-secondary)]">Projeção de Caixa</div>
|
||||
<div class="dash-card__sub">Cobranças em aberto — próximos 6 meses</div>
|
||||
@@ -320,7 +320,7 @@ onMounted(async () => {
|
||||
|
||||
<div v-else class="flex flex-col gap-1.5 pt-1">
|
||||
<div v-for="row in cashflowRows" :key="row.mes_label" class="flex items-center gap-3 px-3 py-2.5 rounded-md bg-[var(--surface-ground,#f8fafc)] hover:bg-[var(--surface-hover,#f1f5f9)] transition-colors duration-100">
|
||||
<span class="font-bold text-[0.8rem] uppercase tracking-wide text-[var(--text-color)] min-w-[3.5rem] flex-shrink-0">{{ row.mes_label }}</span>
|
||||
<span class="font-bold text-[0.8rem] uppercase tracking-wide text-[var(--text-color)] min-w-[3.5rem] shrink-0">{{ row.mes_label }}</span>
|
||||
<div class="flex items-center gap-2 flex-1 flex-wrap text-[0.8rem]">
|
||||
<span class="flex items-center gap-1 text-emerald-600 font-semibold">
|
||||
<i class="pi pi-arrow-up-right text-xs" />
|
||||
@@ -334,7 +334,7 @@ onMounted(async () => {
|
||||
<span class="text-[var(--text-color-secondary)] opacity-30">·</span>
|
||||
<span class="font-bold" :class="Number(row.saldo_projetado) >= 0 ? 'text-emerald-600' : 'text-red-500'"> saldo {{ fmtBRL(row.saldo_projetado) }} </span>
|
||||
</div>
|
||||
<Tag :value="row.count_registros + ' cobranças'" severity="secondary" class="ml-auto text-xs flex-shrink-0" />
|
||||
<Tag :value="row.count_registros + ' cobranças'" severity="secondary" class="ml-auto text-xs shrink-0" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -345,12 +345,12 @@ onMounted(async () => {
|
||||
═══════════════════════════════════════ -->
|
||||
<section class="dash-card rounded-md shadow-[0_0_0_3px_color-mix(in_srgb,var(--primary-color)_7%,transparent)]">
|
||||
<div class="dash-card__head gap-2.5 p-2.5">
|
||||
<i class="pi pi-list cfg-subheader__icon w-10 h-10 rounded-md flex-shrink-0" />
|
||||
<i class="pi pi-list cfg-subheader__icon w-10 h-10 rounded-md shrink-0" />
|
||||
<div class="flex-1">
|
||||
<div class="font-bold tracking-tight text-[var(--text-color-secondary)]">Últimos lançamentos</div>
|
||||
<div class="dash-card__sub">Cobranças e receitas recentes</div>
|
||||
</div>
|
||||
<button class="flex items-center gap-1 bg-transparent border-none cursor-pointer text-xs font-semibold text-[var(--primary-color,#6366f1)] p-0 flex-shrink-0" @click="goToLancamentos">
|
||||
<button class="flex items-center gap-1 bg-transparent border-none cursor-pointer text-xs font-semibold text-[var(--primary-color,#6366f1)] p-0 shrink-0" @click="goToLancamentos">
|
||||
Ver todos <i class="pi pi-arrow-right text-xs" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -302,11 +302,11 @@ onBeforeUnmount(() => {
|
||||
<div class="absolute w-72 h-72 top-0 -left-16 rounded-full blur-[60px] bg-indigo-500/[0.09]" />
|
||||
</div>
|
||||
|
||||
<div class="relative z-[1] px-3 pt-2.5 pb-2">
|
||||
<div class="relative z-1 px-3 pt-2.5 pb-2">
|
||||
<!-- Linha 1: brand + actions -->
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="flex items-center gap-2.5 flex-1 min-w-0">
|
||||
<div class="cfg-subheader__icon grid place-items-center w-10 h-10 rounded-md flex-shrink-0" style="background: color-mix(in srgb, #10b981 15%, transparent); color: #059669">
|
||||
<div class="cfg-subheader__icon grid place-items-center w-10 h-10 rounded-md shrink-0" style="background: color-mix(in srgb, #10b981 15%, transparent); color: #059669">
|
||||
<i class="pi pi-wallet text-base" />
|
||||
</div>
|
||||
<div class="min-w-0">
|
||||
@@ -316,13 +316,13 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
|
||||
<!-- Ações desktop -->
|
||||
<div class="hidden sm:flex items-center gap-2 flex-shrink-0">
|
||||
<div class="hidden sm:flex items-center gap-2 shrink-0">
|
||||
<Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full" :loading="loading" v-tooltip.top="'Recarregar'" @click="applyFilters" />
|
||||
<Button label="Lançamento manual" icon="pi pi-plus" class="rounded-full" @click="openManualDlg" />
|
||||
</div>
|
||||
|
||||
<!-- Mobile -->
|
||||
<div class="flex sm:hidden items-center gap-1 flex-shrink-0">
|
||||
<div class="flex sm:hidden items-center gap-1 shrink-0">
|
||||
<Button icon="pi pi-refresh" severity="secondary" outlined class="h-9 w-9 rounded-full" :loading="loading" @click="applyFilters" />
|
||||
<Button icon="pi pi-plus" class="h-9 w-9 rounded-full" @click="openManualDlg" />
|
||||
</div>
|
||||
@@ -349,7 +349,7 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<div class="text-[1.25rem] font-bold leading-none text-amber-500">{{ fmtBRL(summary.totalPending) }}</div>
|
||||
<div class="flex items-center gap-1.5 text-[0.7rem] text-amber-600/80 font-semibold">
|
||||
<span class="h-1.5 w-1.5 rounded-full bg-amber-400 animate-pulse flex-shrink-0" />
|
||||
<span class="h-1.5 w-1.5 rounded-full bg-amber-400 animate-pulse shrink-0" />
|
||||
Pendente
|
||||
<span class="ml-auto font-bold bg-amber-500/10 rounded-full px-1.5">{{ summary.countByStatus.pending ?? 0 }}</span>
|
||||
</div>
|
||||
@@ -397,12 +397,12 @@ onBeforeUnmount(() => {
|
||||
═══════════════════════════════════════ -->
|
||||
<section class="dash-card rounded-md">
|
||||
<div class="dash-card__head gap-2.5 p-2.5">
|
||||
<i class="pi pi-filter cfg-subheader__icon w-10 h-10 rounded-md flex-shrink-0" />
|
||||
<i class="pi pi-filter cfg-subheader__icon w-10 h-10 rounded-md shrink-0" />
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-bold tracking-tight text-[var(--text-color-secondary)]">Filtros</div>
|
||||
<div class="dash-card__sub">Refine por status, tipo, paciente ou período</div>
|
||||
</div>
|
||||
<Button v-if="hasActiveFilters" label="Limpar" icon="pi pi-filter-slash" severity="danger" outlined size="small" class="rounded-full ml-auto flex-shrink-0" @click="clearFilters" />
|
||||
<Button v-if="hasActiveFilters" label="Limpar" icon="pi pi-filter-slash" severity="danger" outlined size="small" class="rounded-full ml-auto shrink-0" @click="clearFilters" />
|
||||
</div>
|
||||
<div class="px-4 py-3">
|
||||
<div class="flex flex-col sm:flex-row sm:flex-wrap items-start sm:items-end gap-3">
|
||||
@@ -428,7 +428,7 @@ onBeforeUnmount(() => {
|
||||
<Select id="fin-filter-patient" v-model="filterPatient" :options="patients" optionLabel="nome_completo" filter :filterFields="['nome_completo']" showClear class="w-full">
|
||||
<template #option="{ option }">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="h-2 w-2 rounded-full flex-shrink-0" :style="option.identification_color ? { background: option.identification_color } : { background: 'var(--surface-border)' }" />
|
||||
<span class="h-2 w-2 rounded-full shrink-0" :style="option.identification_color ? { background: option.identification_color } : { background: 'var(--surface-border)' }" />
|
||||
<span>{{ option.nome_completo }}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -452,7 +452,7 @@ onBeforeUnmount(() => {
|
||||
Erro de carregamento
|
||||
═══════════════════════════════════════ -->
|
||||
<div v-if="error" class="rounded-md border border-red-500/30 bg-red-500/5 px-4 py-3 flex items-center gap-3 text-red-600">
|
||||
<i class="pi pi-exclamation-triangle flex-shrink-0" />
|
||||
<i class="pi pi-exclamation-triangle shrink-0" />
|
||||
<span class="text-[1rem]">{{ error }}</span>
|
||||
<Button icon="pi pi-refresh" severity="danger" text size="small" class="ml-auto" @click="applyFilters" />
|
||||
</div>
|
||||
@@ -497,7 +497,7 @@ onBeforeUnmount(() => {
|
||||
<!-- Linha 1: paciente + valor + status -->
|
||||
<div class="flex items-start gap-2.5">
|
||||
<div
|
||||
class="h-8 w-8 rounded-full flex-shrink-0 grid place-items-center text-white text-xs font-bold mt-0.5"
|
||||
class="h-8 w-8 rounded-full shrink-0 grid place-items-center text-white text-xs font-bold mt-0.5"
|
||||
:style="rec.patients?.identification_color ? { background: rec.patients.identification_color } : { background: 'var(--primary-color, #6366f1)' }"
|
||||
>
|
||||
{{ rec.patients?.nome_completo?.[0]?.toUpperCase() ?? '?' }}
|
||||
@@ -510,7 +510,7 @@ onBeforeUnmount(() => {
|
||||
{{ rec.agenda_eventos ? fmtDateTime(rec.agenda_eventos.inicio_em) : 'Lançamento manual' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col items-end gap-1 flex-shrink-0">
|
||||
<div class="flex flex-col items-end gap-1 shrink-0">
|
||||
<span class="font-bold text-[var(--text-color)]">{{ fmtBRL(rec.final_amount) }}</span>
|
||||
<Tag :value="STATUS_CFG[rec.status]?.label ?? rec.status" :severity="STATUS_CFG[rec.status]?.severity" class="text-xs" />
|
||||
</div>
|
||||
@@ -547,7 +547,7 @@ onBeforeUnmount(() => {
|
||||
<section class="hidden md:block dash-card rounded-md shadow-[0_0_0_3px_color-mix(in_srgb,var(--primary-color)_7%,transparent)]">
|
||||
<!-- Header -->
|
||||
<div class="dash-card__head gap-2.5 p-2.5">
|
||||
<i class="pi pi-table cfg-subheader__icon w-10 h-10 rounded-md flex-shrink-0" />
|
||||
<i class="pi pi-table cfg-subheader__icon w-10 h-10 rounded-md shrink-0" />
|
||||
<div class="flex-1">
|
||||
<div class="font-bold tracking-tight text-[var(--text-color-secondary)]">Registros</div>
|
||||
<div class="dash-card__sub">Lista completa de cobranças e lançamentos</div>
|
||||
@@ -584,7 +584,7 @@ onBeforeUnmount(() => {
|
||||
<template #body="{ data }">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="h-6 w-6 rounded-full flex-shrink-0 grid place-items-center text-white text-[0.6rem] font-bold"
|
||||
class="h-6 w-6 rounded-full shrink-0 grid place-items-center text-white text-[0.6rem] font-bold"
|
||||
:style="data.patients?.identification_color ? { background: data.patients.identification_color } : { background: 'var(--primary-color, #6366f1)' }"
|
||||
>
|
||||
{{ data.patients?.nome_completo?.[0]?.toUpperCase() ?? '?' }}
|
||||
@@ -688,7 +688,7 @@ onBeforeUnmount(() => {
|
||||
<div class="font-semibold text-sm text-[var(--text-color)] truncate">{{ payDlgRecord.patients?.nome_completo ?? '—' }}</div>
|
||||
<div class="text-[0.75rem] text-[var(--text-color-secondary)] mt-0.5">Vencimento: {{ fmtDate(payDlgRecord.due_date) }}</div>
|
||||
</div>
|
||||
<div class="text-right flex-shrink-0">
|
||||
<div class="text-right shrink-0">
|
||||
<div class="text-lg font-bold text-[var(--text-color)]">{{ fmtBRL(payDlgRecord.final_amount) }}</div>
|
||||
<div v-if="payDlgRecord.discount_amount > 0" class="text-[0.7rem] text-[var(--text-color-secondary)] line-through">
|
||||
{{ fmtBRL(payDlgRecord.amount) }}
|
||||
@@ -745,7 +745,7 @@ onBeforeUnmount(() => {
|
||||
<Select v-model="manualForm.patient" :options="patients" optionLabel="nome_completo" filter :filterFields="['nome_completo']" showClear placeholder="Selecionar paciente..." class="w-full">
|
||||
<template #option="{ option }">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="h-2 w-2 rounded-full flex-shrink-0" :style="option.identification_color ? { background: option.identification_color } : { background: 'var(--surface-border)' }" />
|
||||
<span class="h-2 w-2 rounded-full shrink-0" :style="option.identification_color ? { background: option.identification_color } : { background: 'var(--surface-border)' }" />
|
||||
<span>{{ option.nome_completo }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user