Skip to content

Commit 5b3fec8

Browse files
shreeyash07frozenhelium
authored andcommitted
feat(local-unit): add new fields in local unit form
1 parent 2bff234 commit 5b3fec8

File tree

22 files changed

+1087
-342
lines changed

22 files changed

+1087
-342
lines changed

app/src/components/domain/LocationSearchInput/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useExternalRequest } from '#utils/restRequest';
1111
export interface LocationSearchResult {
1212
addresstype: string;
1313
boundingbox: string[];
14+
readOnly?: boolean;
1415
class: string;
1516
display_name: string;
1617
importance: number;
@@ -41,12 +42,14 @@ interface Props {
4142
className?: string;
4243
onResultSelect: (result: LocationSearchResult | undefined) => void;
4344
countryIso: string;
45+
readOnly?: boolean;
4446
}
4547

4648
function LocationSearchInput(props: Props) {
4749
const {
4850
className,
4951
onResultSelect,
52+
readOnly,
5053
countryIso,
5154
} = props;
5255

@@ -84,6 +87,7 @@ function LocationSearchInput(props: Props) {
8487
name=""
8588
// FIXME: use translations
8689
placeholder="Search for a place"
90+
readOnly={readOnly}
8791
options={undefined}
8892
value={undefined}
8993
keySelector={keySelector}

app/src/utils/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ export const TRAINING_FACILITY_TYPE = 7 satisfies LocalUnitHealthFacilityTypeOpt
209209
export const SPECIALIZED_SERVICES_TYPE = 8 satisfies LocalUnitHealthFacilityTypeOptions;
210210
export const OTHER_TYPE = 9 satisfies LocalUnitHealthFacilityTypeOptions;
211211

212+
type LocalUnitTrainingFacilityTypeOptions = NonNullable<NonNullable<GoApiResponse<'/api/v2/local-units-options/'>['professional_training_facilities']>[number]>['id']
213+
214+
export const OTHER_TRAINING_FACILITIES = 9 satisfies LocalUnitTrainingFacilityTypeOptions;
215+
212216
type LocalUnitAffiliationOptions = NonNullable<NonNullable<GoApiResponse<'/api/v2/local-units-options/'>['affiliation']>[number]>['id']
213217

214218
export const OTHER_AFFILIATION = 9 satisfies LocalUnitAffiliationOptions;

app/src/utils/localUnits.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { type GoApiResponse } from './restRequest';
1010

1111
type LocalUnitResponse = NonNullable<GoApiResponse<'/api/v2/local-units/{id}/'>>;
1212

13-
export function getFormFields(value: LocalUnitResponse | PartialLocalUnits) {
13+
export function getFormFields(value: LocalUnitResponse | PartialLocalUnits | undefined) {
1414
const {
1515
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1616
created_at,
@@ -30,7 +30,7 @@ export function getFormFields(value: LocalUnitResponse | PartialLocalUnits) {
3030
...formValues
3131
// Note: the cast is safe as we're only trying to
3232
// remove fields if they exist
33-
} = removeNull(value) as LocalUnitResponse;
33+
} = removeNull(value ?? {}) as LocalUnitResponse || undefined;
3434

3535
const {
3636
// eslint-disable-next-line @typescript-eslint/no-unused-vars

app/src/views/CountryNsOverviewContextAndStructure/NationalSocietyLocalUnits/ConfigureLocalUnitsModal/ConfirmationModal/index.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from '@ifrc-go/ui';
1111
import { useTranslation } from '@ifrc-go/ui/hooks';
1212
import { resolveToString } from '@ifrc-go/ui/utils';
13+
import { isDefined } from '@togglecorp/fujs';
1314

1415
import useAlert from '#hooks/useAlert';
1516
import { type CountryOutletContext } from '#utils/outletContext';
@@ -18,7 +19,7 @@ import { useLazyRequest } from '#utils/restRequest';
1819
import i18n from './i18n.json';
1920

2021
export type ManageLocalUnitsValues = {
21-
id: number;
22+
id: number | undefined;
2223
country: number;
2324
local_unit_type: number;
2425
enabled: boolean;
@@ -91,7 +92,8 @@ function ConfirmationModal(props: Props) {
9192
url: '/api/v2/externally-managed-local-unit/{id}/',
9293
method: 'PUT',
9394
body: (values: ManageLocalUnitsValues) => values,
94-
pathVariables: manageLocalUnitsValues && { id: manageLocalUnitsValues?.id },
95+
pathVariables: isDefined(manageLocalUnitsValues?.id)
96+
? { id: manageLocalUnitsValues.id } : undefined,
9597
onSuccess: () => {
9698
alert.show(
9799
manageLocalUnitsValues?.enabled
@@ -111,7 +113,8 @@ function ConfirmationModal(props: Props) {
111113
addManageLocalUnit(manageLocalUnitsValues);
112114
}
113115
updateManageLocalUnit(manageLocalUnitsValues);
114-
}, [isNewManageLocalUnit, addManageLocalUnit, manageLocalUnitsValues, updateManageLocalUnit]);
116+
}, [isNewManageLocalUnit,
117+
addManageLocalUnit, manageLocalUnitsValues, updateManageLocalUnit]);
115118

116119
return (
117120
<Modal

app/src/views/CountryNsOverviewContextAndStructure/NationalSocietyLocalUnits/ConfigureLocalUnitsModal/index.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import {
1919
numericIdSelector,
2020
resolveToString,
2121
} from '@ifrc-go/ui/utils';
22-
import { isDefined } from '@togglecorp/fujs';
22+
import {
23+
isDefined,
24+
isNotDefined,
25+
} from '@togglecorp/fujs';
2326

2427
import { type CountryOutletContext } from '#utils/outletContext';
2528
import {
@@ -64,6 +67,16 @@ function ConfigureLocalUnitsModal(props: Props) {
6467

6568
const handleLocalUnitSwitchChange = useCallback((value: boolean, name: number) => {
6669
setLocalUnitType(name);
70+
if (isNotDefined(manageResponse)
71+
&& isDefined(countryResponse)
72+
) {
73+
setManageLocalUnitsValues({
74+
id: undefined,
75+
country: countryResponse.id,
76+
local_unit_type: name,
77+
enabled: value,
78+
});
79+
}
6780
if (isDefined(manageResponse)
6881
&& isDefined(manageResponse[name])
6982
&& isDefined(countryResponse)
@@ -84,11 +97,12 @@ function ConfigureLocalUnitsModal(props: Props) {
8497
]);
8598

8699
const isNewManageLocalUnit = useMemo(() => {
87-
if (isDefined(manageResponse) && isDefined(manageLocalUnitsValues)) {
88-
return !(manageLocalUnitsValues.local_unit_type in manageResponse);
100+
if (isDefined(manageLocalUnitsValues)
101+
&& isDefined(manageLocalUnitsValues.id)) {
102+
return true;
89103
}
90104
return false;
91-
}, [manageResponse, manageLocalUnitsValues]);
105+
}, [manageLocalUnitsValues]);
92106

93107
const {
94108
response: localUnitsOptions,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"namespace": "countryNsOverviewContextAndStructure",
3+
"strings": {
4+
"otherProfileOutputLabel": "Other Profiles",
5+
"otherProfilePositionOutputLabel": "Position",
6+
"otherProfileNumberOutputLabel": "Number"
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { TextOutput } from '@ifrc-go/ui';
2+
import { useTranslation } from '@ifrc-go/ui/hooks';
3+
4+
import DiffWrapper from '#components/DiffWrapper';
5+
6+
import { type PartialLocalUnits } from '../../LocalUnitsFormModal/LocalUnitsForm/schema';
7+
8+
import i18n from './i18n.json';
9+
import styles from './styles.module.css';
10+
11+
type OtherProfile = NonNullable<NonNullable<PartialLocalUnits['health']>['other_profiles']>[number];
12+
13+
interface Props {
14+
newValue: OtherProfile;
15+
oldValue: OtherProfile | undefined;
16+
}
17+
18+
function OtherProfilesDiffOutput(props: Props) {
19+
const {
20+
newValue,
21+
oldValue,
22+
} = props;
23+
24+
const strings = useTranslation(i18n);
25+
26+
return (
27+
<div className={styles.otherProfilesInput}>
28+
<DiffWrapper
29+
hideOnPristine
30+
value={newValue?.position}
31+
previousValue={oldValue?.position}
32+
diffViewEnabled
33+
>
34+
<TextOutput
35+
strongValue
36+
value={newValue.position}
37+
label={strings.otherProfilePositionOutputLabel}
38+
/>
39+
</DiffWrapper>
40+
<DiffWrapper
41+
hideOnPristine
42+
value={newValue?.number}
43+
previousValue={oldValue?.number}
44+
diffViewEnabled
45+
>
46+
<TextOutput
47+
strongValue
48+
valueType="number"
49+
label={strings.otherProfileNumberOutputLabel}
50+
value={newValue.number}
51+
/>
52+
</DiffWrapper>
53+
</div>
54+
);
55+
}
56+
57+
export default OtherProfilesDiffOutput;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.other-profiles-input {
2+
display: flex;
3+
flex-direction: column;
4+
gap: var(--go-ui-spacing-sm);
5+
}

app/src/views/CountryNsOverviewContextAndStructure/NationalSocietyLocalUnits/LocalUnitView/i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@
5555
"localUnitViewDentist": "Dentist",
5656
"localUnitViewNursingAid": "Nursing aid",
5757
"localUnitViewMidwife": "Midwife",
58-
"localUnitViewOtherMedicalHeal": "Other medical heal",
5958
"localUnitViewOtherProfiles": "Other profiles",
59+
"localUnitViewRemovedOtherProfiles": "Removed Other profiles",
60+
"localUnitViewOtherMedicalHeal": "Other medical heal",
6061
"localUnitViewCommentsNS": "Comments by the NS",
6162
"localUnitViewLatitude": "Latitude",
6263
"localUnitViewLongitude": "Longitude",

app/src/views/CountryNsOverviewContextAndStructure/NationalSocietyLocalUnits/LocalUnitView/index.tsx

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import { useMemo } from 'react';
1+
import {
2+
useCallback,
3+
useMemo,
4+
} from 'react';
25
import {
36
Container,
47
TextOutput,
58
} from '@ifrc-go/ui';
69
import { useTranslation } from '@ifrc-go/ui/hooks';
710
import {
11+
injectClientId,
812
numericIdSelector,
913
stringNameSelector,
1014
stringValueSelector,
@@ -27,10 +31,12 @@ import {
2731
useRequest,
2832
} from '#utils/restRequest';
2933

34+
import { injectClientIdToResponse } from '../common';
3035
import {
3136
type PartialLocalUnits,
3237
TYPE_HEALTH_CARE,
3338
} from '../LocalUnitsFormModal/LocalUnitsForm/schema';
39+
import OtherProfilesDiffOutput from './OtherProfilesDiffOutput';
3440

3541
import i18n from './i18n.json';
3642
import styles from './styles.module.css';
@@ -79,15 +85,49 @@ function LocalUnitView(props: Props) {
7985
pathVariables: isDefined(localUnitId) ? { id: localUnitId } : undefined,
8086
});
8187

88+
const previousValue = injectClientIdToResponse(
89+
// eslint-disable-next-line max-len
90+
localUnitPreviousResponse?.previous_data_details as unknown as (LocalUnitResponse | undefined),
91+
);
92+
8293
const newValue = isDefined(locallyChangedValue)
8394
? locallyChangedValue
84-
: localUnitResponse;
95+
: injectClientIdToResponse(localUnitResponse);
96+
8597
const oldValue = isDefined(locallyChangedValue)
86-
? localUnitResponse
87-
: (localUnitPreviousResponse?.previous_data_details as unknown as LocalUnitResponse);
98+
? injectClientIdToResponse(localUnitResponse)
99+
: previousValue;
100+
101+
const getPreviousProfileValue = useCallback((profileClientId: string) => (
102+
oldValue?.health?.other_profiles?.find(
103+
(previousProfile) => injectClientId(previousProfile)?.client_id === profileClientId,
104+
)
105+
), [oldValue]);
106+
107+
const removedOtherProfiles = useMemo(() => (
108+
oldValue?.health?.other_profiles?.filter(({ client_id: oldClientId }) => (
109+
newValue?.health?.other_profiles?.findIndex(
110+
({ client_id: newClientId }) => oldClientId === newClientId,
111+
) === -1
112+
))
113+
), [oldValue, newValue]);
114+
115+
const changedOtherProfiles = useMemo(() => {
116+
const potentiallyChanged = newValue?.health?.other_profiles?.filter(
117+
(newOne) => {
118+
const oldOne = oldValue?.health?.other_profiles?.find(
119+
({ client_id: oldClientId }) => newOne.client_id === oldClientId,
120+
);
121+
122+
return hasDifferences(newOne, oldOne);
123+
},
124+
);
125+
126+
return potentiallyChanged;
127+
}, [oldValue, newValue]);
88128

89129
const hasDifference = useMemo(() => {
90-
if (isNotDefined(newValue) || isNotDefined(oldValue)) {
130+
if (isNotDefined(newValue) && isNotDefined(oldValue)) {
91131
return false;
92132
}
93133

@@ -852,18 +892,32 @@ function LocalUnitView(props: Props) {
852892
value={newValue?.health?.midwife}
853893
/>
854894
</DiffWrapper>
855-
<DiffWrapper
856-
hideOnPristine
857-
value={newValue?.health?.other_profiles}
858-
previousValue={oldValue?.health?.other_profiles}
859-
diffViewEnabled
860-
>
861-
<TextOutput
862-
strongValue
863-
label={strings.localUnitViewOtherProfiles}
864-
value={newValue?.health?.other_profiles}
865-
/>
866-
</DiffWrapper>
895+
{isDefined(changedOtherProfiles) && changedOtherProfiles.length > 0 && (
896+
<>
897+
<span>
898+
{strings.localUnitViewOtherProfiles}
899+
</span>
900+
{newValue?.health?.other_profiles?.map((profile) => (
901+
<OtherProfilesDiffOutput
902+
newValue={profile}
903+
oldValue={getPreviousProfileValue(profile.client_id)}
904+
/>
905+
))}
906+
</>
907+
)}
908+
{isDefined(removedOtherProfiles) && removedOtherProfiles.length > 0 && (
909+
<>
910+
<span>
911+
{strings.localUnitViewRemovedOtherProfiles}
912+
</span>
913+
{removedOtherProfiles?.map((profile) => (
914+
<OtherProfilesDiffOutput
915+
newValue={profile}
916+
oldValue={undefined}
917+
/>
918+
))}
919+
</>
920+
)}
867921
<DiffWrapper
868922
hideOnPristine
869923
value={newValue?.health?.other_medical_heal}

0 commit comments

Comments
 (0)