Added a link from each opportunity to its latest Find a Tender notice

Opportunities from Find a Tender have a link icon before their title.
Clicking it fetches the opportunity with its releases (the list leaves
them out) and opens its newest release's notice,
www.find-tender.service.gov.uk/notice/<release_id>, in a new tab. The
tab is opened on the click and pointed at the notice when the request
returns, so it isn't blocked as a popup; if the request fails, or there
are no releases, it's closed and a toast says why. Opportunities from
other sources have no link for now, but keep its space so the titles
line up.

The icon is lucide-solid's, added for it at 1.52.0.
This commit is contained in:
bwilliams committed 2026-10-19 09:38:14 +01:00
1 parent a6630f112f
commit e98f18b790
8 files changed
+186 -10

No files matched your search

+25 -1
View File
@@ -1,4 +1,4 @@
import type { Opportunity } from '@/types/Opportunities';
import type { Opportunity, OpportunityRelease } from '@/types/Opportunities';
/**
* The opportunities with changed merged in: each replaces the opportunity
@@ -12,3 +12,27 @@ export function mergeOpportunities(
for (const opportunity of changed) byUuid.set(opportunity.uuid, opportunity);
return [...byUuid.values()];
}
/** The source the backend gives opportunities fetched from Find a Tender. */
const FIND_A_TENDER_SOURCE = 'FindATender';
/** Whether the opportunity was fetched from Find a Tender, so its releases are notices there. */
export function isFromFindATender(opportunity: Opportunity): boolean {
return opportunity.source === FIND_A_TENDER_SOURCE;
}
/** The opportunity's newest release, or undefined if it has none. */
export function latestRelease(opportunity: Opportunity): OpportunityRelease | undefined {
let latest: OpportunityRelease | undefined;
for (const release of opportunity.releases ?? []) {
if (!latest || Date.parse(release.release_date) > Date.parse(latest.release_date)) {
latest = release;
}
}
return latest;
}
/** The page of a Find a Tender notice; a Find a Tender release's ID is its notice's. */
export function findATenderNoticeUrl(releaseId: string): string {
return `https://www.find-tender.service.gov.uk/notice/${encodeURIComponent(releaseId)}`;
}