import React, { useEffect, useMemo, useState } from 'react' import { api } from '../api' const CAMPOS_UNIFICADOS = [ { id: 'finalidade', label: 'Finalidade', targets: ['aval_finalidade'] }, { id: 'bairros', label: 'Bairro', targets: ['aval_bairro'] }, { id: 'data', label: 'Data', targets: ['data'] }, { id: 'area', label: 'Area', targets: ['aval_area'] }, { id: 'rh', label: 'RH', targets: ['aval_rh'] }, ] function sortByLabel(items = []) { return [...items].sort((a, b) => a.label.localeCompare(b.label, 'pt-BR', { sensitivity: 'base' })) } function normalizeColunasConfig(rawConfig = {}) { const out = {} CAMPOS_UNIFICADOS.forEach(({ id, targets }) => { const disponiveisMap = new Map() const padrao = [] const padraoVistos = new Set() targets.forEach((target) => { const config = rawConfig?.[target] || {} ;(Array.isArray(config?.disponiveis) ? config.disponiveis : []).forEach((item) => { const itemId = typeof item === 'string' ? item : item?.id const itemLabel = typeof item === 'string' ? item : item?.label || item?.id const idText = String(itemId || '').trim() if (!idText) return if (!disponiveisMap.has(idText)) { disponiveisMap.set(idText, String(itemLabel || idText)) } }) }) const disponiveis = sortByLabel(Array.from(disponiveisMap.entries()).map(([itemId, label]) => ({ id: itemId, label }))) const idsDisponiveis = new Set(disponiveis.map((item) => item.id)) targets.forEach((target) => { const config = rawConfig?.[target] || {} ;(Array.isArray(config?.padrao) ? config.padrao : []).forEach((item) => { const idText = String(item || '').trim() if (!idText || !idsDisponiveis.has(idText) || padraoVistos.has(idText)) return padraoVistos.add(idText) padrao.push(idText) }) }) if (!padrao.length) { disponiveis.forEach((item) => padrao.push(item.id)) } out[id] = { disponiveis, padrao } }) return out } function normalizeSelecionadas(raw = {}, configNormalizada = {}) { const out = {} CAMPOS_UNIFICADOS.forEach(({ id, targets }) => { const disponiveis = new Set((configNormalizada[id]?.disponiveis || []).map((item) => item.id)) const preferidas = [] targets.forEach((target) => { ;(Array.isArray(raw?.[target]) ? raw[target] : []).forEach((item) => preferidas.push(String(item || '').trim())) }) const validas = preferidas.filter((item, idx) => item && disponiveis.has(item) && preferidas.indexOf(item) === idx) if (validas.length) { out[id] = validas return } const padrao = (configNormalizada[id]?.padrao || []).filter((item) => disponiveis.has(item)) out[id] = Array.from(new Set(padrao)) }) return out } function buildPayload(selecionadas = {}, colunasConfig = {}) { const payload = {} CAMPOS_UNIFICADOS.forEach(({ id, targets }) => { const idsDisponiveis = new Set((colunasConfig[id]?.disponiveis || []).map((item) => item.id)) const selecionadasCampo = (selecionadas[id] || []) .map((item) => String(item || '').trim()) .filter((item, idx, arr) => item && idsDisponiveis.has(item) && arr.indexOf(item) === idx) targets.forEach((target) => { payload[target] = [...selecionadasCampo] }) }) return payload } function serializarCampos(campos = {}) { const normalizado = {} Object.keys(campos || {}).sort().forEach((campo) => { normalizado[campo] = [...(campos[campo] || [])] }) return JSON.stringify(normalizado) } export default function PesquisaAdminConfigPanel({ onSaved }) { const [loading, setLoading] = useState(false) const [saving, setSaving] = useState(false) const [error, setError] = useState('') const [status, setStatus] = useState('') const [colunasConfig, setColunasConfig] = useState({}) const [selecionadas, setSelecionadas] = useState({}) const [baseline, setBaseline] = useState('{}') const dirty = useMemo(() => serializarCampos(selecionadas) !== baseline, [selecionadas, baseline]) async function carregar() { setLoading(true) setError('') setStatus('') try { const response = await api.pesquisaAdminConfig() const configNormalizada = normalizeColunasConfig(response.colunas_filtro || {}) const selecionadasNormalizadas = normalizeSelecionadas(response.admin_fontes || {}, configNormalizada) const base = serializarCampos(selecionadasNormalizadas) setColunasConfig(configNormalizada) setSelecionadas(selecionadasNormalizadas) setBaseline(base) } catch (err) { setError(err.message) } finally { setLoading(false) } } useEffect(() => { void carregar() }, []) function findLabel(campo, id) { const match = (colunasConfig[campo]?.disponiveis || []).find((item) => item.id === id) return match?.label || id } function onAdd(campo, value) { const id = String(value || '').trim() if (!id) return setSelecionadas((current) => { const atual = current[campo] || [] if (atual.includes(id)) return current return { ...current, [campo]: [...atual, id] } }) } function onRemove(campo, id) { setSelecionadas((current) => ({ ...current, [campo]: (current[campo] || []).filter((item) => item !== id), })) } function onRestaurarPadrao(campo) { const padrao = colunasConfig[campo]?.padrao || [] setSelecionadas((current) => ({ ...current, [campo]: [...padrao] })) } async function onSalvar() { setSaving(true) setError('') setStatus('') try { const response = await api.pesquisaAdminConfigSalvar(buildPayload(selecionadas, colunasConfig)) const configNormalizada = normalizeColunasConfig(response.colunas_filtro || {}) const selecionadasNormalizadas = normalizeSelecionadas(response.admin_fontes || {}, configNormalizada) const base = serializarCampos(selecionadasNormalizadas) setColunasConfig(configNormalizada) setSelecionadas(selecionadasNormalizadas) setBaseline(base) setStatus(response.status || 'Configuracao salva.') if (onSaved) onSaved() } catch (err) { setError(err.message) } finally { setSaving(false) } } function renderCampo(campo, label) { const configCampo = colunasConfig[campo] || { disponiveis: [], padrao: [] } const selecionadasCampo = selecionadas[campo] || [] const selectedSet = new Set(selecionadasCampo) const opcoesAdicionar = (configCampo.disponiveis || []).filter((item) => !selectedSet.has(item.id)) return (
{label}
{selecionadasCampo.map((itemId) => ( {findLabel(campo, itemId)} ))} {!selecionadasCampo.length ? Nenhuma fonte selecionada. : null}
) } return (
{status ?
{status}
: null} {error ?
{error}
: null}
{CAMPOS_UNIFICADOS.map((campo) => renderCampo(campo.id, campo.label))}
) }