From 7cc6aee3dfeb76f26b6a6a0eabe5a59a21a3551c Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 17 Mar 2026 14:17:24 +0000 Subject: [PATCH 1/6] Add support for marking table as DEATH table on the client side --- app/next-client-app/api/scanreports.ts | 1 + .../(protected)/scanreports/[id]/columns.tsx | 23 +++++ .../[tableId]/fields/[fieldId]/page.tsx | 4 +- .../fields/[fieldId]/update/page.tsx | 4 +- .../[id]/tables/[tableId]/page.tsx | 6 +- .../[id]/tables/[tableId]/update/page.tsx | 2 +- .../components/core/Tooltips.tsx | 43 +++++---- .../scanreports/DeathTableConfirmDialog.tsx | 95 +++++++++++++++++++ .../scanreports/ScanReportTableUpdateForm.tsx | 95 ++++++++++++++++++- app/next-client-app/types/scanreport.ts | 1 + 10 files changed, 250 insertions(+), 24 deletions(-) create mode 100644 app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx diff --git a/app/next-client-app/api/scanreports.ts b/app/next-client-app/api/scanreports.ts index 8ac524bf3..4ee080c60 100644 --- a/app/next-client-app/api/scanreports.ts +++ b/app/next-client-app/api/scanreports.ts @@ -149,6 +149,7 @@ export async function getScanReportTable( permissions: [], jobs: [], trigger_reuse: true, + death_table: false, }; } } diff --git a/app/next-client-app/app/(protected)/scanreports/[id]/columns.tsx b/app/next-client-app/app/(protected)/scanreports/[id]/columns.tsx index 971211261..d32f0285b 100644 --- a/app/next-client-app/app/(protected)/scanreports/[id]/columns.tsx +++ b/app/next-client-app/app/(protected)/scanreports/[id]/columns.tsx @@ -3,6 +3,7 @@ import { ColumnDef } from "@tanstack/react-table"; import { DataTableColumnHeader } from "@/components/data-table/DataTableColumnHeader"; import { EditButton } from "@/components/scanreports/EditButton"; +import { Tooltips } from "@/components/core/Tooltips"; import JobDialog from "@/components/jobs/JobDialog"; import { FindGeneralStatus, DivideJobs } from "@/components/jobs/JobUtils"; import Link from "next/link"; @@ -89,6 +90,28 @@ export const columns: ColumnDef[] = [ ); } }, + { + id: "note", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const { death_table } = row.original; + return ( +
+ {death_table && ( +

+ {" "} + Death table + +

+ )} +
+ ); + } + }, { id: "edit", header: ({ column }) => , diff --git a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/page.tsx b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/page.tsx index 5b7717bfb..0b029769d 100644 --- a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/page.tsx +++ b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/page.tsx @@ -72,7 +72,9 @@ export default async function ScanReportsValue(props: ScanReportsValueProps) { id={id} tableId={tableId} fieldId={fieldId} - tableName={table.name} + tableName={ + table.death_table ? `${table.name} (Death table)` : table.name + } fieldName={field.name} variant="field" /> diff --git a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/update/page.tsx b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/update/page.tsx index 1980563e3..9dd2c7b31 100644 --- a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/update/page.tsx +++ b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/fields/[fieldId]/update/page.tsx @@ -40,7 +40,9 @@ export default async function ScanReportsEditField(props: ScanReportsEditFieldPr id={id} tableId={tableId} fieldId={fieldId} - tableName={table.name} + tableName={ + table.death_table ? `${table.name} (Death table)` : table.name + } fieldName={field.name} variant="fieldUpdate" /> diff --git a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/page.tsx b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/page.tsx index 4104c99d6..63563e5bb 100644 --- a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/page.tsx +++ b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/page.tsx @@ -60,7 +60,11 @@ export default async function ScanReportsField(props: ScanReportsFieldProps) {
diff --git a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/update/page.tsx b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/update/page.tsx index a89c48f76..c02281e29 100644 --- a/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/update/page.tsx +++ b/app/next-client-app/app/(protected)/scanreports/[id]/tables/[tableId]/update/page.tsx @@ -74,7 +74,7 @@ export default async function UpdateTable(props: UpdateTableProps) {
{(table.date_event === null || table.person_id === null) && ( diff --git a/app/next-client-app/components/core/Tooltips.tsx b/app/next-client-app/components/core/Tooltips.tsx index 7b17b3b66..d930237bf 100644 --- a/app/next-client-app/components/core/Tooltips.tsx +++ b/app/next-client-app/components/core/Tooltips.tsx @@ -6,13 +6,14 @@ import { } from "@/components/ui/tooltip"; import { InfoIcon } from "lucide-react"; +import { ReactElement } from "react"; export function Tooltips({ content, link, side = "top", }: { - content: string; + content: string | ReactElement; link?: string; side?: "top" | "bottom" | "left" | "right"; }) { @@ -26,24 +27,28 @@ export function Tooltips({ className="max-w-96 text-center whitespace-pre-wrap" side={side} > -

- {content} - {link && ( - <> - {" "} - Find out more{" "} - - here - - . - - )} -

+ {typeof content === "string" ? ( +

+ {content} + {link && ( + <> + {" "} + Find out more{" "} + + here + + . + + )} +

+ ) : ( + content + )} diff --git a/app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx b/app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx new file mode 100644 index 000000000..bc254da15 --- /dev/null +++ b/app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx @@ -0,0 +1,95 @@ +"use client"; + +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "../ui/dialog"; +import { toast } from "sonner"; +import { Button } from "../ui/button"; +import { updateScanReportTable } from "@/api/scanreports"; +import { useRouter } from "next/navigation"; + +interface DeathTableConfirmDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + scanReportId: number; + tableId: number; + tableName: string; + isDeathTable: boolean; + onSuccess?: () => void; +} + +export function DeathTableConfirmDialog({ + open, + onOpenChange, + scanReportId, + tableId, + tableName, + isDeathTable, + onSuccess, +}: DeathTableConfirmDialogProps) { + const router = useRouter(); + const markingAsDeath = !isDeathTable; + + const handleConfirm = async () => { + const response = await updateScanReportTable( + scanReportId, + tableId, + { death_table: markingAsDeath }, + ); + if (response) { + toast.error( + `Failed to update DEATH table setting: ${response.errorMessage}`, + ); + } else { + toast.success( + markingAsDeath + ? "Table marked as DEATH table successfully." + : "Table unmarked as DEATH table successfully.", + ); + onOpenChange(false); + onSuccess?.(); + router.refresh(); + } + }; + + return ( + + + + + {markingAsDeath ? "Mark as DEATH table" : "Unmark as DEATH table"} + + + {markingAsDeath ? ( + <> + Are you sure you want to mark "{tableName}" as a + DEATH table? This will enable auto-mapping as a death table for + any death SR uploads. + + ) : ( + <> + Are you sure you want to unmark "{tableName}" as a + DEATH table? Auto-mapping as a death table will no longer apply + to this table. + + )} + + + + + + + + + + + ); +} diff --git a/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx b/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx index 2cad5ab96..6f570dfb3 100644 --- a/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx +++ b/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx @@ -1,8 +1,9 @@ "use client"; +import { useState } from "react"; import { Button } from "@/components/ui/button"; import { updateScanReportTable } from "@/api/scanreports"; -import { Save } from "lucide-react"; +import { Check, Save, X } from "lucide-react"; import { toast } from "sonner"; import { FormDataFilter } from "../form-components/FormikUtils"; import { Formik } from "formik"; @@ -10,12 +11,24 @@ import { FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescripti import { FormikSelect } from "../form-components/FormikSelect"; import { useRouter } from "next/navigation"; import { Checkbox } from "../ui/checkbox"; +import { Switch } from "@/components/ui/switch"; +import { Label } from "@/components/ui/label"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Tooltips } from "@/components/core/Tooltips"; import { enableReuseTriggerOption } from "@/constants"; interface FormData { personId: number | null; dateEvent: number | null; triggerReuse: boolean; + death_table: boolean; } export function ScanReportTableUpdateForm({ @@ -32,6 +45,7 @@ export function ScanReportTableUpdateForm({ dateEvent: ScanReportField; }) { const router = useRouter(); + const [isDialogOpen, setIsDialogOpen] = useState(false); const canUpdate = permissions.includes("CanEdit") || permissions.includes("CanAdmin"); @@ -45,6 +59,7 @@ export function ScanReportTableUpdateForm({ person_id: data.personId !== 0 ? data.personId : null, date_event: data.dateEvent !== 0 ? data.dateEvent : null, trigger_reuse: data.triggerReuse, + death_table: data.death_table, }; const response = await updateScanReportTable( @@ -68,6 +83,7 @@ export function ScanReportTableUpdateForm({ dateEvent: initialDateEvent[0].value, personId: initialPersonId[0].value, triggerReuse: scanreportTable.trigger_reuse, + death_table: Boolean(scanreportTable.death_table), }} onSubmit={(data) => { handleSubmit(data); @@ -109,6 +125,83 @@ export function ScanReportTableUpdateForm({ + +
+ + Does this table contain only death data for the OMOP CDM Death + table? + + + + + + Please Confirm Your Choice + + Are you sure you want to set this table as a Death table? + Doing so will result in the following: +
    +
  • + Mapping Rules that are created either manually or + automatically (built from OMOP vocabulary or Reused) + will have Destination table as{" "} + Death. +
  • +
  • + All concepts in this table will be recognised as{" "} + Cause of Death in + OMOP CDM. +
  • +
  • + Destination of Date Event will be{" "} + Death date field in + OMOP CDM. +
  • +
+

+ You can turn off this setting later. Mapping rules will + be refreshed when you save. +

+
+
+ + + + +
+
+ { + if (checked) { + setIsDialogOpen(true); + } else { + setFieldValue("death_table", false); + } + }} + disabled={!canUpdate} + /> + +
+
+ {enableReuseTriggerOption === "true" && ( {({ field }) => ( diff --git a/app/next-client-app/types/scanreport.ts b/app/next-client-app/types/scanreport.ts index 7b04c72ce..8dc1a5a72 100644 --- a/app/next-client-app/types/scanreport.ts +++ b/app/next-client-app/types/scanreport.ts @@ -29,6 +29,7 @@ interface ScanReportTable { permissions: Permission[]; jobs: Job[]; trigger_reuse: boolean; + death_table?: boolean; } interface ScanReportField { From ca7358218facd90a344d6886504635894d0a9e27 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 18 Mar 2026 13:48:41 +0000 Subject: [PATCH 2/6] Fix suggestions from review --- .../components/core/Tooltips.tsx | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/app/next-client-app/components/core/Tooltips.tsx b/app/next-client-app/components/core/Tooltips.tsx index d930237bf..852855967 100644 --- a/app/next-client-app/components/core/Tooltips.tsx +++ b/app/next-client-app/components/core/Tooltips.tsx @@ -6,14 +6,13 @@ import { } from "@/components/ui/tooltip"; import { InfoIcon } from "lucide-react"; -import { ReactElement } from "react"; export function Tooltips({ content, link, side = "top", }: { - content: string | ReactElement; + content: string; link?: string; side?: "top" | "bottom" | "left" | "right"; }) { @@ -27,30 +26,26 @@ export function Tooltips({ className="max-w-96 text-center whitespace-pre-wrap" side={side} > - {typeof content === "string" ? ( -

- {content} - {link && ( - <> - {" "} - Find out more{" "} - - here - - . - - )} -

- ) : ( - content - )} +

+ {content} + {link && ( + <> + {" "} + Find out more{" "} + + here + + . + + )} +

); -} +} \ No newline at end of file From f3f0c1866c15375aac03b3aa29221025056d87f1 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 18 Mar 2026 14:43:57 +0000 Subject: [PATCH 3/6] Fix suggestions from review --- .../scanreports/DeathTableConfirmDialog.tsx | 95 ------------------- 1 file changed, 95 deletions(-) delete mode 100644 app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx diff --git a/app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx b/app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx deleted file mode 100644 index bc254da15..000000000 --- a/app/next-client-app/components/scanreports/DeathTableConfirmDialog.tsx +++ /dev/null @@ -1,95 +0,0 @@ -"use client"; - -import { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "../ui/dialog"; -import { toast } from "sonner"; -import { Button } from "../ui/button"; -import { updateScanReportTable } from "@/api/scanreports"; -import { useRouter } from "next/navigation"; - -interface DeathTableConfirmDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - scanReportId: number; - tableId: number; - tableName: string; - isDeathTable: boolean; - onSuccess?: () => void; -} - -export function DeathTableConfirmDialog({ - open, - onOpenChange, - scanReportId, - tableId, - tableName, - isDeathTable, - onSuccess, -}: DeathTableConfirmDialogProps) { - const router = useRouter(); - const markingAsDeath = !isDeathTable; - - const handleConfirm = async () => { - const response = await updateScanReportTable( - scanReportId, - tableId, - { death_table: markingAsDeath }, - ); - if (response) { - toast.error( - `Failed to update DEATH table setting: ${response.errorMessage}`, - ); - } else { - toast.success( - markingAsDeath - ? "Table marked as DEATH table successfully." - : "Table unmarked as DEATH table successfully.", - ); - onOpenChange(false); - onSuccess?.(); - router.refresh(); - } - }; - - return ( - - - - - {markingAsDeath ? "Mark as DEATH table" : "Unmark as DEATH table"} - - - {markingAsDeath ? ( - <> - Are you sure you want to mark "{tableName}" as a - DEATH table? This will enable auto-mapping as a death table for - any death SR uploads. - - ) : ( - <> - Are you sure you want to unmark "{tableName}" as a - DEATH table? Auto-mapping as a death table will no longer apply - to this table. - - )} - - - - - - - - - - - ); -} From 74a780fc9ffdeb8d176110c516ddba53a17fa7f5 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 19 Mar 2026 18:25:53 +0000 Subject: [PATCH 4/6] Allow mapper to autodetect death date therefore makrking it as true --- app/airflow/dags/libs/queries.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/airflow/dags/libs/queries.py b/app/airflow/dags/libs/queries.py index d37e06490..ab5594974 100644 --- a/app/airflow/dags/libs/queries.py +++ b/app/airflow/dags/libs/queries.py @@ -24,6 +24,20 @@ find_existing_concepts_query = """ + -- This check marks the current table as a "death table" if the user specifically chose the "death_date" field for the date_event. + -- We include this here to ensure that any downstream automapping logic that depends on knowing if a table is a "death table" (for example, only assigning death concepts to death tables) will behave correctly. + -- The check is performed right before we pull existing concepts so the information is always up-to-date in automapping flows. + UPDATE mapping_scanreporttable + SET death_table = TRUE + WHERE id = %(table_id)s + AND date_event_id IS NOT NULL + AND EXISTS ( + SELECT 1 + FROM mapping_scanreportfield f + WHERE f.id = mapping_scanreporttable.date_event_id + AND LOWER(TRIM(f.name)) = 'death_date' + ); + INSERT INTO temp_existing_concepts_%(table_id)s ( object_id, sr_concept_id, source_concept_id, content_type_id ) @@ -139,7 +153,9 @@ -- Because concepts may or may not have the standard_concept_id, in general. And we prefer to use the standard_concept_id, if it exists. WHERE target_concept.concept_id = COALESCE(temp_existing_concepts.standard_concept_id, temp_existing_concepts.source_concept_id); --- When the scan report table is a death table, override dest_table_id to the death OMOP table so rules show destination table: death, field: cause_concept_id +-- If the scan report table has the "death_table" flag set to TRUE, set the destination table to OMOP's "death" table. +-- This ensures that mapping rules will use "death" as the destination table and, for example, will select "cause_concept_id" as the mapped field. +-- Note: The "death_table" flag may have been set automatically if a date_event was mapped to the "death_date" field earlier in the workflow. UPDATE temp_existing_concepts_%(table_id)s temp_existing_concepts SET dest_table_id = (SELECT id FROM mapping_omoptable WHERE "table" = 'death' LIMIT 1) WHERE (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) = TRUE; From a05570459ad36575ebd71549212e3ca15f675515 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 20 Mar 2026 06:37:31 +0000 Subject: [PATCH 5/6] Allow mapper to autodetect death date therefore marking it as true --- app/airflow/dags/libs/queries.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/airflow/dags/libs/queries.py b/app/airflow/dags/libs/queries.py index ab5594974..bb32b5af0 100644 --- a/app/airflow/dags/libs/queries.py +++ b/app/airflow/dags/libs/queries.py @@ -24,9 +24,7 @@ find_existing_concepts_query = """ - -- This check marks the current table as a "death table" if the user specifically chose the "death_date" field for the date_event. - -- We include this here to ensure that any downstream automapping logic that depends on knowing if a table is a "death table" (for example, only assigning death concepts to death tables) will behave correctly. - -- The check is performed right before we pull existing concepts so the information is always up-to-date in automapping flows. + -- If the date_event is "death_date", mark this as a death table. UPDATE mapping_scanreporttable SET death_table = TRUE WHERE id = %(table_id)s From 7f9609753c75b4f7570081440478560299d299cc Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 25 Mar 2026 10:20:44 +0000 Subject: [PATCH 6/6] Added auto-detect for death table upon selecting death_table --- app/airflow/dags/libs/queries.py | 13 ----- .../form-components/FormikSelect.tsx | 6 +- .../scanreports/ScanReportTableUpdateForm.tsx | 58 ++++++++++++++++++- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/app/airflow/dags/libs/queries.py b/app/airflow/dags/libs/queries.py index bb32b5af0..e110761e3 100644 --- a/app/airflow/dags/libs/queries.py +++ b/app/airflow/dags/libs/queries.py @@ -24,18 +24,6 @@ find_existing_concepts_query = """ - -- If the date_event is "death_date", mark this as a death table. - UPDATE mapping_scanreporttable - SET death_table = TRUE - WHERE id = %(table_id)s - AND date_event_id IS NOT NULL - AND EXISTS ( - SELECT 1 - FROM mapping_scanreportfield f - WHERE f.id = mapping_scanreporttable.date_event_id - AND LOWER(TRIM(f.name)) = 'death_date' - ); - INSERT INTO temp_existing_concepts_%(table_id)s ( object_id, sr_concept_id, source_concept_id, content_type_id ) @@ -153,7 +141,6 @@ -- If the scan report table has the "death_table" flag set to TRUE, set the destination table to OMOP's "death" table. -- This ensures that mapping rules will use "death" as the destination table and, for example, will select "cause_concept_id" as the mapped field. --- Note: The "death_table" flag may have been set automatically if a date_event was mapped to the "death_date" field earlier in the workflow. UPDATE temp_existing_concepts_%(table_id)s temp_existing_concepts SET dest_table_id = (SELECT id FROM mapping_omoptable WHERE "table" = 'death' LIMIT 1) WHERE (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) = TRUE; diff --git a/app/next-client-app/components/form-components/FormikSelect.tsx b/app/next-client-app/components/form-components/FormikSelect.tsx index c528c2e4f..ae7121cca 100644 --- a/app/next-client-app/components/form-components/FormikSelect.tsx +++ b/app/next-client-app/components/form-components/FormikSelect.tsx @@ -1,8 +1,6 @@ import { Field, FieldInputProps, FieldProps, FormikProps } from "formik"; import Select from "react-select"; import makeAnimated from "react-select/animated"; -import config from "@/tailwind.config"; -import { useTheme } from "next-themes"; type Option = Object & { value: number; @@ -36,8 +34,8 @@ const CustomSelect = ({ const onChange = (newValue: any, actionMeta: any) => { const selectedValues = isMulti - ? (newValue as Option[]).map((option) => option.value) - : (newValue as Option).value; + ? ((newValue as Option[] | null) ?? []).map((option) => option.value) + : ((newValue as Option | null)?.value ?? null); form.setFieldValue(field.name, selectedValues); }; diff --git a/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx b/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx index 6f570dfb3..50e3258d4 100644 --- a/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx +++ b/app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx @@ -1,12 +1,12 @@ "use client"; -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { Button } from "@/components/ui/button"; import { updateScanReportTable } from "@/api/scanreports"; import { Check, Save, X } from "lucide-react"; import { toast } from "sonner"; import { FormDataFilter } from "../form-components/FormikUtils"; -import { Formik } from "formik"; +import { Formik, useFormikContext } from "formik"; import { FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescription } from "@/components/ui/form"; import { FormikSelect } from "../form-components/FormikSelect"; import { useRouter } from "next/navigation"; @@ -31,6 +31,39 @@ interface FormData { death_table: boolean; } +function DeathDateModalController({ + deathDateFieldId, + setIsDialogOpen, + pendingRevertRef, +}: { + deathDateFieldId?: number; + setIsDialogOpen: (open: boolean) => void; + pendingRevertRef: React.MutableRefObject; +}) { + const { values, setFieldValue } = useFormikContext(); + const prevDateEventRef = useRef(values.dateEvent); + + useEffect(() => { + const prev = prevDateEventRef.current; + const next = values.dateEvent; + prevDateEventRef.current = next; + + if (!deathDateFieldId || next === prev) return; + + if (next === deathDateFieldId && !values.death_table) { + pendingRevertRef.current = prev ?? null; + setIsDialogOpen(true); + return; + } + + if (values.death_table && next !== deathDateFieldId) { + setFieldValue("death_table", false); + } + }, [deathDateFieldId, values.dateEvent, values.death_table]); + + return null; +} + export function ScanReportTableUpdateForm({ scanreportFields, scanreportTable, @@ -46,6 +79,7 @@ export function ScanReportTableUpdateForm({ }) { const router = useRouter(); const [isDialogOpen, setIsDialogOpen] = useState(false); + const pendingDateEventRevertRef = useRef(undefined); const canUpdate = permissions.includes("CanEdit") || permissions.includes("CanAdmin"); @@ -53,6 +87,9 @@ export function ScanReportTableUpdateForm({ const initialPersonId = FormDataFilter(personId); const initialDateEvent = FormDataFilter(dateEvent); + const deathDateField = scanreportFields.find( + (field) => field.name?.trim().toLowerCase() === "death_date", + ); const handleSubmit = async (data: FormData) => { const submittingData = { @@ -92,6 +129,11 @@ export function ScanReportTableUpdateForm({ {({ handleSubmit, values, setFieldValue }) => (
+ Person ID @@ -134,7 +176,16 @@ export function ScanReportTableUpdateForm({ - + { + setIsDialogOpen(open); + if (!open && pendingDateEventRevertRef.current !== undefined) { + setFieldValue("dateEvent", pendingDateEventRevertRef.current); + pendingDateEventRevertRef.current = undefined; + } + }} + > Please Confirm Your Choice @@ -176,6 +227,7 @@ export function ScanReportTableUpdateForm({