Spaces:
Running
Running
Guilherme Silberfarb Costa commited on
Commit ·
d953b73
1
Parent(s): 1aafde3
Refine elaboracao UI layout
Browse files
backend/app/core/elaboracao/formatadores.py
CHANGED
|
@@ -221,7 +221,26 @@ def _renderizar_secao_micro(titulo, resultados_dict, secao_tipo="padrao"):
|
|
| 221 |
html = f'<div class="section-title-orange micro-group-title">{titulo}</div>'
|
| 222 |
html += f'<div class="{grid_class}">'
|
| 223 |
|
| 224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
status = "✅" if info["valido"] else "⚠️"
|
| 226 |
status_class = "micro-ok" if info["valido"] else "micro-warn"
|
| 227 |
categorias_lista = info.get("categorias") or []
|
|
@@ -230,7 +249,7 @@ def _renderizar_secao_micro(titulo, resultados_dict, secao_tipo="padrao"):
|
|
| 230 |
f'<div class="micro-msg {"micro-msg-ok" if item.get("valido") else "micro-msg-fail"}">'
|
| 231 |
f'{escape(str(item.get("mensagem", "")))}'
|
| 232 |
f'</div>'
|
| 233 |
-
for item in categorias_lista
|
| 234 |
)
|
| 235 |
else:
|
| 236 |
mensagens_lista = info["mensagens"]
|
|
@@ -313,14 +332,11 @@ def formatar_outliers_anteriores_html(n_outliers, lista_indices):
|
|
| 313 |
"""Formata informações de outliers excluídos como HTML card."""
|
| 314 |
lista_str = lista_indices if lista_indices else "Nenhum"
|
| 315 |
return f'''
|
| 316 |
-
<div
|
| 317 |
-
|
| 318 |
-
border-radius: 8px; border: 1px solid var(--border-color-primary, #e2e8f0);
|
| 319 |
-
flex-wrap: wrap;">
|
| 320 |
-
<span style="font-weight: 600; color: var(--body-text-color, #495057); white-space: nowrap;">
|
| 321 |
{n_outliers} outlier(s) excluídos do modelo ajustado
|
| 322 |
</span>
|
| 323 |
-
<span
|
| 324 |
Índices: {lista_str}
|
| 325 |
</span>
|
| 326 |
</div>'''
|
|
|
|
| 221 |
html = f'<div class="section-title-orange micro-group-title">{titulo}</div>'
|
| 222 |
html += f'<div class="{grid_class}">'
|
| 223 |
|
| 224 |
+
def ordenar_categoria(item):
|
| 225 |
+
return (
|
| 226 |
+
1 if item.get("valido") else 0,
|
| 227 |
+
int(item.get("ni", 0) or 0),
|
| 228 |
+
str(item.get("categoria", "")),
|
| 229 |
+
)
|
| 230 |
+
|
| 231 |
+
def ordenar_variavel(item):
|
| 232 |
+
coluna, info = item
|
| 233 |
+
categorias = info.get("categorias") or []
|
| 234 |
+
falhas = [cat for cat in categorias if not cat.get("valido")]
|
| 235 |
+
todos_ni = [int(cat.get("ni", 0) or 0) for cat in categorias]
|
| 236 |
+
return (
|
| 237 |
+
1 if info.get("valido") else 0,
|
| 238 |
+
-len(falhas),
|
| 239 |
+
min(todos_ni) if todos_ni else 0,
|
| 240 |
+
str(coluna),
|
| 241 |
+
)
|
| 242 |
+
|
| 243 |
+
for coluna, info in sorted(resultados_dict.items(), key=ordenar_variavel):
|
| 244 |
status = "✅" if info["valido"] else "⚠️"
|
| 245 |
status_class = "micro-ok" if info["valido"] else "micro-warn"
|
| 246 |
categorias_lista = info.get("categorias") or []
|
|
|
|
| 249 |
f'<div class="micro-msg {"micro-msg-ok" if item.get("valido") else "micro-msg-fail"}">'
|
| 250 |
f'{escape(str(item.get("mensagem", "")))}'
|
| 251 |
f'</div>'
|
| 252 |
+
for item in sorted(categorias_lista, key=ordenar_categoria)
|
| 253 |
)
|
| 254 |
else:
|
| 255 |
mensagens_lista = info["mensagens"]
|
|
|
|
| 332 |
"""Formata informações de outliers excluídos como HTML card."""
|
| 333 |
lista_str = lista_indices if lista_indices else "Nenhum"
|
| 334 |
return f'''
|
| 335 |
+
<div class="outliers-previous-card">
|
| 336 |
+
<span class="outliers-previous-count">
|
|
|
|
|
|
|
|
|
|
| 337 |
{n_outliers} outlier(s) excluídos do modelo ajustado
|
| 338 |
</span>
|
| 339 |
+
<span class="outliers-previous-indices">
|
| 340 |
Índices: {lista_str}
|
| 341 |
</span>
|
| 342 |
</div>'''
|
backend/app/services/elaboracao_service.py
CHANGED
|
@@ -1591,6 +1591,7 @@ def fit_model(
|
|
| 1591 |
tabela_outliers_excluidos = _montar_tabela_outliers_excluidos(session)
|
| 1592 |
|
| 1593 |
return {
|
|
|
|
| 1594 |
"diagnosticos_html": diagnosticos_html,
|
| 1595 |
"transformacao_y": session.transformacao_y,
|
| 1596 |
"transformacoes_x": sanitize_value(session.transformacoes_x),
|
|
|
|
| 1591 |
tabela_outliers_excluidos = _montar_tabela_outliers_excluidos(session)
|
| 1592 |
|
| 1593 |
return {
|
| 1594 |
+
"diagnosticos": sanitize_value(resultado["diagnosticos"]),
|
| 1595 |
"diagnosticos_html": diagnosticos_html,
|
| 1596 |
"transformacao_y": session.transformacao_y,
|
| 1597 |
"transformacoes_x": sanitize_value(session.transformacoes_x),
|
frontend/src/components/ElaboracaoTab.jsx
CHANGED
|
@@ -234,6 +234,19 @@ function formatCurrencyBr(value) {
|
|
| 234 |
return num.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })
|
| 235 |
}
|
| 236 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
function formatarValorTabelaKnn(coluna, valor) {
|
| 238 |
if (valor === null || valor === undefined || valor === '') return '-'
|
| 239 |
const nome = String(coluna || '').toLowerCase()
|
|
@@ -690,6 +703,124 @@ function buildScatterPanelFigureMap(panels) {
|
|
| 690 |
return mapa
|
| 691 |
}
|
| 692 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 693 |
function formatConselhoRegistro(elaborador) {
|
| 694 |
if (!elaborador) return ''
|
| 695 |
const conselho = String(elaborador.conselho || '').trim()
|
|
@@ -945,6 +1076,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 945 |
const [section11LocksOpen, setSection11LocksOpen] = useState(false)
|
| 946 |
const [section10ManualOpen, setSection10ManualOpen] = useState(false)
|
| 947 |
const [section6EditOpen, setSection6EditOpen] = useState(true)
|
|
|
|
| 948 |
|
| 949 |
const [fit, setFit] = useState(null)
|
| 950 |
const [dispersaoEixoX, setDispersaoEixoX] = useState('transformado')
|
|
@@ -1012,6 +1144,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1012 |
const [sectionsMountKey, setSectionsMountKey] = useState(0)
|
| 1013 |
const [renderedSectionSteps, setRenderedSectionSteps] = useState(() => ['1'])
|
| 1014 |
const [visibleSectionSteps, setVisibleSectionSteps] = useState(() => ['1'])
|
|
|
|
| 1015 |
const visibleSectionStepsRef = useRef(new Set(['1']))
|
| 1016 |
const elaboracaoShareHref = repoModeloSelecionado
|
| 1017 |
? buildElaboracaoModeloLink(repoModeloSelecionado)
|
|
@@ -1279,6 +1412,68 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1279 |
|
| 1280 |
return faixas
|
| 1281 |
}, [fit?.tabela_metricas?.rows, fit?.variaveis_filtro])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1282 |
const resumoResiduoPadStats = useMemo(() => {
|
| 1283 |
const rows = fit?.tabela_metricas?.rows
|
| 1284 |
if (!Array.isArray(rows) || rows.length === 0) return null
|
|
@@ -1416,10 +1611,6 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1416 |
if (secao10InterativoSelecionado === 'none' || graficosSecao9Interativo.length === 0) return null
|
| 1417 |
return graficosSecao9Interativo.find((item) => String(item.label || '') === secao10InterativoSelecionado) || graficosSecao9Interativo[0]
|
| 1418 |
}, [graficosSecao9Interativo, secao10InterativoSelecionado])
|
| 1419 |
-
const colunasGraficosSecao9 = useMemo(
|
| 1420 |
-
() => Math.max(1, Math.min(3, graficosSecao9.length || 1)),
|
| 1421 |
-
[graficosSecao9.length],
|
| 1422 |
-
)
|
| 1423 |
const colunasOriginaisDispersao = useMemo(() => {
|
| 1424 |
const cols = Array.isArray(dados?.columns) ? dados.columns : []
|
| 1425 |
return cols
|
|
@@ -1505,10 +1696,6 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1505 |
if (secao13InterativoSelecionado === 'none' || graficosSecao12Interativo.length === 0) return null
|
| 1506 |
return graficosSecao12Interativo.find((item) => String(item.label || '') === secao13InterativoSelecionado) || graficosSecao12Interativo[0]
|
| 1507 |
}, [graficosSecao12Interativo, secao13InterativoSelecionado])
|
| 1508 |
-
const colunasGraficosSecao12 = useMemo(
|
| 1509 |
-
() => Math.max(1, Math.min(3, graficosSecao12.length || 1)),
|
| 1510 |
-
[graficosSecao12.length],
|
| 1511 |
-
)
|
| 1512 |
const secao15DiagnosticoPng = useMemo(
|
| 1513 |
() => String(fit?.graficos_diagnostico_modo || '') === 'png',
|
| 1514 |
[fit?.graficos_diagnostico_modo],
|
|
@@ -1619,6 +1806,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1619 |
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
| 1620 |
setRenderedSectionSteps(['1'])
|
| 1621 |
setVisibleSectionSteps(['1'])
|
|
|
|
| 1622 |
visibleSectionStepsRef.current = new Set(['1'])
|
| 1623 |
return undefined
|
| 1624 |
}
|
|
@@ -1632,6 +1820,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1632 |
|
| 1633 |
if (sections.length === 0) {
|
| 1634 |
setVisibleSectionSteps(['1'])
|
|
|
|
| 1635 |
visibleSectionStepsRef.current = new Set(['1'])
|
| 1636 |
return undefined
|
| 1637 |
}
|
|
@@ -1675,8 +1864,10 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 1675 |
.map((section) => section.getAttribute('data-section-step')),
|
| 1676 |
)
|
| 1677 |
const normalizedVisible = nextVisible.length > 0 ? nextVisible : [getClosestStepToTop()]
|
|
|
|
| 1678 |
visibleSectionStepsRef.current = new Set(normalizedVisible)
|
| 1679 |
setVisibleSectionSteps((current) => (isSameSectionStepList(current, normalizedVisible) ? current : normalizedVisible))
|
|
|
|
| 1680 |
}
|
| 1681 |
|
| 1682 |
computeVisibleSteps()
|
|
@@ -3944,7 +4135,11 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 3944 |
|
| 3945 |
return (
|
| 3946 |
<div ref={elaboracaoRootRef} className="tab-content">
|
| 3947 |
-
<div
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3948 |
<aside className="elaboracao-side-nav" aria-label="Navegação de seções da elaboração">
|
| 3949 |
<ol className="elaboracao-side-nav-list">
|
| 3950 |
{ELABORACAO_SECOES_NAV.map((secao) => {
|
|
@@ -4567,7 +4762,9 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4567 |
: 'Há outliers excluídos: não'}
|
| 4568 |
</div>
|
| 4569 |
{outliersAnteriores.length > 0 ? (
|
| 4570 |
-
<div className="resumo-outliers-box">
|
|
|
|
|
|
|
| 4571 |
) : null}
|
| 4572 |
</div>
|
| 4573 |
<div className="download-actions-bar">
|
|
@@ -4582,7 +4779,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4582 |
Fazer download
|
| 4583 |
</button>
|
| 4584 |
</div>
|
| 4585 |
-
<DataTable table={dados} maxHeight={
|
| 4586 |
</div>
|
| 4587 |
</SectionBlock>
|
| 4588 |
|
|
@@ -4710,7 +4907,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4710 |
{colunasX.length}/{colunasXDisponiveis.length} selecionadas
|
| 4711 |
</span>
|
| 4712 |
</div>
|
| 4713 |
-
<div className="checkbox-inline-wrap">
|
| 4714 |
{colunasXDisponiveis.map((col) => (
|
| 4715 |
<label key={`x-${col}`} className="compact-checkbox">
|
| 4716 |
<input
|
|
@@ -4771,7 +4968,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4771 |
|
| 4772 |
<div className="compact-option-group compact-option-group-codigo">
|
| 4773 |
<h4>Variáveis Categóricas Codificadas</h4>
|
| 4774 |
-
<div className="checkbox-inline-wrap">
|
| 4775 |
{colunasX.map((col) => (
|
| 4776 |
<label key={`c-${col}`} className="compact-checkbox">
|
| 4777 |
<input type="checkbox" checked={codigoAlocado.includes(col)} onChange={() => toggleSelection(setCodigoAlocado, col)} />
|
|
@@ -4848,7 +5045,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4848 |
<div className="section6-summary-group">
|
| 4849 |
<div className="section6-summary-label">Variáveis categóricas codificadas:</div>
|
| 4850 |
{selecaoAplicada.codigo_alocado.length > 0 ? (
|
| 4851 |
-
<div className="checkbox-inline-wrap">
|
| 4852 |
{selecaoAplicada.codigo_alocado.map((coluna) => (
|
| 4853 |
<span key={`selected-c-${coluna}`} className="compact-chip">{coluna}</span>
|
| 4854 |
))}
|
|
@@ -4952,24 +5149,6 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4952 |
</div>
|
| 4953 |
{secao10InterativoSelecionado !== 'none' ? (
|
| 4954 |
<>
|
| 4955 |
-
<div className="download-actions-bar">
|
| 4956 |
-
<button
|
| 4957 |
-
type="button"
|
| 4958 |
-
className="btn-download-subtle"
|
| 4959 |
-
title={secao10InterativoAtual?.legenda || ''}
|
| 4960 |
-
onClick={() => {
|
| 4961 |
-
if (!secao10InterativoAtual) return
|
| 4962 |
-
void onDownloadFigurePng(
|
| 4963 |
-
secao10InterativoAtual.figure,
|
| 4964 |
-
`secao10_${sanitizeFileName(secao10InterativoAtual.label, 'dispersao_interativo')}`,
|
| 4965 |
-
{ forceHideLegend: true },
|
| 4966 |
-
)
|
| 4967 |
-
}}
|
| 4968 |
-
disabled={loading || downloadingAssets || !secao10InterativoAtual?.figure}
|
| 4969 |
-
>
|
| 4970 |
-
Fazer download
|
| 4971 |
-
</button>
|
| 4972 |
-
</div>
|
| 4973 |
{secao10InterativoAtual?.figure ? (
|
| 4974 |
<PlotFigure
|
| 4975 |
key={`s9-interativo-plot-${secao10InterativoAtual.id}`}
|
|
@@ -4982,6 +5161,23 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4982 |
forceHideLegend
|
| 4983 |
className="plot-stretch"
|
| 4984 |
lazy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4985 |
/>
|
| 4986 |
) : (
|
| 4987 |
<div className="empty-box">Grafico indisponivel.</div>
|
|
@@ -4991,57 +5187,24 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 4991 |
</>
|
| 4992 |
) : (
|
| 4993 |
<>
|
| 4994 |
-
<div className="download-actions-bar">
|
| 4995 |
-
{graficosSecao9.length > 1 ? <span className="download-actions-label">Fazer download:</span> : null}
|
| 4996 |
-
{graficosSecao9.map((item, idx) => {
|
| 4997 |
-
const fileBase = `secao10_${sanitizeFileName(item.label, `dispersao_${idx + 1}`)}`
|
| 4998 |
-
return (
|
| 4999 |
-
<button
|
| 5000 |
-
key={`s9-dl-${item.id}`}
|
| 5001 |
-
type="button"
|
| 5002 |
-
className="btn-download-subtle"
|
| 5003 |
-
title={item.legenda}
|
| 5004 |
-
onClick={() => onDownloadFigurePng(item.figure, fileBase, { forceHideLegend: true })}
|
| 5005 |
-
disabled={loading || downloadingAssets || !item.figure}
|
| 5006 |
-
>
|
| 5007 |
-
{graficosSecao9.length > 1 ? item.label : 'Fazer download'}
|
| 5008 |
-
</button>
|
| 5009 |
-
)
|
| 5010 |
-
})}
|
| 5011 |
-
{graficosSecao9.length > 1 ? (
|
| 5012 |
-
<button
|
| 5013 |
-
type="button"
|
| 5014 |
-
className="btn-download-subtle"
|
| 5015 |
-
onClick={() => onDownloadFiguresPngBatch(
|
| 5016 |
-
graficosSecao9.map((item, idx) => ({
|
| 5017 |
-
figure: item.figure,
|
| 5018 |
-
fileNameBase: `secao10_${sanitizeFileName(item.label, `dispersao_${idx + 1}`)}`,
|
| 5019 |
-
forceHideLegend: true,
|
| 5020 |
-
})),
|
| 5021 |
-
)}
|
| 5022 |
-
disabled={loading || downloadingAssets || graficosSecao9.length === 0}
|
| 5023 |
-
>
|
| 5024 |
-
Todos
|
| 5025 |
-
</button>
|
| 5026 |
-
) : null}
|
| 5027 |
-
</div>
|
| 5028 |
{graficosSecao9.length > 0 ? (
|
| 5029 |
-
<
|
| 5030 |
-
{graficosSecao9
|
| 5031 |
-
|
| 5032 |
-
|
| 5033 |
-
|
| 5034 |
-
|
| 5035 |
-
|
| 5036 |
-
|
| 5037 |
-
|
| 5038 |
-
|
| 5039 |
-
|
| 5040 |
-
|
| 5041 |
-
|
| 5042 |
-
|
| 5043 |
-
|
| 5044 |
-
|
|
|
|
| 5045 |
) : (
|
| 5046 |
<div className="empty-box">Grafico indisponivel.</div>
|
| 5047 |
)}
|
|
@@ -5121,41 +5284,44 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5121 |
</div>
|
| 5122 |
</div>
|
| 5123 |
{(selection.busca?.resultados || []).length > 0 ? (
|
| 5124 |
-
<div className="
|
| 5125 |
-
|
| 5126 |
-
|
| 5127 |
-
|
| 5128 |
-
|
| 5129 |
-
<div className="transform-suggestion-
|
| 5130 |
-
<span className="transform-suggestion-
|
| 5131 |
-
<
|
| 5132 |
-
|
| 5133 |
-
|
| 5134 |
-
|
|
|
|
|
|
|
|
|
|
| 5135 |
</div>
|
| 5136 |
-
|
| 5137 |
-
|
| 5138 |
-
|
| 5139 |
-
|
| 5140 |
-
|
| 5141 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5142 |
</div>
|
| 5143 |
-
|
| 5144 |
-
|
| 5145 |
-
|
| 5146 |
-
<div key={`scol-${item.rank || idx}-${coluna}`} className="transform-suggestion-item">
|
| 5147 |
-
<span className="transform-suggestion-col">{coluna}</span>
|
| 5148 |
-
<span className="transform-suggestion-fn">{transf}</span>
|
| 5149 |
-
<span className={grauBadgeClass(grau)}>{GRAU_LABEL_CURTO[grau] || 'Sem enq.'}</span>
|
| 5150 |
-
</div>
|
| 5151 |
-
)
|
| 5152 |
-
})}
|
| 5153 |
</div>
|
| 5154 |
-
|
| 5155 |
-
|
| 5156 |
-
</button>
|
| 5157 |
-
</div>
|
| 5158 |
-
))}
|
| 5159 |
</div>
|
| 5160 |
) : (
|
| 5161 |
<div dangerouslySetInnerHTML={{ __html: selection.busca?.html || '' }} />
|
|
@@ -5284,7 +5450,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5284 |
Modo PNG automático para mais de {secao13PngPayload?.limiar || fit?.grafico_dispersao_modelo_limiar_png || 1500} pontos. Ao final da seção, podem ser gerados individualmente os gráficos interativos.
|
| 5285 |
</div>
|
| 5286 |
) : null}
|
| 5287 |
-
<div className="row dispersao-config-row">
|
| 5288 |
<div className="dispersao-config-field">
|
| 5289 |
<label>Eixo X</label>
|
| 5290 |
<select
|
|
@@ -5401,7 +5567,7 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5401 |
</div>
|
| 5402 |
{secao13InterativoSelecionado !== 'none' ? (
|
| 5403 |
<>
|
| 5404 |
-
<div className="row dispersao-config-row">
|
| 5405 |
<div className="dispersao-config-field">
|
| 5406 |
<label>Eixo X (interativo)</label>
|
| 5407 |
<select
|
|
@@ -5489,24 +5655,6 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5489 |
)}
|
| 5490 |
</select>
|
| 5491 |
</div>
|
| 5492 |
-
<div className="download-actions-bar">
|
| 5493 |
-
<button
|
| 5494 |
-
type="button"
|
| 5495 |
-
className="btn-download-subtle"
|
| 5496 |
-
title={secao13InterativoAtual?.legenda || ''}
|
| 5497 |
-
onClick={() => {
|
| 5498 |
-
if (!secao13InterativoAtual) return
|
| 5499 |
-
void onDownloadFigurePng(
|
| 5500 |
-
secao13InterativoAtual.figure,
|
| 5501 |
-
`secao13_${sanitizeFileName(secao13InterativoAtual.label, 'dispersao_interativo')}`,
|
| 5502 |
-
{ forceHideLegend: true },
|
| 5503 |
-
)
|
| 5504 |
-
}}
|
| 5505 |
-
disabled={loading || downloadingAssets || !secao13InterativoAtual?.figure}
|
| 5506 |
-
>
|
| 5507 |
-
Fazer download
|
| 5508 |
-
</button>
|
| 5509 |
-
</div>
|
| 5510 |
{secao13InterativoAtual?.figure ? (
|
| 5511 |
<PlotFigure
|
| 5512 |
key={`s12-interativo-plot-${secao13InterativoAtual.id}`}
|
|
@@ -5519,6 +5667,23 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5519 |
forceHideLegend
|
| 5520 |
className="plot-stretch"
|
| 5521 |
lazy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5522 |
/>
|
| 5523 |
) : (
|
| 5524 |
<div className="empty-box">Grafico indisponivel.</div>
|
|
@@ -5528,57 +5693,24 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5528 |
</>
|
| 5529 |
) : (
|
| 5530 |
<>
|
| 5531 |
-
<div className="download-actions-bar">
|
| 5532 |
-
{graficosSecao12.length > 1 ? <span className="download-actions-label">Fazer download:</span> : null}
|
| 5533 |
-
{graficosSecao12.map((item, idx) => {
|
| 5534 |
-
const fileBase = `secao13_${sanitizeFileName(item.label, `dispersao_${idx + 1}`)}`
|
| 5535 |
-
return (
|
| 5536 |
-
<button
|
| 5537 |
-
key={`s12-dl-${item.id}`}
|
| 5538 |
-
type="button"
|
| 5539 |
-
className="btn-download-subtle"
|
| 5540 |
-
title={item.legenda}
|
| 5541 |
-
onClick={() => onDownloadFigurePng(item.figure, fileBase, { forceHideLegend: true })}
|
| 5542 |
-
disabled={loading || downloadingAssets || !item.figure}
|
| 5543 |
-
>
|
| 5544 |
-
{graficosSecao12.length > 1 ? item.label : 'Fazer download'}
|
| 5545 |
-
</button>
|
| 5546 |
-
)
|
| 5547 |
-
})}
|
| 5548 |
-
{graficosSecao12.length > 1 ? (
|
| 5549 |
-
<button
|
| 5550 |
-
type="button"
|
| 5551 |
-
className="btn-download-subtle"
|
| 5552 |
-
onClick={() => onDownloadFiguresPngBatch(
|
| 5553 |
-
graficosSecao12.map((item, idx) => ({
|
| 5554 |
-
figure: item.figure,
|
| 5555 |
-
fileNameBase: `secao13_${sanitizeFileName(item.label, `dispersao_${idx + 1}`)}`,
|
| 5556 |
-
forceHideLegend: true,
|
| 5557 |
-
})),
|
| 5558 |
-
)}
|
| 5559 |
-
disabled={loading || downloadingAssets || graficosSecao12.length === 0}
|
| 5560 |
-
>
|
| 5561 |
-
Todos
|
| 5562 |
-
</button>
|
| 5563 |
-
) : null}
|
| 5564 |
-
</div>
|
| 5565 |
{graficosSecao12.length > 0 ? (
|
| 5566 |
-
<
|
| 5567 |
-
{graficosSecao12
|
| 5568 |
-
|
| 5569 |
-
|
| 5570 |
-
|
| 5571 |
-
|
| 5572 |
-
|
| 5573 |
-
|
| 5574 |
-
|
| 5575 |
-
|
| 5576 |
-
|
| 5577 |
-
|
| 5578 |
-
|
| 5579 |
-
|
| 5580 |
-
|
| 5581 |
-
|
|
|
|
| 5582 |
) : (
|
| 5583 |
<div className="empty-box">Grafico indisponivel.</div>
|
| 5584 |
)}
|
|
@@ -5587,54 +5719,100 @@ export default function ElaboracaoTab({ sessionId, authUser, quickLoadRequest =
|
|
| 5587 |
</SectionBlock>
|
| 5588 |
|
| 5589 |
<SectionBlock step="14" title="Diagnóstico de Modelo" subtitle="Resumo diagnóstico e tabelas principais do ajuste.">
|
| 5590 |
-
<div
|
| 5591 |
-
|
| 5592 |
-
|
| 5593 |
-
|
| 5594 |
-
|
| 5595 |
-
|
| 5596 |
-
|
| 5597 |
-
|
| 5598 |
-
|
| 5599 |
-
|
| 5600 |
-
|
| 5601 |
-
|
| 5602 |
-
|
| 5603 |
-
|
| 5604 |
-
|
| 5605 |
-
|
| 5606 |
-
|
| 5607 |
-
|
| 5608 |
-
|
| 5609 |
-
<button
|
| 5610 |
-
type="button"
|
| 5611 |
-
className="btn-download-subtle"
|
| 5612 |
-
onClick={() => onDownloadTableCsv(fit.tabela_obs_calc, 'secao14_obs_calc')}
|
| 5613 |
-
disabled={loading || downloadingAssets || !fit.tabela_obs_calc}
|
| 5614 |
-
>
|
| 5615 |
-
Obs x Calc
|
| 5616 |
-
</button>
|
| 5617 |
-
<button
|
| 5618 |
-
type="button"
|
| 5619 |
-
className="btn-download-subtle"
|
| 5620 |
-
onClick={() => onDownloadTablesCsvBatch([
|
| 5621 |
-
{ table: fit.tabela_coef, fileNameBase: 'secao14_coeficientes' },
|
| 5622 |
-
{ table: fit.tabela_obs_calc, fileNameBase: 'secao14_obs_calc' },
|
| 5623 |
-
])}
|
| 5624 |
-
disabled={loading || downloadingAssets || (!fit.tabela_coef && !fit.tabela_obs_calc)}
|
| 5625 |
-
>
|
| 5626 |
-
Todos
|
| 5627 |
-
</button>
|
| 5628 |
</div>
|
| 5629 |
-
|
| 5630 |
-
|
| 5631 |
-
|
| 5632 |
-
|
| 5633 |
-
|
| 5634 |
-
|
| 5635 |
-
|
| 5636 |
-
|
| 5637 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5638 |
</div>
|
| 5639 |
</SectionBlock>
|
| 5640 |
|
|
|
|
| 234 |
return num.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' })
|
| 235 |
}
|
| 236 |
|
| 237 |
+
function Section14MetricRows({ rows }) {
|
| 238 |
+
return (
|
| 239 |
+
<div className="section14-field-grid">
|
| 240 |
+
{(rows || []).map((row) => (
|
| 241 |
+
<div key={row.label} className="section14-field-row">
|
| 242 |
+
<span className="section14-field-label">{row.label}</span>
|
| 243 |
+
<span className="section14-field-value">{row.value}</span>
|
| 244 |
+
</div>
|
| 245 |
+
))}
|
| 246 |
+
</div>
|
| 247 |
+
)
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
function formatarValorTabelaKnn(coluna, valor) {
|
| 251 |
if (valor === null || valor === undefined || valor === '') return '-'
|
| 252 |
const nome = String(coluna || '').toLowerCase()
|
|
|
|
| 703 |
return mapa
|
| 704 |
}
|
| 705 |
|
| 706 |
+
function ScatterPlotCarousel({
|
| 707 |
+
items,
|
| 708 |
+
indexedFigureMap,
|
| 709 |
+
onRequestIndexedFigure,
|
| 710 |
+
itemKeyPrefix,
|
| 711 |
+
sectionFilePrefix,
|
| 712 |
+
onDownloadFigure,
|
| 713 |
+
onDownloadAll,
|
| 714 |
+
loading = false,
|
| 715 |
+
downloadingAssets = false,
|
| 716 |
+
}) {
|
| 717 |
+
const [page, setPage] = useState(0)
|
| 718 |
+
const pageSize = 2
|
| 719 |
+
const safeItems = Array.isArray(items) ? items : []
|
| 720 |
+
const totalPages = Math.max(1, Math.ceil(safeItems.length / pageSize))
|
| 721 |
+
const itemsSignature = safeItems.map((item) => String(item?.id || item?.label || '')).join('|')
|
| 722 |
+
const startIndex = Math.min(page, totalPages - 1) * pageSize
|
| 723 |
+
const visibleItems = safeItems.slice(startIndex, startIndex + pageSize)
|
| 724 |
+
|
| 725 |
+
useEffect(() => {
|
| 726 |
+
setPage(0)
|
| 727 |
+
}, [itemsSignature])
|
| 728 |
+
|
| 729 |
+
useEffect(() => {
|
| 730 |
+
setPage((current) => Math.min(current, totalPages - 1))
|
| 731 |
+
}, [totalPages])
|
| 732 |
+
|
| 733 |
+
if (safeItems.length === 0) {
|
| 734 |
+
return <div className="empty-box">Grafico indisponivel.</div>
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
function getPairTitle(pageIndex) {
|
| 738 |
+
const pair = safeItems.slice(pageIndex * pageSize, (pageIndex * pageSize) + pageSize)
|
| 739 |
+
return pair.map((item) => String(item?.label || item?.title || '').trim()).filter(Boolean).join(' e ')
|
| 740 |
+
}
|
| 741 |
+
|
| 742 |
+
function getPairLabel(pageIndex) {
|
| 743 |
+
const title = getPairTitle(pageIndex)
|
| 744 |
+
if (title) return title
|
| 745 |
+
const pairStart = (pageIndex * pageSize) + 1
|
| 746 |
+
const pairEnd = Math.min(pairStart + pageSize - 1, safeItems.length)
|
| 747 |
+
return pairStart === pairEnd ? String(pairStart) : `${pairStart}-${pairEnd}`
|
| 748 |
+
}
|
| 749 |
+
|
| 750 |
+
function buildFileNameBase(item, itemIndex) {
|
| 751 |
+
return `${sectionFilePrefix}_${sanitizeFileName(item?.label, `dispersao_${itemIndex + 1}`)}`
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
return (
|
| 755 |
+
<div className="scatter-carousel">
|
| 756 |
+
{typeof onDownloadAll === 'function' && safeItems.length > 1 ? (
|
| 757 |
+
<div className="scatter-carousel-actions">
|
| 758 |
+
<button
|
| 759 |
+
type="button"
|
| 760 |
+
className="btn-download-subtle scatter-carousel-download-all"
|
| 761 |
+
onClick={onDownloadAll}
|
| 762 |
+
disabled={loading || downloadingAssets || safeItems.length === 0}
|
| 763 |
+
>
|
| 764 |
+
Baixar todos os gráficos
|
| 765 |
+
</button>
|
| 766 |
+
</div>
|
| 767 |
+
) : null}
|
| 768 |
+
{totalPages > 1 ? (
|
| 769 |
+
<div className="scatter-carousel-pills" aria-label="Escolher dupla de gráficos">
|
| 770 |
+
{Array.from({ length: totalPages }, (_, pageIndex) => {
|
| 771 |
+
const pairStart = (pageIndex * pageSize) + 1
|
| 772 |
+
const pairEnd = Math.min(pairStart + pageSize - 1, safeItems.length)
|
| 773 |
+
const active = pageIndex === page
|
| 774 |
+
return (
|
| 775 |
+
<button
|
| 776 |
+
key={`scatter-pair-${pairStart}-${pairEnd}`}
|
| 777 |
+
type="button"
|
| 778 |
+
className={`scatter-carousel-pill${active ? ' is-active' : ''}`}
|
| 779 |
+
onClick={() => setPage(pageIndex)}
|
| 780 |
+
title={getPairTitle(pageIndex)}
|
| 781 |
+
aria-current={active ? 'true' : undefined}
|
| 782 |
+
>
|
| 783 |
+
{getPairLabel(pageIndex)}
|
| 784 |
+
</button>
|
| 785 |
+
)
|
| 786 |
+
})}
|
| 787 |
+
</div>
|
| 788 |
+
) : null}
|
| 789 |
+
<div className="scatter-carousel-track">
|
| 790 |
+
{visibleItems.map((item, visibleIndex) => {
|
| 791 |
+
const itemIndex = startIndex + visibleIndex
|
| 792 |
+
const fileNameBase = buildFileNameBase(item, itemIndex)
|
| 793 |
+
return (
|
| 794 |
+
<PlotFigure
|
| 795 |
+
key={`${itemKeyPrefix}-${item.id}`}
|
| 796 |
+
figure={item.figure}
|
| 797 |
+
indexedFigure={indexedFigureMap?.get(String(item.label || '').trim()) || null}
|
| 798 |
+
onRequestIndexedFigure={onRequestIndexedFigure}
|
| 799 |
+
title={item.title}
|
| 800 |
+
subtitle={item.subtitle}
|
| 801 |
+
showPointIndexToggle
|
| 802 |
+
forceHideLegend
|
| 803 |
+
className="plot-stretch"
|
| 804 |
+
lazy
|
| 805 |
+
headerActions={typeof onDownloadFigure === 'function' ? (
|
| 806 |
+
<button
|
| 807 |
+
type="button"
|
| 808 |
+
className="btn-download-subtle plot-card-download-btn"
|
| 809 |
+
title={item.legenda || item.label || 'Fazer download'}
|
| 810 |
+
onClick={() => onDownloadFigure(item.figure, fileNameBase, { forceHideLegend: true })}
|
| 811 |
+
disabled={loading || downloadingAssets || !item.figure}
|
| 812 |
+
>
|
| 813 |
+
Fazer download
|
| 814 |
+
</button>
|
| 815 |
+
) : null}
|
| 816 |
+
/>
|
| 817 |
+
)
|
| 818 |
+
})}
|
| 819 |
+
</div>
|
| 820 |
+
</div>
|
| 821 |
+
)
|
| 822 |
+
}
|
| 823 |
+
|
| 824 |
function formatConselhoRegistro(elaborador) {
|
| 825 |
if (!elaborador) return ''
|
| 826 |
const conselho = String(elaborador.conselho || '').trim()
|
|
|
|
| 1076 |
const [section11LocksOpen, setSection11LocksOpen] = useState(false)
|
| 1077 |
const [section10ManualOpen, setSection10ManualOpen] = useState(false)
|
| 1078 |
const [section6EditOpen, setSection6EditOpen] = useState(true)
|
| 1079 |
+
const [section14Tab, setSection14Tab] = useState('diagnosticos')
|
| 1080 |
|
| 1081 |
const [fit, setFit] = useState(null)
|
| 1082 |
const [dispersaoEixoX, setDispersaoEixoX] = useState('transformado')
|
|
|
|
| 1144 |
const [sectionsMountKey, setSectionsMountKey] = useState(0)
|
| 1145 |
const [renderedSectionSteps, setRenderedSectionSteps] = useState(() => ['1'])
|
| 1146 |
const [visibleSectionSteps, setVisibleSectionSteps] = useState(() => ['1'])
|
| 1147 |
+
const [currentSectionStep, setCurrentSectionStep] = useState('1')
|
| 1148 |
const visibleSectionStepsRef = useRef(new Set(['1']))
|
| 1149 |
const elaboracaoShareHref = repoModeloSelecionado
|
| 1150 |
? buildElaboracaoModeloLink(repoModeloSelecionado)
|
|
|
|
| 1412 |
|
| 1413 |
return faixas
|
| 1414 |
}, [fit?.tabela_metricas?.rows, fit?.variaveis_filtro])
|
| 1415 |
+
const section14DiagnosticosGerais = useMemo(() => {
|
| 1416 |
+
const diagnosticos = fit?.diagnosticos || {}
|
| 1417 |
+
return [
|
| 1418 |
+
{ label: 'Número de observações', value: formatNumberBr(diagnosticos.n, 0) },
|
| 1419 |
+
{ label: 'Número de variáveis independentes', value: formatNumberBr(diagnosticos.k, 0) },
|
| 1420 |
+
{ label: 'Desvio padrão dos resíduos', value: formatMetric4(diagnosticos.desvio_padrao_residuos) },
|
| 1421 |
+
{ label: 'MSE', value: formatMetric4(diagnosticos.mse) },
|
| 1422 |
+
{ label: 'R²', value: formatMetric4(diagnosticos.r2) },
|
| 1423 |
+
{ label: 'R² ajustado', value: formatMetric4(diagnosticos.r2_ajustado) },
|
| 1424 |
+
{ label: 'Correlação Pearson', value: formatMetric4(diagnosticos.r_pearson) },
|
| 1425 |
+
]
|
| 1426 |
+
}, [fit?.diagnosticos])
|
| 1427 |
+
const section14Testes = useMemo(() => {
|
| 1428 |
+
const diagnosticos = fit?.diagnosticos || {}
|
| 1429 |
+
return [
|
| 1430 |
+
{
|
| 1431 |
+
id: 'f',
|
| 1432 |
+
label: 'Teste F',
|
| 1433 |
+
rows: [
|
| 1434 |
+
{ label: 'Estatística F', value: formatMetric4(diagnosticos.Fc) },
|
| 1435 |
+
{ label: 'P-valor', value: formatMetric4(diagnosticos.p_valor_F) },
|
| 1436 |
+
{ label: 'Interpretação', value: diagnosticos.interp_F || '-' },
|
| 1437 |
+
],
|
| 1438 |
+
},
|
| 1439 |
+
{
|
| 1440 |
+
id: 'ks',
|
| 1441 |
+
label: 'Normalidade KS',
|
| 1442 |
+
rows: [
|
| 1443 |
+
{ label: 'Estatística KS', value: formatMetric4(diagnosticos.ks_stat) },
|
| 1444 |
+
{ label: 'P-valor', value: formatMetric4(diagnosticos.ks_p) },
|
| 1445 |
+
{ label: 'Interpretação', value: diagnosticos.interp_KS || '-' },
|
| 1446 |
+
],
|
| 1447 |
+
},
|
| 1448 |
+
{
|
| 1449 |
+
id: 'curva',
|
| 1450 |
+
label: 'Curva normal',
|
| 1451 |
+
rows: [
|
| 1452 |
+
{ label: 'Percentuais atingidos', value: diagnosticos.perc_resid || '-' },
|
| 1453 |
+
{ label: 'Ideal 68%', value: 'aceitável entre 64% e 75%' },
|
| 1454 |
+
{ label: 'Ideal 90%', value: 'aceitável entre 88% e 95%' },
|
| 1455 |
+
{ label: 'Ideal 95%', value: 'aceitável entre 95% e 100%' },
|
| 1456 |
+
],
|
| 1457 |
+
},
|
| 1458 |
+
{
|
| 1459 |
+
id: 'dw',
|
| 1460 |
+
label: 'Durbin-Watson',
|
| 1461 |
+
rows: [
|
| 1462 |
+
{ label: 'Estatística DW', value: formatMetric4(diagnosticos.dw) },
|
| 1463 |
+
{ label: 'Interpretação', value: diagnosticos.interp_DW || '-' },
|
| 1464 |
+
],
|
| 1465 |
+
},
|
| 1466 |
+
{
|
| 1467 |
+
id: 'bp',
|
| 1468 |
+
label: 'Breusch-Pagan',
|
| 1469 |
+
rows: [
|
| 1470 |
+
{ label: 'Estatística LM', value: formatMetric4(diagnosticos.bp_lm) },
|
| 1471 |
+
{ label: 'P-valor', value: formatMetric4(diagnosticos.bp_p) },
|
| 1472 |
+
{ label: 'Interpretação', value: diagnosticos.interp_BP || '-' },
|
| 1473 |
+
],
|
| 1474 |
+
},
|
| 1475 |
+
]
|
| 1476 |
+
}, [fit?.diagnosticos])
|
| 1477 |
const resumoResiduoPadStats = useMemo(() => {
|
| 1478 |
const rows = fit?.tabela_metricas?.rows
|
| 1479 |
if (!Array.isArray(rows) || rows.length === 0) return null
|
|
|
|
| 1611 |
if (secao10InterativoSelecionado === 'none' || graficosSecao9Interativo.length === 0) return null
|
| 1612 |
return graficosSecao9Interativo.find((item) => String(item.label || '') === secao10InterativoSelecionado) || graficosSecao9Interativo[0]
|
| 1613 |
}, [graficosSecao9Interativo, secao10InterativoSelecionado])
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1614 |
const colunasOriginaisDispersao = useMemo(() => {
|
| 1615 |
const cols = Array.isArray(dados?.columns) ? dados.columns : []
|
| 1616 |
return cols
|
|
|
|
| 1696 |
if (secao13InterativoSelecionado === 'none' || graficosSecao12Interativo.length === 0) return null
|
| 1697 |
return graficosSecao12Interativo.find((item) => String(item.label || '') === secao13InterativoSelecionado) || graficosSecao12Interativo[0]
|
| 1698 |
}, [graficosSecao12Interativo, secao13InterativoSelecionado])
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1699 |
const secao15DiagnosticoPng = useMemo(
|
| 1700 |
() => String(fit?.graficos_diagnostico_modo || '') === 'png',
|
| 1701 |
[fit?.graficos_diagnostico_modo],
|
|
|
|
| 1806 |
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
| 1807 |
setRenderedSectionSteps(['1'])
|
| 1808 |
setVisibleSectionSteps(['1'])
|
| 1809 |
+
setCurrentSectionStep('1')
|
| 1810 |
visibleSectionStepsRef.current = new Set(['1'])
|
| 1811 |
return undefined
|
| 1812 |
}
|
|
|
|
| 1820 |
|
| 1821 |
if (sections.length === 0) {
|
| 1822 |
setVisibleSectionSteps(['1'])
|
| 1823 |
+
setCurrentSectionStep('1')
|
| 1824 |
visibleSectionStepsRef.current = new Set(['1'])
|
| 1825 |
return undefined
|
| 1826 |
}
|
|
|
|
| 1864 |
.map((section) => section.getAttribute('data-section-step')),
|
| 1865 |
)
|
| 1866 |
const normalizedVisible = nextVisible.length > 0 ? nextVisible : [getClosestStepToTop()]
|
| 1867 |
+
const nextCurrentStep = getClosestStepToTop()
|
| 1868 |
visibleSectionStepsRef.current = new Set(normalizedVisible)
|
| 1869 |
setVisibleSectionSteps((current) => (isSameSectionStepList(current, normalizedVisible) ? current : normalizedVisible))
|
| 1870 |
+
setCurrentSectionStep((current) => (current === nextCurrentStep ? current : nextCurrentStep))
|
| 1871 |
}
|
| 1872 |
|
| 1873 |
computeVisibleSteps()
|
|
|
|
| 4135 |
|
| 4136 |
return (
|
| 4137 |
<div ref={elaboracaoRootRef} className="tab-content">
|
| 4138 |
+
<div
|
| 4139 |
+
className={`elaboracao-layout${repoModeloDropdownOpen ? ' is-repo-model-open' : ''}`}
|
| 4140 |
+
style={sideNavDynamicStyle}
|
| 4141 |
+
data-current-section-step={currentSectionStep}
|
| 4142 |
+
>
|
| 4143 |
<aside className="elaboracao-side-nav" aria-label="Navegação de seções da elaboração">
|
| 4144 |
<ol className="elaboracao-side-nav-list">
|
| 4145 |
{ELABORACAO_SECOES_NAV.map((secao) => {
|
|
|
|
| 4762 |
: 'Há outliers excluídos: não'}
|
| 4763 |
</div>
|
| 4764 |
{outliersAnteriores.length > 0 ? (
|
| 4765 |
+
<div className="resumo-outliers-box resumo-outliers-box-scrollable">
|
| 4766 |
+
Índices excluídos: {joinSelection(outliersAnteriores)}
|
| 4767 |
+
</div>
|
| 4768 |
) : null}
|
| 4769 |
</div>
|
| 4770 |
<div className="download-actions-bar">
|
|
|
|
| 4779 |
Fazer download
|
| 4780 |
</button>
|
| 4781 |
</div>
|
| 4782 |
+
<DataTable table={dados} maxHeight={320} />
|
| 4783 |
</div>
|
| 4784 |
</SectionBlock>
|
| 4785 |
|
|
|
|
| 4907 |
{colunasX.length}/{colunasXDisponiveis.length} selecionadas
|
| 4908 |
</span>
|
| 4909 |
</div>
|
| 4910 |
+
<div className="checkbox-inline-wrap checkbox-inline-wrap-scrollable">
|
| 4911 |
{colunasXDisponiveis.map((col) => (
|
| 4912 |
<label key={`x-${col}`} className="compact-checkbox">
|
| 4913 |
<input
|
|
|
|
| 4968 |
|
| 4969 |
<div className="compact-option-group compact-option-group-codigo">
|
| 4970 |
<h4>Variáveis Categóricas Codificadas</h4>
|
| 4971 |
+
<div className="checkbox-inline-wrap checkbox-inline-wrap-scrollable">
|
| 4972 |
{colunasX.map((col) => (
|
| 4973 |
<label key={`c-${col}`} className="compact-checkbox">
|
| 4974 |
<input type="checkbox" checked={codigoAlocado.includes(col)} onChange={() => toggleSelection(setCodigoAlocado, col)} />
|
|
|
|
| 5045 |
<div className="section6-summary-group">
|
| 5046 |
<div className="section6-summary-label">Variáveis categóricas codificadas:</div>
|
| 5047 |
{selecaoAplicada.codigo_alocado.length > 0 ? (
|
| 5048 |
+
<div className="checkbox-inline-wrap checkbox-inline-wrap-scrollable">
|
| 5049 |
{selecaoAplicada.codigo_alocado.map((coluna) => (
|
| 5050 |
<span key={`selected-c-${coluna}`} className="compact-chip">{coluna}</span>
|
| 5051 |
))}
|
|
|
|
| 5149 |
</div>
|
| 5150 |
{secao10InterativoSelecionado !== 'none' ? (
|
| 5151 |
<>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5152 |
{secao10InterativoAtual?.figure ? (
|
| 5153 |
<PlotFigure
|
| 5154 |
key={`s9-interativo-plot-${secao10InterativoAtual.id}`}
|
|
|
|
| 5161 |
forceHideLegend
|
| 5162 |
className="plot-stretch"
|
| 5163 |
lazy
|
| 5164 |
+
headerActions={(
|
| 5165 |
+
<button
|
| 5166 |
+
type="button"
|
| 5167 |
+
className="btn-download-subtle plot-card-download-btn"
|
| 5168 |
+
title={secao10InterativoAtual?.legenda || ''}
|
| 5169 |
+
onClick={() => {
|
| 5170 |
+
void onDownloadFigurePng(
|
| 5171 |
+
secao10InterativoAtual.figure,
|
| 5172 |
+
`secao10_${sanitizeFileName(secao10InterativoAtual.label, 'dispersao_interativo')}`,
|
| 5173 |
+
{ forceHideLegend: true },
|
| 5174 |
+
)
|
| 5175 |
+
}}
|
| 5176 |
+
disabled={loading || downloadingAssets || !secao10InterativoAtual?.figure}
|
| 5177 |
+
>
|
| 5178 |
+
Fazer download
|
| 5179 |
+
</button>
|
| 5180 |
+
)}
|
| 5181 |
/>
|
| 5182 |
) : (
|
| 5183 |
<div className="empty-box">Grafico indisponivel.</div>
|
|
|
|
| 5187 |
</>
|
| 5188 |
) : (
|
| 5189 |
<>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5190 |
{graficosSecao9.length > 0 ? (
|
| 5191 |
+
<ScatterPlotCarousel
|
| 5192 |
+
items={graficosSecao9}
|
| 5193 |
+
indexedFigureMap={graficosSecao9ComIndicesMap}
|
| 5194 |
+
onRequestIndexedFigure={ensureSecao10GraficoComIndices}
|
| 5195 |
+
itemKeyPrefix="s9-plot"
|
| 5196 |
+
sectionFilePrefix="secao10"
|
| 5197 |
+
onDownloadFigure={onDownloadFigurePng}
|
| 5198 |
+
onDownloadAll={() => onDownloadFiguresPngBatch(
|
| 5199 |
+
graficosSecao9.map((item, idx) => ({
|
| 5200 |
+
figure: item.figure,
|
| 5201 |
+
fileNameBase: `secao10_${sanitizeFileName(item.label, `dispersao_${idx + 1}`)}`,
|
| 5202 |
+
forceHideLegend: true,
|
| 5203 |
+
})),
|
| 5204 |
+
)}
|
| 5205 |
+
loading={loading}
|
| 5206 |
+
downloadingAssets={downloadingAssets}
|
| 5207 |
+
/>
|
| 5208 |
) : (
|
| 5209 |
<div className="empty-box">Grafico indisponivel.</div>
|
| 5210 |
)}
|
|
|
|
| 5284 |
</div>
|
| 5285 |
</div>
|
| 5286 |
{(selection.busca?.resultados || []).length > 0 ? (
|
| 5287 |
+
<div className="section11-suggestions-block">
|
| 5288 |
+
<div className="section11-suggestions-title">Transformações Sugeridas</div>
|
| 5289 |
+
<div className="transform-suggestions-grid">
|
| 5290 |
+
{(selection.busca?.resultados || []).map((item, idx) => (
|
| 5291 |
+
<div key={`sug-${item.rank || idx + 1}`} className="transform-suggestion-card">
|
| 5292 |
+
<div className="transform-suggestion-head">
|
| 5293 |
+
<span className="transform-suggestion-rank">#{item.rank || idx + 1}</span>
|
| 5294 |
+
<div className="transform-suggestion-metrics">
|
| 5295 |
+
<span className="transform-suggestion-r2">R² = {formatMetric4(item.r2)}</span>
|
| 5296 |
+
<span className="transform-suggestion-r2adj">R² ajustado = {formatMetric4(item.r2_ajustado)}</span>
|
| 5297 |
+
<span className={grauBadgeClass(Number(item.grau_f ?? 0))}>
|
| 5298 |
+
Teste F: {GRAU_LABEL_CURTO[Number(item.grau_f ?? 0)] || 'Sem enq.'}
|
| 5299 |
+
</span>
|
| 5300 |
+
</div>
|
| 5301 |
</div>
|
| 5302 |
+
<div className="transform-suggestion-list">
|
| 5303 |
+
<div className="transform-suggestion-item transform-suggestion-item-y">
|
| 5304 |
+
<span className="transform-suggestion-col">{`${colunaY || 'Y'} (Y)`}</span>
|
| 5305 |
+
<span className="transform-suggestion-fn">{item.transformacao_y || '(x)'}</span>
|
| 5306 |
+
<span className="transform-suggestion-item-note">Dependente</span>
|
| 5307 |
+
</div>
|
| 5308 |
+
{Object.entries(item.transformacoes_x || {}).map(([coluna, transf]) => {
|
| 5309 |
+
const grau = Number(item.graus_coef?.[coluna] ?? 0)
|
| 5310 |
+
return (
|
| 5311 |
+
<div key={`scol-${item.rank || idx}-${coluna}`} className="transform-suggestion-item">
|
| 5312 |
+
<span className="transform-suggestion-col">{coluna}</span>
|
| 5313 |
+
<span className="transform-suggestion-fn">{transf}</span>
|
| 5314 |
+
<span className={grauBadgeClass(grau)}>{GRAU_LABEL_CURTO[grau] || 'Sem enq.'}</span>
|
| 5315 |
+
</div>
|
| 5316 |
+
)
|
| 5317 |
+
})}
|
| 5318 |
</div>
|
| 5319 |
+
<button className="btn-adopt-model" onClick={() => onAdoptSuggestion(idx)} disabled={loading}>
|
| 5320 |
+
Adotar e Ajustar Modelo
|
| 5321 |
+
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5322 |
</div>
|
| 5323 |
+
))}
|
| 5324 |
+
</div>
|
|
|
|
|
|
|
|
|
|
| 5325 |
</div>
|
| 5326 |
) : (
|
| 5327 |
<div dangerouslySetInnerHTML={{ __html: selection.busca?.html || '' }} />
|
|
|
|
| 5450 |
Modo PNG automático para mais de {secao13PngPayload?.limiar || fit?.grafico_dispersao_modelo_limiar_png || 1500} pontos. Ao final da seção, podem ser gerados individualmente os gráficos interativos.
|
| 5451 |
</div>
|
| 5452 |
) : null}
|
| 5453 |
+
<div className="row dispersao-config-row dispersao-config-panel">
|
| 5454 |
<div className="dispersao-config-field">
|
| 5455 |
<label>Eixo X</label>
|
| 5456 |
<select
|
|
|
|
| 5567 |
</div>
|
| 5568 |
{secao13InterativoSelecionado !== 'none' ? (
|
| 5569 |
<>
|
| 5570 |
+
<div className="row dispersao-config-row dispersao-config-panel">
|
| 5571 |
<div className="dispersao-config-field">
|
| 5572 |
<label>Eixo X (interativo)</label>
|
| 5573 |
<select
|
|
|
|
| 5655 |
)}
|
| 5656 |
</select>
|
| 5657 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5658 |
{secao13InterativoAtual?.figure ? (
|
| 5659 |
<PlotFigure
|
| 5660 |
key={`s12-interativo-plot-${secao13InterativoAtual.id}`}
|
|
|
|
| 5667 |
forceHideLegend
|
| 5668 |
className="plot-stretch"
|
| 5669 |
lazy
|
| 5670 |
+
headerActions={(
|
| 5671 |
+
<button
|
| 5672 |
+
type="button"
|
| 5673 |
+
className="btn-download-subtle plot-card-download-btn"
|
| 5674 |
+
title={secao13InterativoAtual?.legenda || ''}
|
| 5675 |
+
onClick={() => {
|
| 5676 |
+
void onDownloadFigurePng(
|
| 5677 |
+
secao13InterativoAtual.figure,
|
| 5678 |
+
`secao13_${sanitizeFileName(secao13InterativoAtual.label, 'dispersao_interativo')}`,
|
| 5679 |
+
{ forceHideLegend: true },
|
| 5680 |
+
)
|
| 5681 |
+
}}
|
| 5682 |
+
disabled={loading || downloadingAssets || !secao13InterativoAtual?.figure}
|
| 5683 |
+
>
|
| 5684 |
+
Fazer download
|
| 5685 |
+
</button>
|
| 5686 |
+
)}
|
| 5687 |
/>
|
| 5688 |
) : (
|
| 5689 |
<div className="empty-box">Grafico indisponivel.</div>
|
|
|
|
| 5693 |
</>
|
| 5694 |
) : (
|
| 5695 |
<>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5696 |
{graficosSecao12.length > 0 ? (
|
| 5697 |
+
<ScatterPlotCarousel
|
| 5698 |
+
items={graficosSecao12}
|
| 5699 |
+
indexedFigureMap={graficosSecao12ComIndicesMap}
|
| 5700 |
+
onRequestIndexedFigure={ensureSecao13GraficoComIndices}
|
| 5701 |
+
itemKeyPrefix="s12-plot"
|
| 5702 |
+
sectionFilePrefix="secao13"
|
| 5703 |
+
onDownloadFigure={onDownloadFigurePng}
|
| 5704 |
+
onDownloadAll={() => onDownloadFiguresPngBatch(
|
| 5705 |
+
graficosSecao12.map((item, idx) => ({
|
| 5706 |
+
figure: item.figure,
|
| 5707 |
+
fileNameBase: `secao13_${sanitizeFileName(item.label, `dispersao_${idx + 1}`)}`,
|
| 5708 |
+
forceHideLegend: true,
|
| 5709 |
+
})),
|
| 5710 |
+
)}
|
| 5711 |
+
loading={loading}
|
| 5712 |
+
downloadingAssets={downloadingAssets}
|
| 5713 |
+
/>
|
| 5714 |
) : (
|
| 5715 |
<div className="empty-box">Grafico indisponivel.</div>
|
| 5716 |
)}
|
|
|
|
| 5719 |
</SectionBlock>
|
| 5720 |
|
| 5721 |
<SectionBlock step="14" title="Diagnóstico de Modelo" subtitle="Resumo diagnóstico e tabelas principais do ajuste.">
|
| 5722 |
+
<div className="section14-tabs" role="tablist" aria-label="Conteúdos do diagnóstico do modelo">
|
| 5723 |
+
{[
|
| 5724 |
+
{ id: 'diagnosticos', label: 'Diagnósticos' },
|
| 5725 |
+
{ id: 'testes', label: 'Testes' },
|
| 5726 |
+
{ id: 'equacoes', label: 'Equações' },
|
| 5727 |
+
{ id: 'coeficientes', label: 'Coeficientes' },
|
| 5728 |
+
{ id: 'obs_calc', label: 'Obs x Calc' },
|
| 5729 |
+
].map((tab) => (
|
| 5730 |
+
<button
|
| 5731 |
+
key={`sec14-tab-${tab.id}`}
|
| 5732 |
+
type="button"
|
| 5733 |
+
className={`section14-tab-pill${section14Tab === tab.id ? ' is-active' : ''}`}
|
| 5734 |
+
onClick={() => setSection14Tab(tab.id)}
|
| 5735 |
+
aria-selected={section14Tab === tab.id}
|
| 5736 |
+
role="tab"
|
| 5737 |
+
>
|
| 5738 |
+
{tab.label}
|
| 5739 |
+
</button>
|
| 5740 |
+
))}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5741 |
</div>
|
| 5742 |
+
|
| 5743 |
+
<div className="section14-panel" role="tabpanel">
|
| 5744 |
+
{section14Tab === 'diagnosticos' ? (
|
| 5745 |
+
fit?.diagnosticos ? (
|
| 5746 |
+
<div className="section14-diagnostics-panel">
|
| 5747 |
+
<h4>Estatísticas Gerais</h4>
|
| 5748 |
+
<Section14MetricRows rows={section14DiagnosticosGerais} />
|
| 5749 |
+
</div>
|
| 5750 |
+
) : (
|
| 5751 |
+
<div className="section14-diagnostics-panel" dangerouslySetInnerHTML={{ __html: fit.diagnosticos_html || '' }} />
|
| 5752 |
+
)
|
| 5753 |
+
) : null}
|
| 5754 |
+
|
| 5755 |
+
{section14Tab === 'testes' ? (
|
| 5756 |
+
fit?.diagnosticos ? (
|
| 5757 |
+
<div className="section14-tests-panel">
|
| 5758 |
+
<div className="section14-tests-grid">
|
| 5759 |
+
{section14Testes.map((teste) => (
|
| 5760 |
+
<div key={`sec14-test-card-${teste.id}`} className="section14-test-card">
|
| 5761 |
+
<h4>{teste.label}</h4>
|
| 5762 |
+
<Section14MetricRows rows={teste.rows} />
|
| 5763 |
+
</div>
|
| 5764 |
+
))}
|
| 5765 |
+
</div>
|
| 5766 |
+
</div>
|
| 5767 |
+
) : (
|
| 5768 |
+
<div className="section14-diagnostics-panel" dangerouslySetInnerHTML={{ __html: fit.diagnosticos_html || '' }} />
|
| 5769 |
+
)
|
| 5770 |
+
) : null}
|
| 5771 |
+
|
| 5772 |
+
{section14Tab === 'equacoes' ? (
|
| 5773 |
+
<div className="equation-formats-section section14-equations-panel">
|
| 5774 |
+
<h4>Equações do Modelo</h4>
|
| 5775 |
+
<EquationFormatsPanel
|
| 5776 |
+
equacoes={fit.equacoes}
|
| 5777 |
+
onDownload={(mode) => void onDownloadEquacao(mode)}
|
| 5778 |
+
disabled={loading || downloadingAssets}
|
| 5779 |
+
/>
|
| 5780 |
+
</div>
|
| 5781 |
+
) : null}
|
| 5782 |
+
|
| 5783 |
+
{section14Tab === 'coeficientes' ? (
|
| 5784 |
+
<div className="section14-table-panel">
|
| 5785 |
+
<div className="section14-table-head">
|
| 5786 |
+
<h4>Tabela de Coeficientes</h4>
|
| 5787 |
+
<button
|
| 5788 |
+
type="button"
|
| 5789 |
+
className="btn-download-subtle"
|
| 5790 |
+
onClick={() => onDownloadTableCsv(fit.tabela_coef, 'secao14_coeficientes')}
|
| 5791 |
+
disabled={loading || downloadingAssets || !fit.tabela_coef}
|
| 5792 |
+
>
|
| 5793 |
+
Fazer download
|
| 5794 |
+
</button>
|
| 5795 |
+
</div>
|
| 5796 |
+
<DataTable table={fit.tabela_coef} maxHeight={460} />
|
| 5797 |
+
</div>
|
| 5798 |
+
) : null}
|
| 5799 |
+
|
| 5800 |
+
{section14Tab === 'obs_calc' ? (
|
| 5801 |
+
<div className="section14-table-panel">
|
| 5802 |
+
<div className="section14-table-head">
|
| 5803 |
+
<h4>Valores Observados x Calculados</h4>
|
| 5804 |
+
<button
|
| 5805 |
+
type="button"
|
| 5806 |
+
className="btn-download-subtle"
|
| 5807 |
+
onClick={() => onDownloadTableCsv(fit.tabela_obs_calc, 'secao14_obs_calc')}
|
| 5808 |
+
disabled={loading || downloadingAssets || !fit.tabela_obs_calc}
|
| 5809 |
+
>
|
| 5810 |
+
Fazer download
|
| 5811 |
+
</button>
|
| 5812 |
+
</div>
|
| 5813 |
+
<DataTable table={fit.tabela_obs_calc} maxHeight={460} />
|
| 5814 |
+
</div>
|
| 5815 |
+
) : null}
|
| 5816 |
</div>
|
| 5817 |
</SectionBlock>
|
| 5818 |
|
frontend/src/components/PlotFigure.jsx
CHANGED
|
@@ -12,6 +12,7 @@ function PlotFigure({
|
|
| 12 |
className = '',
|
| 13 |
lazy = false,
|
| 14 |
showPointIndexToggle = false,
|
|
|
|
| 15 |
}) {
|
| 16 |
const containerRef = useRef(null)
|
| 17 |
const [shouldRenderPlot, setShouldRenderPlot] = useState(() => !lazy)
|
|
@@ -115,22 +116,27 @@ function PlotFigure({
|
|
| 115 |
|
| 116 |
return (
|
| 117 |
<div ref={containerRef} className={cardClassName}>
|
| 118 |
-
{title || subtitle ? (
|
| 119 |
<div className="plot-card-head">
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
</div>
|
| 135 |
) : null}
|
| 136 |
{shouldRenderPlot ? (
|
|
|
|
| 12 |
className = '',
|
| 13 |
lazy = false,
|
| 14 |
showPointIndexToggle = false,
|
| 15 |
+
headerActions = null,
|
| 16 |
}) {
|
| 17 |
const containerRef = useRef(null)
|
| 18 |
const [shouldRenderPlot, setShouldRenderPlot] = useState(() => !lazy)
|
|
|
|
| 116 |
|
| 117 |
return (
|
| 118 |
<div ref={containerRef} className={cardClassName}>
|
| 119 |
+
{title || subtitle || showPointIndexToggle || headerActions ? (
|
| 120 |
<div className="plot-card-head">
|
| 121 |
+
<div className="plot-card-head-main">
|
| 122 |
+
{title ? <h4 className="plot-card-title">{title}</h4> : null}
|
| 123 |
+
{subtitle ? <div className="plot-card-subtitle">{subtitle}</div> : null}
|
| 124 |
+
</div>
|
| 125 |
+
<div className="plot-card-head-actions">
|
| 126 |
+
{showPointIndexToggle ? (
|
| 127 |
+
<label className={`plot-card-toggle${canToggleIndices ? '' : ' is-disabled'}`}>
|
| 128 |
+
<input
|
| 129 |
+
type="checkbox"
|
| 130 |
+
checked={showPointIndices}
|
| 131 |
+
disabled={!canToggleIndices || loadingIndexedFigure}
|
| 132 |
+
onChange={handleToggleChange}
|
| 133 |
+
title={toggleTitle}
|
| 134 |
+
/>
|
| 135 |
+
{loadingIndexedFigure ? 'Carregando índices...' : 'Exibir índices dos pontos'}
|
| 136 |
+
</label>
|
| 137 |
+
) : null}
|
| 138 |
+
{headerActions}
|
| 139 |
+
</div>
|
| 140 |
</div>
|
| 141 |
) : null}
|
| 142 |
{shouldRenderPlot ? (
|
frontend/src/styles.css
CHANGED
|
@@ -1793,6 +1793,32 @@ textarea {
|
|
| 1793 |
inset 0 0 0 1px #dfe9f3;
|
| 1794 |
animation: sectionIn 0.35s ease both;
|
| 1795 |
animation-delay: calc(var(--section-order, 1) * 25ms);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1796 |
}
|
| 1797 |
|
| 1798 |
.section-head {
|
|
@@ -2068,6 +2094,15 @@ textarea {
|
|
| 2068 |
gap: 14px;
|
| 2069 |
}
|
| 2070 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2071 |
.dispersao-config-field {
|
| 2072 |
display: grid;
|
| 2073 |
gap: 6px;
|
|
@@ -3153,8 +3188,7 @@ button.pesquisa-coluna-remove:hover {
|
|
| 3153 |
.plot-card-toggle {
|
| 3154 |
display: inline-flex;
|
| 3155 |
align-items: center;
|
| 3156 |
-
gap:
|
| 3157 |
-
margin-top: 8px;
|
| 3158 |
color: #42586e;
|
| 3159 |
font-size: 0.8rem;
|
| 3160 |
font-weight: 700;
|
|
@@ -5021,6 +5055,152 @@ button.btn-upload-select {
|
|
| 5021 |
font-size: 0.9rem;
|
| 5022 |
}
|
| 5023 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5024 |
.map-frame {
|
| 5025 |
display: block;
|
| 5026 |
width: 100%;
|
|
@@ -5605,6 +5785,14 @@ button.btn-upload-select {
|
|
| 5605 |
gap: 8px 10px;
|
| 5606 |
}
|
| 5607 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5608 |
.checkbox-inline-wrap-tools {
|
| 5609 |
align-items: center;
|
| 5610 |
margin-bottom: 6px;
|
|
@@ -5697,14 +5885,14 @@ button.btn-upload-select {
|
|
| 5697 |
align-items: flex-start;
|
| 5698 |
justify-content: space-between;
|
| 5699 |
gap: 8px;
|
| 5700 |
-
margin-bottom:
|
| 5701 |
}
|
| 5702 |
|
| 5703 |
.transform-suggestion-metrics {
|
| 5704 |
display: flex;
|
| 5705 |
flex-direction: column;
|
| 5706 |
align-items: flex-end;
|
| 5707 |
-
gap:
|
| 5708 |
}
|
| 5709 |
|
| 5710 |
.transform-suggestion-rank {
|
|
@@ -5719,8 +5907,8 @@ button.btn-upload-select {
|
|
| 5719 |
background: #eaf4fe;
|
| 5720 |
color: #1e4d78;
|
| 5721 |
font-family: 'JetBrains Mono', monospace;
|
| 5722 |
-
font-size: 0.
|
| 5723 |
-
padding:
|
| 5724 |
font-weight: 700;
|
| 5725 |
}
|
| 5726 |
|
|
@@ -5730,8 +5918,8 @@ button.btn-upload-select {
|
|
| 5730 |
background: #f4f8fc;
|
| 5731 |
color: #355a78;
|
| 5732 |
font-family: 'JetBrains Mono', monospace;
|
| 5733 |
-
font-size: 0.
|
| 5734 |
-
padding:
|
| 5735 |
font-weight: 700;
|
| 5736 |
}
|
| 5737 |
|
|
@@ -5777,8 +5965,11 @@ button.btn-upload-select {
|
|
| 5777 |
|
| 5778 |
.section11-search-criteria {
|
| 5779 |
margin-top: 8px;
|
| 5780 |
-
padding
|
| 5781 |
-
border
|
|
|
|
|
|
|
|
|
|
| 5782 |
display: grid;
|
| 5783 |
gap: 8px;
|
| 5784 |
}
|
|
@@ -5795,6 +5986,21 @@ button.btn-upload-select {
|
|
| 5795 |
margin-bottom: 0;
|
| 5796 |
}
|
| 5797 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5798 |
.transform-preview-summary {
|
| 5799 |
border: 1px solid #d8e5f2;
|
| 5800 |
border-radius: 12px;
|
|
@@ -5940,6 +6146,7 @@ button.btn-upload-select {
|
|
| 5940 |
.transform-suggestion-col {
|
| 5941 |
color: #2e4358;
|
| 5942 |
font-weight: 700;
|
|
|
|
| 5943 |
min-width: 0;
|
| 5944 |
overflow: hidden;
|
| 5945 |
text-overflow: ellipsis;
|
|
@@ -6001,6 +6208,11 @@ button.btn-upload-select {
|
|
| 6001 |
color: #9d2f2f;
|
| 6002 |
}
|
| 6003 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6004 |
.transform-suggestion-card button {
|
| 6005 |
width: 100%;
|
| 6006 |
justify-content: center;
|
|
@@ -6034,6 +6246,84 @@ button.btn-upload-select {
|
|
| 6034 |
gap: 12px;
|
| 6035 |
}
|
| 6036 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6037 |
.section-disclaimer-warning {
|
| 6038 |
margin: 0 0 10px;
|
| 6039 |
padding: 9px 12px;
|
|
@@ -6106,13 +6396,34 @@ button.btn-upload-select {
|
|
| 6106 |
.plot-card-head {
|
| 6107 |
margin: 4px 4px 8px;
|
| 6108 |
min-height: 42px;
|
| 6109 |
-
display:
|
| 6110 |
-
align-
|
| 6111 |
-
|
|
|
|
| 6112 |
position: relative;
|
| 6113 |
z-index: 2;
|
| 6114 |
}
|
| 6115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6116 |
.plot-card-title {
|
| 6117 |
margin: 0;
|
| 6118 |
color: #2f465c;
|
|
@@ -6245,6 +6556,30 @@ button.btn-upload-select {
|
|
| 6245 |
margin-bottom: 10px;
|
| 6246 |
}
|
| 6247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6248 |
.outlier-actions-row {
|
| 6249 |
display: flex;
|
| 6250 |
flex-wrap: wrap;
|
|
@@ -6481,6 +6816,13 @@ button.btn-upload-select {
|
|
| 6481 |
margin-top: 8px;
|
| 6482 |
}
|
| 6483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6484 |
.outliers-excluidos-details {
|
| 6485 |
margin-top: 10px;
|
| 6486 |
border: 1px solid #dbe6f1;
|
|
@@ -7050,6 +7392,11 @@ button.btn-download-subtle {
|
|
| 7050 |
.micro-msg-grid-codigo {
|
| 7051 |
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 7052 |
gap: 6px 14px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7053 |
}
|
| 7054 |
|
| 7055 |
.micro-msg {
|
|
@@ -7271,6 +7618,18 @@ button.btn-download-subtle {
|
|
| 7271 |
grid-template-columns: 1fr;
|
| 7272 |
}
|
| 7273 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7274 |
.plot-card {
|
| 7275 |
min-height: 340px;
|
| 7276 |
}
|
|
|
|
| 1793 |
inset 0 0 0 1px #dfe9f3;
|
| 1794 |
animation: sectionIn 0.35s ease both;
|
| 1795 |
animation-delay: calc(var(--section-order, 1) * 25ms);
|
| 1796 |
+
transition: border-color 0.18s ease, box-shadow 0.18s ease;
|
| 1797 |
+
}
|
| 1798 |
+
|
| 1799 |
+
.elaboracao-layout[data-current-section-step="1"] .workflow-section[data-section-step="1"],
|
| 1800 |
+
.elaboracao-layout[data-current-section-step="2"] .workflow-section[data-section-step="2"],
|
| 1801 |
+
.elaboracao-layout[data-current-section-step="3"] .workflow-section[data-section-step="3"],
|
| 1802 |
+
.elaboracao-layout[data-current-section-step="4"] .workflow-section[data-section-step="4"],
|
| 1803 |
+
.elaboracao-layout[data-current-section-step="5"] .workflow-section[data-section-step="5"],
|
| 1804 |
+
.elaboracao-layout[data-current-section-step="6"] .workflow-section[data-section-step="6"],
|
| 1805 |
+
.elaboracao-layout[data-current-section-step="7"] .workflow-section[data-section-step="7"],
|
| 1806 |
+
.elaboracao-layout[data-current-section-step="8"] .workflow-section[data-section-step="8"],
|
| 1807 |
+
.elaboracao-layout[data-current-section-step="9"] .workflow-section[data-section-step="9"],
|
| 1808 |
+
.elaboracao-layout[data-current-section-step="10"] .workflow-section[data-section-step="10"],
|
| 1809 |
+
.elaboracao-layout[data-current-section-step="11"] .workflow-section[data-section-step="11"],
|
| 1810 |
+
.elaboracao-layout[data-current-section-step="12"] .workflow-section[data-section-step="12"],
|
| 1811 |
+
.elaboracao-layout[data-current-section-step="13"] .workflow-section[data-section-step="13"],
|
| 1812 |
+
.elaboracao-layout[data-current-section-step="14"] .workflow-section[data-section-step="14"],
|
| 1813 |
+
.elaboracao-layout[data-current-section-step="15"] .workflow-section[data-section-step="15"],
|
| 1814 |
+
.elaboracao-layout[data-current-section-step="16"] .workflow-section[data-section-step="16"],
|
| 1815 |
+
.elaboracao-layout[data-current-section-step="17"] .workflow-section[data-section-step="17"],
|
| 1816 |
+
.elaboracao-layout[data-current-section-step="18"] .workflow-section[data-section-step="18"],
|
| 1817 |
+
.elaboracao-layout[data-current-section-step="19"] .workflow-section[data-section-step="19"] {
|
| 1818 |
+
border-color: #111820;
|
| 1819 |
+
box-shadow:
|
| 1820 |
+
0 8px 22px rgba(20, 28, 36, 0.1),
|
| 1821 |
+
inset 0 0 0 1px #dfe9f3;
|
| 1822 |
}
|
| 1823 |
|
| 1824 |
.section-head {
|
|
|
|
| 2094 |
gap: 14px;
|
| 2095 |
}
|
| 2096 |
|
| 2097 |
+
.dispersao-config-panel {
|
| 2098 |
+
margin: 0 0 14px;
|
| 2099 |
+
padding: 12px;
|
| 2100 |
+
border: 1px solid #d7e2ee;
|
| 2101 |
+
border-left: 4px solid #2f80cf;
|
| 2102 |
+
border-radius: 8px;
|
| 2103 |
+
background: linear-gradient(180deg, #fbfdff 0%, #f5f9fd 100%);
|
| 2104 |
+
}
|
| 2105 |
+
|
| 2106 |
.dispersao-config-field {
|
| 2107 |
display: grid;
|
| 2108 |
gap: 6px;
|
|
|
|
| 3188 |
.plot-card-toggle {
|
| 3189 |
display: inline-flex;
|
| 3190 |
align-items: center;
|
| 3191 |
+
gap: 6px;
|
|
|
|
| 3192 |
color: #42586e;
|
| 3193 |
font-size: 0.8rem;
|
| 3194 |
font-weight: 700;
|
|
|
|
| 5055 |
font-size: 0.9rem;
|
| 5056 |
}
|
| 5057 |
|
| 5058 |
+
.section14-tabs {
|
| 5059 |
+
display: flex;
|
| 5060 |
+
align-items: center;
|
| 5061 |
+
justify-content: center;
|
| 5062 |
+
flex-wrap: wrap;
|
| 5063 |
+
gap: 8px;
|
| 5064 |
+
margin: 0 0 12px;
|
| 5065 |
+
padding: 10px;
|
| 5066 |
+
border: 1px solid #d7e2ee;
|
| 5067 |
+
border-radius: 8px;
|
| 5068 |
+
background: linear-gradient(180deg, #fbfdff 0%, #f5f9fd 100%);
|
| 5069 |
+
}
|
| 5070 |
+
|
| 5071 |
+
.section14-tab-pill {
|
| 5072 |
+
min-height: 34px;
|
| 5073 |
+
padding: 7px 12px;
|
| 5074 |
+
border: 1px solid #c3d2e1;
|
| 5075 |
+
border-radius: 8px;
|
| 5076 |
+
background: linear-gradient(180deg, #f8fbff 0%, #edf4fa 100%);
|
| 5077 |
+
color: #4b6177;
|
| 5078 |
+
font-family: 'Sora', sans-serif;
|
| 5079 |
+
font-size: 0.78rem;
|
| 5080 |
+
font-weight: 800;
|
| 5081 |
+
box-shadow: none;
|
| 5082 |
+
}
|
| 5083 |
+
|
| 5084 |
+
.section14-tab-pill:hover,
|
| 5085 |
+
.section14-tab-pill:focus-visible {
|
| 5086 |
+
transform: translateY(-1px);
|
| 5087 |
+
border-color: #d06f00;
|
| 5088 |
+
color: #6c3900;
|
| 5089 |
+
}
|
| 5090 |
+
|
| 5091 |
+
.section14-tab-pill.is-active {
|
| 5092 |
+
border-color: #bf6500;
|
| 5093 |
+
background: linear-gradient(180deg, #ff9f31 0%, #e67900 100%);
|
| 5094 |
+
color: #ffffff;
|
| 5095 |
+
}
|
| 5096 |
+
|
| 5097 |
+
.section14-panel {
|
| 5098 |
+
border: 1px solid #dbe5ef;
|
| 5099 |
+
border-radius: 8px;
|
| 5100 |
+
background: #ffffff;
|
| 5101 |
+
padding: 12px;
|
| 5102 |
+
}
|
| 5103 |
+
|
| 5104 |
+
.section14-diagnostics-panel .dai-card {
|
| 5105 |
+
margin: 0;
|
| 5106 |
+
border: none;
|
| 5107 |
+
padding: 0;
|
| 5108 |
+
}
|
| 5109 |
+
|
| 5110 |
+
.section14-equations-panel {
|
| 5111 |
+
margin: 0;
|
| 5112 |
+
}
|
| 5113 |
+
|
| 5114 |
+
.section14-diagnostics-panel h4,
|
| 5115 |
+
.section14-test-card h4,
|
| 5116 |
+
.section14-equations-panel h4,
|
| 5117 |
+
.section14-table-head h4 {
|
| 5118 |
+
margin: 0;
|
| 5119 |
+
color: #3b4f64;
|
| 5120 |
+
font-family: 'Sora', sans-serif;
|
| 5121 |
+
font-size: 0.9rem;
|
| 5122 |
+
}
|
| 5123 |
+
|
| 5124 |
+
.section14-diagnostics-panel,
|
| 5125 |
+
.section14-tests-panel,
|
| 5126 |
+
.section14-table-panel {
|
| 5127 |
+
display: grid;
|
| 5128 |
+
gap: 10px;
|
| 5129 |
+
}
|
| 5130 |
+
|
| 5131 |
+
.section14-field-grid {
|
| 5132 |
+
display: grid;
|
| 5133 |
+
border: 1px solid #e1eaf2;
|
| 5134 |
+
border-radius: 8px;
|
| 5135 |
+
overflow: hidden;
|
| 5136 |
+
}
|
| 5137 |
+
|
| 5138 |
+
.section14-tests-grid {
|
| 5139 |
+
display: grid;
|
| 5140 |
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
| 5141 |
+
gap: 12px;
|
| 5142 |
+
}
|
| 5143 |
+
|
| 5144 |
+
.section14-test-card {
|
| 5145 |
+
display: grid;
|
| 5146 |
+
align-content: start;
|
| 5147 |
+
gap: 8px;
|
| 5148 |
+
padding: 10px;
|
| 5149 |
+
border: 1px solid #dbe6f1;
|
| 5150 |
+
border-radius: 8px;
|
| 5151 |
+
background: #fbfdff;
|
| 5152 |
+
}
|
| 5153 |
+
|
| 5154 |
+
.section14-test-card h4 {
|
| 5155 |
+
font-size: 0.82rem;
|
| 5156 |
+
}
|
| 5157 |
+
|
| 5158 |
+
.section14-test-card .section14-field-row {
|
| 5159 |
+
padding: 6px 8px;
|
| 5160 |
+
}
|
| 5161 |
+
|
| 5162 |
+
.section14-test-card .section14-field-label {
|
| 5163 |
+
font-size: 0.78rem;
|
| 5164 |
+
}
|
| 5165 |
+
|
| 5166 |
+
.section14-test-card .section14-field-value {
|
| 5167 |
+
font-size: 0.68rem;
|
| 5168 |
+
line-height: 1.25;
|
| 5169 |
+
}
|
| 5170 |
+
|
| 5171 |
+
.section14-field-row {
|
| 5172 |
+
display: flex;
|
| 5173 |
+
justify-content: space-between;
|
| 5174 |
+
gap: 12px;
|
| 5175 |
+
padding: 8px 10px;
|
| 5176 |
+
border-bottom: 1px solid #edf2f6;
|
| 5177 |
+
background: #ffffff;
|
| 5178 |
+
}
|
| 5179 |
+
|
| 5180 |
+
.section14-field-row:last-child {
|
| 5181 |
+
border-bottom: none;
|
| 5182 |
+
}
|
| 5183 |
+
|
| 5184 |
+
.section14-field-label {
|
| 5185 |
+
color: #586e84;
|
| 5186 |
+
font-weight: 700;
|
| 5187 |
+
}
|
| 5188 |
+
|
| 5189 |
+
.section14-field-value {
|
| 5190 |
+
color: #24384d;
|
| 5191 |
+
font-family: 'JetBrains Mono', monospace;
|
| 5192 |
+
font-size: 0.82rem;
|
| 5193 |
+
text-align: right;
|
| 5194 |
+
}
|
| 5195 |
+
|
| 5196 |
+
.section14-table-head {
|
| 5197 |
+
display: flex;
|
| 5198 |
+
align-items: center;
|
| 5199 |
+
justify-content: space-between;
|
| 5200 |
+
gap: 10px;
|
| 5201 |
+
flex-wrap: wrap;
|
| 5202 |
+
}
|
| 5203 |
+
|
| 5204 |
.map-frame {
|
| 5205 |
display: block;
|
| 5206 |
width: 100%;
|
|
|
|
| 5785 |
gap: 8px 10px;
|
| 5786 |
}
|
| 5787 |
|
| 5788 |
+
.checkbox-inline-wrap-scrollable {
|
| 5789 |
+
max-height: 132px;
|
| 5790 |
+
overflow-y: auto;
|
| 5791 |
+
padding-right: 6px;
|
| 5792 |
+
align-content: flex-start;
|
| 5793 |
+
overscroll-behavior: contain;
|
| 5794 |
+
}
|
| 5795 |
+
|
| 5796 |
.checkbox-inline-wrap-tools {
|
| 5797 |
align-items: center;
|
| 5798 |
margin-bottom: 6px;
|
|
|
|
| 5885 |
align-items: flex-start;
|
| 5886 |
justify-content: space-between;
|
| 5887 |
gap: 8px;
|
| 5888 |
+
margin-bottom: 12px;
|
| 5889 |
}
|
| 5890 |
|
| 5891 |
.transform-suggestion-metrics {
|
| 5892 |
display: flex;
|
| 5893 |
flex-direction: column;
|
| 5894 |
align-items: flex-end;
|
| 5895 |
+
gap: 5px;
|
| 5896 |
}
|
| 5897 |
|
| 5898 |
.transform-suggestion-rank {
|
|
|
|
| 5907 |
background: #eaf4fe;
|
| 5908 |
color: #1e4d78;
|
| 5909 |
font-family: 'JetBrains Mono', monospace;
|
| 5910 |
+
font-size: 0.72rem;
|
| 5911 |
+
padding: 2px 6px;
|
| 5912 |
font-weight: 700;
|
| 5913 |
}
|
| 5914 |
|
|
|
|
| 5918 |
background: #f4f8fc;
|
| 5919 |
color: #355a78;
|
| 5920 |
font-family: 'JetBrains Mono', monospace;
|
| 5921 |
+
font-size: 0.7rem;
|
| 5922 |
+
padding: 2px 6px;
|
| 5923 |
font-weight: 700;
|
| 5924 |
}
|
| 5925 |
|
|
|
|
| 5965 |
|
| 5966 |
.section11-search-criteria {
|
| 5967 |
margin-top: 8px;
|
| 5968 |
+
padding: 12px;
|
| 5969 |
+
border: 1px solid #d7e2ee;
|
| 5970 |
+
border-left: 4px solid #2f80cf;
|
| 5971 |
+
border-radius: 8px;
|
| 5972 |
+
background: linear-gradient(180deg, #fbfdff 0%, #f5f9fd 100%);
|
| 5973 |
display: grid;
|
| 5974 |
gap: 8px;
|
| 5975 |
}
|
|
|
|
| 5986 |
margin-bottom: 0;
|
| 5987 |
}
|
| 5988 |
|
| 5989 |
+
.section11-suggestions-block {
|
| 5990 |
+
margin-top: 18px;
|
| 5991 |
+
padding-top: 16px;
|
| 5992 |
+
border-top: 1px solid #d7e2ee;
|
| 5993 |
+
display: grid;
|
| 5994 |
+
gap: 10px;
|
| 5995 |
+
}
|
| 5996 |
+
|
| 5997 |
+
.section11-suggestions-title {
|
| 5998 |
+
color: #3a4f64;
|
| 5999 |
+
font-family: 'Sora', sans-serif;
|
| 6000 |
+
font-size: 0.9rem;
|
| 6001 |
+
font-weight: 800;
|
| 6002 |
+
}
|
| 6003 |
+
|
| 6004 |
.transform-preview-summary {
|
| 6005 |
border: 1px solid #d8e5f2;
|
| 6006 |
border-radius: 12px;
|
|
|
|
| 6146 |
.transform-suggestion-col {
|
| 6147 |
color: #2e4358;
|
| 6148 |
font-weight: 700;
|
| 6149 |
+
font-size: 0.84rem;
|
| 6150 |
min-width: 0;
|
| 6151 |
overflow: hidden;
|
| 6152 |
text-overflow: ellipsis;
|
|
|
|
| 6208 |
color: #9d2f2f;
|
| 6209 |
}
|
| 6210 |
|
| 6211 |
+
.transform-suggestion-card .grau-badge {
|
| 6212 |
+
font-size: 0.68rem;
|
| 6213 |
+
padding: 2px 6px;
|
| 6214 |
+
}
|
| 6215 |
+
|
| 6216 |
.transform-suggestion-card button {
|
| 6217 |
width: 100%;
|
| 6218 |
justify-content: center;
|
|
|
|
| 6246 |
gap: 12px;
|
| 6247 |
}
|
| 6248 |
|
| 6249 |
+
.scatter-carousel {
|
| 6250 |
+
display: grid;
|
| 6251 |
+
gap: 10px;
|
| 6252 |
+
margin-top: 10px;
|
| 6253 |
+
padding: 12px;
|
| 6254 |
+
border: 1px solid #d7e2ee;
|
| 6255 |
+
border-radius: 8px;
|
| 6256 |
+
background: linear-gradient(180deg, #ffffff 0%, #f7fbff 100%);
|
| 6257 |
+
}
|
| 6258 |
+
|
| 6259 |
+
.scatter-carousel-controls {
|
| 6260 |
+
display: inline-flex;
|
| 6261 |
+
align-items: center;
|
| 6262 |
+
gap: 8px;
|
| 6263 |
+
}
|
| 6264 |
+
|
| 6265 |
+
.scatter-carousel-btn {
|
| 6266 |
+
min-width: 104px;
|
| 6267 |
+
}
|
| 6268 |
+
|
| 6269 |
+
.scatter-carousel-download-all {
|
| 6270 |
+
min-width: 190px;
|
| 6271 |
+
}
|
| 6272 |
+
|
| 6273 |
+
.scatter-carousel-actions {
|
| 6274 |
+
display: flex;
|
| 6275 |
+
justify-content: center;
|
| 6276 |
+
}
|
| 6277 |
+
|
| 6278 |
+
.scatter-carousel-pills {
|
| 6279 |
+
display: flex;
|
| 6280 |
+
align-items: center;
|
| 6281 |
+
justify-content: center;
|
| 6282 |
+
gap: 7px;
|
| 6283 |
+
flex-wrap: wrap;
|
| 6284 |
+
width: 100%;
|
| 6285 |
+
padding: 8px 0 10px;
|
| 6286 |
+
border-top: 1px solid #e4edf5;
|
| 6287 |
+
border-bottom: 1px solid #e4edf5;
|
| 6288 |
+
}
|
| 6289 |
+
|
| 6290 |
+
.scatter-carousel-pill {
|
| 6291 |
+
max-width: min(360px, 100%);
|
| 6292 |
+
min-height: 32px;
|
| 6293 |
+
padding: 6px 11px;
|
| 6294 |
+
border: 1px solid #c3d2e1;
|
| 6295 |
+
border-radius: 8px;
|
| 6296 |
+
background: linear-gradient(180deg, #f8fbff 0%, #edf4fa 100%);
|
| 6297 |
+
color: #5b7188;
|
| 6298 |
+
font-family: 'Sora', sans-serif;
|
| 6299 |
+
font-size: 0.74rem;
|
| 6300 |
+
font-weight: 800;
|
| 6301 |
+
line-height: 1.18;
|
| 6302 |
+
text-align: left;
|
| 6303 |
+
overflow: hidden;
|
| 6304 |
+
text-overflow: ellipsis;
|
| 6305 |
+
box-shadow: 0 3px 8px rgba(23, 37, 50, 0.1);
|
| 6306 |
+
}
|
| 6307 |
+
|
| 6308 |
+
.scatter-carousel-pill:hover,
|
| 6309 |
+
.scatter-carousel-pill:focus-visible {
|
| 6310 |
+
transform: translateY(-1px);
|
| 6311 |
+
border-color: #d06f00;
|
| 6312 |
+
color: #6c3900;
|
| 6313 |
+
}
|
| 6314 |
+
|
| 6315 |
+
.scatter-carousel-pill.is-active {
|
| 6316 |
+
border-color: #bf6500;
|
| 6317 |
+
background: linear-gradient(180deg, #ff9f31 0%, #e67900 100%);
|
| 6318 |
+
color: #ffffff;
|
| 6319 |
+
}
|
| 6320 |
+
|
| 6321 |
+
.scatter-carousel-track {
|
| 6322 |
+
display: grid;
|
| 6323 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 6324 |
+
gap: 12px;
|
| 6325 |
+
}
|
| 6326 |
+
|
| 6327 |
.section-disclaimer-warning {
|
| 6328 |
margin: 0 0 10px;
|
| 6329 |
padding: 9px 12px;
|
|
|
|
| 6396 |
.plot-card-head {
|
| 6397 |
margin: 4px 4px 8px;
|
| 6398 |
min-height: 42px;
|
| 6399 |
+
display: flex;
|
| 6400 |
+
align-items: flex-start;
|
| 6401 |
+
justify-content: space-between;
|
| 6402 |
+
gap: 10px;
|
| 6403 |
position: relative;
|
| 6404 |
z-index: 2;
|
| 6405 |
}
|
| 6406 |
|
| 6407 |
+
.plot-card-head-main {
|
| 6408 |
+
min-width: 0;
|
| 6409 |
+
display: grid;
|
| 6410 |
+
gap: 2px;
|
| 6411 |
+
}
|
| 6412 |
+
|
| 6413 |
+
.plot-card-head-actions {
|
| 6414 |
+
display: inline-flex;
|
| 6415 |
+
align-items: center;
|
| 6416 |
+
justify-content: flex-end;
|
| 6417 |
+
gap: 8px;
|
| 6418 |
+
flex-wrap: wrap;
|
| 6419 |
+
flex-shrink: 0;
|
| 6420 |
+
}
|
| 6421 |
+
|
| 6422 |
+
.plot-card-download-btn {
|
| 6423 |
+
font-size: 0.76rem;
|
| 6424 |
+
padding: 6px 9px;
|
| 6425 |
+
}
|
| 6426 |
+
|
| 6427 |
.plot-card-title {
|
| 6428 |
margin: 0;
|
| 6429 |
color: #2f465c;
|
|
|
|
| 6556 |
margin-bottom: 10px;
|
| 6557 |
}
|
| 6558 |
|
| 6559 |
+
.outliers-previous-card {
|
| 6560 |
+
display: grid;
|
| 6561 |
+
gap: 8px;
|
| 6562 |
+
padding: 10px 16px;
|
| 6563 |
+
border: 1px solid #dbe6f0;
|
| 6564 |
+
border-radius: 8px;
|
| 6565 |
+
background: #f8f9fa;
|
| 6566 |
+
}
|
| 6567 |
+
|
| 6568 |
+
.outliers-previous-count {
|
| 6569 |
+
color: #495057;
|
| 6570 |
+
font-weight: 700;
|
| 6571 |
+
}
|
| 6572 |
+
|
| 6573 |
+
.outliers-previous-indices {
|
| 6574 |
+
max-height: 92px;
|
| 6575 |
+
overflow-y: auto;
|
| 6576 |
+
overflow-wrap: anywhere;
|
| 6577 |
+
padding-right: 10px;
|
| 6578 |
+
color: #6c757d;
|
| 6579 |
+
font-size: 0.86rem;
|
| 6580 |
+
line-height: 1.35;
|
| 6581 |
+
}
|
| 6582 |
+
|
| 6583 |
.outlier-actions-row {
|
| 6584 |
display: flex;
|
| 6585 |
flex-wrap: wrap;
|
|
|
|
| 6816 |
margin-top: 8px;
|
| 6817 |
}
|
| 6818 |
|
| 6819 |
+
.resumo-outliers-box-scrollable {
|
| 6820 |
+
max-height: 92px;
|
| 6821 |
+
overflow-y: auto;
|
| 6822 |
+
overflow-wrap: anywhere;
|
| 6823 |
+
padding-right: 12px;
|
| 6824 |
+
}
|
| 6825 |
+
|
| 6826 |
.outliers-excluidos-details {
|
| 6827 |
margin-top: 10px;
|
| 6828 |
border: 1px solid #dbe6f1;
|
|
|
|
| 7392 |
.micro-msg-grid-codigo {
|
| 7393 |
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 7394 |
gap: 6px 14px;
|
| 7395 |
+
max-height: 144px;
|
| 7396 |
+
overflow-y: auto;
|
| 7397 |
+
padding-right: 6px;
|
| 7398 |
+
align-content: start;
|
| 7399 |
+
overscroll-behavior: contain;
|
| 7400 |
}
|
| 7401 |
|
| 7402 |
.micro-msg {
|
|
|
|
| 7618 |
grid-template-columns: 1fr;
|
| 7619 |
}
|
| 7620 |
|
| 7621 |
+
.scatter-carousel-track {
|
| 7622 |
+
grid-template-columns: 1fr;
|
| 7623 |
+
}
|
| 7624 |
+
|
| 7625 |
+
.scatter-carousel-controls {
|
| 7626 |
+
width: 100%;
|
| 7627 |
+
}
|
| 7628 |
+
|
| 7629 |
+
.scatter-carousel-btn {
|
| 7630 |
+
flex: 1;
|
| 7631 |
+
}
|
| 7632 |
+
|
| 7633 |
.plot-card {
|
| 7634 |
min-height: 340px;
|
| 7635 |
}
|