import React, { useEffect, useMemo, useState } from 'react' import { api, downloadBlob } from '../api' function normalizarChave(value) { return String(value || '') .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') .toLowerCase() .trim() .replace(/\.dai$/i, '') } function resolverModeloId(chave, modelos) { const normalizada = normalizarChave(chave) if (!normalizada) return '' for (const modelo of modelos || []) { const candidatos = [modelo?.id, modelo?.arquivo, modelo?.nome_modelo] .map(normalizarChave) .filter(Boolean) if (candidatos.includes(normalizada)) return String(modelo.id || '') } return '' } function formatarFonte(fonte) { if (!fonte || typeof fonte !== 'object') return '' if (String(fonte.provider || '').toLowerCase() === 'hf_dataset') { const repo = String(fonte.repo_id || '').trim() const revisao = String(fonte.revision || '').trim() return `HF Dataset${repo ? ` (${repo})` : ''}${revisao ? ` | revisão ${revisao.slice(0, 8)}` : ''}` } return 'Pasta local' } export default function AnexosModal({ open, defaultModeloId = '', avaliacao = null, lockModelo = false, title = 'Gerar anexos', onClose, }) { const [modelos, setModelos] = useState([]) const [fonte, setFonte] = useState(null) const [modeloSelecionado, setModeloSelecionado] = useState('') const [colunas, setColunas] = useState([]) const [loadingModelos, setLoadingModelos] = useState(false) const [loadingColunas, setLoadingColunas] = useState(false) const [generating, setGenerating] = useState(false) const [downloading, setDownloading] = useState(false) const [error, setError] = useState('') const [result, setResult] = useState(null) const colunasSelecionadas = useMemo( () => colunas.filter((item) => item.selected).map((item) => item.name), [colunas], ) const busy = loadingModelos || loadingColunas || generating || downloading const blocking = generating || downloading const canGenerate = Boolean(modeloSelecionado && colunasSelecionadas.length && !busy) useEffect(() => { if (!open) return undefined let active = true setLoadingModelos(true) setError('') setResult(null) setColunas([]) setModeloSelecionado('') api.anexosModelos() .then((response) => { if (!active) return const lista = Array.isArray(response?.modelos) ? response.modelos : [] const resolvido = resolverModeloId(defaultModeloId, lista) setModelos(lista) setFonte(response?.fonte || null) if (lockModelo && defaultModeloId && !resolvido) { setModeloSelecionado('') setError('O modelo usado nesta avaliação não foi encontrado no repositório configurado.') return } setModeloSelecionado(resolvido || String(lista[0]?.id || '')) }) .catch((err) => { if (!active) return setModelos([]) setModeloSelecionado('') setError(err?.message || 'Não foi possível carregar os modelos.') }) .finally(() => { if (active) setLoadingModelos(false) }) return () => { active = false } }, [open, defaultModeloId, lockModelo]) useEffect(() => { if (!open || !modeloSelecionado) { setColunas([]) return undefined } let active = true setLoadingColunas(true) setError('') setResult(null) api.anexosModeloColunas(modeloSelecionado) .then((response) => { if (!active) return setColunas((response?.columns || []).map((name) => ({ name, selected: true }))) }) .catch((err) => { if (!active) return setColunas([]) setError(err?.message || 'Não foi possível carregar as colunas do modelo.') }) .finally(() => { if (active) setLoadingColunas(false) }) return () => { active = false } }, [open, modeloSelecionado]) if (!open) return null function toggleColuna(nome) { setColunas((current) => current.map((item) => ( item.name === nome ? { ...item, selected: !item.selected } : item ))) setResult(null) } function moverColuna(index, direction) { setColunas((current) => { const destino = index + direction if (destino < 0 || destino >= current.length) return current const next = [...current] ;[next[index], next[destino]] = [next[destino], next[index]] return next }) setResult(null) } async function gerar(event) { event.preventDefault() if (!canGenerate) return setGenerating(true) setError('') setResult(null) try { const response = await api.anexosGerar( modeloSelecionado, colunasSelecionadas, avaliacao, ) setResult(response) } catch (err) { setError(err?.message || 'Falha ao gerar os anexos.') } finally { setGenerating(false) } } async function baixar() { const filename = String(result?.filename || '').trim() if (!filename) return setDownloading(true) setError('') try { const blob = await api.anexosDownload(filename) downloadBlob(blob, filename) } catch (err) { setError(err?.message || 'Falha ao baixar os anexos.') } finally { setDownloading(false) } } function fechar() { if (!blocking && typeof onClose === 'function') onClose() } return (
Fonte: {formatarFonte(fonte)}
: null}