implementado filtro26

This commit is contained in:
Luiz Silva 2026-02-17 11:33:44 -03:00
parent ba0e116a92
commit 5124844773
18 changed files with 3247 additions and 3257 deletions

View file

@ -14,11 +14,13 @@
</div>
<div v-else class="eli-tabela-modal-filtro__lista">
<div v-for="(linha, idx) in linhas" :key="String(linha.coluna)" class="eli-tabela-modal-filtro__linha">
<div v-for="(linha, idx) in linhas" :key="String(linha.chave)" class="eli-tabela-modal-filtro__linha">
<div class="eli-tabela-modal-filtro__entrada">
<component
:is="componenteEntrada(linha.entrada)"
v-model:value="linha.valor"
:value="linha.valor"
@update:value="(v: any) => (linha.valor = v)"
@input="(v: any) => (linha.valor = v)"
:opcoes="opcoesEntrada(linha.entrada)"
density="compact"
/>
@ -38,12 +40,12 @@
<div class="eli-tabela-modal-filtro__acoes">
<select
v-model="colunaParaAdicionar"
v-model="chaveParaAdicionar"
class="eli-tabela-modal-filtro__select"
:disabled="!opcoesParaAdicionar.length"
>
<option disabled value="">Selecione um filtro…</option>
<option v-for="o in opcoesParaAdicionar" :key="String(o.coluna)" :value="String(o.coluna)">
<option v-for="o in opcoesParaAdicionar" :key="String(o.chave)" :value="String(o.chave)">
{{ rotuloDoFiltro(o) }}
</option>
</select>
@ -51,7 +53,7 @@
type="button"
class="eli-tabela-modal-filtro__botao"
@click="adicionar"
:disabled="!colunaParaAdicionar"
:disabled="!chaveParaAdicionar"
>
Adicionar
</button>
@ -80,33 +82,23 @@ import {
EliEntradaNumero,
EliEntradaTexto,
} from "../EliEntrada"
import type {
ComponenteEntrada,
TipoEntrada,
} from "../EliEntrada/tiposEntradas"
import type { ComponenteEntrada } from "../EliEntrada/tiposEntradas"
import type { tipoEliTabelaConsulta } from "./types-eli-tabela"
type FiltroBase<T> = NonNullable<
tipoEliTabelaConsulta<T>["filtroAvancado"]
>[number]
type LinhaFiltro<T> = {
coluna: keyof T
type LinhaFiltro = {
chave: string
entrada: ComponenteEntrada
operador: string
// biome-ignore lint/suspicious/noExplicitAny: dynamic value
valor: any
}
function isTipoEntrada(v: unknown): v is TipoEntrada {
return v === "texto" || v === "numero" || v === "dataHora"
}
// biome-ignore lint/suspicious/noExplicitAny: dynamic typing needed
function rotuloDoFiltro(f: FiltroBase<any>) {
// biome-ignore lint/suspicious/noExplicitAny: dynamic access
const rotulo = (f?.entrada?.[1] as any)?.rotulo
return rotulo ? String(rotulo) : String(f?.coluna ?? "Filtro")
return f.rotulo
}
export default defineComponent({
@ -114,7 +106,7 @@ export default defineComponent({
props: {
aberto: { type: Boolean, required: true },
filtrosBase: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic filter type
// biome-ignore lint/suspicious/noExplicitAny: generic component
type: Array as PropType<Array<FiltroBase<any>>>,
required: true,
},
@ -131,19 +123,18 @@ export default defineComponent({
salvar: (_linhas: any[]) => true,
},
setup(props, { emit }) {
// biome-ignore lint/suspicious/noExplicitAny: dynamic value
const linhas = ref<Array<LinhaFiltro<any>>>([])
const linhas = ref<Array<LinhaFiltro>>([])
const colunaParaAdicionar = ref<string>("")
const chaveParaAdicionar = ref<string>("")
const colunasDisponiveis = computed(() =>
(props.filtrosBase ?? []).map((b) => String(b.coluna)),
const chavesDisponiveis = computed(() =>
(props.filtrosBase ?? []).map((b) => String(b.chave)),
)
const opcoesParaAdicionar = computed(() => {
const usadas = new Set(linhas.value.map((l) => String(l.coluna)))
const usadas = new Set(linhas.value.map((l) => String(l.chave)))
return (props.filtrosBase ?? []).filter(
(b) => !usadas.has(String(b.coluna)),
(b) => !usadas.has(String(b.chave)),
)
})
@ -169,42 +160,30 @@ export default defineComponent({
function normalizarModelo() {
const base = props.filtrosBase ?? []
const modelo = Array.isArray(props.modelo) ? props.modelo : []
// biome-ignore lint/suspicious/noExplicitAny: dynamic model
linhas.value = modelo.map((m: any) => {
// operador vem travado no base
const baseItem =
base.find((b) => String(b.coluna) === String(m.coluna)) ?? base[0]
const entrada = (baseItem?.entrada ?? m.entrada) as ComponenteEntrada
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
const col = (baseItem?.coluna ?? m.coluna) as any
const op = String(baseItem?.operador ?? "=")
const val = m.valor ?? valorInicialPorEntrada(entrada)
linhas.value = modelo
// biome-ignore lint/suspicious/noExplicitAny: dynamic model item
.map((m: any) => {
const baseItem =
base.find((b) => String(b.chave) === String(m.chave)) ?? base[0]
return {
coluna: col,
operador: op,
entrada,
valor: val,
// biome-ignore lint/suspicious/noExplicitAny: dynamic cast
} as LinhaFiltro<any>
})
if (!baseItem) return null
// se vazio e existe base, adiciona 1 linha default
// não auto-adiciona; usuário escolhe quais filtros quer usar
const entrada = (baseItem.entrada ?? m.entrada) as ComponenteEntrada
const chave = String(baseItem.chave ?? m.chave)
const val = m.valor ?? valorInicialPorEntrada(entrada)
// se algum filtro mudou a coluna para valor inválido, ajusta
for (const l of linhas.value) {
if (!colunasDisponiveis.value.includes(String(l.coluna))) continue
l.operador = String(
base.find((b) => String(b.coluna) === String(l.coluna))?.operador ??
"=",
)
// sanity
if (l.entrada && !isTipoEntrada(l.entrada[0])) {
// biome-ignore lint/suspicious/noExplicitAny: dynamic sanity
l.entrada = ["texto", { rotulo: "Valor" }] as any
}
}
return {
chave: chave,
entrada,
valor: val,
} as LinhaFiltro
})
.filter(Boolean) as LinhaFiltro[]
// se algum filtro mudou a chave para valor inválido, ajusta
linhas.value = linhas.value.filter((l) =>
chavesDisponiveis.value.includes(String(l.chave)),
)
}
watch(
@ -216,24 +195,21 @@ export default defineComponent({
)
function adicionar() {
if (!colunaParaAdicionar.value) return
if (!chaveParaAdicionar.value) return
const b0 = (props.filtrosBase ?? []).find(
(b) => String(b.coluna) === String(colunaParaAdicionar.value),
(b) => String(b.chave) === String(chaveParaAdicionar.value),
)
if (!b0) return
// evita repetição
if (linhas.value.some((l) => String(l.coluna) === String(b0.coluna)))
return
if (linhas.value.some((l) => String(l.chave) === String(b0.chave))) return
linhas.value.push({
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
coluna: b0.coluna as any,
chave: String(b0.chave),
entrada: b0.entrada,
operador: String(b0.operador ?? "="),
valor: valorInicialPorEntrada(b0.entrada),
})
colunaParaAdicionar.value = ""
chaveParaAdicionar.value = ""
}
function remover(idx: number) {
@ -252,7 +228,7 @@ export default defineComponent({
emit(
"salvar",
linhas.value.map((l) => ({
coluna: l.coluna,
chave: l.chave,
valor: l.valor,
})),
)
@ -261,12 +237,11 @@ export default defineComponent({
return {
linhas,
opcoesParaAdicionar,
colunaParaAdicionar,
chaveParaAdicionar,
componenteEntrada,
opcoesEntrada,
adicionar,
remover,
// exibimos operador fixo só como texto
emitFechar,
emitSalvar,
emitLimpar,