ajustes na tabela de consulta
This commit is contained in:
parent
aea3da6585
commit
1446d6225b
78 changed files with 17921 additions and 17580 deletions
62
src/componentes/EliEntrada/EliEntradaConfirmacao.vue
Normal file
62
src/componentes/EliEntrada/EliEntradaConfirmacao.vue
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<v-switch
|
||||
v-model="localValue"
|
||||
:label="rotuloExibido"
|
||||
:color="opcoes?.cor ?? 'primary'"
|
||||
:disabled="Boolean(opcoes?.desabilitado)"
|
||||
:density="opcoes?.densidade ?? 'comfortable'"
|
||||
hide-details
|
||||
v-bind="attrs"
|
||||
@focus="() => emit('focus')"
|
||||
@blur="() => emit('blur')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, type PropType } from "vue"
|
||||
import { VSwitch } from "vuetify/components"
|
||||
import type { PadroesEntradas } from "./tiposEntradas"
|
||||
|
||||
type EntradaConfirmacao = PadroesEntradas["confirmacao"]
|
||||
|
||||
export default defineComponent({
|
||||
name: "EliEntradaConfirmacao",
|
||||
components: { VSwitch },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean as PropType<EntradaConfirmacao["value"]>,
|
||||
default: false,
|
||||
},
|
||||
opcoes: {
|
||||
type: Object as PropType<EntradaConfirmacao["opcoes"]>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
"update:value": (_v: EntradaConfirmacao["value"]) => true,
|
||||
input: (_v: EntradaConfirmacao["value"]) => true,
|
||||
change: (_v: EntradaConfirmacao["value"]) => true,
|
||||
focus: () => true,
|
||||
blur: () => true,
|
||||
},
|
||||
setup(props, { attrs, emit }) {
|
||||
const localValue = computed<EntradaConfirmacao["value"]>({
|
||||
get: () => props.value,
|
||||
set: (v) => {
|
||||
emit("update:value", v)
|
||||
emit("input", v)
|
||||
emit("change", v)
|
||||
},
|
||||
})
|
||||
|
||||
const rotuloExibido = computed(() => {
|
||||
if (localValue.value && props.opcoes?.rotuloAtivo) return props.opcoes.rotuloAtivo
|
||||
if (!localValue.value && props.opcoes?.rotuloInativo) return props.opcoes.rotuloInativo
|
||||
return props.opcoes?.rotulo ?? ""
|
||||
})
|
||||
|
||||
return { attrs, emit, localValue, rotuloExibido }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
95
src/componentes/EliEntrada/EliEntradaSelecaoMultipla.vue
Normal file
95
src/componentes/EliEntrada/EliEntradaSelecaoMultipla.vue
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<v-select
|
||||
v-model="localValue"
|
||||
:label="opcoes?.rotulo"
|
||||
:placeholder="opcoes?.placeholder"
|
||||
:items="itens"
|
||||
item-title="rotulo"
|
||||
item-value="chave"
|
||||
:loading="carregando"
|
||||
:disabled="carregando"
|
||||
:menu-props="{ maxHeight: 320, zIndex: 99999 }"
|
||||
:clearable="Boolean(opcoes?.limpavel)"
|
||||
:error="Boolean(opcoes?.erro)"
|
||||
:error-messages="opcoes?.mensagensErro"
|
||||
:hint="opcoes?.dica"
|
||||
:persistent-hint="Boolean(opcoes?.dicaPersistente)"
|
||||
:density="opcoes?.densidade ?? 'comfortable'"
|
||||
:variant="opcoes?.variante ?? 'outlined'"
|
||||
multiple
|
||||
chips
|
||||
closable-chips
|
||||
v-bind="attrs"
|
||||
@focus="() => emit('focus')"
|
||||
@blur="() => emit('blur')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onMounted, type PropType, ref, watch } from "vue"
|
||||
import { VSelect } from "vuetify/components"
|
||||
import type { PadroesEntradas } from "./tiposEntradas"
|
||||
|
||||
type EntradaSelecaoMultipla = PadroesEntradas["selecaoMultipla"]
|
||||
type ItemSelecao = { chave: string; rotulo: string }
|
||||
|
||||
export default defineComponent({
|
||||
name: "EliEntradaSelecaoMultipla",
|
||||
components: { VSelect },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: {
|
||||
type: [Array, null] as unknown as PropType<EntradaSelecaoMultipla["value"]>,
|
||||
default: () => [],
|
||||
},
|
||||
opcoes: {
|
||||
type: Object as PropType<EntradaSelecaoMultipla["opcoes"]>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
"update:value": (_v: EntradaSelecaoMultipla["value"]) => true,
|
||||
input: (_v: EntradaSelecaoMultipla["value"]) => true,
|
||||
change: (_v: EntradaSelecaoMultipla["value"]) => true,
|
||||
focus: () => true,
|
||||
blur: () => true,
|
||||
},
|
||||
setup(props, { attrs, emit }) {
|
||||
const itens = ref<ItemSelecao[]>([])
|
||||
const carregando = ref(false)
|
||||
|
||||
const localValue = computed<EntradaSelecaoMultipla["value"]>({
|
||||
get: () => props.value ?? [],
|
||||
set: (v) => {
|
||||
const valor = Array.isArray(v) ? v : []
|
||||
emit("update:value", valor)
|
||||
emit("input", valor)
|
||||
emit("change", valor)
|
||||
},
|
||||
})
|
||||
|
||||
async function carregarItens() {
|
||||
carregando.value = true
|
||||
try {
|
||||
const resultado = await props.opcoes.itens()
|
||||
itens.value = [...(Array.isArray(resultado) ? resultado : [])]
|
||||
} finally {
|
||||
carregando.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.opcoes.itens,
|
||||
() => {
|
||||
void carregarItens()
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
void carregarItens()
|
||||
})
|
||||
|
||||
return { attrs, emit, localValue, itens, carregando }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
@ -1,14 +1,18 @@
|
|||
import EliEntradaConfirmacao from "./EliEntradaConfirmacao.vue"
|
||||
import EliEntradaDataHora from "./EliEntradaDataHora.vue"
|
||||
import EliEntradaNumero from "./EliEntradaNumero.vue"
|
||||
import EliEntradaParagrafo from "./EliEntradaParagrafo.vue"
|
||||
import EliEntradaSelecao from "./EliEntradaSelecao.vue"
|
||||
import EliEntradaSelecaoMultipla from "./EliEntradaSelecaoMultipla.vue"
|
||||
import EliEntradaTexto from "./EliEntradaTexto.vue"
|
||||
|
||||
export type { PadroesEntradas, TipoEntrada } from "./tiposEntradas"
|
||||
export {
|
||||
EliEntradaConfirmacao,
|
||||
EliEntradaDataHora,
|
||||
EliEntradaNumero,
|
||||
EliEntradaParagrafo,
|
||||
EliEntradaSelecao,
|
||||
EliEntradaSelecaoMultipla,
|
||||
EliEntradaTexto,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import type { Component } from "vue"
|
||||
import EliEntradaConfirmacao from "./EliEntradaConfirmacao.vue"
|
||||
import EliEntradaDataHora from "./EliEntradaDataHora.vue"
|
||||
import EliEntradaNumero from "./EliEntradaNumero.vue"
|
||||
import EliEntradaParagrafo from "./EliEntradaParagrafo.vue"
|
||||
import EliEntradaSelecao from "./EliEntradaSelecao.vue"
|
||||
import EliEntradaSelecaoMultipla from "./EliEntradaSelecaoMultipla.vue"
|
||||
import EliEntradaTexto from "./EliEntradaTexto.vue"
|
||||
|
||||
import type { TipoEntrada } from "./tiposEntradas"
|
||||
|
|
@ -17,10 +19,12 @@ import type { TipoEntrada } from "./tiposEntradas"
|
|||
* 2. Adicionar a chave em `TipoEntrada` (tiposEntradas.ts)
|
||||
* 3. Registrar aqui no mapa
|
||||
*/
|
||||
export const registryTabelaCelulas = {
|
||||
export const registryTabelaCelulas: Record<TipoEntrada, Component> = {
|
||||
texto: EliEntradaTexto,
|
||||
numero: EliEntradaNumero,
|
||||
dataHora: EliEntradaDataHora,
|
||||
paragrafo: EliEntradaParagrafo,
|
||||
selecao: EliEntradaSelecao,
|
||||
} as const satisfies Record<TipoEntrada, Component>
|
||||
selecaoMultipla: EliEntradaSelecaoMultipla,
|
||||
confirmacao: EliEntradaConfirmacao,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,6 +177,60 @@ export type PadroesEntradas = {
|
|||
variante?: import("../../tipos").CampoVariante
|
||||
}
|
||||
>
|
||||
|
||||
selecaoMultipla: tipoPadraoEntrada<
|
||||
string[] | null | undefined,
|
||||
{
|
||||
/**
|
||||
* Carrega os itens da seleção (sincrono ou async).
|
||||
* - Cada item precisa ter uma chave estável (value) e um rótulo (title).
|
||||
*/
|
||||
itens: () =>
|
||||
| { chave: string; rotulo: string }[]
|
||||
| Promise<{ chave: string; rotulo: string }[]>
|
||||
|
||||
/** Se true, mostra ícone para limpar o valor (Vuetify clearable). */
|
||||
limpavel?: boolean
|
||||
|
||||
/** Estado de erro (visual). */
|
||||
erro?: boolean
|
||||
|
||||
/** Mensagens de erro. */
|
||||
mensagensErro?: string | string[]
|
||||
|
||||
/** Texto de apoio. */
|
||||
dica?: string
|
||||
|
||||
/** Mantém a dica sempre visível. */
|
||||
dicaPersistente?: boolean
|
||||
|
||||
/** Densidade do campo (Vuetify). */
|
||||
densidade?: import("../../tipos").CampoDensidade
|
||||
|
||||
/** Variante do v-text-field (Vuetify). */
|
||||
variante?: import("../../tipos").CampoVariante
|
||||
}
|
||||
>
|
||||
|
||||
confirmacao: tipoPadraoEntrada<
|
||||
boolean,
|
||||
{
|
||||
/** Cor do switch quando ativo (Vuetify color). */
|
||||
cor?: string
|
||||
|
||||
/** Se true, desabilita a interação. */
|
||||
desabilitado?: boolean
|
||||
|
||||
/** Texto exibido ao lado do switch quando ativo. */
|
||||
rotuloAtivo?: string
|
||||
|
||||
/** Texto exibido ao lado do switch quando inativo. */
|
||||
rotuloInativo?: string
|
||||
|
||||
/** Densidade do campo (Vuetify). */
|
||||
densidade?: import("../../tipos").CampoDensidade
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import "./EliTabelaAcoes.css";
|
||||
@import "./EliTabelaSelecao.css";
|
||||
.eli-tabela {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -132,7 +134,6 @@
|
|||
background: rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
|
||||
.eli-tabela--erro {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
|
@ -244,284 +245,6 @@
|
|||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
/* Altura padrão para controles do cabeçalho (busca e botões)
|
||||
* - Mantém alinhamento visual entre input de busca e ações
|
||||
* - Pode ser sobrescrita via CSS no consumidor, se necessário
|
||||
*/
|
||||
--eli-tabela-cabecalho-controle-altura: 34px;
|
||||
|
||||
/* Borda dos controles do cabeçalho: menos "pílula", mais quadrado.
|
||||
* Ajuste fino via CSS no consumidor, se necessário.
|
||||
*/
|
||||
--eli-tabela-cabecalho-controle-radius: 8px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho {
|
||||
display: inline-flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: var(--eli-tabela-cabecalho-controle-altura);
|
||||
padding: 0 14px;
|
||||
border-radius: var(--eli-tabela-cabecalho-controle-radius);
|
||||
border: none;
|
||||
background: var(--cor-eli-primaria-bg);
|
||||
color: var(--cor-eli-primaria-escura);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-botao:hover,
|
||||
.eli-tabela__acoes-cabecalho-botao:focus-visible {
|
||||
background: var(--cor-eli-primaria-clara);
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-botao:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-icone {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-rotulo {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 9999px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: rgba(15, 23, 42, 0.72);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle-icone {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle:hover,
|
||||
.eli-tabela__acoes-toggle:focus-visible {
|
||||
background-color: rgba(15, 23, 42, 0.08);
|
||||
color: rgba(15, 23, 42, 0.95);
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle:disabled {
|
||||
cursor: default;
|
||||
color: rgba(148, 163, 184, 0.8);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-menu {
|
||||
min-width: 180px;
|
||||
padding: 6px 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
background: var(--cor-eli-superficie);
|
||||
border: 1px solid rgba(15, 23, 42, 0.08);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.18);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-botao {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-botao:hover,
|
||||
.eli-tabela__acoes-item-botao:focus-visible {
|
||||
background-color: rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-botao:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-icone {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-texto {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
* Expander (colunas invisíveis)
|
||||
* ========================= */
|
||||
|
||||
.eli-tabela__th--expander,
|
||||
.eli-tabela__td--expander {
|
||||
width: 42px;
|
||||
padding: 6px 8px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 9999px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: rgba(15, 23, 42, 0.72);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao:hover,
|
||||
.eli-tabela__expander-botao:focus-visible {
|
||||
background-color: rgba(15, 23, 42, 0.08);
|
||||
color: rgba(15, 23, 42, 0.95);
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao--ativo {
|
||||
background-color: rgba(15, 23, 42, 0.06);
|
||||
color: rgba(15, 23, 42, 0.95);
|
||||
}
|
||||
|
||||
.eli-tabela__td--detalhes {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.eli-tabela__tr--detalhes .eli-tabela__td {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.eli-tabela__detalhes {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.eli-tabela__detalhe {
|
||||
display: grid;
|
||||
grid-template-columns: 180px 1fr;
|
||||
gap: 10px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.eli-tabela__detalhe-rotulo {
|
||||
font-weight: 600;
|
||||
color: rgba(15, 23, 42, 0.85);
|
||||
}
|
||||
|
||||
.eli-tabela__detalhe-valor {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.eli-tabela__detalhe {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================
|
||||
* Seleção (Checkboxes)
|
||||
* ========================================= */
|
||||
.eli-tabela__th--selecao,
|
||||
.eli-tabela__td--selecao {
|
||||
width: 48px;
|
||||
min-width: 48px;
|
||||
max-width: 48px;
|
||||
text-align: center;
|
||||
padding: 0 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
cursor: pointer;
|
||||
border: 2px solid rgba(0, 0, 0, 0.54);
|
||||
border-radius: 2px;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
transition: all 0.2s ease-in-out;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:hover {
|
||||
border-color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:checked,
|
||||
.eli-tabela__checkbox:indeterminate {
|
||||
background-color: var(--cor-eli-primaria);
|
||||
border-color: var(--cor-eli-primaria);
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 4px;
|
||||
width: 4px;
|
||||
height: 9px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:indeterminate::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 2px;
|
||||
width: 8px;
|
||||
height: 2px;
|
||||
background-color: white;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--cor-eli-primaria-clara);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
v-if="exibirBusca || temAcoesSuperiores"
|
||||
:exibirBusca="exibirBusca"
|
||||
:exibirBotaoFiltroAvancado="exibirFiltroAvancado"
|
||||
:filtrosAtivosResumo="filtrosAtivosResumo"
|
||||
:valorBusca="valorBusca"
|
||||
:acoesCabecalho="acoesSuperiores"
|
||||
:parametrosConsulta="parametrosConsultaAtuais"
|
||||
|
|
|
|||
207
src/componentes/EliTabela/EliTabelaAcoes.css
Normal file
207
src/componentes/EliTabela/EliTabelaAcoes.css
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/* =========================
|
||||
* EliTabela — Ações de linha, Menu e Seleção (Checkboxes)
|
||||
* Extraído de EliTabela.css para manter cada arquivo CSS abaixo de 250 linhas.
|
||||
* ========================= */
|
||||
|
||||
.eli-tabela__acoes-cabecalho {
|
||||
display: inline-flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: var(--eli-tabela-cabecalho-controle-altura);
|
||||
padding: 0 14px;
|
||||
border-radius: var(--eli-tabela-cabecalho-controle-radius);
|
||||
border: none;
|
||||
background: var(--cor-eli-primaria-bg);
|
||||
color: var(--cor-eli-primaria-escura);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-botao:hover,
|
||||
.eli-tabela__acoes-cabecalho-botao:focus-visible {
|
||||
background: var(--cor-eli-primaria-clara);
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-botao:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-icone {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-cabecalho-rotulo {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 9999px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: rgba(15, 23, 42, 0.72);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle-icone {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle:hover,
|
||||
.eli-tabela__acoes-toggle:focus-visible {
|
||||
background-color: rgba(15, 23, 42, 0.08);
|
||||
color: rgba(15, 23, 42, 0.95);
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-toggle:disabled {
|
||||
cursor: default;
|
||||
color: rgba(148, 163, 184, 0.8);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-menu {
|
||||
min-width: 180px;
|
||||
padding: 6px 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
background: var(--cor-eli-superficie);
|
||||
border: 1px solid rgba(15, 23, 42, 0.08);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.18);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-botao {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-botao:hover,
|
||||
.eli-tabela__acoes-item-botao:focus-visible {
|
||||
background-color: rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-botao:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-icone {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.eli-tabela__acoes-item-texto {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
* Expander (colunas invisíveis)
|
||||
* ========================= */
|
||||
|
||||
.eli-tabela__th--expander,
|
||||
.eli-tabela__td--expander {
|
||||
width: 42px;
|
||||
padding: 6px 8px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 9999px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: rgba(15, 23, 42, 0.72);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao:hover,
|
||||
.eli-tabela__expander-botao:focus-visible {
|
||||
background-color: rgba(15, 23, 42, 0.08);
|
||||
color: rgba(15, 23, 42, 0.95);
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela__expander-botao--ativo {
|
||||
background-color: rgba(15, 23, 42, 0.06);
|
||||
color: rgba(15, 23, 42, 0.95);
|
||||
}
|
||||
|
||||
.eli-tabela__td--detalhes {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.eli-tabela__tr--detalhes .eli-tabela__td {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.eli-tabela__detalhes {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.eli-tabela__detalhe {
|
||||
display: grid;
|
||||
grid-template-columns: 180px 1fr;
|
||||
gap: 10px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.eli-tabela__detalhe-rotulo {
|
||||
font-weight: 600;
|
||||
color: rgba(15, 23, 42, 0.85);
|
||||
}
|
||||
|
||||
.eli-tabela__detalhe-valor {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.eli-tabela__detalhe {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -16,9 +16,16 @@
|
|||
v-if="exibirBotaoFiltroAvancado"
|
||||
type="button"
|
||||
class="eli-tabela__acoes-cabecalho-botao eli-tabela__acoes-cabecalho-botao--filtro"
|
||||
:title="tooltipFiltro"
|
||||
@click="emitFiltroAvancado"
|
||||
>
|
||||
<Filter :size="15" :stroke-width="2" />
|
||||
<span class="eli-tabela__filtro-icone-container">
|
||||
<Filter :size="15" :stroke-width="2" />
|
||||
<span
|
||||
v-if="filtrosAtivosResumo.quantidade > 0"
|
||||
class="eli-tabela__filtro-badge"
|
||||
>{{ filtrosAtivosResumo.quantidade }}</span>
|
||||
</span>
|
||||
Filtro
|
||||
</button>
|
||||
<EliTabelaCaixaDeBusca :modelo="valorBusca" @buscar="emitBuscar" />
|
||||
|
|
@ -70,6 +77,11 @@ export default defineComponent({
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
filtrosAtivosResumo: {
|
||||
type: Object as PropType<{ quantidade: number; rotulos: string[] }>,
|
||||
required: false,
|
||||
default: () => ({ quantidade: 0, rotulos: [] }),
|
||||
},
|
||||
valorBusca: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
@ -107,6 +119,12 @@ export default defineComponent({
|
|||
setup(props, { emit }) {
|
||||
const temAcoesCabecalho = computed(() => props.acoesCabecalho.length > 0)
|
||||
|
||||
const tooltipFiltro = computed(() => {
|
||||
const { quantidade, rotulos } = props.filtrosAtivosResumo
|
||||
if (quantidade === 0) return "Filtro avançado"
|
||||
return `Filtros ativos (${quantidade}):\n${rotulos.map((r) => `• ${r}`).join("\n")}`
|
||||
})
|
||||
|
||||
function emitBuscar(texto: string) {
|
||||
emit("buscar", texto)
|
||||
}
|
||||
|
|
@ -119,7 +137,7 @@ export default defineComponent({
|
|||
emit("filtroAvancado")
|
||||
}
|
||||
|
||||
return { temAcoesCabecalho, emitBuscar, emitColunas, emitFiltroAvancado }
|
||||
return { temAcoesCabecalho, tooltipFiltro, emitBuscar, emitColunas, emitFiltroAvancado }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
@ -131,4 +149,28 @@ export default defineComponent({
|
|||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.eli-tabela__filtro-icone-container {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.eli-tabela__filtro-badge {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: -9px;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
padding: 0 4px;
|
||||
border-radius: 9999px;
|
||||
background: var(--cor-eli-erro, #dc3545);
|
||||
color: #fff;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import "./EliTabelaModalColunasItens.css";
|
||||
|
||||
.eli-tabela-modal-colunas__overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
|
|
@ -162,181 +164,3 @@
|
|||
.eli-tabela-modal-colunas__lista--invisiveis {
|
||||
background: var(--cor-eli-fundo);
|
||||
}
|
||||
|
||||
/* ── Item ── */
|
||||
.eli-tabela-modal-colunas__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--cor-eli-borda);
|
||||
background: var(--cor-eli-superficie);
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
transition: box-shadow 0.15s ease, opacity 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item + .eli-tabela-modal-colunas__item {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item:hover {
|
||||
border-color: var(--cor-eli-borda-forte);
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item--invisivel {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item--arrastando {
|
||||
opacity: 0.15;
|
||||
border-style: dashed;
|
||||
border-color: var(--cor-eli-primaria-media);
|
||||
}
|
||||
|
||||
/* ── Partes do item ── */
|
||||
.eli-tabela-modal-colunas__item-handle {
|
||||
color: var(--cor-eli-borda-forte);
|
||||
flex-shrink: 0;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item:hover .eli-tabela-modal-colunas__item-handle {
|
||||
color: var(--cor-eli-neutro);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-texto {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 0.875rem;
|
||||
color: var(--cor-eli-neutro-escuro);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-badge-icone {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-badge-icone--visivel {
|
||||
color: var(--cor-eli-primaria-acao);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-badge-icone--invisivel {
|
||||
color: var(--cor-eli-borda-forte);
|
||||
}
|
||||
|
||||
/* ── Estado vazio ── */
|
||||
.eli-tabela-modal-colunas__vazio {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 24px 12px;
|
||||
text-align: center;
|
||||
font-size: 0.8rem;
|
||||
color: var(--cor-eli-neutro);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__vazio-icone {
|
||||
color: var(--cor-eli-borda-forte);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__vazio-icone--ok {
|
||||
color: var(--cor-eli-primaria-acao);
|
||||
}
|
||||
|
||||
/* ── Animações TransitionGroup ── */
|
||||
.list-move,
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.list-enter-from,
|
||||
.list-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.list-leave-active {
|
||||
position: absolute;
|
||||
width: calc(100% - 16px);
|
||||
}
|
||||
|
||||
/* ── Footer ── */
|
||||
.eli-tabela-modal-colunas__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid var(--cor-eli-borda);
|
||||
background: var(--cor-eli-fundo);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: 34px;
|
||||
padding: 0 16px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--cor-eli-borda);
|
||||
background: var(--cor-eli-superficie);
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--sec {
|
||||
color: var(--cor-eli-neutro-escuro);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--sec:hover,
|
||||
.eli-tabela-modal-colunas__botao--sec:focus-visible {
|
||||
background: var(--cor-eli-fundo);
|
||||
border-color: var(--cor-eli-borda-forte);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--sec:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--prim {
|
||||
border: none;
|
||||
background: var(--cor-eli-primaria);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--prim:hover,
|
||||
.eli-tabela-modal-colunas__botao--prim:focus-visible {
|
||||
background: var(--cor-eli-primaria-escura);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--prim:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* ── Responsivo ── */
|
||||
@media (max-width: 720px) {
|
||||
.eli-tabela-modal-colunas__conteudo {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__coluna + .eli-tabela-modal-colunas__coluna {
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--cor-eli-borda);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
182
src/componentes/EliTabela/EliTabelaModalColunasItens.css
Normal file
182
src/componentes/EliTabela/EliTabelaModalColunasItens.css
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/* =========================
|
||||
* EliTabelaModalColunas — Itens, estados e footer
|
||||
* Extraído de EliTabelaModalColunas.css para manter cada arquivo abaixo de 250 linhas.
|
||||
* ========================= */
|
||||
|
||||
/* ── Item ── */
|
||||
.eli-tabela-modal-colunas__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--cor-eli-borda);
|
||||
background: var(--cor-eli-superficie);
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
transition: box-shadow 0.15s ease, opacity 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item + .eli-tabela-modal-colunas__item {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item:hover {
|
||||
border-color: var(--cor-eli-borda-forte);
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item--invisivel {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item--arrastando {
|
||||
opacity: 0.15;
|
||||
border-style: dashed;
|
||||
border-color: var(--cor-eli-primaria-media);
|
||||
}
|
||||
|
||||
/* ── Partes do item ── */
|
||||
.eli-tabela-modal-colunas__item-handle {
|
||||
color: var(--cor-eli-borda-forte);
|
||||
flex-shrink: 0;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item:hover .eli-tabela-modal-colunas__item-handle {
|
||||
color: var(--cor-eli-neutro);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-texto {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 0.875rem;
|
||||
color: var(--cor-eli-neutro-escuro);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-badge-icone {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-badge-icone--visivel {
|
||||
color: var(--cor-eli-primaria-acao);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__item-badge-icone--invisivel {
|
||||
color: var(--cor-eli-borda-forte);
|
||||
}
|
||||
|
||||
/* ── Estado vazio ── */
|
||||
.eli-tabela-modal-colunas__vazio {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 24px 12px;
|
||||
text-align: center;
|
||||
font-size: 0.8rem;
|
||||
color: var(--cor-eli-neutro);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__vazio-icone {
|
||||
color: var(--cor-eli-borda-forte);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__vazio-icone--ok {
|
||||
color: var(--cor-eli-primaria-acao);
|
||||
}
|
||||
|
||||
/* ── Animações TransitionGroup ── */
|
||||
.list-move,
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.list-enter-from,
|
||||
.list-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.list-leave-active {
|
||||
position: absolute;
|
||||
width: calc(100% - 16px);
|
||||
}
|
||||
|
||||
/* ── Footer ── */
|
||||
.eli-tabela-modal-colunas__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid var(--cor-eli-borda);
|
||||
background: var(--cor-eli-fundo);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: 34px;
|
||||
padding: 0 16px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--cor-eli-borda);
|
||||
background: var(--cor-eli-superficie);
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--sec {
|
||||
color: var(--cor-eli-neutro-escuro);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--sec:hover,
|
||||
.eli-tabela-modal-colunas__botao--sec:focus-visible {
|
||||
background: var(--cor-eli-fundo);
|
||||
border-color: var(--cor-eli-borda-forte);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--sec:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--prim {
|
||||
border: none;
|
||||
background: var(--cor-eli-primaria);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--prim:hover,
|
||||
.eli-tabela-modal-colunas__botao--prim:focus-visible {
|
||||
background: var(--cor-eli-primaria-escura);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__botao--prim:focus-visible {
|
||||
outline: 2px solid var(--cor-eli-primaria-clara);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* ── Responsivo ── */
|
||||
@media (max-width: 720px) {
|
||||
.eli-tabela-modal-colunas__conteudo {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-colunas__coluna + .eli-tabela-modal-colunas__coluna {
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--cor-eli-borda);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
@import "./EliTabelaModalFiltroFormula.css";
|
||||
|
||||
.eli-tabela-modal-filtro__overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
|
|
@ -217,227 +219,3 @@
|
|||
outline: none;
|
||||
border-color: var(--cor-eli-primaria);
|
||||
}
|
||||
|
||||
/* ── Fórmula de combinação ───────────────────── */
|
||||
.eli-tabela-modal-filtro__formula-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-label {
|
||||
font-size: 0.82rem;
|
||||
font-weight: 500;
|
||||
color: rgba(15, 23, 42, 0.55);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.eli-tabela-modal-filtro__formula-ajuda {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: rgba(15, 23, 42, 0.35);
|
||||
cursor: help;
|
||||
transition: color 0.15s;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-ajuda:hover,
|
||||
.eli-tabela-modal-filtro__formula-ajuda:focus-visible {
|
||||
color: var(--cor-eli-primaria);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-ajuda:hover .eli-tabela-modal-filtro__formula-tooltip,
|
||||
.eli-tabela-modal-filtro__formula-ajuda:focus-visible .eli-tabela-modal-filtro__formula-tooltip {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip {
|
||||
position: absolute;
|
||||
bottom: calc(100% + 10px);
|
||||
right: 0;
|
||||
width: 280px;
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
border-radius: 10px;
|
||||
padding: 14px 16px;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.55;
|
||||
z-index: 100;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateY(4px);
|
||||
transition: opacity 0.18s ease, transform 0.18s ease;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 6px;
|
||||
border: 6px solid transparent;
|
||||
border-top-color: #0f172a;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip strong {
|
||||
font-size: 0.82rem;
|
||||
color: var(--cor-eli-fundo);
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip p {
|
||||
margin: 6px 0 4px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip ul {
|
||||
margin: 4px 0 8px 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip li {
|
||||
margin-bottom: 3px;
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip code {
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
color: #7dd3fc;
|
||||
font-size: 0.78rem;
|
||||
background: rgba(255, 255, 255, 0.07);
|
||||
border-radius: 4px;
|
||||
padding: 1px 4px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-input {
|
||||
width: 220px;
|
||||
height: 36px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.12);
|
||||
padding: 0 10px;
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
font-size: 0.85rem;
|
||||
background: var(--cor-eli-fundo);
|
||||
transition: border-color 0.15s, background 0.15s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--cor-eli-primaria);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip-nota {
|
||||
margin-top: 8px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* ── Footer ──────────────────────────────────── */
|
||||
.eli-tabela-modal-filtro__footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 14px 20px;
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__footer-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* ── Botões ──────────────────────────────────── */
|
||||
.eli-tabela-modal-filtro__botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
height: 36px;
|
||||
padding: 0 16px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.12);
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--sec:hover:not(:disabled),
|
||||
.eli-tabela-modal-filtro__botao--sec:focus-visible {
|
||||
background: rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--prim {
|
||||
border: none;
|
||||
background: var(--cor-eli-primaria);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--prim:hover:not(:disabled),
|
||||
.eli-tabela-modal-filtro__botao--prim:focus-visible {
|
||||
background: var(--cor-eli-primaria-escura);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--perigo {
|
||||
color: rgba(220, 38, 38, 0.85);
|
||||
border-color: rgba(220, 38, 38, 0.18);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--perigo:hover:not(:disabled),
|
||||
.eli-tabela-modal-filtro__botao--perigo:focus-visible {
|
||||
background: rgba(239, 68, 68, 0.06);
|
||||
border-color: rgba(220, 38, 38, 0.3);
|
||||
color: rgba(220, 38, 38, 1);
|
||||
}
|
||||
|
||||
/* ── Responsivo ──────────────────────────────── */
|
||||
@media (max-width: 600px) {
|
||||
.eli-tabela-modal-filtro__lista {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.eli-tabela-modal-filtro__rodape-filtros {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.eli-tabela-modal-filtro__acoes {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Transição de abertura/fechamento ────────── */
|
||||
.eli-tabela-modal-filtro-enter-active,
|
||||
.eli-tabela-modal-filtro-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro-enter-active .eli-tabela-modal-filtro__modal,
|
||||
.eli-tabela-modal-filtro-leave-active .eli-tabela-modal-filtro__modal {
|
||||
transition: transform 0.2s ease, opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro-enter-from,
|
||||
.eli-tabela-modal-filtro-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro-enter-from .eli-tabela-modal-filtro__modal,
|
||||
.eli-tabela-modal-filtro-leave-to .eli-tabela-modal-filtro__modal {
|
||||
transform: scale(0.96);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
225
src/componentes/EliTabela/EliTabelaModalFiltroFormula.css
Normal file
225
src/componentes/EliTabela/EliTabelaModalFiltroFormula.css
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/* =========================
|
||||
* EliTabelaModalFiltroAvancado — Fórmula, tooltip, botões e transições
|
||||
* Extraído de EliTabelaModalFiltroAvancado.css para manter cada arquivo abaixo de 250 linhas.
|
||||
* ========================= */
|
||||
|
||||
/* ── Fórmula de combinação ───────────────────── */
|
||||
.eli-tabela-modal-filtro__formula-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-label {
|
||||
font-size: 0.82rem;
|
||||
font-weight: 500;
|
||||
color: rgba(15, 23, 42, 0.55);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-ajuda {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: rgba(15, 23, 42, 0.35);
|
||||
cursor: help;
|
||||
transition: color 0.15s;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-ajuda:hover,
|
||||
.eli-tabela-modal-filtro__formula-ajuda:focus-visible {
|
||||
color: var(--cor-eli-primaria);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-ajuda:hover .eli-tabela-modal-filtro__formula-tooltip,
|
||||
.eli-tabela-modal-filtro__formula-ajuda:focus-visible .eli-tabela-modal-filtro__formula-tooltip {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip {
|
||||
position: absolute;
|
||||
bottom: calc(100% + 10px);
|
||||
right: 0;
|
||||
width: 280px;
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
border-radius: 10px;
|
||||
padding: 14px 16px;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.55;
|
||||
z-index: 100;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateY(4px);
|
||||
transition: opacity 0.18s ease, transform 0.18s ease;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 6px;
|
||||
border: 6px solid transparent;
|
||||
border-top-color: #0f172a;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip strong {
|
||||
font-size: 0.82rem;
|
||||
color: var(--cor-eli-fundo);
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip p {
|
||||
margin: 6px 0 4px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip ul {
|
||||
margin: 4px 0 8px 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip li {
|
||||
margin-bottom: 3px;
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip code {
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
color: #7dd3fc;
|
||||
font-size: 0.78rem;
|
||||
background: rgba(255, 255, 255, 0.07);
|
||||
border-radius: 4px;
|
||||
padding: 1px 4px;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-input {
|
||||
width: 220px;
|
||||
height: 36px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.12);
|
||||
padding: 0 10px;
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
font-size: 0.85rem;
|
||||
background: var(--cor-eli-fundo);
|
||||
transition: border-color 0.15s, background 0.15s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--cor-eli-primaria);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__formula-tooltip-nota {
|
||||
margin-top: 8px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* ── Footer ──────────────────────────────────── */
|
||||
.eli-tabela-modal-filtro__footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 14px 20px;
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__footer-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* ── Botões ──────────────────────────────────── */
|
||||
.eli-tabela-modal-filtro__botao {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
height: 36px;
|
||||
padding: 0 16px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.12);
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--sec:hover:not(:disabled),
|
||||
.eli-tabela-modal-filtro__botao--sec:focus-visible {
|
||||
background: rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--prim {
|
||||
border: none;
|
||||
background: var(--cor-eli-primaria);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--prim:hover:not(:disabled),
|
||||
.eli-tabela-modal-filtro__botao--prim:focus-visible {
|
||||
background: var(--cor-eli-primaria-escura);
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--perigo {
|
||||
color: rgba(220, 38, 38, 0.85);
|
||||
border-color: rgba(220, 38, 38, 0.18);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro__botao--perigo:hover:not(:disabled),
|
||||
.eli-tabela-modal-filtro__botao--perigo:focus-visible {
|
||||
background: rgba(239, 68, 68, 0.06);
|
||||
border-color: rgba(220, 38, 38, 0.3);
|
||||
color: rgba(220, 38, 38, 1);
|
||||
}
|
||||
|
||||
/* ── Responsivo ──────────────────────────────── */
|
||||
@media (max-width: 600px) {
|
||||
.eli-tabela-modal-filtro__lista {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.eli-tabela-modal-filtro__rodape-filtros {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.eli-tabela-modal-filtro__acoes {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Transição de abertura/fechamento ────────── */
|
||||
.eli-tabela-modal-filtro-enter-active,
|
||||
.eli-tabela-modal-filtro-leave-active {
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro-enter-active .eli-tabela-modal-filtro__modal,
|
||||
.eli-tabela-modal-filtro-leave-active .eli-tabela-modal-filtro__modal {
|
||||
transition: transform 0.2s ease, opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro-enter-from,
|
||||
.eli-tabela-modal-filtro-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.eli-tabela-modal-filtro-enter-from .eli-tabela-modal-filtro__modal,
|
||||
.eli-tabela-modal-filtro-leave-to .eli-tabela-modal-filtro__modal {
|
||||
transform: scale(0.96);
|
||||
opacity: 0;
|
||||
}
|
||||
66
src/componentes/EliTabela/EliTabelaSelecao.css
Normal file
66
src/componentes/EliTabela/EliTabelaSelecao.css
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* =========================================
|
||||
* Seleção (Checkboxes)
|
||||
* Extraído de EliTabela.css para manter cada arquivo abaixo de 250 linhas.
|
||||
* ========================================= */
|
||||
.eli-tabela__th--selecao,
|
||||
.eli-tabela__td--selecao {
|
||||
width: 48px;
|
||||
min-width: 48px;
|
||||
max-width: 48px;
|
||||
text-align: center;
|
||||
padding: 0 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
cursor: pointer;
|
||||
border: 2px solid rgba(0, 0, 0, 0.54);
|
||||
border-radius: 2px;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
transition: all 0.2s ease-in-out;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:hover {
|
||||
border-color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:checked,
|
||||
.eli-tabela__checkbox:indeterminate {
|
||||
background-color: var(--cor-eli-primaria);
|
||||
border-color: var(--cor-eli-primaria);
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 4px;
|
||||
width: 4px;
|
||||
height: 9px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:indeterminate::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 2px;
|
||||
width: 8px;
|
||||
height: 2px;
|
||||
background-color: white;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.eli-tabela__checkbox:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--cor-eli-primaria-clara);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { LucideIcon } from "@lucide/vue"
|
||||
import type { tipoFiltroDeltaColunaTipada } from "p-comuns"
|
||||
import type { tipoCondicaoFiltroDeltaTipado, tipoFiltroDeltaColunaTipada } from "p-comuns"
|
||||
|
||||
import type { tipoResposta } from "p-respostas"
|
||||
import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas"
|
||||
|
|
@ -160,9 +160,17 @@ export type tipoEliTabelaConsulta<T> = {
|
|||
chave: string
|
||||
/** Rótulo exibido no select de adicionar filtro */
|
||||
rotulo: string
|
||||
/** vai gerar filtro e mescla com os filtros já existentes */
|
||||
filtro: (valor: unknown) => tipoFiltroDeltaColunaTipada<Extract<keyof T, string>> | undefined
|
||||
/** vai gerar filtro e mescla com os filtros já existentes , id é gerado de forma altomatica para esse local*/
|
||||
filtro: (
|
||||
valor: unknown,
|
||||
) =>
|
||||
| Pick<
|
||||
tipoCondicaoFiltroDeltaTipado<Extract<keyof T, string>>,
|
||||
"coluna" | "operador" | "valor"
|
||||
>
|
||||
| undefined
|
||||
/** componente de entrada que vai receber o valor para o filtro */
|
||||
entrada: ComponenteEntrada
|
||||
}[]
|
||||
}
|
||||
;("")
|
||||
|
|
|
|||
|
|
@ -49,12 +49,13 @@ export function useEliTabelaFiltrosAvancados(
|
|||
.map((f) => {
|
||||
const b = base.find((x) => String(x.chave) === String(f.chave))
|
||||
if (!b) return null
|
||||
return { chave: f.chave, filtro: b.filtro(f.valor) }
|
||||
const condicao = b.filtro(f.valor)
|
||||
if (!condicao) return null
|
||||
return { chave: f.chave, condicao }
|
||||
})
|
||||
.filter(
|
||||
(f): f is { chave: string; filtro: tipoFiltroDeltaColunaTipada<string> } =>
|
||||
f !== null && f.filtro !== undefined && f.filtro !== null,
|
||||
)
|
||||
.filter((f): f is { chave: string; condicao: tipoCondicaoFiltroDelta } => f !== null)
|
||||
|
||||
if (filtrosIndividuais.length === 0) return []
|
||||
|
||||
if (filtrosFormula.value && filtrosIndividuais.length > 1) {
|
||||
const condicoesFinais: tipoCondicaoFiltroDelta[] = []
|
||||
|
|
@ -62,25 +63,22 @@ export function useEliTabelaFiltrosAvancados(
|
|||
filtrosIndividuais.forEach(({ chave }, i) => {
|
||||
formulaFinal = formulaFinal.replace(new RegExp(`\\{${chave}\\}`, "g"), `{c${i + 1}}`)
|
||||
})
|
||||
let globalIdx = 1
|
||||
for (let i = 0; i < filtrosIndividuais.length; i++) {
|
||||
const { filtro } = filtrosIndividuais[i]
|
||||
const idMap: Record<string, string> = {}
|
||||
for (const cond of filtro.condicoes) {
|
||||
const novoId = `{c${globalIdx++}}`
|
||||
idMap[cond.id] = novoId
|
||||
condicoesFinais.push({ ...cond, id: novoId })
|
||||
}
|
||||
let formulaLocal = filtro.formula
|
||||
for (const [oldId, newId] of Object.entries(idMap)) {
|
||||
formulaLocal = formulaLocal.replace(new RegExp(`\\{${oldId.slice(1, -1)}\\}`, "g"), newId)
|
||||
}
|
||||
const subst = filtro.condicoes.length > 1 ? `(${formulaLocal})` : formulaLocal
|
||||
formulaFinal = formulaFinal.replace(new RegExp(`\\{c${i + 1}\\}`, "g"), subst)
|
||||
}
|
||||
filtrosIndividuais.forEach(({ condicao }, i) => {
|
||||
const novoId = `{c${i + 1}}`
|
||||
condicoesFinais.push({ ...condicao, id: novoId })
|
||||
})
|
||||
return [{ condicoes: condicoesFinais, formula: formulaFinal }]
|
||||
}
|
||||
return filtrosIndividuais.map((f) => f.filtro)
|
||||
|
||||
/** Sem fórmula customizada: monta condições com IDs sequenciais e fórmula "E" */
|
||||
const condicoesFinais: tipoCondicaoFiltroDelta[] = filtrosIndividuais.map(
|
||||
({ condicao }, i) => ({
|
||||
...condicao,
|
||||
id: `{c${i + 1}}`,
|
||||
}),
|
||||
)
|
||||
const formula = condicoesFinais.map((c) => c.id).join(" E ")
|
||||
return [{ condicoes: condicoesFinais, formula }]
|
||||
})
|
||||
|
||||
function abrirModalFiltro() {
|
||||
|
|
@ -114,12 +112,82 @@ export function useEliTabelaFiltrosAvancados(
|
|||
else void carregar()
|
||||
}
|
||||
|
||||
const nomesOperadores: Record<string, string> = {
|
||||
"=": "igual a",
|
||||
"!=": "diferente de",
|
||||
">": "maior que",
|
||||
"<": "menor que",
|
||||
">=": "maior ou igual a",
|
||||
"<=": "menor ou igual a",
|
||||
like: "contém",
|
||||
in: "em",
|
||||
"∩": "possui",
|
||||
}
|
||||
|
||||
function formatarFiltroAtivo(entrada: unknown, valor: unknown): string {
|
||||
const [tipo, opcoes] = Array.isArray(entrada)
|
||||
? (entrada as [string, Record<string, unknown>])
|
||||
: [entrada as string, {} as Record<string, unknown>]
|
||||
|
||||
if (tipo === "confirmacao") {
|
||||
const opt = opcoes || {}
|
||||
if (valor === true) return (opt.rotuloAtivo as string) || "Sim"
|
||||
if (valor === false) return (opt.rotuloInativo as string) || "Não"
|
||||
return String(valor)
|
||||
}
|
||||
|
||||
if ((tipo === "selecao" || tipo === "selecaoMultipla") && typeof opcoes?.itens === "function") {
|
||||
try {
|
||||
const itensResult = opcoes.itens()
|
||||
if (Array.isArray(itensResult)) {
|
||||
const findLabel = (key: string) => {
|
||||
const found = (itensResult as { chave: string; rotulo: string }[]).find(
|
||||
(item) => String(item.chave) === String(key),
|
||||
)
|
||||
return found ? found.rotulo : key
|
||||
}
|
||||
if (Array.isArray(valor)) {
|
||||
return valor.map((v) => findLabel(String(v))).join(", ")
|
||||
}
|
||||
return findLabel(String(valor))
|
||||
}
|
||||
} catch {
|
||||
// Fallback
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(valor)) {
|
||||
return valor.map(String).join(", ")
|
||||
}
|
||||
return String(valor)
|
||||
}
|
||||
|
||||
/** Resumo dos filtros ativos para badge e tooltip do cabecalho */
|
||||
const filtrosAtivosResumo = computed(() => {
|
||||
const base = props.tabela.filtroAvancado ?? []
|
||||
const ativos = (filtrosUi.value ?? []).filter((f) => f && f.chave !== undefined)
|
||||
const rotulos: string[] = []
|
||||
for (const f of ativos) {
|
||||
const b = base.find((x) => String(x.chave) === String(f.chave))
|
||||
if (b) {
|
||||
const condicao = b.filtro(f.valor)
|
||||
if (condicao) {
|
||||
const opStr = nomesOperadores[condicao.operador] || condicao.operador
|
||||
const valStr = formatarFiltroAtivo(b.entrada, condicao.valor)
|
||||
rotulos.push(`${b.rotulo} ${opStr} "${valStr}"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
return { quantidade: rotulos.length, rotulos }
|
||||
})
|
||||
|
||||
return {
|
||||
filtrosUi,
|
||||
filtrosFormula,
|
||||
modalFiltroAberto,
|
||||
exibirFiltroAvancado,
|
||||
filtrosAvancadosAtivos,
|
||||
filtrosAtivosResumo,
|
||||
abrirModalFiltro,
|
||||
fecharModalFiltro,
|
||||
limparFiltrosAvancados,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,16 @@
|
|||
*
|
||||
* Extraído de `EliTabelaModalFiltroAvancado.vue` para manter o componente abaixo de 250 linhas.
|
||||
*/
|
||||
import { computed, type Ref, ref, watch } from "vue"
|
||||
import { EliEntradaDataHora, EliEntradaNumero, EliEntradaTexto } from "../EliEntrada"
|
||||
import { type Component, computed, type Ref, ref, watch } from "vue"
|
||||
import {
|
||||
EliEntradaConfirmacao,
|
||||
EliEntradaDataHora,
|
||||
EliEntradaNumero,
|
||||
EliEntradaParagrafo,
|
||||
EliEntradaSelecao,
|
||||
EliEntradaSelecaoMultipla,
|
||||
EliEntradaTexto,
|
||||
} from "../EliEntrada"
|
||||
import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas"
|
||||
import type { tipoEliTabelaConsulta } from "./types-eli-tabela"
|
||||
|
||||
|
|
@ -97,10 +105,14 @@ export function useFiltroAvancado({
|
|||
return (filtrosBase.value ?? []).filter((b) => !usadas.has(String(b.chave)))
|
||||
})
|
||||
|
||||
function componenteEntrada(entrada: ComponenteEntrada) {
|
||||
function componenteEntrada(entrada: ComponenteEntrada): Component {
|
||||
const tipo = entrada?.[0]
|
||||
if (tipo === "numero") return EliEntradaNumero
|
||||
if (tipo === "dataHora") return EliEntradaDataHora
|
||||
if (tipo === "selecao") return EliEntradaSelecao
|
||||
if (tipo === "selecaoMultipla") return EliEntradaSelecaoMultipla
|
||||
if (tipo === "paragrafo") return EliEntradaParagrafo
|
||||
if (tipo === "confirmacao") return EliEntradaConfirmacao
|
||||
return EliEntradaTexto
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +126,9 @@ export function useFiltroAvancado({
|
|||
|
||||
function valorInicialPorEntrada(entrada: ComponenteEntrada) {
|
||||
if (entrada?.[0] === "numero") return null
|
||||
if (entrada?.[0] === "selecao") return null
|
||||
if (entrada?.[0] === "selecaoMultipla") return []
|
||||
if (entrada?.[0] === "confirmacao") return false
|
||||
return ""
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue