diff --git a/src/assets/texts.json b/src/assets/texts.json index 4ff3ef7..8e6604f 100644 --- a/src/assets/texts.json +++ b/src/assets/texts.json @@ -10,6 +10,8 @@ "crossmatch.triage.pending": "Pending", "crossmatch.triage.resolved": "Resolved", "crossmatch.triage.verbose.pending": "Pending manual check", - "crossmatch.triage.verbose.resolved": "Resolved" + "crossmatch.triage.verbose.resolved": "Resolved", + "crossmatch.action.mark_new": "Mark as new", + "crossmatch.action.resolve": "Match to this PGC" } } diff --git a/src/pages/CrossmatchResults.tsx b/src/pages/CrossmatchResults.tsx index 456fd01..9d879b7 100644 --- a/src/pages/CrossmatchResults.tsx +++ b/src/pages/CrossmatchResults.tsx @@ -12,7 +12,6 @@ import { getCrossmatchRecords } from "../clients/admin/sdk.gen"; import type { GetRecordsCrossmatchResponse, RecordCrossmatch, - RecordCrossmatchStatus, RecordTriageStatus, ValidationError, } from "../clients/admin/types.gen"; @@ -27,12 +26,10 @@ import { adminClient } from "../clients/config"; interface CrossmatchFiltersProps { tableName: string | null; - status: RecordCrossmatchStatus | null; triageStatus: string | null; pageSize: number; onApplyFilters: ( tableName: string, - status: string, triageStatus: string, pageSize: number, ) => void; @@ -40,12 +37,10 @@ interface CrossmatchFiltersProps { function CrossmatchFilters({ tableName, - status, triageStatus, pageSize, onApplyFilters, }: CrossmatchFiltersProps): ReactElement { - const [localStatus, setLocalStatus] = useState(status || "all"); const [localTriageStatus, setLocalTriageStatus] = useState( triageStatus ?? "pending", ); @@ -53,19 +48,13 @@ function CrossmatchFilters({ const [localTableName, setLocalTableName] = useState(tableName || ""); useEffect(() => { - setLocalStatus(status || "all"); setLocalTriageStatus(triageStatus ?? "pending"); setLocalPageSize(pageSize); setLocalTableName(tableName || ""); - }, [status, triageStatus, pageSize, tableName]); + }, [triageStatus, pageSize, tableName]); function applyFilters(): void { - onApplyFilters( - localTableName, - localStatus, - localTriageStatus, - localPageSize, - ); + onApplyFilters(localTableName, localTriageStatus, localPageSize); } return ( @@ -78,18 +67,6 @@ function CrossmatchFilters({ onEnter={applyFilters} /> - - {displayName} - +
+ + {displayName} + + {triageStatusLabel} +
); } @@ -156,14 +144,6 @@ function CrossmatchResults({ ); } - function getStatusLabel(status: RecordCrossmatchStatus): string { - return getResource(`crossmatch.status.${status}`).Title; - } - - function getTriageStatusLabel(triageStatus: RecordTriageStatus): string { - return getResource(`crossmatch.triage.${triageStatus}`).Title; - } - const columns: Column[] = [ { name: "Record name", @@ -174,8 +154,6 @@ function CrossmatchResults({ return NULL; }, }, - { name: "Status" }, - { name: "Manual check status" }, { name: "Candidates", renderCell: (recordIndex: CellPrimitive) => { @@ -188,10 +166,8 @@ function CrossmatchResults({ ]; const tableData: Record[] = - data?.records.map((record: RecordCrossmatch, index: number) => ({ + data?.records.map((_: RecordCrossmatch, index: number) => ({ "Record name": index, - Status: getStatusLabel(record.status), - "Manual check status": getTriageStatusLabel(record.triage_status), Candidates: index, })) || []; @@ -200,7 +176,6 @@ function CrossmatchResults({ async function fetcher( tableName: string | null, - status: RecordCrossmatchStatus | null, triageStatus: RecordTriageStatus | null, page: number, pageSize: number, @@ -213,7 +188,6 @@ async function fetcher( client: adminClient, query: { table_name: tableName, - status: status, triage_status: triageStatus, page: page, page_size: pageSize, @@ -239,7 +213,6 @@ export function CrossmatchResultsPage(): ReactElement { const [searchParams, setSearchParams] = useSearchParams(); const tableName = searchParams.get("table_name"); - const status = searchParams.get("status") as RecordCrossmatchStatus | null; const triageStatusParam = searchParams.get("triage_status"); const apiTriageStatus: RecordTriageStatus | null = triageStatusParam === null || triageStatusParam === "" @@ -255,8 +228,8 @@ export function CrossmatchResultsPage(): ReactElement { }, [tableName]); const { data, loading, error } = useDataFetching( - () => fetcher(tableName, status, apiTriageStatus, page, pageSize), - [tableName, status, apiTriageStatus, page, pageSize], + () => fetcher(tableName, apiTriageStatus, page, pageSize), + [tableName, apiTriageStatus, page, pageSize], ); function handlePageChange(newPage: number): void { @@ -267,7 +240,6 @@ export function CrossmatchResultsPage(): ReactElement { function handleApplyFilters( newTableName: string, - newStatus: string, newTriageStatus: string, newPageSize: number, ): void { @@ -279,12 +251,6 @@ export function CrossmatchResultsPage(): ReactElement { newSearchParams.delete("table_name"); } - if (newStatus === "all") { - newSearchParams.delete("status"); - } else { - newSearchParams.set("status", newStatus); - } - if (newTriageStatus === "all") { newSearchParams.set("triage_status", "all"); } else { @@ -320,7 +286,6 @@ export function CrossmatchResultsPage(): ReactElement {

Crossmatch results

(null); + const [resolving, setResolving] = useState<"new" | number | null>(null); const [resolveError, setResolveError] = useState(null); const { crossmatch, @@ -174,36 +175,57 @@ function RecordCrossmatchDetails({ `crossmatch.triage.verbose.${crossmatch.triage_status}`, ).Title; + async function submitCrossmatchResolution( + statuses: StatusesPayload, + ): Promise { + const response = await setCrossmatchResults({ + client: adminClient, + body: { statuses }, + }); + + if (response.error || !response.data?.data) { + throw new Error( + typeof response.error === "object" + ? JSON.stringify(response.error) + : String(response.error || "Unknown error"), + ); + } + + window.location.reload(); + } + async function resolveCandidate(pgc: number): Promise { setResolveError(null); - setResolvingPgc(pgc); + setResolving(pgc); try { - const response = await setCrossmatchResults({ - client: adminClient, - body: { - statuses: { - existing: { - record_ids: [crossmatch.record_id], - pgcs: [pgc], - triage_statuses: ["resolved"], - }, - }, + await submitCrossmatchResolution({ + existing: { + record_ids: [crossmatch.record_id], + pgcs: [pgc], + triage_statuses: ["resolved"], }, }); + } catch (err) { + setResolveError(`${err}`); + } finally { + setResolving(null); + } + } - if (response.error || !response.data?.data) { - throw new Error( - typeof response.error === "object" - ? JSON.stringify(response.error) - : String(response.error || "Unknown error"), - ); - } - - window.location.reload(); + async function markAsNew(): Promise { + setResolveError(null); + setResolving("new"); + try { + await submitCrossmatchResolution({ + new: { + record_ids: [crossmatch.record_id], + triage_statuses: ["resolved"], + }, + }); } catch (err) { setResolveError(`${err}`); } finally { - setResolvingPgc(null); + setResolving(null); } } @@ -243,6 +265,19 @@ function RecordCrossmatchDetails({ ? "1 candidate" : `${candidates.length} candidates`}

+ {showResolveControls && ( +
+ +
+ )} @@ -254,14 +289,15 @@ function RecordCrossmatchDetails({ )} + {resolveError && ( +

+ {resolveError} +

+ )} + {candidates.length > 0 && (

Crossmatch Candidates

- {resolveError && ( -

- {resolveError} -

- )} {candidates.map((candidate) => ( resolveCandidate(candidate.pgc)} > - {resolvingPgc === candidate.pgc ? "Resolving…" : "Resolve"} + {resolving === candidate.pgc + ? "Saving…" + : getResource("crossmatch.action.resolve").Title} )}