From 88b30d8168a077fda4adaa6ccf397de562308d1e Mon Sep 17 00:00:00 2001
From: casperiv0 <53900565+casperiv0@users.noreply.github.com>
Date: Mon, 23 Oct 2023 19:06:42 +0200
Subject: [PATCH] feat: call 911 disposition code
---
.../migration.sql | 8 +++++
apps/api/prisma/schema.prisma | 17 +++++++----
.../admin/values/import-values-controller.ts | 1 +
apps/client/locales/en/calls.json | 3 +-
apps/client/locales/en/values.json | 4 ++-
.../admin/values/ManageValueModal.tsx | 12 ++++++++
.../modals/manage-911-call-form.tsx | 29 ++++++++++++++++++-
.../form/inputs/value-select-field.tsx | 2 ++
apps/client/src/lib/admin/values/values.tsx | 6 +++-
packages/schemas/src/admin/values/import.ts | 1 +
10 files changed, 73 insertions(+), 10 deletions(-)
create mode 100644 apps/api/prisma/migrations/20231023170026_disposition_code_call/migration.sql
diff --git a/apps/api/prisma/migrations/20231023170026_disposition_code_call/migration.sql b/apps/api/prisma/migrations/20231023170026_disposition_code_call/migration.sql
new file mode 100644
index 000000000..6a2de6ae7
--- /dev/null
+++ b/apps/api/prisma/migrations/20231023170026_disposition_code_call/migration.sql
@@ -0,0 +1,8 @@
+-- AlterTable
+ALTER TABLE "Call911" ADD COLUMN "dispositionCodeId" TEXT;
+
+-- AlterTable
+ALTER TABLE "CallTypeValue" ADD COLUMN "isDisposition" BOOLEAN NOT NULL DEFAULT false;
+
+-- AddForeignKey
+ALTER TABLE "Call911" ADD CONSTRAINT "Call911_dispositionCodeId_fkey" FOREIGN KEY ("dispositionCodeId") REFERENCES "CallTypeValue"("id") ON DELETE SET NULL ON UPDATE CASCADE;
diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma
index 1bf6cee7c..881bc3936 100644
--- a/apps/api/prisma/schema.prisma
+++ b/apps/api/prisma/schema.prisma
@@ -824,11 +824,14 @@ model WeaponValue {
}
model CallTypeValue {
- id String @id @default(cuid())
- priority String?
- valueId String
- value Value @relation("callTypeValueToValue", fields: [valueId], references: [id], onDelete: Cascade)
- Call911 Call911[]
+ id String @id @default(cuid())
+ priority String?
+ valueId String
+ isDisposition Boolean @default(false)
+ value Value @relation("callTypeValueToValue", fields: [valueId], references: [id], onDelete: Cascade)
+
+ dispositionCodeToCall Call911[] @relation("dispositionCodeToCall")
+ callTypeToCall Call911[] @relation("callTypeToCall")
}
// notifications
@@ -1310,12 +1313,14 @@ model Call911 {
ended Boolean? @default(false)
situationCode StatusValue? @relation(fields: [situationCodeId], references: [id])
situationCodeId String?
+ dispositionCode CallTypeValue? @relation("dispositionCodeToCall", fields: [dispositionCodeId], references: [id])
+ dispositionCodeId String?
viaDispatch Boolean? @default(false)
divisions DivisionValue[]
departments DepartmentValue[]
events Call911Event[]
incidents LeoIncident[]
- type CallTypeValue? @relation(fields: [typeId], references: [id])
+ type CallTypeValue? @relation("callTypeToCall", fields: [typeId], references: [id])
typeId String?
Officer Officer[] @relation("activeCall")
EmsFdDeputy EmsFdDeputy[] @relation("emsFdActiveCall")
diff --git a/apps/api/src/controllers/admin/values/import-values-controller.ts b/apps/api/src/controllers/admin/values/import-values-controller.ts
index 35606388a..566ab5a37 100644
--- a/apps/api/src/controllers/admin/values/import-values-controller.ts
+++ b/apps/api/src/controllers/admin/values/import-values-controller.ts
@@ -483,6 +483,7 @@ export const typeHandlers = {
where: { id: String(id) },
...makePrismaData(ValueType.CALL_TYPE, {
priority: item.priority,
+ isDisposition: item.isDisposition ?? false,
value: item.value,
isDisabled: item.isDisabled,
}),
diff --git a/apps/client/locales/en/calls.json b/apps/client/locales/en/calls.json
index ec8524d4b..087505c3d 100644
--- a/apps/client/locales/en/calls.json
+++ b/apps/client/locales/en/calls.json
@@ -69,7 +69,8 @@
"id": "id",
"towLogsDescription": "Here you can view all archived tow logs. This allows you to view all tow logs that have been ended/archived.",
"addAllUnits": "Add all active units",
- "openCallModalAfterCreation": "Open Manage 911 call modal after call creation?"
+ "openCallModalAfterCreation": "Open Manage 911 call modal after call creation?",
+ "dispositionCode": "Disposition Code"
},
"Events": {
"unitAssignedToCall": "{unit} has been assigned to this call.",
diff --git a/apps/client/locales/en/values.json b/apps/client/locales/en/values.json
index 3fb97e347..eddca38d0 100644
--- a/apps/client/locales/en/values.json
+++ b/apps/client/locales/en/values.json
@@ -74,7 +74,9 @@
"FELONY": "Felony",
"warningApplicable": "Warning Applicable",
"warningNotApplicable": "Warning Not Applicable",
- "isPrimary": "Is Primary"
+ "isPrimary": "Is Primary",
+ "isDispositionDescription": "A disposition code can be used when a call is closed. This will be used to determine the outcome of the call.",
+ "isDisposition": "Is Disposition"
},
"PENAL_CODE_GROUP": {
"MANAGE": "Manage Penal Code Groups",
diff --git a/apps/client/src/components/admin/values/ManageValueModal.tsx b/apps/client/src/components/admin/values/ManageValueModal.tsx
index 7d1964924..706cdc7cc 100644
--- a/apps/client/src/components/admin/values/ManageValueModal.tsx
+++ b/apps/client/src/components/admin/values/ManageValueModal.tsx
@@ -133,6 +133,7 @@ function createInitialValues(options: CreateInitialValuesOptions) {
licenseType: value && isBaseValue(value) ? value.licenseType : null,
isDefault: value && isBaseValue(value) ? value.isDefault : undefined,
priority: value && isCallTypeValue(value) ? value.priority ?? undefined : undefined,
+ isDisposition: value && isCallTypeValue(value) ? value.isDisposition ?? undefined : undefined,
officerRankImageId: "",
officerRankDepartments:
@@ -376,6 +377,17 @@ export function ManageValueModal({ onCreate, onUpdate, type, value }: Props) {
/>
) : null}
+ {type === ValueType.CALL_TYPE ? (
+ setFieldValue("isDisposition", value)}
+ isSelected={values.isDisposition}
+ description={tValues("isDispositionDescription")}
+ >
+ {tValues("isDisposition")}
+
+ ) : null}
+
{type === ValueType.OFFICER_RANK ? (
<>
diff --git a/apps/client/src/components/dispatch/active-calls/modals/manage-911-call-form.tsx b/apps/client/src/components/dispatch/active-calls/modals/manage-911-call-form.tsx
index c572188fe..4e3e8c259 100644
--- a/apps/client/src/components/dispatch/active-calls/modals/manage-911-call-form.tsx
+++ b/apps/client/src/components/dispatch/active-calls/modals/manage-911-call-form.tsx
@@ -111,6 +111,7 @@ export function Manage911CallForm({ call, isDisabled, setShowAlert, handleClose
departments: call?.departments?.map((dep) => ({ value: dep.id, label: dep.value.value })) ?? [],
divisions: call?.divisions?.map((dep) => ({ value: dep.id, label: dep.value.value })) ?? [],
situationCode: call?.situationCodeId ?? null,
+ dispositionCodeId: call?.dispositionCodeId ?? null,
type: call?.typeId ?? null,
notifyAssignedUnits: true,
openCallModalAfterCreation: true,
@@ -208,7 +209,7 @@ export function Manage911CallForm({ call, isDisabled, setShowAlert, handleClose
) : null}
-
+
value.type === StatusValueType.SITUATION_CODE}
+ className="w-full"
+ />
+
+ value.isDisposition}
+ className="w-full"
/>
!value.isDisposition}
+ className="w-full"
/>
+ value.type === StatusValueType.SITUATION_CODE}
+ />
+
(props: Props) {
}, [getDefaultSearchValue]);
function handleSuggestionPress(node?: Node | null) {
+ if (node) setSearch(node?.textValue);
+
const fieldData = { [props.fieldName]: node?.key ?? null };
setValues({ ...values, ...fieldData });
props.onSelectionChange?.((node?.value as T | null) ?? null);
diff --git a/apps/client/src/lib/admin/values/values.tsx b/apps/client/src/lib/admin/values/values.tsx
index 16a74ddf5..da8637f9f 100644
--- a/apps/client/src/lib/admin/values/values.tsx
+++ b/apps/client/src/lib/admin/values/values.tsx
@@ -189,6 +189,7 @@ export function useTableDataOfType(type: ValueType) {
return {
priority: v.priority ?? common("none"),
+ isDisposition: common(yesOrNoText(v.isDisposition)),
};
}
case ValueType.DRIVERSLICENSE_CATEGORY: {
@@ -275,7 +276,10 @@ export function useTableHeadersOfType(type: ValueType): ColumnDef<{ id: string }
];
}
case ValueType.CALL_TYPE: {
- return [{ header: t("priority"), accessorKey: "priority" }];
+ return [
+ { header: t("priority"), accessorKey: "priority" },
+ { header: t("isDisposition"), accessorKey: "isDisposition" },
+ ];
}
case ValueType.DRIVERSLICENSE_CATEGORY: {
return [
diff --git a/packages/schemas/src/admin/values/import.ts b/packages/schemas/src/admin/values/import.ts
index 7eed18f13..b45c13de6 100644
--- a/packages/schemas/src/admin/values/import.ts
+++ b/packages/schemas/src/admin/values/import.ts
@@ -144,6 +144,7 @@ export const QUALIFICATION_ARR = z.array(QUALIFICATION_SCHEMA).min(1);
*/
export const CALL_TYPE_SCHEMA = BASE_VALUE_SCHEMA.extend({
priority: z.string().nullish(),
+ isDisposition: z.boolean().nullish(),
});
export const CALL_TYPE_ARR = z.array(CALL_TYPE_SCHEMA).min(1);