Skip to content

Commit 7f96097

Browse files
committed
Added auto-detect for death table upon selecting death_table
1 parent a055704 commit 7f96097

3 files changed

Lines changed: 57 additions & 20 deletions

File tree

app/airflow/dags/libs/queries.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@
2424

2525

2626
find_existing_concepts_query = """
27-
-- If the date_event is "death_date", mark this as a death table.
28-
UPDATE mapping_scanreporttable
29-
SET death_table = TRUE
30-
WHERE id = %(table_id)s
31-
AND date_event_id IS NOT NULL
32-
AND EXISTS (
33-
SELECT 1
34-
FROM mapping_scanreportfield f
35-
WHERE f.id = mapping_scanreporttable.date_event_id
36-
AND LOWER(TRIM(f.name)) = 'death_date'
37-
);
38-
3927
INSERT INTO temp_existing_concepts_%(table_id)s (
4028
object_id, sr_concept_id, source_concept_id, content_type_id
4129
)
@@ -153,7 +141,6 @@
153141
154142
-- If the scan report table has the "death_table" flag set to TRUE, set the destination table to OMOP's "death" table.
155143
-- This ensures that mapping rules will use "death" as the destination table and, for example, will select "cause_concept_id" as the mapped field.
156-
-- 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.
157144
UPDATE temp_existing_concepts_%(table_id)s temp_existing_concepts
158145
SET dest_table_id = (SELECT id FROM mapping_omoptable WHERE "table" = 'death' LIMIT 1)
159146
WHERE (SELECT death_table FROM mapping_scanreporttable WHERE id = %(table_id)s) = TRUE;

app/next-client-app/components/form-components/FormikSelect.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { Field, FieldInputProps, FieldProps, FormikProps } from "formik";
22
import Select from "react-select";
33
import makeAnimated from "react-select/animated";
4-
import config from "@/tailwind.config";
5-
import { useTheme } from "next-themes";
64

75
type Option = Object & {
86
value: number;
@@ -36,8 +34,8 @@ const CustomSelect = ({
3634

3735
const onChange = (newValue: any, actionMeta: any) => {
3836
const selectedValues = isMulti
39-
? (newValue as Option[]).map((option) => option.value)
40-
: (newValue as Option).value;
37+
? ((newValue as Option[] | null) ?? []).map((option) => option.value)
38+
: ((newValue as Option | null)?.value ?? null);
4139

4240
form.setFieldValue(field.name, selectedValues);
4341
};

app/next-client-app/components/scanreports/ScanReportTableUpdateForm.tsx

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"use client";
22

3-
import { useState } from "react";
3+
import { useEffect, useRef, useState } from "react";
44
import { Button } from "@/components/ui/button";
55
import { updateScanReportTable } from "@/api/scanreports";
66
import { Check, Save, X } from "lucide-react";
77
import { toast } from "sonner";
88
import { FormDataFilter } from "../form-components/FormikUtils";
9-
import { Formik } from "formik";
9+
import { Formik, useFormikContext } from "formik";
1010
import { FormField, FormItem, FormLabel, FormControl, FormMessage, FormDescription } from "@/components/ui/form";
1111
import { FormikSelect } from "../form-components/FormikSelect";
1212
import { useRouter } from "next/navigation";
@@ -31,6 +31,39 @@ interface FormData {
3131
death_table: boolean;
3232
}
3333

34+
function DeathDateModalController({
35+
deathDateFieldId,
36+
setIsDialogOpen,
37+
pendingRevertRef,
38+
}: {
39+
deathDateFieldId?: number;
40+
setIsDialogOpen: (open: boolean) => void;
41+
pendingRevertRef: React.MutableRefObject<number | null | undefined>;
42+
}) {
43+
const { values, setFieldValue } = useFormikContext<FormData>();
44+
const prevDateEventRef = useRef(values.dateEvent);
45+
46+
useEffect(() => {
47+
const prev = prevDateEventRef.current;
48+
const next = values.dateEvent;
49+
prevDateEventRef.current = next;
50+
51+
if (!deathDateFieldId || next === prev) return;
52+
53+
if (next === deathDateFieldId && !values.death_table) {
54+
pendingRevertRef.current = prev ?? null;
55+
setIsDialogOpen(true);
56+
return;
57+
}
58+
59+
if (values.death_table && next !== deathDateFieldId) {
60+
setFieldValue("death_table", false);
61+
}
62+
}, [deathDateFieldId, values.dateEvent, values.death_table]);
63+
64+
return null;
65+
}
66+
3467
export function ScanReportTableUpdateForm({
3568
scanreportFields,
3669
scanreportTable,
@@ -46,13 +79,17 @@ export function ScanReportTableUpdateForm({
4679
}) {
4780
const router = useRouter();
4881
const [isDialogOpen, setIsDialogOpen] = useState(false);
82+
const pendingDateEventRevertRef = useRef<number | null | undefined>(undefined);
4983
const canUpdate =
5084
permissions.includes("CanEdit") || permissions.includes("CanAdmin");
5185

5286
const fieldOptions = FormDataFilter<ScanReportField>(scanreportFields);
5387

5488
const initialPersonId = FormDataFilter<ScanReportField>(personId);
5589
const initialDateEvent = FormDataFilter<ScanReportField>(dateEvent);
90+
const deathDateField = scanreportFields.find(
91+
(field) => field.name?.trim().toLowerCase() === "death_date",
92+
);
5693

5794
const handleSubmit = async (data: FormData) => {
5895
const submittingData = {
@@ -92,6 +129,11 @@ export function ScanReportTableUpdateForm({
92129
{({ handleSubmit, values, setFieldValue }) => (
93130
<form className="w-full max-w-2xl" onSubmit={handleSubmit}>
94131
<div className="flex flex-col gap-5">
132+
<DeathDateModalController
133+
deathDateFieldId={deathDateField?.id}
134+
setIsDialogOpen={setIsDialogOpen}
135+
pendingRevertRef={pendingDateEventRevertRef}
136+
/>
95137

96138
<FormItem>
97139
<FormLabel>Person ID</FormLabel>
@@ -134,7 +176,16 @@ export function ScanReportTableUpdateForm({
134176
<Tooltips
135177
content="In the Carrot data standard, death data is provided in a separate file (e.g. death.csv). Mark Yes if this table contains that death data to be mapped to the OMOP Death table."
136178
/>
137-
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
179+
<Dialog
180+
open={isDialogOpen}
181+
onOpenChange={(open) => {
182+
setIsDialogOpen(open);
183+
if (!open && pendingDateEventRevertRef.current !== undefined) {
184+
setFieldValue("dateEvent", pendingDateEventRevertRef.current);
185+
pendingDateEventRevertRef.current = undefined;
186+
}
187+
}}
188+
>
138189
<DialogContent>
139190
<DialogHeader>
140191
<DialogTitle>Please Confirm Your Choice</DialogTitle>
@@ -176,6 +227,7 @@ export function ScanReportTableUpdateForm({
176227
<Button
177228
type="button"
178229
onClick={() => {
230+
pendingDateEventRevertRef.current = undefined;
179231
setFieldValue("death_table", true);
180232
setIsDialogOpen(false);
181233
}}

0 commit comments

Comments
 (0)