fix(catalogue): keep filtered investment results separate from educational guides

This commit is contained in:
2026-10-28 21:04:10 +02:00
parent 6520d303f7
commit 54d1b2a543
7 changed files with 113 additions and 8 deletions
@@ -1769,3 +1769,14 @@ Relatório: `catalogue-province-coverage-qa-20261028.json`. Instalação pelo pr
Pedido expresso da Tempo: o dropdown deve abrir em «Pesquisar província», sem um segundo controlo «Seleccione». `ProvinceSelect` e `TerritoryLevel` passam a usar o mesmo combobox, aplicado a província, distrito, posto administrativo e localidade. Pesquisar e escolher fica num único campo; a paginação permanece na lista. Escrever ou sair com Escape não substitui a selecção guardada; escolher e limpar são acções expressas. Mantêm-se a hierarquia, os endpoints existentes e os controlos de acesso, sem novos dados ou publicações.
Quatro testes do contrato de eventos/estado passaram: abertura/escolha, preservação ao escrever/Escape, teclado e bloqueio de resultado antigo durante carregamento, limpeza e dependência do nível anterior. Tipos e compilação QA passaram. As 6 provas nacionais/617 verificações são reutilizadas porque o PHP territorial não mudou. Este delta continua em QA e não comprova apresentação ou sessão real no navegador. Será agrupado com a correcção provincial; falta autenticação SSH antes da entrega, sem nova aprovação organizacional.
28/10 - Before catalogue presentation checks: accepted province QA6/617 and unified selector QA4 remain preserved and uninstalled. Tempo reports Tourism/Cabo Delgado shows educational text and broad sector links. Read-only public API confirmed zero filtered records;unfiltered tourism returns16 records,all declared in Inhambane. This does not establish absence of tourism supply in Cabo Delgado. Correct presentation to retain filters and expose guides only as optional links;do not republish or reassign opportunities to manufacture results.
## 28/10/2026 — resultados do catálogo separados do apoio educativo, QA
A Tempo esclareceu que a combinação província/sector deve apresentar as oportunidades correspondentes, sem texto educativo ou atalhos que troquem a consulta por todas as oportunidades do sector. A consulta pública anónima conferiu Turismo/Cabo Delgado = zero oportunidades cadastradas; Turismo sem localização = 16, todas declaradas em Inhambane. Este snapshot não prova ausência de oferta turística em Cabo Delgado e não substitui inventário de fontes ou consulta autenticada.
Correcção de apresentação em QA: título dos resultados explicita sector e hierarquia escolhidos; removidos os cartões educativos e o botão sectorial sem localização da área de resultados. Os guias mantêm-se como títulos ligados em apoio opcional fechado por defeito. A remoção da localização é uma acção expressamente identificada como pesquisa noutras províncias. O estado vazio refere o cadastro consultado e a cobertura incompleta, sem fabricar oportunidades nem alargar automaticamente filtros.
Dois testes SSR do novo apoio opcional passaram, bem como tipos e compilação. As provas territoriais nacionais 6/617 e os quatro testes do selector são reutilizados; não mudou a consulta PHP ou o controlo territorial neste delta. Mantêm-se histórico, publicações, permissões, fontes e base interna. Este candidato continua sem instalação, dependente de autenticação SSH; a sessão real permanece sem prova visual. Relatório existente: `catalogue-province-coverage-qa-20261028.json`, campo `catalogue_result_presentation`. Requisitos V2-07/V2-10 actualizados na mesma matriz; L8 permanece parcial.
@@ -86,5 +86,46 @@
"publication_data_permissions_and_territory_rules": "unchanged",
"national_province_evidence": "6 tests/617 assertions reused;unchanged PHP runtime",
"status": "QA_not_installed"
},
"catalogue_result_presentation": {
"Tempo_request": "Province+sector must show matching opportunities,not educational text and unfiltered national sector shortcuts",
"public_read_snapshot": {
"filtered": {
"total": 0,
"province": "Cabo Delgado",
"sector": "turismo",
"province_id": "059b02ca-7095-577a-8705-4d4c46896747"
},
"active_writes": 0,
"sector_only": {
"total": 16,
"declared_provinces": [
"Inhambane"
],
"sector": "turismo"
},
"method": "anonymous public API read; no authenticated session claimed",
"meaning": "public catalogue snapshot;not evidence of absence of market supply",
"checked_at": "2026-10-28T19:03:36.8285860Z",
"target": "https://teste-investidor.tempo.co.mz/"
},
"UI_changes": [
"Heading identifies applied sector and territorial path",
"Educational cards and their broad sector opportunity button removed from catalogue results",
"Guide titles remain available only inside closed optional support details",
"Removing location is explicitly labelled as searching other provinces",
"Empty state is limited to published records in the consulted catalogue;not absence of market supply"
],
"QA": {
"new_component_SSR_tests": 2,
"failures": 0,
"types": "passed",
"build": "passed",
"accepted_national_and_selector_proofs": "reused;backend and selector unchanged"
},
"status": "QA_not_installed",
"authenticated_visual_validation": "pending;public API read does not prove real session behaviour",
"active_writes": 0,
"new_publications": 0
}
}
@@ -7327,3 +7327,14 @@ Relatório: `catalogue-province-coverage-qa-20261028.json`. Instalação pelo pr
Pedido expresso da Tempo: o dropdown deve abrir em «Pesquisar província», sem um segundo controlo «Seleccione». `ProvinceSelect` e `TerritoryLevel` passam a usar o mesmo combobox, aplicado a província, distrito, posto administrativo e localidade. Pesquisar e escolher fica num único campo; a paginação permanece na lista. Escrever ou sair com Escape não substitui a selecção guardada; escolher e limpar são acções expressas. Mantêm-se a hierarquia, os endpoints existentes e os controlos de acesso, sem novos dados ou publicações.
Quatro testes do contrato de eventos/estado passaram: abertura/escolha, preservação ao escrever/Escape, teclado e bloqueio de resultado antigo durante carregamento, limpeza e dependência do nível anterior. Tipos e compilação QA passaram. As 6 provas nacionais/617 verificações são reutilizadas porque o PHP territorial não mudou. Este delta continua em QA e não comprova apresentação ou sessão real no navegador. Será agrupado com a correcção provincial; falta autenticação SSH antes da entrega, sem nova aprovação organizacional.
28/10 - Before catalogue presentation checks: accepted province QA6/617 and unified selector QA4 remain preserved and uninstalled. Tempo reports Tourism/Cabo Delgado shows educational text and broad sector links. Read-only public API confirmed zero filtered records;unfiltered tourism returns16 records,all declared in Inhambane. This does not establish absence of tourism supply in Cabo Delgado. Correct presentation to retain filters and expose guides only as optional links;do not republish or reassign opportunities to manufacture results.
## 28/10/2026 — resultados do catálogo separados do apoio educativo, QA
A Tempo esclareceu que a combinação província/sector deve apresentar as oportunidades correspondentes, sem texto educativo ou atalhos que troquem a consulta por todas as oportunidades do sector. A consulta pública anónima conferiu Turismo/Cabo Delgado = zero oportunidades cadastradas; Turismo sem localização = 16, todas declaradas em Inhambane. Este snapshot não prova ausência de oferta turística em Cabo Delgado e não substitui inventário de fontes ou consulta autenticada.
Correcção de apresentação em QA: título dos resultados explicita sector e hierarquia escolhidos; removidos os cartões educativos e o botão sectorial sem localização da área de resultados. Os guias mantêm-se como títulos ligados em apoio opcional fechado por defeito. A remoção da localização é uma acção expressamente identificada como pesquisa noutras províncias. O estado vazio refere o cadastro consultado e a cobertura incompleta, sem fabricar oportunidades nem alargar automaticamente filtros.
Dois testes SSR do novo apoio opcional passaram, bem como tipos e compilação. As provas territoriais nacionais 6/617 e os quatro testes do selector são reutilizados; não mudou a consulta PHP ou o controlo territorial neste delta. Mantêm-se histórico, publicações, permissões, fontes e base interna. Este candidato continua sem instalação, dependente de autenticação SSH; a sessão real permanece sem prova visual. Relatório existente: `catalogue-province-coverage-qa-20261028.json`, campo `catalogue_result_presentation`. Requisitos V2-07/V2-10 actualizados na mesma matriz; L8 permanece parcial.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
import { Link } from '@inertiajs/react';
import type { EducationalArticle } from './educational-article-card';
/** Guides remain available on request; they are not matching investment results. */
export default function CatalogueGuideLinks({ articles }: { articles: EducationalArticle[] }) {
if (!articles.length) return null;
return <details className="rounded border p-3">
<summary className="cursor-pointer font-medium">Guias do sector — apoio opcional</summary>
<ul className="mt-3 space-y-2">
{articles.map((article) => <li key={article.href}>
<Link className="underline" href={article.href}>Ler guia: {article.title}</Link>
</li>)}
</ul>
</details>;
}
+11 -6
View File
@@ -1,4 +1,4 @@
import EducationalGuides from '@/components/educational-guides';
import CatalogueGuideLinks from '@/components/catalogue-guide-links';
import OpportunityCorridorGroups, { type CorridorGroup } from '@/components/opportunity-corridor-groups';
import { searchTerritoryHref } from '@/lib/search-territory';
import type { EducationalArticle } from '@/components/educational-article-card';
@@ -381,6 +381,11 @@ export default function Catalogue({
);
}}
/>
<h2 className="text-xl font-semibold">
Oportunidades publicadas
{filters.sector && ` · ${references.sectors.find((sector) => sector.slug === filters.sector)?.name ?? filters.sector}`}
{territorySelection.length > 0 && ` · ${territorySelection.map((territory) => territory.name).join(' / ')}`}
</h2>
<SearchState
loading={searchLoading}
error={searchError}
@@ -423,7 +428,7 @@ export default function Catalogue({
}));
}}
>
Alargar pesquisa (remover localização)
Pesquisar noutras províncias (remover localização)
</button>
)}
{['grid', 'list', 'map', 'combined', 'corridors'].map((value, i) => (
@@ -646,10 +651,10 @@ export default function Catalogue({
))}
</div>
)}
{!results.total && (
{!searchLoading && !searchError && !results.total && (
<p className={card}>
Sem oportunidades com estes filtros. Explore as fichas
territoriais ou{' '}
Não há oportunidades publicadas com estes filtros no cadastro consultado.
A informação disponível pode ser incompleta. Pode{' '}
<Link href="/apoio" className="underline">
peça apoio
</Link>
@@ -757,7 +762,7 @@ export default function Catalogue({
</div>
</section>
)}
<EducationalGuides articles={guides} />
<CatalogueGuideLinks articles={guides} />
</Frame>
);
}
@@ -0,0 +1,22 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {createRequire} from 'node:module';
import React from 'react';
import {renderToStaticMarkup} from 'react-dom/server';
import ts from 'typescript';
const require=createRequire(import.meta.url);
const source=fs.readFileSync(new URL('../../resources/js/components/catalogue-guide-links.tsx',import.meta.url),'utf8');
const compiled=ts.transpileModule(source,{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2022,jsx:ts.JsxEmit.ReactJSX}}).outputText;
const module={exports:{}};
new Function('require','module','exports',compiled)(name=>name==='@inertiajs/react'?{Link:({href,children,...props})=>React.createElement('a',{href,...props},children)}:require(name),module,module.exports);
const render=articles=>renderToStaticMarkup(React.createElement(module.exports.default,{articles}));
test('catalogue guides are closed optional links, not educational bodies or nationwide opportunity shortcuts',()=>{
const html=render([{title:'Turismo',href:'/artigos/turismo',summary:'EDUCATIONAL-BODY-NOT-A-RESULT',image:{href:'/photo.jpg',alt:'ILLUSTRATION'},opportunities_href:'/oportunidades?sector=turismo',opportunities_label:'ALL-NATIONAL-OPPORTUNITIES',has_opportunities:true}]);
assert.match(html,/<details\b/);assert.doesNotMatch(html,/<details[^>]*\bopen\b/);
assert.match(html,/apoio opcional/);assert.match(html,/href="\/artigos\/turismo"/);
for(const forbidden of ['EDUCATIONAL-BODY-NOT-A-RESULT','ALL-NATIONAL-OPPORTUNITIES','/oportunidades?sector=turismo','photo.jpg','<img'])assert.ok(!html.includes(forbidden),forbidden);
});
test('no educational substitute is rendered when no guides are available',()=>{
assert.equal(render([]),'');
});