From a7eab9c073bf59a42c84d31d8c8431dc9da29fcd Mon Sep 17 00:00:00 2001 From: Mike <100624415+marqueone-ps@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:58:05 -0800 Subject: [PATCH] feature/CE-39 - Add animal outcome (#271) --- backend/src/main.ts | 6 +- backend/src/types/models/code-tables/age.ts | 5 + .../models/code-tables/conflict-history.ts | 5 + .../types/models/code-tables/drug-method.ts | 5 + .../code-tables/drug-remaining-outcome.ts | 5 + backend/src/types/models/code-tables/drug.ts | 5 + .../src/types/models/code-tables/ear-tag.ts | 5 + backend/src/types/models/code-tables/index.ts | 15 +- backend/src/types/models/code-tables/sex.ts | 5 + .../types/models/code-tables/threat-level.ts | 5 + .../code-tables/wildlfe-complaint-outcome.ts | 5 + .../src/v1/code-table/code-table.service.ts | 99 ++++ frontend/package.json | 2 +- frontend/src/app/App.tsx | 4 +- frontend/src/app/common/methods.tsx | 84 +-- .../components/common/comp-icon-button.tsx | 29 ++ .../src/app/components/common/comp-input.tsx | 17 +- .../details/complaint-details-create.tsx | 4 +- .../details/complaint-details-edit.tsx | 4 +- .../animal-outcomes/add-animal-outcome.tsx | 436 ++++++++++++++++ .../outcomes/animal-outcomes/add-drug.tsx | 244 +++++++++ .../outcomes/animal-outcomes/add-ear-tag.tsx | 87 ++++ .../animal-outcomes/animal-outcome-item.tsx | 266 ++++++++++ .../animal-outcomes/drug-authorization.tsx | 89 ++++ .../outcomes/animal-outcomes/drug-item.tsx | 135 +++++ .../animal-outcomes/edit-animal-outcome.tsx | 431 ++++++++++++++++ .../hwcr-equipment/equipment-form.tsx | 4 +- .../outcomes/hwcr-outcome-by-animal.tsx | 128 ++++- .../outcomes/hwcr-outcome-report.tsx | 3 +- .../src/app/constants/code-table-types.ts | 12 +- frontend/src/app/store/reducers/code-table.ts | 478 +++++++++++++----- frontend/src/app/store/reducers/officer.ts | 62 ++- frontend/src/app/types/app/code-tables/age.ts | 5 + .../types/app/code-tables/conflict-history.ts | 5 + .../app/types/app/code-tables/drug-method.ts | 5 + .../app/code-tables/drug-remaining-outcome.ts | 5 + .../src/app/types/app/code-tables/drug.ts | 5 + .../src/app/types/app/code-tables/ear-tag.ts | 5 + frontend/src/app/types/app/code-tables/sex.ts | 5 + .../app/types/app/code-tables/threat-level.ts | 5 + .../code-tables/wildlife-complaint-outcome.ts | 5 + .../outcomes/wildlife/animal-outcome.ts | 23 + .../outcomes/wildlife/animal-tag.ts | 5 + .../outcomes/wildlife/drug-authorization.ts | 4 + .../complaints/outcomes/wildlife/drug-used.ts | 14 + .../src/app/types/state/code-table-state.ts | 29 +- frontend/src/assets/sass/app.scss | 1 + frontend/src/assets/sass/colours.scss | 1 + frontend/src/assets/sass/complaint.scss | 16 + frontend/src/assets/sass/form.scss | 22 + frontend/src/assets/sass/outcome-report.scss | 351 +++++++------ 51 files changed, 2811 insertions(+), 384 deletions(-) create mode 100644 backend/src/types/models/code-tables/age.ts create mode 100644 backend/src/types/models/code-tables/conflict-history.ts create mode 100644 backend/src/types/models/code-tables/drug-method.ts create mode 100644 backend/src/types/models/code-tables/drug-remaining-outcome.ts create mode 100644 backend/src/types/models/code-tables/drug.ts create mode 100644 backend/src/types/models/code-tables/ear-tag.ts create mode 100644 backend/src/types/models/code-tables/sex.ts create mode 100644 backend/src/types/models/code-tables/threat-level.ts create mode 100644 backend/src/types/models/code-tables/wildlfe-complaint-outcome.ts create mode 100644 frontend/src/app/components/common/comp-icon-button.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-animal-outcome.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-drug.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-ear-tag.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/animal-outcome-item.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-authorization.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-item.tsx create mode 100644 frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/edit-animal-outcome.tsx create mode 100644 frontend/src/app/types/app/code-tables/age.ts create mode 100644 frontend/src/app/types/app/code-tables/conflict-history.ts create mode 100644 frontend/src/app/types/app/code-tables/drug-method.ts create mode 100644 frontend/src/app/types/app/code-tables/drug-remaining-outcome.ts create mode 100644 frontend/src/app/types/app/code-tables/drug.ts create mode 100644 frontend/src/app/types/app/code-tables/ear-tag.ts create mode 100644 frontend/src/app/types/app/code-tables/sex.ts create mode 100644 frontend/src/app/types/app/code-tables/threat-level.ts create mode 100644 frontend/src/app/types/app/code-tables/wildlife-complaint-outcome.ts create mode 100644 frontend/src/app/types/app/complaints/outcomes/wildlife/animal-outcome.ts create mode 100644 frontend/src/app/types/app/complaints/outcomes/wildlife/animal-tag.ts create mode 100644 frontend/src/app/types/app/complaints/outcomes/wildlife/drug-authorization.ts create mode 100644 frontend/src/app/types/app/complaints/outcomes/wildlife/drug-used.ts create mode 100644 frontend/src/assets/sass/form.scss diff --git a/backend/src/main.ts b/backend/src/main.ts index ad6260a03..db01027c6 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -17,10 +17,10 @@ async function bootstrap() { process.env.TZ='UTC'; const config = new DocumentBuilder() - .setTitle("Compliance and Enforcement API") - .setDescription("The Complicance and Enforcement API") + .setTitle("Compliance and Enforcement - Complaint Management API") + .setDescription("The Complicance and Enforcement - Complaint Management API") .setVersion("1.0") - .addTag("Compliance and Enforcement") + .addTag("Compliance and Enforcement - Complaint Management") .build(); const document = SwaggerModule.createDocument(app, config); diff --git a/backend/src/types/models/code-tables/age.ts b/backend/src/types/models/code-tables/age.ts new file mode 100644 index 000000000..a18aba8c9 --- /dev/null +++ b/backend/src/types/models/code-tables/age.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface Age extends BaseCodeTable { + age: string; +} diff --git a/backend/src/types/models/code-tables/conflict-history.ts b/backend/src/types/models/code-tables/conflict-history.ts new file mode 100644 index 000000000..a3c67df99 --- /dev/null +++ b/backend/src/types/models/code-tables/conflict-history.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface ConflictHistory extends BaseCodeTable { + conflictHistory: string; +} diff --git a/backend/src/types/models/code-tables/drug-method.ts b/backend/src/types/models/code-tables/drug-method.ts new file mode 100644 index 000000000..a1f800c9e --- /dev/null +++ b/backend/src/types/models/code-tables/drug-method.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface DrugMethod extends BaseCodeTable { + method: string; +} diff --git a/backend/src/types/models/code-tables/drug-remaining-outcome.ts b/backend/src/types/models/code-tables/drug-remaining-outcome.ts new file mode 100644 index 000000000..7352ea7a6 --- /dev/null +++ b/backend/src/types/models/code-tables/drug-remaining-outcome.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface DrugRemainingOutcome extends BaseCodeTable { + outcome: string; +} diff --git a/backend/src/types/models/code-tables/drug.ts b/backend/src/types/models/code-tables/drug.ts new file mode 100644 index 000000000..81cb51712 --- /dev/null +++ b/backend/src/types/models/code-tables/drug.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface Drug extends BaseCodeTable { + drug: string; +} diff --git a/backend/src/types/models/code-tables/ear-tag.ts b/backend/src/types/models/code-tables/ear-tag.ts new file mode 100644 index 000000000..1df82e1a2 --- /dev/null +++ b/backend/src/types/models/code-tables/ear-tag.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface EarTag extends BaseCodeTable { + earTag: string; +} diff --git a/backend/src/types/models/code-tables/index.ts b/backend/src/types/models/code-tables/index.ts index b86ff6439..d5560ebc9 100644 --- a/backend/src/types/models/code-tables/index.ts +++ b/backend/src/types/models/code-tables/index.ts @@ -35,11 +35,18 @@ export const AvailableCodeTables = [ "justification", "assessment-type", "prevent-education-action", + "sex", + "age", + "threat-level", + "conflict-history", + "ear-tag", + "drugs", + "drug-methods", + "drug-remaining-outcomes", + "wildlife-outcomes", ]; -export const AvailableAgencies = [ - "cos" -] +export const AvailableAgencies = ["cos"]; export default BaseCodeTable; export { @@ -60,5 +67,5 @@ export { ReportedBy, Justification, AssessmentType, - PreventEducationAction + PreventEducationAction, }; diff --git a/backend/src/types/models/code-tables/sex.ts b/backend/src/types/models/code-tables/sex.ts new file mode 100644 index 000000000..f4b12de8c --- /dev/null +++ b/backend/src/types/models/code-tables/sex.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface Sex extends BaseCodeTable { + sex: string; +} diff --git a/backend/src/types/models/code-tables/threat-level.ts b/backend/src/types/models/code-tables/threat-level.ts new file mode 100644 index 000000000..a0c918a4e --- /dev/null +++ b/backend/src/types/models/code-tables/threat-level.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface ThreatLevel extends BaseCodeTable { + threatLevel: string; +} diff --git a/backend/src/types/models/code-tables/wildlfe-complaint-outcome.ts b/backend/src/types/models/code-tables/wildlfe-complaint-outcome.ts new file mode 100644 index 000000000..350dee7ac --- /dev/null +++ b/backend/src/types/models/code-tables/wildlfe-complaint-outcome.ts @@ -0,0 +1,5 @@ +import { BaseCodeTable } from "./code-table"; + +export interface WildlifeComplaintOutcome extends BaseCodeTable { + outcome: string; +} diff --git a/backend/src/v1/code-table/code-table.service.ts b/backend/src/v1/code-table/code-table.service.ts index 602071ab9..cf246bfef 100644 --- a/backend/src/v1/code-table/code-table.service.ts +++ b/backend/src/v1/code-table/code-table.service.ts @@ -34,6 +34,15 @@ import { ReportedByCode } from "../reported_by_code/entities/reported_by_code.en import { Justification } from "src/types/models/code-tables/justification"; import { AssessmentType } from "src/types/models/code-tables/assessment-type"; import { PreventEducationAction } from "src/types/models/code-tables/prevent-education-action"; +import { Sex } from "src/types/models/code-tables/sex"; +import { Age } from "src/types/models/code-tables/age"; +import { ThreatLevel } from "src/types/models/code-tables/threat-level"; +import { ConflictHistory } from "src/types/models/code-tables/conflict-history"; +import { EarTag } from "src/types/models/code-tables/ear-tag"; +import { Drug } from "src/types/models/code-tables/drug"; +import { DrugMethod } from "src/types/models/code-tables/drug-method"; +import { DrugRemainingOutcome } from "src/types/models/code-tables/drug-remaining-outcome"; +import { WildlifeComplaintOutcome } from "src/types/models/code-tables/wildlfe-complaint-outcome"; @Injectable() export class CodeTableService { @@ -428,6 +437,96 @@ export class CodeTableService { ]; return data; } + case "sex": { + const data: Array = [ + { sex: "M", shortDescription: "Male", longDescription: "Male", displayOrder: 1, isActive: true }, + { sex: "F", shortDescription: "Female", longDescription: "Female", displayOrder: 2, isActive: true }, + { sex: "U", shortDescription: "Unknown", longDescription: "Unknown", displayOrder: 3, isActive: true }, + ] + + return data; + } + case "age": { + const data: Array = [ + { age: "ADLT", shortDescription: "Adult", longDescription: "Adult", displayOrder: 1, isActive: true }, + { age: "YRLN", shortDescription: "Yearling", longDescription: "Yearling", displayOrder: 2, isActive: true }, + { age: "YOFY", shortDescription: "Young of the year", longDescription: "Young of the year", displayOrder: 3, isActive: true }, + { age: "UNKN", shortDescription: "Unknown", longDescription: "Unknown", displayOrder: 4, isActive: true }, + ] + + return data; + } + case "threat-level": { + const data: Array = [ + { threatLevel: "1", shortDescription: "Category 1", longDescription: "Category 1", displayOrder: 1, isActive: true }, + { threatLevel: "2", shortDescription: "Category 2", longDescription: "Category 2", displayOrder: 2, isActive: true }, + { threatLevel: "3", shortDescription: "Category 3", longDescription: "Category 3", displayOrder: 3, isActive: true }, + { threatLevel: "U", shortDescription: "Unknown", longDescription: "Unknown", displayOrder: 4, isActive: true }, + ] + + return data; + } + case "conflict-history": { + const data: Array = [ + { conflictHistory: "L", shortDescription: "Low", longDescription: "Low", displayOrder: 1, isActive: true }, + { conflictHistory: "M", shortDescription: "Medium", longDescription: "Medium", displayOrder: 2, isActive: true }, + { conflictHistory: "H", shortDescription: "High", longDescription: "High", displayOrder: 3, isActive: true }, + { conflictHistory: "U", shortDescription: "Unknown", longDescription: "Unknown", displayOrder: 4, isActive: true }, + ] + + return data; + } + case "ear-tag": { + const data: Array = [ + { earTag: "L", shortDescription: "Left", longDescription: "Left", displayOrder: 1, isActive: true }, + { earTag: "R", shortDescription: "Right", longDescription: "Right", displayOrder: 2, isActive: true }, + ] + + return data; + } + case "drugs": { + const data: Array = [ + { drug: "ATPMZ", shortDescription: "Atipamezole", longDescription: "Atipamezole", displayOrder: 1, isActive: true }, + { drug: "BAMII", shortDescription: "BAM II", longDescription: "Butorphanol Azaperone Medetomidine", displayOrder: 2, isActive: true }, + { drug: "MDTMD", shortDescription: "Medetomidine", longDescription: "Medetomidine", displayOrder: 3, isActive: true }, + { drug: "NLTRX", shortDescription: "Naltrexone", longDescription: "Naltrexone", displayOrder: 4, isActive: true }, + { drug: "ZLTIL", shortDescription: "Zoletil", longDescription: "Zoletil", displayOrder: 5, isActive: true }, + ] + + return data; + } + case "drug-methods": { + const data: Array = [ + { method: "DART", shortDescription: "Dart", longDescription: "Dart", displayOrder: 1, isActive: true }, + { method: "HINJ", shortDescription: "Hand injection", longDescription: "Hand injection", displayOrder: 2, isActive: true }, + { method: "PSRG", shortDescription: "Pole syringe", longDescription: "Pole syringe", displayOrder: 3, isActive: true }, + ] + + return data; + } + case "drug-remaining-outcomes": { + const data: Array = [ + { outcome: "DISC", shortDescription: "Discarded", longDescription: "Discarded", displayOrder: 1, isActive: true }, + { outcome: "STOR", shortDescription: "Storage", longDescription: "Storage", displayOrder: 2, isActive: true }, + { outcome: "RDIS", shortDescription: "Reverse distribution", longDescription: "Reverse distribution", displayOrder: 3, isActive: true }, + ] + + return data; + } + case "wildlife-outcomes": { + const data: Array = [ + { outcome: "DEADONARR", shortDescription: "Dead on arrival", longDescription: "Dead on arrival", displayOrder: 1, isActive: true }, + { outcome: "DESTRYCOS", shortDescription: "Destroyed by COS", longDescription: "Destroyed by COS", displayOrder: 2, isActive: true }, + { outcome: "DESTRYOTH", shortDescription: "Destroyed by other", longDescription: "Destroyed by other", displayOrder: 3, isActive: true }, + { outcome: "GONEONARR", shortDescription: "Gone on arrival", longDescription: "Gone on arrival", displayOrder: 4, isActive: true }, + { outcome: "REFRTOBIO", shortDescription: "Referred to biologist", longDescription: "Referred to biologist", displayOrder: 5, isActive: true }, + { outcome: "SHRTRELOC", shortDescription: "Short-distance relocation", longDescription: "Short-distance relocation", displayOrder: 6, isActive: true }, + { outcome: "TRANSLCTD", shortDescription: "Translocated", longDescription: "Translocated", displayOrder: 7, isActive: true }, + { outcome: "TRANSREHB", shortDescription: "Transfer to rehab", longDescription: "Transfer to rehab", displayOrder: 8, isActive: true }, + ] + + return data; + } } }; diff --git a/frontend/package.json b/frontend/package.json index d52c14254..08a8582ca 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -158,4 +158,4 @@ "overrides": { "typescript": "^5.0.4" } -} +} \ No newline at end of file diff --git a/frontend/src/app/App.tsx b/frontend/src/app/App.tsx index 4c52d7171..7281dc828 100644 --- a/frontend/src/app/App.tsx +++ b/frontend/src/app/App.tsx @@ -11,7 +11,7 @@ import ProtectedRoutes from "./components/routing"; import ScrollToTop from "./common/scroll-to-top"; import NotAuthorized, { NotFound } from "./components/containers/pages"; import { ComplaintDetailsEdit } from "./components/containers/complaints/details/complaint-details-edit"; -import ColorReference from "./components/reference"; +import ColorReference, { MiscReference, SpaceReference } from "./components/reference"; import { ModalComponent as Modal } from "./components/modal/modal"; import { useAppDispatch } from "./hooks/hooks"; import { ZoneAtAGlance } from "./components/containers/zone-at-a-glance/zone-at-a-glance"; @@ -63,7 +63,7 @@ const App: FC = () => { } /> } /> - } /> + } /> ); diff --git a/frontend/src/app/common/methods.tsx b/frontend/src/app/common/methods.tsx index 5656363b8..b575d740b 100644 --- a/frontend/src/app/common/methods.tsx +++ b/frontend/src/app/common/methods.tsx @@ -26,7 +26,11 @@ export const getAvatarInitials = (input: string): string => { } }; -export const getSelectedOfficer = (officers: Option[], personGuid: UUID | string, update: ComplaintDto | undefined): any => { +export const getSelectedOfficer = ( + officers: Option[], + personGuid: UUID | string, + update: ComplaintDto | undefined +): any => { if (update && personGuid) { const { delegates } = update; @@ -106,24 +110,22 @@ export const formatDateTime = (input: string | undefined): string => { // given a filename and complaint identifier, inject the complaint identifier inbetween the file name and extension export const injectComplaintIdentifierToFilename = (filename: string, complaintIdentifier: string): string => { // Find the last dot in the filename to separate the extension - const lastDotIndex = filename.lastIndexOf('.'); + const lastDotIndex = filename.lastIndexOf("."); // If there's no dot, just append the complaintId at the end if (lastDotIndex === -1) { - return (`${filename} ${complaintIdentifier}`); + return `${filename} ${complaintIdentifier}`; } const fileNameWithoutExtension = filename.substring(0, lastDotIndex); const fileExtension = filename.substring(lastDotIndex); // Otherwise, insert the complaintId before the extension - return (`${fileNameWithoutExtension} ${complaintIdentifier}${fileExtension}`); -} + return `${fileNameWithoutExtension} ${complaintIdentifier}${fileExtension}`; +}; // Used to retrieve the coordinates in the decimal format -export const parseDecimalDegreesCoordinates = ( - coordinates: Coordinate, -): { lat: number; lng: number } => { +export const parseDecimalDegreesCoordinates = (coordinates: Coordinate): { lat: number; lng: number } => { if (!coordinates) { return { lat: 0, lng: 0 }; } @@ -155,10 +157,7 @@ export const isWithinBC = (coordinates: Coordinate): boolean => { ); }; -export const parseCoordinates = ( - coordinates: Coordinate, - coordinateType: Coordinates, -): number | string => { +export const parseCoordinates = (coordinates: Coordinate, coordinateType: Coordinates): number | string => { if (!coordinates) { return 0; } @@ -179,10 +178,7 @@ export const getComplaintTypeFromUrl = (): number => { return -1; }; -export const renderCoordinates = ( - coordinates: Coordinate, - coordinateType: Coordinates, -): JSX.Element => { +export const renderCoordinates = (coordinates: Coordinate, coordinateType: Coordinates): JSX.Element => { const result = parseCoordinates(coordinates, coordinateType); return result === 0 ? <>{"Not Provided"} : <>{result}; @@ -199,60 +195,66 @@ export const applyStatusClass = (state: string): string => { } }; -export const truncateString = (str: string, maxLength: number): string=> { +export const truncateString = (str: string, maxLength: number): string => { if (str?.length > maxLength) { - return str.substring(0, maxLength) + '...'; // Adds an ellipsis to indicate truncation + return str.substring(0, maxLength) + "..."; // Adds an ellipsis to indicate truncation } else { return str; } -} +}; export const removeFile = (fileList: FileList, fileToRemove: File): File[] => { // Convert the FileList to an array const filesArray = Array.from(fileList); // Filter out the file you want to remove - const updatedFilesArray = filesArray.filter(file => file !== fileToRemove); + const updatedFilesArray = filesArray.filter((file) => file !== fileToRemove); return updatedFilesArray; -} +}; -export const getStatusByStatusCode = (code: string, codes: Array): string => { - if(from(codes).any(({complaintStatus}) => complaintStatus === code)){ - const selected = from(codes).first(({complaintStatus}) => complaintStatus === code) +export const getStatusByStatusCode = (code: string, codes: Array): string => { + if (from(codes).any(({ complaintStatus }) => complaintStatus === code)) { + const selected = from(codes).first(({ complaintStatus }) => complaintStatus === code); - return selected.longDescription + return selected.longDescription; } return ""; -} +}; -export const getViolationByViolationCode = (code: string, codes: Array): string => { - if(codes && from(codes).any(({violation}) => violation === code)){ - const selected = from(codes).first(({violation}) => violation === code); +export const getViolationByViolationCode = (code: string, codes: Array): string => { + if (codes && from(codes).any(({ violation }) => violation === code)) { + const selected = from(codes).first(({ violation }) => violation === code); return selected.longDescription; } - return "" -} + return ""; +}; -export const getSpeciesBySpeciesCode = (code: string, codes: Array): string => { - if(codes && from(codes).any(({species}) => species === code)){ - const selected = from(codes).first(({species}) => species === code); +export const getSpeciesBySpeciesCode = (code: string, codes: Array): string => { + if (codes && from(codes).any(({ species }) => species === code)) { + const selected = from(codes).first(({ species }) => species === code); return selected.longDescription; } - return "" -} + return ""; +}; -export const getNatureOfComplaintByNatureOfComplaintCode = (code: string, codes: Array): string => { - if(codes && from(codes).any(({natureOfComplaint}) => natureOfComplaint === code)){ - const selected = from(codes).first(({natureOfComplaint}) => natureOfComplaint === code); +export const getNatureOfComplaintByNatureOfComplaintCode = (code: string, codes: Array): string => { + if (codes && from(codes).any(({ natureOfComplaint }) => natureOfComplaint === code)) { + const selected = from(codes).first(({ natureOfComplaint }) => natureOfComplaint === code); return selected.longDescription; } - return "" -} + return ""; +}; + +export const pad = (num: string, size: number): string => { + num = num.toString(); + while (num.length < size) num = "0" + num; + return num; +}; diff --git a/frontend/src/app/components/common/comp-icon-button.tsx b/frontend/src/app/components/common/comp-icon-button.tsx new file mode 100644 index 000000000..3f356f435 --- /dev/null +++ b/frontend/src/app/components/common/comp-icon-button.tsx @@ -0,0 +1,29 @@ +import { FC } from "react"; + +type props = { + classNames?: string; + children: React.ReactNode; + onClick: Function; +}; + +export const CompIconButton: FC = ({ classNames, children, onClick }) => { + const handleClickEvent = () => { + onClick() + }; + + const renderClassNames = () => { + let results = "comp-icon-button-container"; + + if(classNames){ + results = `${results} ${classNames}` + } + + return results; + } + + return ( + + ); +}; diff --git a/frontend/src/app/components/common/comp-input.tsx b/frontend/src/app/components/common/comp-input.tsx index 3e494eccc..add7c0870 100644 --- a/frontend/src/app/components/common/comp-input.tsx +++ b/frontend/src/app/components/common/comp-input.tsx @@ -2,7 +2,7 @@ import { FC } from "react"; type Props = { id: string; - divId: string; + divid: string; type: "input" | "number" | "text"; label?: string; inputClass?: string; @@ -26,7 +26,7 @@ const noop = () => {}; export const CompInput: FC = ({ id, - divId, + divid, type, inputClass, formClass, @@ -64,6 +64,7 @@ export const CompInput: FC = ({ const props = { id: id, + divid, value: value, // defaultValue: defaultValue, className: inputClasses.join(" "), @@ -82,7 +83,7 @@ export const CompInput: FC = ({ } return ( -
+
{label && (
- - //
- // {label && ( - // - // )} - // {Component} - // {error &&
{error}
} - //
); }; diff --git a/frontend/src/app/components/containers/complaints/details/complaint-details-create.tsx b/frontend/src/app/components/containers/complaints/details/complaint-details-create.tsx index ceb4ba17a..8f5f8c4fd 100644 --- a/frontend/src/app/components/containers/complaints/details/complaint-details-create.tsx +++ b/frontend/src/app/components/containers/complaints/details/complaint-details-create.tsx @@ -829,7 +829,7 @@ export const CreateComplaint: FC = () => { { /> { { /> = ({ animalCount, agency, species, assigned, add, cancel }) => { + const speciesList = useAppSelector(selectSpeciesCodeDropdown); + const ages = useAppSelector(selectAgeDropdown); + const sexes = useAppSelector(selectSexDropdown); + const threatLevels = useAppSelector(selectThreatLevelDropdown); + const conflictHistories = useAppSelector(selectConflictHistoryDropdown); + + const outcomes = useAppSelector(selectWildlifeComplaintOutcome); + const officers = useAppSelector(selectOfficersByAgencyDropdown(agency)); + + const [data, applyData] = useState({ + id: animalCount, + species: "", + sex: "", + age: "", + threatLevel: "", + conflictHistory: "", + tags: [], + drugs: [], + outcome: "", + officer: "", + isEditable: false + }); + + useEffect(() => { + if (species) { + updateModel("species", species); + } + }, [species]); + + useEffect(() => { + if (assigned) { + updateModel("officer", assigned); + } + }, [assigned]); + + const getValue = (property: string): Option | undefined => { + switch (property) { + case "species": { + const { species } = data; + return speciesList.find((item) => item.value === species); + } + case "sex": { + const { sex } = data; + return sexes.find((item) => item.value === sex); + } + + case "age": { + const { age } = data; + return ages.find((item) => item.value === age); + } + + case "threatLevel": { + const { threatLevel } = data; + return threatLevels.find((item) => item.value === threatLevel); + } + + case "conflictHistory": { + const { conflictHistory } = data; + return conflictHistories.find((item) => item.value === conflictHistory); + } + + case "assigned": { + const { officer } = data; + return officers.find((item) => item.value === officer); + } + + case "outcome": { + const { outcome } = data; + return outcomes.find((item) => item.value === outcome); + } + } + }; + + const isValid = (): boolean => { + const { species, sex, age, threatLevel, conflictHistory, outcome, officer, date } = data; + + let isValid = true; + + if (!species || !age || !sex || !threatLevel || !conflictHistory) { + isValid = false; + } + + if (!outcome || !officer || !date) { + isValid = false; + } + + return isValid; + }; + + const updateModel = (property: string, value: string | Date | Array | null | undefined) => { + const model = { ...data, [property]: value }; + applyData(model); + }; + + const save = () => { + if (isValid()) { + console.log("add animal"); + add(data); + } else { + console.log("show errors"); + } + }; + + const addEarTag = () => { + const { tags } = data; + + if (tags.length < 2) { + let id = tags.length + 1; + + const update = [...tags, { id, ear: "", number: "" }]; + updateModel("tags", update); + } + }; + + const renderEarTags = () => { + const { tags } = data; + + if (tags && from(tags).any()) { + let isLeftEarUsed = false; + + const selected = tags.find((item) => item.ear === "L"); + if (selected) { + isLeftEarUsed = true; + } + + return from(tags) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + const { id } = item; + return ( + + ); + }); + } + }; + + const updateEarTag = (tag: AnimalTag) => { + const { tags: source } = data; + + const items = source.filter(({ id }) => id !== tag.id); + const update = [...items, tag]; + + updateModel("tags", update); + }; + + const removeEarTag = (id: number) => { + const { tags: source } = data; + const items = source.filter((tag) => id !== tag.id); + let updatedId = 0; + + const update = from(items) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + updatedId = updatedId + 1; + return { ...item, id: updatedId }; + }); + + updateModel("tags", update); + }; + + const addDrug = () => { + const { drugs } = data; + + let id = drugs.length + 1; + + const update = [ + ...drugs, + { + id, + vial: "", + drug: "", + amountUsed: -1, + amountDiscarded: -1, + reactions: "", + remainingUse: "", + injectionMethod: "", + discardMethod: "", + officer: "", + }, + ]; + updateModel("drugs", update); + }; + + const renderDrugs = () => { + const { drugs } = data; + + if (drugs && from(drugs).any()) { + const { drugAuthorization } = data; + + return ( + <> + {from(drugs) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + const { id } = item; + return ; + })} + + + + ); + } + }; + + const removeDrug = (id: number) => { + const { drugs: source } = data; + const items = source.filter((drug) => id !== drug.id); + let updatedId = 0; + + const update = from(items) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + updatedId = updatedId + 1; + return { ...item, id: updatedId }; + }); + + updateModel("drugs", update); + }; + + const updateDrug = (drug: DrugUsed) => { + const { drugs: source } = data; + + const items = source.filter(({ id }) => id !== drug.id); + const update = [...items, drug]; + + updateModel("drugs", update); + }; + + return ( +
+
+
Animal {pad(animalCount.toString(), 2)}
+
+
Animal information
+ +
+ + + + { + updateModel("species", evt?.value); + }} + value={getValue("species")} + /> + + + + { + updateModel("sex", evt?.value); + }} + value={getValue("sex")} + /> + + + + { + updateModel("age", evt?.value); + }} + value={getValue("age")} + /> + + + + { + updateModel("threatLevel", evt?.value); + }} + value={getValue("threatLevel")} + /> + + + + { + updateModel("conflictHistory", evt?.value); + }} + value={getValue("conflictHistory")} + /> + + +
+ + {renderEarTags()} + {data.tags.length < 2 && ( + + )} + + {renderDrugs()} + + +
Outcome
+
+ + + { + updateModel("outcome", evt?.value); + }} + value={getValue("outcome")} + /> + + +
+ + { + updateModel("officer", evt?.value); + }} + className="comp-details-input" + options={officers} + placeholder="Select" + enableValidation={false} + value={getValue("assigned")} + /> +
+ + + +
+ + { + updateModel("date", evt); + }} + selected={data.date} + /> +
+ +
+
+ +
+ + +
+
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-drug.tsx b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-drug.tsx new file mode 100644 index 000000000..9b8d00051 --- /dev/null +++ b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-drug.tsx @@ -0,0 +1,244 @@ +import { FC, useState } from "react"; +import { Row, Col } from "react-bootstrap"; +import { CompInput } from "../../../../common/comp-input"; +import { CompSelect } from "../../../../common/comp-select"; +import { BsFillXCircleFill, BsXCircle } from "react-icons/bs"; +import { useAppSelector } from "../../../../../hooks/hooks"; +import { selectDrugUseMethods, selectDrugs, selectRemainingDrugUse } from "../../../../../store/reducers/code-table"; +import { CompIconButton } from "../../../../common/comp-icon-button"; +import Option from "../../../../../types/app/option"; + +type props = { + id: number; + + vial: string; + drug: string; + amountUsed: number; + amountDiscarded: number; + + reactions: string; + remainingUse: string; + + injectionMethod: string; + discardMethod: string; + + remove: Function; + update: Function; +}; + +export const AddDrug: FC = ({ + id, + vial, + drug, + amountUsed, + injectionMethod, + discardMethod, + amountDiscarded, + reactions, + remainingUse, + remove, + update, +}) => { + const drugs = useAppSelector(selectDrugs); + const drugUseMethods = useAppSelector(selectDrugUseMethods); + const remainingDrugUse = useAppSelector(selectRemainingDrugUse); + + const [showDiscarded, setShowDiscarded] = useState(true); + + const updateModel = (property: string, value: string | Date | number | null | undefined) => { + const source = { + id, + vial, + drug, + amountUsed, + amountDiscarded, + reactions, + remainingUse, + injectionMethod, + discardMethod, + }; + const updatedTag = { ...source, [property]: value }; + + update(updatedTag); + }; + + const getValue = (property: string): Option | undefined => { + switch (property) { + case "drug": { + return drugs.find((item) => item.value === drug); + } + + case "injection-method": { + return drugUseMethods.find((item) => item.value === injectionMethod); + } + + case "remaining": { + return remainingDrugUse.find((item) => item.value === remainingUse); + } + } + }; + + const handleAmountUsed = (input: string) => { + updateModel("amountUsed", input); + }; + + const handleAmountDiscarded = (input: string) => { + updateModel("amountDiscarded", input); + }; + + const handleRemainingUsed = (input: string) => { + setShowDiscarded(input === "DISC"); + updateModel("remainingUse", input); + }; + + return ( +
+ + + + { + const { + target: { value }, + } = evt; + updateModel("vial", value); + }} + /> + + + + { + updateModel("drug", evt?.value); + }} + value={getValue("drug")} + /> + + + + { + const { + target: { value }, + } = evt; + handleAmountUsed(value); + }} + /> + + + + { + updateModel("injectionMethod", evt?.value); + }} + value={getValue("injection-method")} + /> + + + + { + const { + target: { value }, + } = evt; + updateModel("reactions", value); + }} + /> + + + remove(id)}> + + + + + + + + + { + handleRemainingUsed(evt?.value ?? ""); + }} + value={getValue("remaining")} + /> + + + {showDiscarded && ( + <> + {" "} + + { + const { + target: { value }, + } = evt; + handleAmountDiscarded(value); + }} + /> + + )} + + + {showDiscarded && ( + <> + + { + const { + target: { value }, + } = evt; + updateModel("discardMethod", value); + }} + /> + + )} + + + + +
+
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-ear-tag.tsx b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-ear-tag.tsx new file mode 100644 index 000000000..9562e1fa8 --- /dev/null +++ b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/add-ear-tag.tsx @@ -0,0 +1,87 @@ +import { FC, useEffect } from "react"; +import { Col, Row } from "react-bootstrap"; +import { CompInput } from "../../../../common/comp-input"; +import { CompSelect } from "../../../../common/comp-select"; +import { useAppSelector } from "../../../../../hooks/hooks"; +import { selectEarDropdown } from "../../../../../store/reducers/code-table"; +import { BsXCircle, BsFillXCircleFill } from "react-icons/bs"; +import { CompIconButton } from "../../../../common/comp-icon-button"; + +type props = { + id: number; + ear: string; + number: string; + isLeftEarUsed: boolean; + update: Function; + remove: Function; +}; + +export const AddEarTag: FC = ({ id, ear, number, isLeftEarUsed, update, remove }) => { + const ears = useAppSelector(selectEarDropdown); + const leftEar = ears.find((ear) => ear.value === "L"); + const rightEar = ears.find((ear) => ear.value === "R"); + + let selectedEar = ear === "R" ? rightEar : leftEar; + + useEffect(() => { + if (!ear) { + updateModel("ear", isLeftEarUsed ? "R" : "L"); + } + }, [ear, isLeftEarUsed]); + + const updateModel = (property: string, value: string | undefined) => { + const source = { id, ear, number }; + const updatedTag = { ...source, [property]: value }; + + update(updatedTag); + }; + + return ( +
+ + + + { + const { + target: { value }, + } = evt; + + if (value.length <= 6) { + updateModel("number", value); + } + }} + /> + + + + { + updateModel("ear", evt?.value); + }} + value={selectedEar} + /> + + + remove(id)}> + + + + + + + +
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/animal-outcome-item.tsx b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/animal-outcome-item.tsx new file mode 100644 index 000000000..4f740d301 --- /dev/null +++ b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/animal-outcome-item.tsx @@ -0,0 +1,266 @@ +import { FC, useEffect, useState } from "react"; +import { AnimalTag } from "../../../../../types/app/complaints/outcomes/wildlife/animal-tag"; +import { DrugUsed } from "../../../../../types/app/complaints/outcomes/wildlife/drug-used"; +import { DrugAuthorization } from "../../../../../types/app/complaints/outcomes/wildlife/drug-authorization"; +import { useAppSelector } from "../../../../../hooks/hooks"; +import { + selectSpeciesCodeDropdown, + selectAgeDropdown, + selectSexDropdown, + selectThreatLevelDropdown, + selectConflictHistoryDropdown, + selectWildlifeComplaintOutcome, + selectEarDropdown, +} from "../../../../../store/reducers/code-table"; +import { selectOfficersByAgencyDropdown } from "../../../../../store/reducers/officer"; +import { formatDate, getAvatarInitials } from "../../../../../common/methods"; +import { from } from "linq-to-typescript"; +import { DrugItem } from "./drug-item"; +import { Button } from "react-bootstrap"; +import { BsPencil } from "react-icons/bs"; + +type props = { + id: number; + agency: string; + species: string; + sex: string; + age: string; + threatLevel: string; + conflictHistory: string; + tags: Array; + drugs: Array; + drugAuthorization?: DrugAuthorization; + outcome: string; + officer: string; + date?: Date; + isEditable: boolean; + edit: Function; +}; +export const AnimalOutcomeItem: FC = ({ + id, + agency, + species, + sex, + age, + threatLevel, + conflictHistory, + tags, + drugs, + drugAuthorization, + outcome, + officer, + edit, +}) => { + const speciesList = useAppSelector(selectSpeciesCodeDropdown); + const ages = useAppSelector(selectAgeDropdown); + const sexes = useAppSelector(selectSexDropdown); + const threatLevels = useAppSelector(selectThreatLevelDropdown); + const conflictHistories = useAppSelector(selectConflictHistoryDropdown); + + const ears = useAppSelector(selectEarDropdown); + const leftEar = ears.find((ear) => ear.value === "L"); + const rightEar = ears.find((ear) => ear.value === "R"); + + const outcomes = useAppSelector(selectWildlifeComplaintOutcome); + const officers = useAppSelector(selectOfficersByAgencyDropdown(agency)); + + const [animal, setAnimal] = useState(""); + const [animalSex, setAnimalSex] = useState(""); + const [animalAge, setAnimalAge] = useState(""); + const [animalThreatLevel, setAnimalThreatLevel] = useState(""); + const [animalHistory, setAnimalHistory] = useState(""); + const [animalOutcome, setAnimalOutcome] = useState(""); + + useEffect(() => { + if (species) { + const selected = from(speciesList).firstOrDefault((item) => item.value === species); + if (selected?.label) { + setAnimal(selected.label); + } + } + }, [species, speciesList]); + + useEffect(() => { + if (sex) { + const selected = from(sexes).firstOrDefault((item) => item.value === sex); + if (selected?.label) { + setAnimalSex(selected.label); + } + } + }, [sex, sexes]); + + useEffect(() => { + if (age) { + const selected = from(ages).firstOrDefault((item) => item.value === age); + if (selected?.label) { + setAnimalAge(selected.label); + } + } + }, [age, ages]); + + useEffect(() => { + if (threatLevel) { + const selected = from(threatLevels).firstOrDefault((item) => item.value === threatLevel); + if (selected?.label) { + setAnimalThreatLevel(selected.label); + } + } + }, [threatLevel, threatLevels]); + + useEffect(() => { + if (conflictHistory) { + const selected = from(conflictHistories).firstOrDefault((item) => item.value === conflictHistory); + if (selected?.label) { + setAnimalHistory(selected.label); + } + } + }, [conflictHistory, conflictHistories]); + + useEffect(() => { + if (outcome) { + const selected = from(outcomes).firstOrDefault((item) => item.value === outcome); + if (selected?.label) { + setAnimalOutcome(selected.label); + } + } + }, [outcome, outcomes]); + + const assignedOfficer = () => { + if (officer) { + const selected = officers.find((item) => item.value === officer); + return selected?.label ?? ""; + } + + return ""; + }; + + return ( +
+
+
+
+
+
+ +
+
+ {animal}, +
+
{animalSex},
+
{animalAge}
+
+ Threat level: {animalThreatLevel} +
+
+ Conflict history: {animalHistory} +
+
+
+
+
+
+ + {from(tags).any() && ( +
+
+
+ +
    + {tags.map(({ id, number, ear }) => ( +
  • + {number} {ear === "L" ? leftEar?.label : rightEar?.label} side +
  • + ))} +
+
+
+
+
+ )} + + {from(drugs).any() && ( +
+
+
+ + +
+ {drugs.map((item) => { + const { officer, date } = drugAuthorization || {}; + return ; + })} +
+
+
+
+ )} + +
+
+
+ + {animalOutcome} +
+
+
+
+ +
+
+
+ +
+ + {assignedOfficer()} + +
+
+
+
+
+ +
+ {formatDate(new Date().toString())} +
+
+
+
+
+
+
+ +
+
+
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-authorization.tsx b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-authorization.tsx new file mode 100644 index 000000000..435442562 --- /dev/null +++ b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-authorization.tsx @@ -0,0 +1,89 @@ +import { FC, useEffect } from "react"; +import { Row, Col } from "react-bootstrap"; +import { CompSelect } from "../../../../common/comp-select"; +import DatePicker from "react-datepicker"; +import { useAppSelector } from "../../../../../hooks/hooks"; +import { selectOfficersByAgencyDropdown } from "../../../../../store/reducers/officer"; +import Option from "../../../../../types/app/option"; + +type Props = { + assigned: string | null; + officer?: string; + date?: Date; + agency: string; + update: Function; +}; + +export const DrugAuthorization: FC = ({ agency, assigned, officer, date, update }) => { + const officers = useAppSelector(selectOfficersByAgencyDropdown(agency)); + + useEffect(() => { + if(!officer && assigned){ + updateModel("officer", assigned) + } + }, [officer, assigned]) + + const getValue = (property: string): Option | undefined => { + if (property === "officer") { + return officers.find((item) => item.value === (officer)); + } + }; + + const updateModel = (property: string, value: string | Date | null | undefined) => { + const source = { officer, date }; + const authorization = { ...source, [property]: value }; + + update("drugAuthorization", authorization); + }; + + + return ( +
+ + +
+ + { + updateModel("officer", evt?.value); + }} + className="comp-details-input" + options={officers} + placeholder="Select" + enableValidation={false} + value={getValue("officer")} + /> +
+ + + +
+ + { + updateModel("date", evt); + }} + selected={date} + /> +
+ + + +
+
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-item.tsx b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-item.tsx new file mode 100644 index 000000000..508a80d70 --- /dev/null +++ b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/drug-item.tsx @@ -0,0 +1,135 @@ +import { FC, useEffect, useState } from "react"; +import { Row, Col } from "react-bootstrap"; +import { useAppSelector } from "../../../../../hooks/hooks"; +import { selectDrugs, selectDrugUseMethods, selectRemainingDrugUse } from "../../../../../store/reducers/code-table"; +import { formatDate, getAvatarInitials } from "../../../../../common/methods"; +import { selectOfficersByAgencyDropdown } from "../../../../../store/reducers/officer"; +import { from } from "linq-to-typescript"; + +type props = { + vial: string; + drug: string; + amountUsed: number; + amountDiscarded: number; + + injectionMethod: string; + discardMethod: string; + + reactions: string; + remainingUse: string; + + officer?: string; + date?: Date; + + agency: string; +}; + +export const DrugItem: FC = ({ + vial, + drug, + amountUsed, + amountDiscarded, + injectionMethod, + discardMethod, + reactions, + remainingUse, + officer, + date, + agency, +}) => { + const drugs = useAppSelector(selectDrugs); + const drugUseMethods = useAppSelector(selectDrugUseMethods); + const remainingDrugUse = useAppSelector(selectRemainingDrugUse); + const officers = useAppSelector(selectOfficersByAgencyDropdown(agency)); + + const [injectedMethod, setInjectedMethod] = useState(""); + const [remaining, setRemaining] = useState(""); + const [drugUsed, setDrugUsed] = useState(""); + + useEffect(() => { + if (injectionMethod) { + const selected = from(drugUseMethods).firstOrDefault((item) => item.value === injectionMethod); + if (selected?.label) { + setInjectedMethod(selected.label); + } + } + }, [drugUseMethods, injectionMethod]); + + useEffect(() => { + if (remainingUse) { + const selected = from(remainingDrugUse).firstOrDefault((item) => item.value === remainingUse); + if (selected?.label) { + setRemaining(selected.label); + } + } + }, [remainingDrugUse, remainingUse]); + + useEffect(() => { + if (drug) { + const selected = from(drugs).firstOrDefault((item) => item.value === drug); + if (selected?.label) { + setDrugUsed(selected.label); + } + } + }, [drug, drugs]); + + const assignedOfficer = () => { + if (officer) { + const selected = officers.find((item) => item.value === officer); + return selected?.label ?? ""; + } + + return ""; + }; + + return ( +
+ + + Vial #{vial} + + + {drugUsed} + + + + + Amount used {amountUsed}ml + + + Injection method {injectedMethod} + + + Adverse reactions {reactions} + + + + + Fate of remaining drug in vial {remaining} + + + Amount discarded {amountDiscarded}ml + + + Discard method {discardMethod} + + + + + Officer +
+ + {assignedOfficer()} + +
+ + + Date {formatDate(date?.toString())} + +
+
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/edit-animal-outcome.tsx b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/edit-animal-outcome.tsx new file mode 100644 index 000000000..48a0dc6fd --- /dev/null +++ b/frontend/src/app/components/containers/complaints/outcomes/animal-outcomes/edit-animal-outcome.tsx @@ -0,0 +1,431 @@ +import { FC, useState } from "react"; +import { AnimalTag } from "../../../../../types/app/complaints/outcomes/wildlife/animal-tag"; +import { DrugUsed } from "../../../../../types/app/complaints/outcomes/wildlife/drug-used"; +import { useAppSelector } from "../../../../../hooks/hooks"; +import { + selectSpeciesCodeDropdown, + selectAgeDropdown, + selectSexDropdown, + selectThreatLevelDropdown, + selectConflictHistoryDropdown, + selectWildlifeComplaintOutcome, +} from "../../../../../store/reducers/code-table"; +import { selectOfficersByAgencyDropdown } from "../../../../../store/reducers/officer"; +import { AnimalOutcome } from "../../../../../types/app/complaints/outcomes/wildlife/animal-outcome"; +import { pad } from "../../../../../common/methods"; +import { Row, Col, Button } from "react-bootstrap"; +import { CompSelect } from "../../../../common/comp-select"; +import Option from "../../../../../types/app/option"; +import { from } from "linq-to-typescript"; +import { AddEarTag } from "./add-ear-tag"; +import { BsPlusCircle } from "react-icons/bs"; +import { AddDrug } from "./add-drug"; +import { DrugAuthorization } from "../../../../../types/app/complaints/outcomes/wildlife/drug-authorization"; +import { DrugAuthorization as AddDrugAuthorization } from "./drug-authorization"; +import DatePicker from "react-datepicker"; + +type props = { + id: number; + agency: string; + species: string; + sex: string; + age: string; + threatLevel: string; + conflictHistory: string; + tags: Array; + drugs: Array; + drugAuthorization?: DrugAuthorization; + outcome: string; + officer: string; + date?: Date; + isEditable: boolean; + update: Function; + cancel: Function; +}; + +export const EditAnimalOutcome: FC = ({ + id, + agency, + species, + sex, + age, + threatLevel, + conflictHistory, + tags, + drugs, + drugAuthorization, + outcome, + officer, + date, + isEditable, + update, + cancel, +}) => { + const speciesList = useAppSelector(selectSpeciesCodeDropdown); + const ages = useAppSelector(selectAgeDropdown); + const sexes = useAppSelector(selectSexDropdown); + const threatLevels = useAppSelector(selectThreatLevelDropdown); + const conflictHistories = useAppSelector(selectConflictHistoryDropdown); + + const outcomes = useAppSelector(selectWildlifeComplaintOutcome); + const officers = useAppSelector(selectOfficersByAgencyDropdown(agency)); + + const [data, applyData] = useState({ + id, + species, + sex, + age, + threatLevel, + conflictHistory, + tags, + drugs, + outcome, + officer, + date, + isEditable, + }); + + const updateModel = (property: string, value: string | Date | Array | null | undefined) => { + const model = { ...data, [property]: value }; + applyData(model); + }; + + const getValue = (property: string): Option | undefined => { + switch (property) { + case "species": { + const { species } = data; + return speciesList.find((item) => item.value === species); + } + case "sex": { + const { sex } = data; + return sexes.find((item) => item.value === sex); + } + + case "age": { + const { age } = data; + return ages.find((item) => item.value === age); + } + + case "threatLevel": { + const { threatLevel } = data; + return threatLevels.find((item) => item.value === threatLevel); + } + + case "conflictHistory": { + const { conflictHistory } = data; + return conflictHistories.find((item) => item.value === conflictHistory); + } + + case "assigned": { + const { officer } = data; + return officers.find((item) => item.value === officer); + } + + case "outcome": { + const { outcome } = data; + return outcomes.find((item) => item.value === outcome); + } + } + }; + + const renderEarTags = () => { + const { tags } = data; + + if (tags && from(tags).any()) { + let isLeftEarUsed = false; + + const selected = tags.find((item) => item.ear === "L"); + if (selected) { + isLeftEarUsed = true; + } + + return from(tags) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + const { id } = item; + return ( + + ); + }); + } + }; + + const addEarTag = () => { + const { tags } = data; + + if (tags.length < 2) { + let id = tags.length + 1; + + const update = [...tags, { id, ear: "", number: "" }]; + updateModel("tags", update); + } + }; + + const updateEarTag = (tag: AnimalTag) => { + const { tags: source } = data; + + const items = source.filter(({ id }) => id !== tag.id); + const update = [...items, tag]; + + updateModel("tags", update); + }; + + const removeEarTag = (id: number) => { + const { tags: source } = data; + const items = source.filter((tag) => id !== tag.id); + let updatedId = 0; + + const update = from(items) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + updatedId = updatedId + 1; + return { ...item, id: updatedId }; + }); + + updateModel("tags", update); + }; + + const addDrug = () => { + const { drugs } = data; + + let id = drugs.length + 1; + + const update = [ + ...drugs, + { + id, + vial: "", + drug: "", + amountUsed: -1, + amountDiscarded: -1, + reactions: "", + remainingUse: "", + injectionMethod: "", + discardMethod: "", + officer: "", + }, + ]; + updateModel("drugs", update); + }; + + const removeDrug = (id: number) => { + const { drugs: source } = data; + const items = source.filter((drug) => id !== drug.id); + let updatedId = 0; + + const update = from(items) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + updatedId = updatedId + 1; + return { ...item, id: updatedId }; + }); + + updateModel("drugs", update); + }; + + const updateDrug = (drug: DrugUsed) => { + const { drugs: source } = data; + + const items = source.filter(({ id }) => id !== drug.id); + const update = [...items, drug]; + + updateModel("drugs", update); + }; + + const renderDrugs = () => { + const { drugs } = data; + + if (drugs && from(drugs).any()) { + return ( + <> + {from(drugs) + .orderBy((item) => item.id) + .toArray() + .map((item) => { + const { id } = item; + return ; + })} + + + + ); + } + }; + + return ( +
+
+
Animal {pad(id.toString(), 2)}
+
+
Animal information
+ +
+ + + + { + updateModel("species", evt?.value); + }} + value={getValue("species")} + /> + + + + { + updateModel("sex", evt?.value); + }} + value={getValue("sex")} + /> + + + + { + updateModel("age", evt?.value); + }} + value={getValue("age")} + /> + + + + { + updateModel("threatLevel", evt?.value); + }} + value={getValue("threatLevel")} + /> + + + + { + updateModel("conflictHistory", evt?.value); + }} + value={getValue("conflictHistory")} + /> + + +
+ + {renderEarTags()} + {data.tags.length < 2 && ( + + )} + + {renderDrugs()} + + +
Outcome
+
+ + + + { + updateModel("outcome", evt?.value); + }} + value={getValue("outcome")} + /> + + +
+ + { + updateModel("officer", evt?.value); + }} + className="comp-details-input" + options={officers} + placeholder="Select" + enableValidation={false} + value={getValue("assigned")} + /> +
+ + + +
+ + { + updateModel("date", evt); + }} + selected={data.date} + /> +
+ +
+ +
+ + +
+
+ ); +}; diff --git a/frontend/src/app/components/containers/complaints/outcomes/hwcr-equipment/equipment-form.tsx b/frontend/src/app/components/containers/complaints/outcomes/hwcr-equipment/equipment-form.tsx index 7474d9c02..e869c9f55 100644 --- a/frontend/src/app/components/containers/complaints/outcomes/hwcr-equipment/equipment-form.tsx +++ b/frontend/src/app/components/containers/complaints/outcomes/hwcr-equipment/equipment-form.tsx @@ -274,7 +274,7 @@ export const EquipmentForm: FC = ({
= ({
{ - return ( -
-
Outcome by animal
-
- -
-
- ); +export const HWCROutcomeByAnimal: FC = () => { + const complaint = useAppSelector(selectComplaint); + + const { species, delegates, ownedBy: agency } = (complaint as WildlifeComplaint) || {}; + const [animals, setAnimals] = useState>([]); + const [showForm, setShowForm] = useState(false); + const [assigned, setAssigned] = useState(""); + + useEffect(() => { + if (delegates && from(delegates).any()) { + const assigned = delegates.find((item) => item.type === "ASSIGNEE"); + if (assigned && assigned?.person !== null) { + const { + person: { id }, + } = assigned; + setAssigned(id); + } + } + }, [complaint, delegates]); + + const add = (model: AnimalOutcome) => { + const update = [...animals, model]; + setAnimals(update); + setShowForm(false); + }; + + const cancel = () => { + setShowForm(false); + }; + + const updateEditFlag = (id: number, isEditable: boolean) => { + if (from(animals).any((item) => item.id === id)) { + let original = from(animals).first((item) => item.id === id); + let editable = { ...original, isEditable }; + + let index = animals.findIndex((item) => item.id === id); + + let update = [...animals.slice(0, index), editable, ...animals.slice(index + 1)]; + setAnimals(update); + } + }; + + const edit = (id: number) => { + updateEditFlag(id, true); + }; + + const cancelEdit = (id: number) => { + updateEditFlag(id, false); + }; + + const update = (model: AnimalOutcome) => { + const { id } = model; + + if (from(animals).any((item) => item.id === id)) { + const filtered = animals.filter((item) => item.id !== id); + const updated = [...filtered, model]; + const update = from(updated) + .orderBy((item) => item.id) + .toArray(); + + setAnimals(update); + } + }; + + const renderAnimals = () => { + if (animals && from(animals).any()) { + return animals.map((outcome) => { + const { id, isEditable } = outcome; + + return isEditable ? ( + + ) : ( + + ); + }); + } + }; + + return ( +
+
Outcome by animal
+
+ {renderAnimals()} + + {!showForm ? ( + + ) : ( + + )} +
+
+ ); }; - \ No newline at end of file diff --git a/frontend/src/app/components/containers/complaints/outcomes/hwcr-outcome-report.tsx b/frontend/src/app/components/containers/complaints/outcomes/hwcr-outcome-report.tsx index 50617ac19..2207f7dff 100644 --- a/frontend/src/app/components/containers/complaints/outcomes/hwcr-outcome-report.tsx +++ b/frontend/src/app/components/containers/complaints/outcomes/hwcr-outcome-report.tsx @@ -21,5 +21,4 @@ export const HWCROutcomeReport: FC = () => {
); - }; - \ No newline at end of file + }; \ No newline at end of file diff --git a/frontend/src/app/constants/code-table-types.ts b/frontend/src/app/constants/code-table-types.ts index 2056201e0..af340592a 100644 --- a/frontend/src/app/constants/code-table-types.ts +++ b/frontend/src/app/constants/code-table-types.ts @@ -13,7 +13,17 @@ export const CODE_TABLE_TYPES = { REPORTED_BY: "reported-by", JUSTIFICATION: "justification", ASSESSMENT_TYPE: "assessment-type", - PREVENT_EDUCATION_ACTION: "prevent-education-action" + PREVENT_EDUCATION_ACTION: "prevent-education-action", + SEX: "sex", + AGE: "age", + THREAT_LEVEL: "threat-level", + CONFLICT_HISTORY: "conflict-history", + EARS: "ear-tag", + WILDLIFE_OUTCOMES: "wildlife-outcomes", + DRUGS: "drugs", + DRUG_METHOD_USE: "drug-methods", + REMAINING_DRUG_USE: "drug-remaining-outcomes", + // ORGANIZATION_UNIT_TYPE: "organization-unit-type", // ORGANIZATION_UNIT: "organization-unit", // PERSON_TYPE: "person-complaint", diff --git a/frontend/src/app/store/reducers/code-table.ts b/frontend/src/app/store/reducers/code-table.ts index 3c93373c2..8de0b04f3 100644 --- a/frontend/src/app/store/reducers/code-table.ts +++ b/frontend/src/app/store/reducers/code-table.ts @@ -22,6 +22,15 @@ import { ReportedBy } from "../../types/app/code-tables/reported-by"; import { Justification } from "../../types/app/code-tables/justification"; import { AssessmentType } from "../../types/app/code-tables/assesment-type"; import { PreventEducationAction } from "../../types/app/code-tables/prevent-education-action"; +import { Sex } from "../../types/app/code-tables/sex"; +import { Age } from "../../types/app/code-tables/age"; +import { ThreatLevel } from "../../types/app/code-tables/threat-level"; +import { ConflictHistory } from "../../types/app/code-tables/conflict-history"; +import { EarTag } from "../../types/app/code-tables/ear-tag"; +import { WildlifeComplaintOutcome } from "../../types/app/code-tables/wildlife-complaint-outcome"; +import { Drug } from "../../types/app/code-tables/drug"; +import { DrugMethod } from "../../types/app/code-tables/drug-method"; +import { DrugRemainingOutcome } from "../../types/app/code-tables/drug-remaining-outcome"; const initialState: CodeTableState = { agency: [], @@ -39,6 +48,15 @@ const initialState: CodeTableState = { justification: [], "assessment-type": [], "prevent-education-action": [], + sex: [], + age: [], + "threat-level": [], + "conflict-history": [], + "ear-tag": [], + "wildlife-outcomes": [], + drugs: [], + "drug-methods":[], + "drug-remaining-outcomes":[], }; export const codeTableSlice = createSlice({ @@ -46,10 +64,7 @@ export const codeTableSlice = createSlice({ initialState, reducers: { - setCodeTable: ( - state: CodeTableState, - action: PayloadAction<{ key: string; data: Array }> - ) => { + setCodeTable: (state: CodeTableState, action: PayloadAction<{ key: string; data: Array }>) => { const { payload: { key, data }, } = action; @@ -83,6 +98,15 @@ export const fetchCodeTables = (): AppThunk => async (dispatch) => { justification, "assessment-type": assessmentType, "prevent-education-action": preventEducationAction, + sex, + age, + "threat-level": threatLevels, + "conflict-history": conflictHistory, + "ear-tag": ears, + "wildlife-outcomes": wildlifeOutcomes, + drugs, + "drug-methods": drugUseMethods, + "drug-remaining-outcomes": remainingDrugUse }, } = state; @@ -142,13 +166,39 @@ export const fetchCodeTables = (): AppThunk => async (dispatch) => { if (!from(preventEducationAction).any()) { dispatch(fetchPreventEducationAction()); } + if (!from(sex).any()) { + dispatch(fetchSexes()); + } + if (!from(age).any()) { + dispatch(fetchAges()); + } + if (!from(threatLevels).any()) { + dispatch(fetchThreatLevels()); + } + if (!from(conflictHistory).any()) { + dispatch(fetchConfictHistories()); + } + if (!from(ears).any()) { + dispatch(fetchEars()); + } + if (!from(wildlifeOutcomes).any()) { + dispatch(fetchWildlifeComplaintOutcomes()); + } + + if (!from(drugs).any()) { + dispatch(fetchDrugs()); + } + if (!from(drugUseMethods).any()) { + dispatch(fetchDrugUseMethods()); + } + if (!from(remainingDrugUse).any()) { + dispatch(fetchRemainingDrugUse()); + } } catch (error) {} }; export const fetchAgencies = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.AGENCY}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.AGENCY}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -158,9 +208,7 @@ export const fetchAgencies = (): AppThunk => async (dispatch) => { }; export const fetchAttractants = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.ATTRACTANT}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.ATTRACTANT}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -170,9 +218,7 @@ export const fetchAttractants = (): AppThunk => async (dispatch) => { }; export const fetchComplaintStatus = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.COMPLAINT_STATUS}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.COMPLAINT_STATUS}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -197,9 +243,7 @@ export const fetchNatureOfComplaints = (): AppThunk => async (dispatch) => { }; export const fetchSpecies = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.SPECIES}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.SPECIES}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -212,9 +256,7 @@ export const fetchSpecies = (): AppThunk => async (dispatch) => { }; export const fetchViolations = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.VIOLATIONS}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.VIOLATIONS}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -227,9 +269,7 @@ export const fetchViolations = (): AppThunk => async (dispatch) => { }; export const fetchComplaintTypeCodes = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.COMPLAINT_TYPE}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.COMPLAINT_TYPE}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -245,13 +285,8 @@ export const fetchComplaintTypeCodes = (): AppThunk => async (dispatch) => { export const fetchAreaCodes = (): AppThunk => async (dispatch) => { const agency = "cos"; //-- TODO: when CE-212 is started this needs to be updated - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/organization-by-agency/${agency}` - ); - const response = await get>( - dispatch, - parameters - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/organization-by-agency/${agency}`); + const response = await get>(dispatch, parameters); if (response && from(response).any()) { const payload = { @@ -265,9 +300,7 @@ export const fetchAreaCodes = (): AppThunk => async (dispatch) => { export const fetchRegions = (): AppThunk => async (dispatch) => { const agency = "cos"; //-- TODO: when CE-212 is started this needs to be updated - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/regions-by-agency/${agency}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/regions-by-agency/${agency}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -282,9 +315,7 @@ export const fetchRegions = (): AppThunk => async (dispatch) => { export const fetchZones = (): AppThunk => async (dispatch) => { const agency = "cos"; //-- TODO: when CE-212 is started this needs to be updated - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/zones-by-agency/${agency}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/zones-by-agency/${agency}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -299,9 +330,7 @@ export const fetchZones = (): AppThunk => async (dispatch) => { export const fetchCommunities = (): AppThunk => async (dispatch) => { const agency = "cos"; //-- TODO: when CE-212 is started this needs to be updated - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/communities-by-agency/${agency}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/communities-by-agency/${agency}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { @@ -314,9 +343,7 @@ export const fetchCommunities = (): AppThunk => async (dispatch) => { }; export const fetchReportedByCodes = (): AppThunk => async (dispatch) => { - const parameters = generateApiParameters( - `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.REPORTED_BY}` - ); + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.REPORTED_BY}`); const response = await get>(dispatch, parameters); if (response && from(response).any()) { const payload = { key: CODE_TABLE_TYPES.REPORTED_BY, data: response }; @@ -350,7 +377,7 @@ export const fetchPreventEducationAction = (): AppThunk => async (dispatch) => { const parameters = generateApiParameters( `${config.API_BASE_URL}/v1/code-table/case-management/${CODE_TABLE_TYPES.PREVENT_EDUCATION_ACTION}` ); - + const response = await get>(dispatch, parameters); if (response && from(response).any()) { const payload = { key: CODE_TABLE_TYPES.PREVENT_EDUCATION_ACTION, data: response }; @@ -358,6 +385,105 @@ export const fetchPreventEducationAction = (): AppThunk => async (dispatch) => { } }; +export const fetchSexes = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.SEX}`); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.SEX, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchAges = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.AGE}`); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.AGE, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchThreatLevels = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.THREAT_LEVEL}`); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.THREAT_LEVEL, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchConfictHistories = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.CONFLICT_HISTORY}`); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.CONFLICT_HISTORY, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchEars = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters(`${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.EARS}`); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.EARS, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchWildlifeComplaintOutcomes = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters( + `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.WILDLIFE_OUTCOMES}` + ); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.WILDLIFE_OUTCOMES, data: response }; + dispatch(setCodeTable(payload)); + } +}; + + +export const fetchDrugs = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters( + `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.DRUGS}` + ); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.DRUGS, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchDrugUseMethods = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters( + `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.DRUG_METHOD_USE}` + ); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.DRUG_METHOD_USE, data: response }; + dispatch(setCodeTable(payload)); + } +}; + +export const fetchRemainingDrugUse = (): AppThunk => async (dispatch) => { + const parameters = generateApiParameters( + `${config.API_BASE_URL}/v1/code-table/${CODE_TABLE_TYPES.REMAINING_DRUG_USE}` + ); + + const response = await get>(dispatch, parameters); + if (response && from(response).any()) { + const payload = { key: CODE_TABLE_TYPES.REMAINING_DRUG_USE, data: response }; + dispatch(setCodeTable(payload)); + } +}; + export const selectCodeTable = (table: string) => (state: RootState): Array => { @@ -367,9 +493,7 @@ export const selectCodeTable = return selected; }; -export const selectComplaintTypeDropdown = ( - state: RootState -): Array