fix: open individual sectors from catalogue cards without repeated detail
tests / ci (push) Canceled after 0s
tests / ci (push) Canceled after 0s
This commit is contained in:
@@ -71,7 +71,6 @@ class PortalServicesController extends Controller
|
||||
$props = ['section' => $page, 'filters' => $filters, 'countries' => app(CountryCatalogue::class)->all()];
|
||||
if ($page === 'sectors') {
|
||||
$props['sectors'] = \App\Services\SectorOrganization::catalog();
|
||||
$props['sectorDetails'] = $props['sectors']->map(fn (Sector $sector) => app(\App\Services\SectorInvestment::class)->page($sector))->values();
|
||||
}
|
||||
if (in_array($page, ['documents', 'legislation'], true)) {
|
||||
$query = $this->resources();
|
||||
|
||||
@@ -1403,3 +1403,16 @@ O relatório comum tinha um conflito de imports. Foram conservados ambos e as ch
|
||||
Retomar na sessão local com SSH autenticado, usando a autorização já registada: medir espaço/inodes na partição efectiva, comparar com compilação e backup, conferir main e revisão activa, criar e ensaiar backup fresco, instalar L8 e conferir apenas o seu delta. Depois repetir as guardas necessárias para a candidata conjunta e conferir o delta proactivo preservando L8. Manter a versão activa até a nova estar pronta. Excluir fixtures QA dos inputs de instalação; não executar seeders/importações de amostras, não publicar pilotos privados nem usar o pacote QA como cópia da base activa. SGF TEMPO separado.
|
||||
|
||||
Recibo de preparação: `docs/investmoz/unification/sequential-delivery-preparation-20261027.json`. Provas e instrução de passagem: `outputs/sequential-delivery-20261027/`. Os recibos de execução e as duas revisões servidas serão registados apenas depois de execução real na sessão autenticada; este recibo não os substitui.
|
||||
|
||||
|
||||
## 27/10/2026 — correcção delimitada da navegação dos sectores
|
||||
|
||||
Reprodução local autorizada da intenção de `88b39b527859bd420f2e223a7afea89bea38de54`, indisponível no origin/outro ambiente. Base exacta `9fda6d6e12832a3cf25e7314f1f895dd430238c5`; novo ramo `codex/sector-navigation-fix-local-20261027`. Não se afirma identidade binária com o pacote externo. QA concluída; instalação ainda pendente nesta revisão documental.
|
||||
|
||||
**Causa e alteração:** o índice `/sectores` carregava `sectorDetails` para todos os sectores e apresentava as páginas completas abaixo dos cartões; os cartões passavam a âncoras locais. Removidos esse carregamento e a apresentação agregada. Os cartões usam `sector.url`, preservando as páginas individuais, a especialização Fintech e os caminhos históricos existentes. O índice mantém descrições curtas, contagens e acesso aos sectores, sem repetir guias e oportunidades de todos eles.
|
||||
|
||||
**Preservação:** página individual, `SectorContent`, `SectorEntry`, `SectorInvestment`, `SectorOrganization`, filtros, dados mestres, originais e continuidade para o mesmo dossier não foram alterados. PEC `7fdb6b42` continua no seu ramo QA; não é integrado nesta correcção. L8 instalado e percurso proactivo de `9fda6d6e` preservados. Songo/Gurué privados; sem fixtures QA no activo, publicação, importações, migrations ou alterações de permissões.
|
||||
|
||||
**Delta demonstrado:** actualizados os dois testes afectados de `SectorCatalogueContentTest` e acrescentado um caso de isolamento/regresso/recarregamento:3 testes/319 asserções, base isolada `proactive_investment_20261027_test`, loopback55441, transacções com rollback; sem `migrate:fresh`. Wayfinder `--with-form`, TypeScript e build QA aprovados. Navegador real:10 cartões, acesso separado a Agronegócio e Turismo, oportunidades próprias, filtro Agronegócio mantido no catálogo, recarregamento da página individual e regresso ao índice sem repetição. Entrada Turismo para o dossier conserva o contexto sectorial na ligação e encaminha o visitante para a autenticação existente; não se repetiu a prova completa de gravação do dossier já aceite. A amostra QA não tem guias editoriais carregados; a preservação dos guias assenta na comparação dos consumidores/fontes, e será conferida no destino sem republicar conteúdo. A captura de imagem do browser devolveu «0 width»; árvore de acessibilidade e testes guardados, sem alegação de captura visual inexistente.
|
||||
|
||||
Requisitos existentes actualizados apenas neste delta: `MASTER-471012ab-0007` e `MASTER-9dee08d0-0017`; não se encerra automaticamente o âmbito mais amplo dessas linhas. Recibo QA: `docs/investmoz/unification/sector-navigation-qa-20261027.json`. Provas locais: `outputs/sector-navigation-fix-20261027/`. Entrega autorizada seguirá o processo Git existente, com capacidade, backup/restauro fresco, comparação de fonte/dados/schema/configuração/permissões e revisão efectivamente servida.
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"date": "2026-10-27",
|
||||
"status": "QA passed; not yet installed",
|
||||
"source_intention": "88b39b527859bd420f2e223a7afea89bea38de54",
|
||||
"reproduced_locally": true,
|
||||
"byte_equivalence_to_external_commit": false,
|
||||
"baseline": "9fda6d6e12832a3cf25e7314f1f895dd430238c5",
|
||||
"branch": "codex/sector-navigation-fix-local-20261027",
|
||||
"runtime_delta": [
|
||||
"app/Http/Controllers/PortalServicesController.php",
|
||||
"resources/js/pages/portal/services.tsx"
|
||||
],
|
||||
"tests": {
|
||||
"feature_tests": 3,
|
||||
"assertions": 319,
|
||||
"database": "proactive_investment_20261027_test",
|
||||
"port": 55441,
|
||||
"rollback": true,
|
||||
"routes": "passed",
|
||||
"typescript": "passed",
|
||||
"build": "passed"
|
||||
},
|
||||
"browser": {
|
||||
"index_cards": 10,
|
||||
"separate_sectors": [
|
||||
"agronegocio",
|
||||
"turismo"
|
||||
],
|
||||
"opportunities_isolated": true,
|
||||
"filter": "agronegocio",
|
||||
"back": true,
|
||||
"reload": true,
|
||||
"fintech_url_preserved": true,
|
||||
"dossier_entry": "sector:3; existing guest authentication, no new dossier created",
|
||||
"screenshots": "capture unavailable: zero width; AX proof retained",
|
||||
"editorial_guides": "not loaded in QA sample; consumers unchanged, destination to check"
|
||||
},
|
||||
"protected_files": [
|
||||
{
|
||||
"file": "resources/js/components/sector-content.tsx",
|
||||
"sha256_LF": "4ee55554f8a88ba7db1ac0dc74259d4e66603979c3873f9ec897437830b8e0ae",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "resources/js/components/sector-entry.tsx",
|
||||
"sha256_LF": "96672c709b70f840d105c664a92d49a17acb66cd852d43dadaa8f3fef8b3e845",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "resources/js/components/public-sector-cards.tsx",
|
||||
"sha256_LF": "858ba6235ef8b46461d416b3264436e4df2c9555b8e6d8c3644dbd8c55463484",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "app/Services/SectorInvestment.php",
|
||||
"sha256_LF": "0b8fbc6e3d03ede627e95332703e4749a53d86708bdc0f9579e958caf30e4d17",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "app/Services/SectorOrganization.php",
|
||||
"sha256_LF": "f0e54fe6acfe746c6758387f43610232cb51371b0404bcefaf466d8b704f3ae3",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "app/Http/Controllers/PublicPortalController.php",
|
||||
"sha256_LF": "cb6abd75533660a52e18148cc5f1ab706d2e08f9c94334510541e6b0e003b461",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "resources/js/lib/project-dossier.ts",
|
||||
"sha256_LF": "d59f3fa4dcb3fade1f967564c972e30932aa095a4e5dd4ba0be8b4e07492ef0a",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "resources/js/lib/irpc-annual-settlement.ts",
|
||||
"sha256_LF": "8cca5316259e3ebabfa75be9f64143a8664a447ac30b23b882318edfd70a68f1",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"file": "routes/web.php",
|
||||
"sha256_LF": "95930c76977d446b74a422acc4b60869ff6bae5d4567c21cc644484c5f09cbda",
|
||||
"unchanged": true
|
||||
}
|
||||
],
|
||||
"pec_branch_not_integrated": "7fdb6b42",
|
||||
"active_writes": 0,
|
||||
"private_pilots_published": false
|
||||
}
|
||||
@@ -6924,3 +6924,16 @@ O relatório comum tinha um conflito de imports. Foram conservados ambos e as ch
|
||||
Retomar na sessão local com SSH autenticado, usando a autorização já registada: medir espaço/inodes na partição efectiva, comparar com compilação e backup, conferir main e revisão activa, criar e ensaiar backup fresco, instalar L8 e conferir apenas o seu delta. Depois repetir as guardas necessárias para a candidata conjunta e conferir o delta proactivo preservando L8. Manter a versão activa até a nova estar pronta. Excluir fixtures QA dos inputs de instalação; não executar seeders/importações de amostras, não publicar pilotos privados nem usar o pacote QA como cópia da base activa. SGF TEMPO separado.
|
||||
|
||||
Recibo de preparação: `docs/investmoz/unification/sequential-delivery-preparation-20261027.json`. Provas e instrução de passagem: `outputs/sequential-delivery-20261027/`. Os recibos de execução e as duas revisões servidas serão registados apenas depois de execução real na sessão autenticada; este recibo não os substitui.
|
||||
|
||||
|
||||
## 27/10/2026 — correcção delimitada da navegação dos sectores
|
||||
|
||||
Reprodução local autorizada da intenção de `88b39b527859bd420f2e223a7afea89bea38de54`, indisponível no origin/outro ambiente. Base exacta `9fda6d6e12832a3cf25e7314f1f895dd430238c5`; novo ramo `codex/sector-navigation-fix-local-20261027`. Não se afirma identidade binária com o pacote externo. QA concluída; instalação ainda pendente nesta revisão documental.
|
||||
|
||||
**Causa e alteração:** o índice `/sectores` carregava `sectorDetails` para todos os sectores e apresentava as páginas completas abaixo dos cartões; os cartões passavam a âncoras locais. Removidos esse carregamento e a apresentação agregada. Os cartões usam `sector.url`, preservando as páginas individuais, a especialização Fintech e os caminhos históricos existentes. O índice mantém descrições curtas, contagens e acesso aos sectores, sem repetir guias e oportunidades de todos eles.
|
||||
|
||||
**Preservação:** página individual, `SectorContent`, `SectorEntry`, `SectorInvestment`, `SectorOrganization`, filtros, dados mestres, originais e continuidade para o mesmo dossier não foram alterados. PEC `7fdb6b42` continua no seu ramo QA; não é integrado nesta correcção. L8 instalado e percurso proactivo de `9fda6d6e` preservados. Songo/Gurué privados; sem fixtures QA no activo, publicação, importações, migrations ou alterações de permissões.
|
||||
|
||||
**Delta demonstrado:** actualizados os dois testes afectados de `SectorCatalogueContentTest` e acrescentado um caso de isolamento/regresso/recarregamento:3 testes/319 asserções, base isolada `proactive_investment_20261027_test`, loopback55441, transacções com rollback; sem `migrate:fresh`. Wayfinder `--with-form`, TypeScript e build QA aprovados. Navegador real:10 cartões, acesso separado a Agronegócio e Turismo, oportunidades próprias, filtro Agronegócio mantido no catálogo, recarregamento da página individual e regresso ao índice sem repetição. Entrada Turismo para o dossier conserva o contexto sectorial na ligação e encaminha o visitante para a autenticação existente; não se repetiu a prova completa de gravação do dossier já aceite. A amostra QA não tem guias editoriais carregados; a preservação dos guias assenta na comparação dos consumidores/fontes, e será conferida no destino sem republicar conteúdo. A captura de imagem do browser devolveu «0 width»; árvore de acessibilidade e testes guardados, sem alegação de captura visual inexistente.
|
||||
|
||||
Requisitos existentes actualizados apenas neste delta: `MASTER-471012ab-0007` e `MASTER-9dee08d0-0017`; não se encerra automaticamente o âmbito mais amplo dessas linhas. Recibo QA: `docs/investmoz/unification/sector-navigation-qa-20261027.json`. Provas locais: `outputs/sector-navigation-fix-20261027/`. Entrega autorizada seguirá o processo Git existente, com capacidade, backup/restauro fresco, comparação de fonte/dados/schema/configuração/permissões e revisão efectivamente servida.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -71,7 +71,6 @@ type Page<T> = {
|
||||
};
|
||||
type Props = {
|
||||
sectorEntry?: SectorDetailData['sectorEntry'];
|
||||
sectorDetails?: SectorDetailData[];
|
||||
countries?: Country[];
|
||||
section: string;
|
||||
filters?: Record<string, string | string[]>;
|
||||
@@ -518,41 +517,9 @@ export default function Services(p: Props) {
|
||||
description: sector.short_description,
|
||||
opportunitiesCount: sector.opportunities_count,
|
||||
specializations: sector.specializations,
|
||||
url: p.sectorDetails?.length
|
||||
? `#sector-${sector.slug}`
|
||||
: sector.url,
|
||||
url: sector.url,
|
||||
}))}
|
||||
/>
|
||||
{p.sectorDetails?.map((detail) => (
|
||||
<section
|
||||
id={`sector-${detail.sector.slug}`}
|
||||
key={detail.sector.id}
|
||||
aria-labelledby={`sector-heading-${detail.sector.slug}`}
|
||||
className="scroll-mt-24 space-y-5 border-t border-slate-200 pt-6"
|
||||
>
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<h2
|
||||
id={`sector-heading-${detail.sector.slug}`}
|
||||
className="text-2xl font-bold"
|
||||
>
|
||||
{detail.sector.name}
|
||||
</h2>
|
||||
<Link
|
||||
href={`/sectores/${detail.sector.slug}`}
|
||||
className="inline-flex min-h-11 items-center text-sm font-semibold underline"
|
||||
>
|
||||
Abrir página do sector
|
||||
</Link>
|
||||
</div>
|
||||
<SectorContent {...detail} headingLevel={3} />
|
||||
<a
|
||||
href="#sectores-indice"
|
||||
className="inline-flex min-h-11 items-center text-sm font-semibold underline"
|
||||
>
|
||||
Voltar à lista de sectores
|
||||
</a>
|
||||
</section>
|
||||
))}
|
||||
{!p.sectors?.length && (
|
||||
<p>Não existem sectores publicados.</p>
|
||||
)}
|
||||
|
||||
@@ -47,17 +47,22 @@ class SectorCatalogueContentTest extends TestCase
|
||||
$before = [DB::table('desk_cases')->count(), DB::table('opportunities')->count(), DB::table('portal_resources')->count()];
|
||||
|
||||
$props = $this->get('/sectores')->assertOk()->inertiaProps();
|
||||
$this->assertSame(array_column($props['sectors'], 'id'), array_column(array_column($props['sectorDetails'], 'sector'), 'id'));
|
||||
foreach ($props['sectorDetails'] as $detail) {
|
||||
$single = $this->get('/sectores/'.$detail['sector']['slug'])->assertOk()->inertiaProps();
|
||||
$this->assertSame($single['sector'], $detail['sector']);
|
||||
$this->assertSame($single['sectorEntry'], $detail['sectorEntry']);
|
||||
$this->assertSame($single['opportunities'], $detail['opportunities']);
|
||||
$this->assertIsArray($detail['sectorEntry']['articles']);
|
||||
$this->assertIsArray($detail['sectorEntry']['relations']);
|
||||
$this->assertIsArray($detail['sectorEntry']['locations']);
|
||||
$this->assertArrayNotHasKey('sectorDetails', $props);
|
||||
$ids = array_column($props['sectors'], 'id');
|
||||
$this->assertSame($ids, array_values(array_unique($ids)));
|
||||
foreach ($props['sectors'] as $card) {
|
||||
$this->assertSame(\App\Services\SectorOrganization::href($card['slug']), $card['url']);
|
||||
$this->assertStringNotContainsString('#', $card['url']);
|
||||
$single = $this->get($card['url'])->assertOk()->inertiaProps();
|
||||
$this->assertSame('sector', $single['section']);
|
||||
$this->assertSame($card['id'], $single['sector']['id']);
|
||||
$this->assertArrayNotHasKey('sectorDetails', $single);
|
||||
$this->assertArrayNotHasKey('sectors', $single);
|
||||
$this->assertIsArray($single['sectorEntry']['articles']);
|
||||
$this->assertIsArray($single['sectorEntry']['relations']);
|
||||
$this->assertIsArray($single['sectorEntry']['locations']);
|
||||
}
|
||||
$entry = collect($props['sectorDetails'])->firstWhere('sector.id', $withoutGuide->id)['sectorEntry'];
|
||||
$entry = $this->get('/sectores/'.$withoutGuide->slug)->assertOk()->inertiaProps()['sectorEntry'];
|
||||
$this->assertSame([], $entry['articles']);
|
||||
$this->assertSame('/minhas-oportunidades/create?sector_id='.$withoutGuide->id, $entry['register_href']);
|
||||
$this->assertNotNull($entry['start_href']);
|
||||
@@ -80,10 +85,11 @@ class SectorCatalogueContentTest extends TestCase
|
||||
}
|
||||
config(['investor-path.enabled' => false, 'portal.profile_access_enabled' => false]);
|
||||
$props = $this->get('/sectores')->assertOk()->inertiaProps();
|
||||
$ids = array_column(array_column($props['sectorDetails'], 'sector'), 'id');
|
||||
$this->assertArrayNotHasKey('sectorDetails', $props);
|
||||
$ids = array_column($props['sectors'], 'id');
|
||||
$this->assertNotContains($unpublished->id, $ids);
|
||||
$this->assertNotContains($inactive->id, $ids);
|
||||
$detail = collect($props['sectorDetails'])->firstWhere('sector.id', $public->id);
|
||||
$detail = $this->get('/sectores/'.$public->slug)->assertOk()->inertiaProps();
|
||||
$this->assertSame([$slugs['published']], array_column($detail['opportunities'], 'slug'));
|
||||
$this->assertNull($detail['sectorEntry']['start_href']);
|
||||
$this->assertNull($detail['sectorEntry']['register_href']);
|
||||
@@ -92,4 +98,29 @@ class SectorCatalogueContentTest extends TestCase
|
||||
$this->get('/sectores/'.$unpublished->slug)->assertNotFound();
|
||||
$this->get('/sectores/'.$inactive->slug)->assertNotFound();
|
||||
}
|
||||
public function test_selecting_a_sector_keeps_opportunities_scoped_on_reload_and_return(): void
|
||||
{
|
||||
$a = $this->sector();$b = $this->sector();
|
||||
foreach ([$a, $b] as $sector) {
|
||||
$slug = 'qa-isolated-'.Str::lower(Str::random(12));
|
||||
Opportunity::create(['sector_id'=>$sector->id, 'reference'=>$slug, 'title'=>$slug, 'slug'=>$slug,
|
||||
'summary'=>'Synthetic scoped opportunity', 'status'=>'published', 'published_at'=>now()->subDay()]);
|
||||
}
|
||||
$index = $this->get('/sectores')->assertOk()->inertiaProps();
|
||||
foreach ([$a, $b, $a] as $sector) {
|
||||
$url = collect($index['sectors'])->firstWhere('id', $sector->id)['url'];
|
||||
$first = $this->get($url)->assertOk()->inertiaProps();
|
||||
$reload = $this->get($url)->assertOk()->inertiaProps();
|
||||
$this->assertSame($first['sector'], $reload['sector']);
|
||||
$this->assertSame($first['opportunities'], $reload['opportunities']);
|
||||
$this->assertSame($sector->id, $first['sector']['id']);
|
||||
$this->assertSame(Opportunity::where('sector_id',$sector->id)->pluck('slug')->all(), array_column($first['opportunities'],'slug'));
|
||||
$this->assertSame('/investimentos/a-partir-do-setor/'.$sector->slug, $first['sectorEntry']['start_href']);
|
||||
$this->get($first['sectorEntry']['start_href'])->assertRedirect('/login');
|
||||
$returned = $this->get('/sectores')->assertOk()->inertiaProps();
|
||||
$this->assertSame($index['sectors'], $returned['sectors']);
|
||||
$this->assertArrayNotHasKey('sectorDetails', $returned);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user