diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/models/UpdatePropertyDetailsFormModel.ts b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/models/UpdatePropertyDetailsFormModel.ts
index 27390fdb41..401743c7de 100644
--- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/models/UpdatePropertyDetailsFormModel.ts
+++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/models/UpdatePropertyDetailsFormModel.ts
@@ -4,10 +4,13 @@ import { isEmpty } from 'lodash';
import { ApiGen_CodeTypes_PropertyPPHStatusTypes } from '@/models/api/generated/ApiGen_CodeTypes_PropertyPPHStatusTypes';
import { ApiGen_Concepts_Address } from '@/models/api/generated/ApiGen_Concepts_Address';
import { ApiGen_Concepts_CodeType } from '@/models/api/generated/ApiGen_Concepts_CodeType';
+import { ApiGen_Concepts_HistoricalFileNumber } from '@/models/api/generated/ApiGen_Concepts_HistoricalFileNumber';
import { ApiGen_Concepts_Property } from '@/models/api/generated/ApiGen_Concepts_Property';
import { EpochIsoDateTime } from '@/models/api/UtcIsoDateTime';
+import { getEmptyBaseAudit } from '@/models/defaultInitializers';
import {
booleanToString,
+ emptyStringtoNullable,
fromTypeCode,
stringToBoolean,
stringToNull,
@@ -80,6 +83,47 @@ export class AddressFormModel {
}
}
+export class HistoricalNumberForm {
+ id: number | null = null;
+ propertyId: number;
+ historicalNumber = '';
+ historicalNumberType = '';
+ otherHistoricalNumberType = '';
+ isDisabled = false;
+ rowVersion: number | null = null;
+
+ static fromApi(base: ApiGen_Concepts_HistoricalFileNumber): HistoricalNumberForm {
+ const historicalNumberForm = new HistoricalNumberForm();
+ historicalNumberForm.id = base.id;
+ historicalNumberForm.propertyId = base.propertyId;
+ historicalNumberForm.historicalNumber = base.historicalFileNumber ?? '';
+ historicalNumberForm.historicalNumberType =
+ fromTypeCode(base.historicalFileNumberTypeCode) ?? '';
+ historicalNumberForm.otherHistoricalNumberType = base.otherHistFileNumberTypeCode ?? '';
+ historicalNumberForm.isDisabled = base.isDisabled ?? false;
+ historicalNumberForm.rowVersion = base.rowVersion ?? null;
+
+ return historicalNumberForm;
+ }
+
+ toApi(): ApiGen_Concepts_HistoricalFileNumber {
+ return {
+ id: this.id ?? 0,
+ propertyId: this.propertyId,
+ property: null,
+ historicalFileNumber: emptyStringtoNullable(this.historicalNumber),
+ historicalFileNumberTypeCode: toTypeCodeNullable(this.historicalNumberType),
+ otherHistFileNumberTypeCode: emptyStringtoNullable(this.otherHistoricalNumberType),
+ isDisabled: this.isDisabled,
+ ...getEmptyBaseAudit(this.rowVersion),
+ };
+ }
+
+ isEmpty(): boolean {
+ return this.historicalNumber.trim() === '' && this.historicalNumberType.trim() === '';
+ }
+}
+
export class UpdatePropertyDetailsFormModel {
id?: number;
rowVersion?: number;
@@ -125,6 +169,9 @@ export class UpdatePropertyDetailsFormModel {
districtTypeCode?: number;
districtTypeCodeDescription?: string;
+ // historical numbers
+ historicalNumbers: HistoricalNumberForm[] = [];
+
// multi-selects
anomalies?: PropertyAnomalyFormModel[];
tenures?: PropertyTenureFormModel[];
diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/validation.ts b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/validation.ts
index a97ab5c8dc..515eb3f7a1 100644
--- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/validation.ts
+++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetails/update/validation.ts
@@ -1,6 +1,8 @@
+/* eslint-disable no-template-curly-in-string */
import * as Yup from 'yup';
import { PropertyTenureTypes } from '@/constants/index';
+import { exists } from '@/utils';
import { stringToBoolean } from '@/utils/formUtils';
import { PropertyTenureFormModel } from './models';
@@ -35,4 +37,19 @@ export const UpdatePropertyDetailsYupSchema = Yup.object().shape({
postal: Yup.string().max(20, 'Postal must be at most 20 characters'),
}),
generalLocation: Yup.string().max(2000, 'General location must be less than 2000 characters'),
+ historicalNumbers: Yup.array().of(
+ Yup.object().shape({
+ historicalNumber: Yup.string()
+ .required('Historical File # is required')
+ .max(500, 'Historical File # must be at most ${max} characters'),
+ historicalNumberType: Yup.string().required('Historical File # type is required'),
+ otherHistoricalNumberType: Yup.string().when('historicalNumberType', {
+ is: (historicalType: string) => exists(historicalType) && historicalType === 'OTHER',
+ then: Yup.string()
+ .required('Other Description is required')
+ .max(200, 'Other Description must be at most ${max} characters'),
+ otherwise: Yup.string().nullable(),
+ }),
+ }),
+ ),
});
diff --git a/source/frontend/src/features/mapSideBar/research/common/ResearchHeader.test.tsx b/source/frontend/src/features/mapSideBar/research/common/ResearchHeader.test.tsx
index 5af320f7d0..174079c39a 100644
--- a/source/frontend/src/features/mapSideBar/research/common/ResearchHeader.test.tsx
+++ b/source/frontend/src/features/mapSideBar/research/common/ResearchHeader.test.tsx
@@ -70,6 +70,13 @@ vi.mocked(useHistoricalNumberRepository).mockReturnValue({
loading: false,
status: 200,
},
+ updatePropertyHistoricalNumbers: {
+ error: null,
+ response: [],
+ execute: vi.fn().mockResolvedValue([]),
+ loading: false,
+ status: 200,
+ },
});
describe('ResearchHeader component', () => {
diff --git a/source/frontend/src/hooks/pims-api/useApiHistoricalNumbers.ts b/source/frontend/src/hooks/pims-api/useApiHistoricalNumbers.ts
index cd3fb0e737..437f2c48f0 100644
--- a/source/frontend/src/hooks/pims-api/useApiHistoricalNumbers.ts
+++ b/source/frontend/src/hooks/pims-api/useApiHistoricalNumbers.ts
@@ -5,7 +5,7 @@ import { ApiGen_Concepts_HistoricalFileNumber } from '@/models/api/generated/Api
import useAxiosApi from './useApi';
/**
- * PIMS API wrapper to centralize all AJAX requests to the interest holder endpoints.
+ * PIMS API wrapper to centralize all AJAX requests to the historic number endpoints.
* @returns Object containing functions to make requests to the PIMS API.
*/
export const useApiHistoricalNumbers = () => {
@@ -17,6 +17,14 @@ export const useApiHistoricalNumbers = () => {
api.get
(
`/properties/${propertyId}/historicalNumbers`,
),
+ putHistoricalNumbers: (
+ propertyId: number,
+ historicalNumbers: ApiGen_Concepts_HistoricalFileNumber[],
+ ) =>
+ api.put(
+ `/properties/${propertyId}/historicalNumbers`,
+ historicalNumbers,
+ ),
}),
[api],
);
diff --git a/source/frontend/src/hooks/repositories/useHistoricalNumberRepository.ts b/source/frontend/src/hooks/repositories/useHistoricalNumberRepository.ts
index ba4ee4290f..30c2e2949b 100644
--- a/source/frontend/src/hooks/repositories/useHistoricalNumberRepository.ts
+++ b/source/frontend/src/hooks/repositories/useHistoricalNumberRepository.ts
@@ -11,7 +11,8 @@ import { useApiHistoricalNumbers } from '../pims-api/useApiHistoricalNumbers';
* hook that interacts with the Historical Number API.
*/
export const useHistoricalNumberRepository = () => {
- const { getByPropertyId: getByPropertyIdApi } = useApiHistoricalNumbers();
+ const { getByPropertyId: getByPropertyIdApi, putHistoricalNumbers: putHistoricalNumbersApi } =
+ useApiHistoricalNumbers();
const getPropertyHistoricalNumbers = useApiRequestWrapper<
(propertyId: number) => Promise>
@@ -24,10 +25,26 @@ export const useHistoricalNumberRepository = () => {
onError: useAxiosErrorHandler('Failed to load property historical numbers'),
});
+ const updatePropertyHistoricalNumbers = useApiRequestWrapper<
+ (
+ propertyId: number,
+ historicalNumbers: ApiGen_Concepts_HistoricalFileNumber[],
+ ) => Promise>
+ >({
+ requestFunction: useCallback(
+ async (propertyId: number, historicalNumbers: ApiGen_Concepts_HistoricalFileNumber[]) =>
+ await putHistoricalNumbersApi(propertyId, historicalNumbers),
+ [putHistoricalNumbersApi],
+ ),
+ requestName: 'updatePropertyHistoricalNumbers',
+ throwError: true,
+ });
+
return useMemo(
() => ({
getPropertyHistoricalNumbers,
+ updatePropertyHistoricalNumbers,
}),
- [getPropertyHistoricalNumbers],
+ [getPropertyHistoricalNumbers, updatePropertyHistoricalNumbers],
);
};