This commit is contained in:
Luiz Silva 2026-02-15 15:17:08 -03:00
parent 8a5596e860
commit 57325f6744
100 changed files with 16153 additions and 4623 deletions

View file

@ -74,27 +74,39 @@
</template>
<script lang="ts">
import { computed, defineComponent, PropType, ref, watch } from "vue";
import { EliEntradaTexto, EliEntradaNumero, EliEntradaDataHora } from "../EliEntrada";
import type { ComponenteEntrada, TipoEntrada } from "../EliEntrada/tiposEntradas";
import type { tipoEliTabelaConsulta } from "./types-eli-tabela";
import { computed, defineComponent, type PropType, ref, watch } from "vue"
import {
EliEntradaDataHora,
EliEntradaNumero,
EliEntradaTexto,
} from "../EliEntrada"
import type {
ComponenteEntrada,
TipoEntrada,
} from "../EliEntrada/tiposEntradas"
import type { tipoEliTabelaConsulta } from "./types-eli-tabela"
type FiltroBase<T> = NonNullable<tipoEliTabelaConsulta<T>["filtroAvancado"]>[number];
type FiltroBase<T> = NonNullable<
tipoEliTabelaConsulta<T>["filtroAvancado"]
>[number]
type LinhaFiltro<T> = {
coluna: keyof T;
entrada: ComponenteEntrada;
operador: string;
valor: any;
};
function isTipoEntrada(v: unknown): v is TipoEntrada {
return v === "texto" || v === "numero" || v === "dataHora";
coluna: keyof T
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>) {
const rotulo = (f?.entrada?.[1] as any)?.rotulo;
return rotulo ? String(rotulo) : String(f?.coluna ?? "Filtro");
// biome-ignore lint/suspicious/noExplicitAny: dynamic access
const rotulo = (f?.entrada?.[1] as any)?.rotulo
return rotulo ? String(rotulo) : String(f?.coluna ?? "Filtro")
}
export default defineComponent({
@ -102,10 +114,12 @@ export default defineComponent({
props: {
aberto: { type: Boolean, required: true },
filtrosBase: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic filter type
type: Array as PropType<Array<FiltroBase<any>>>,
required: true,
},
modelo: {
// biome-ignore lint/suspicious/noExplicitAny: dynamic model
type: Array as PropType<Array<any>>,
required: true,
},
@ -113,67 +127,82 @@ export default defineComponent({
emits: {
fechar: () => true,
limpar: () => true,
// biome-ignore lint/suspicious/noExplicitAny: dynamic lines
salvar: (_linhas: any[]) => true,
},
setup(props, { emit }) {
const linhas = ref<Array<LinhaFiltro<any>>>([]);
// biome-ignore lint/suspicious/noExplicitAny: dynamic value
const linhas = ref<Array<LinhaFiltro<any>>>([])
const colunaParaAdicionar = ref<string>("");
const colunaParaAdicionar = ref<string>("")
const colunasDisponiveis = computed(() => (props.filtrosBase ?? []).map((b) => String(b.coluna)));
const colunasDisponiveis = computed(() =>
(props.filtrosBase ?? []).map((b) => String(b.coluna)),
)
const opcoesParaAdicionar = computed(() => {
const usadas = new Set(linhas.value.map((l) => String(l.coluna)));
return (props.filtrosBase ?? []).filter((b) => !usadas.has(String(b.coluna)));
});
const usadas = new Set(linhas.value.map((l) => String(l.coluna)))
return (props.filtrosBase ?? []).filter(
(b) => !usadas.has(String(b.coluna)),
)
})
function componenteEntrada(entrada: ComponenteEntrada) {
const tipo = entrada?.[0];
if (tipo === "numero") return EliEntradaNumero;
if (tipo === "dataHora") return EliEntradaDataHora;
return EliEntradaTexto;
const tipo = entrada?.[0]
if (tipo === "numero") return EliEntradaNumero
if (tipo === "dataHora") return EliEntradaDataHora
return EliEntradaTexto
}
function opcoesEntrada(entrada: ComponenteEntrada) {
// o rótulo vem do próprio componente (entrada[1].rotulo)
return (entrada?.[1] as any) ?? { rotulo: "" };
// biome-ignore lint/suspicious/noExplicitAny: dynamic options
return (entrada?.[1] as any) ?? { rotulo: "" }
}
function valorInicialPorEntrada(entrada: ComponenteEntrada) {
const tipo = entrada?.[0];
if (tipo === "numero") return null;
return "";
const tipo = entrada?.[0]
if (tipo === "numero") return null
return ""
}
function normalizarModelo() {
const base = props.filtrosBase ?? [];
const modelo = Array.isArray(props.modelo) ? props.modelo : [];
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;
const col = (baseItem?.coluna ?? m.coluna) as any;
const op = String(baseItem?.operador ?? "=");
const val = m.valor ?? valorInicialPorEntrada(entrada);
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)
return {
coluna: col,
operador: op,
entrada,
valor: val,
} as LinhaFiltro<any>;
});
// biome-ignore lint/suspicious/noExplicitAny: dynamic cast
} as LinhaFiltro<any>
})
// se vazio e existe base, adiciona 1 linha default
// não auto-adiciona; usuário escolhe quais filtros quer usar
// 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 ?? "="));
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])) {
l.entrada = ["texto", { rotulo: "Valor" }] as any;
// biome-ignore lint/suspicious/noExplicitAny: dynamic sanity
l.entrada = ["texto", { rotulo: "Valor" }] as any
}
}
}
@ -181,38 +210,42 @@ export default defineComponent({
watch(
() => [props.aberto, props.filtrosBase, props.modelo] as const,
() => {
if (props.aberto) normalizarModelo();
if (props.aberto) normalizarModelo()
},
{ deep: true, immediate: true }
);
{ deep: true, immediate: true },
)
function adicionar() {
if (!colunaParaAdicionar.value) return;
const b0 = (props.filtrosBase ?? []).find((b) => String(b.coluna) === String(colunaParaAdicionar.value));
if (!b0) return;
if (!colunaParaAdicionar.value) return
const b0 = (props.filtrosBase ?? []).find(
(b) => String(b.coluna) === String(colunaParaAdicionar.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.coluna) === String(b0.coluna)))
return
linhas.value.push({
// biome-ignore lint/suspicious/noExplicitAny: dynamic column
coluna: b0.coluna as any,
entrada: b0.entrada,
operador: String(b0.operador ?? "="),
valor: valorInicialPorEntrada(b0.entrada),
});
})
colunaParaAdicionar.value = "";
colunaParaAdicionar.value = ""
}
function remover(idx: number) {
linhas.value.splice(idx, 1);
linhas.value.splice(idx, 1)
}
function emitFechar() {
emit("fechar");
emit("fechar")
}
function emitLimpar() {
emit("limpar");
emit("limpar")
}
function emitSalvar() {
@ -221,8 +254,8 @@ export default defineComponent({
linhas.value.map((l) => ({
coluna: l.coluna,
valor: l.valor,
}))
);
})),
)
}
return {
@ -238,9 +271,9 @@ export default defineComponent({
emitSalvar,
emitLimpar,
rotuloDoFiltro,
};
}
},
});
})
</script>
<style>