@spokane-folio/security-incident 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +32 -0
- package/.github/workflows/CODEOWNERS +8 -0
- package/.github/workflows/pr-validation.yml +44 -0
- package/.github/workflows/release.yml +64 -0
- package/.prettierrc +6 -0
- package/.stripesclirc +4 -0
- package/CHANGELOG.md +8 -0
- package/CONTRIBUTING.md +4 -0
- package/LICENSE +201 -0
- package/README.md +16 -0
- package/administrator-documentation/roles-and-permissions.md +65 -0
- package/administrator-documentation/track-settings-admin-guide-sketch.md +192 -0
- package/administrator-documentation/using-the-application.md +192 -0
- package/icons/app.png +0 -0
- package/icons/app.svg +1 -0
- package/icons/playButton.png +0 -0
- package/icons/profilePicThumbnail.png +0 -0
- package/jest.config.js +10 -0
- package/module-descriptor.json +75 -0
- package/output/service-worker.js +0 -0
- package/package.json +146 -0
- package/src/components/incidents/ColumnChooser.js +37 -0
- package/src/components/incidents/CreateMedia.js +132 -0
- package/src/components/incidents/CreatePane.js +1215 -0
- package/src/components/incidents/CreatePane.test.js +138 -0
- package/src/components/incidents/CreateReport.js +102 -0
- package/src/components/incidents/DetailsPane.js +1267 -0
- package/src/components/incidents/DetailsPane.test.js +150 -0
- package/src/components/incidents/EditPane.js +2334 -0
- package/src/components/incidents/EditPane.test.js +187 -0
- package/src/components/incidents/GetDetails.js +55 -0
- package/src/components/incidents/GetListDQLinkIncident.js +81 -0
- package/src/components/incidents/GetListDynamicQuery.js +66 -0
- package/src/components/incidents/GetLocations.js +57 -0
- package/src/components/incidents/GetMedia.js +98 -0
- package/src/components/incidents/GetName.js +111 -0
- package/src/components/incidents/GetNameCreatedBy.js +94 -0
- package/src/components/incidents/GetOrgLocaleSettings.js +61 -0
- package/src/components/incidents/GetPatronGroups.js +52 -0
- package/src/components/incidents/GetSelf.js +65 -0
- package/src/components/incidents/GetSummary.js +110 -0
- package/src/components/incidents/IncidentTypeCard.js +53 -0
- package/src/components/incidents/IncidentTypeCard.test.js +133 -0
- package/src/components/incidents/IncidentsPaneset.js +810 -0
- package/src/components/incidents/IncidentsPaneset.test.js +128 -0
- package/src/components/incidents/LinkedIncident.js +86 -0
- package/src/components/incidents/ModalAddMedia.js +262 -0
- package/src/components/incidents/ModalAddMedia.test.js +97 -0
- package/src/components/incidents/ModalAttentionDecOfService.js +111 -0
- package/src/components/incidents/ModalCustomWitness.js +469 -0
- package/src/components/incidents/ModalCustomWitness.test.js +147 -0
- package/src/components/incidents/ModalCustomerDetails.js +480 -0
- package/src/components/incidents/ModalCustomerDetails.test.js +116 -0
- package/src/components/incidents/ModalDescribeCustomer.js +361 -0
- package/src/components/incidents/ModalDescribeCustomer.test.js +156 -0
- package/src/components/incidents/ModalDirtyFormWarn.js +62 -0
- package/src/components/incidents/ModalLinkIncident.js +1213 -0
- package/src/components/incidents/ModalLinkIncidentStyle.css +32 -0
- package/src/components/incidents/ModalSelectIncidentTypes.js +178 -0
- package/src/components/incidents/ModalSelectIncidentTypes.test.js +273 -0
- package/src/components/incidents/ModalSelectKnownCustomer.js +395 -0
- package/src/components/incidents/ModalSelectWitness.js +406 -0
- package/src/components/incidents/ModalSelectWitness.test.js +308 -0
- package/src/components/incidents/ModalStyle.css +44 -0
- package/src/components/incidents/ModalTrespass.js +741 -0
- package/src/components/incidents/ModalViewCustomerDetails.js +241 -0
- package/src/components/incidents/ModalViewMedia.js +86 -0
- package/src/components/incidents/ModalViewTrespass.js +210 -0
- package/src/components/incidents/ResultsPane.js +437 -0
- package/src/components/incidents/ResultsPane.test.js +120 -0
- package/src/components/incidents/SearchCustomerOrWitness.js +108 -0
- package/src/components/incidents/Thumbnail.js +72 -0
- package/src/components/incidents/ThumbnailMarkRemoval.js +38 -0
- package/src/components/incidents/ThumbnailSkeleton.js +30 -0
- package/src/components/incidents/ThumbnailStyles.js +49 -0
- package/src/components/incidents/ThumbnailTempPreSave.js +71 -0
- package/src/components/incidents/UpdateReport.js +84 -0
- package/src/components/incidents/__snapshots__/CreatePane.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/DetailsPane.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/EditPane.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/IncidentTypeCard.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/IncidentsPaneset.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ModalAddMedia.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ModalCustomerDetails.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ModalSelectWitness.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ResultsPane.test.js.snap +3 -0
- package/src/components/incidents/helpers/ProfilePicture/ProfilePicture.css +5 -0
- package/src/components/incidents/helpers/ProfilePicture/ProfilePicture.js +51 -0
- package/src/components/incidents/helpers/ProfilePicture/isAValidURL.js +3 -0
- package/src/components/incidents/helpers/ProfilePicture/useProfilePicture.js +127 -0
- package/src/components/incidents/helpers/buildQueryString.js +28 -0
- package/src/components/incidents/helpers/cleanFormValues.js +53 -0
- package/src/components/incidents/helpers/computeEditedCustomers.js +124 -0
- package/src/components/incidents/helpers/convertDateIgnoringTZ.js +8 -0
- package/src/components/incidents/helpers/convertUTCISOToLocalePrettyTime.js +15 -0
- package/src/components/incidents/helpers/convertUTCISOToPrettyDate.js +19 -0
- package/src/components/incidents/helpers/decodeParamsToForm.js +20 -0
- package/src/components/incidents/helpers/deepNormalizeForComparison.js +39 -0
- package/src/components/incidents/helpers/extractFilterString.js +12 -0
- package/src/components/incidents/helpers/formatDateAndTimeToUTCISO.js +14 -0
- package/src/components/incidents/helpers/formatDateToUTCISO.js +14 -0
- package/src/components/incidents/helpers/formatTimeToUTCISO.js +28 -0
- package/src/components/incidents/helpers/getCurrentTime.js +20 -0
- package/src/components/incidents/helpers/getTodayDate.js +12 -0
- package/src/components/incidents/helpers/handlebarsHelpers.js +148 -0
- package/src/components/incidents/helpers/hasFormChangedAtCreate.js +50 -0
- package/src/components/incidents/helpers/hasTopLevelChangeAffectedDeclaration.js +90 -0
- package/src/components/incidents/helpers/hasTopLevelFormChanged.js +111 -0
- package/src/components/incidents/helpers/identifyCurrentTrespassDocs.js +109 -0
- package/src/components/incidents/helpers/isSameHtml.js +13 -0
- package/src/components/incidents/helpers/isValidDateFormat.js +14 -0
- package/src/components/incidents/helpers/isValidTimeInput.js +11 -0
- package/src/components/incidents/helpers/isValidUTCTimeFormat.js +14 -0
- package/src/components/incidents/helpers/parseMMDDYYYY.js +7 -0
- package/src/components/incidents/helpers/parseQueryString.js +16 -0
- package/src/components/incidents/helpers/sortTrespassDocuments.js +44 -0
- package/src/components/incidents/helpers/stripHTML.js +11 -0
- package/src/components/incidents/helpers/trespassDocUtils.js +197 -0
- package/src/components/incidents/helpers/validateTrespassDetails.js +37 -0
- package/src/components/incidents/usePersistedColModalLink.js +70 -0
- package/src/components/incidents/usePersistedColumns.js +70 -0
- package/src/components/incidents/usePersistedSort.js +23 -0
- package/src/components/incidents/usePersistedSortModalLink.js +23 -0
- package/src/contexts/IncidentContext.js +433 -0
- package/src/index.js +61 -0
- package/src/routes/Application.js +13 -0
- package/src/settings/GetIncidentCategories.js +56 -0
- package/src/settings/GetIncidentTypesDetails.js +88 -0
- package/src/settings/GetIncidentTypesIds.js +74 -0
- package/src/settings/GetLocationsInService.js +54 -0
- package/src/settings/GetSingleCustomLocationDetails.js +60 -0
- package/src/settings/GetSingleIncidentTypeDetails.js +60 -0
- package/src/settings/GetTrespassReasons.js +67 -0
- package/src/settings/GetTrespassTemplates.js +51 -0
- package/src/settings/IncidentCategoriesPane.js +285 -0
- package/src/settings/IncidentCategoriesPane.test.js +229 -0
- package/src/settings/IncidentTypeDetailsPane.js +215 -0
- package/src/settings/IncidentTypeDetailsPane.test.js +220 -0
- package/src/settings/IncidentTypeEditPane.js +211 -0
- package/src/settings/IncidentTypeEditPane.test.js +170 -0
- package/src/settings/IncidentTypesPaneset.js +167 -0
- package/src/settings/IncidentTypesPaneset.test.js +124 -0
- package/src/settings/LocationInServiceEditPane.js +320 -0
- package/src/settings/LocationsPaneset.js +415 -0
- package/src/settings/LocationsPaneset.test.js +106 -0
- package/src/settings/ModalDeleteCategory.js +47 -0
- package/src/settings/ModalDeleteIncidentType.js +49 -0
- package/src/settings/ModalDeleteLocationInService.js +49 -0
- package/src/settings/ModalDeleteTrespassReason.js +49 -0
- package/src/settings/ModalPreviewTrespassDoc.js +65 -0
- package/src/settings/ModalTrespassDocTokens.js +83 -0
- package/src/settings/NewIncidentTypePane.js +182 -0
- package/src/settings/PutIncidentType.js +60 -0
- package/src/settings/PutLocationsInService.js +52 -0
- package/src/settings/PutTrespassReasons.js +61 -0
- package/src/settings/PutTrespassTemplate.js +50 -0
- package/src/settings/TrespassDoc.css +17 -0
- package/src/settings/TrespassDocDetailsPane.js +215 -0
- package/src/settings/TrespassDocEditPane.js +538 -0
- package/src/settings/TrespassDocPaneset.js +581 -0
- package/src/settings/TrespassReasonDetailsPane.js +171 -0
- package/src/settings/TrespassReasonEditPane.js +221 -0
- package/src/settings/TrespassReasonsPaneset.js +282 -0
- package/src/settings/__snapshots__/IncidentCategoriesPane.test.js.snap +3 -0
- package/src/settings/__snapshots__/IncidentTypeDetailsPane.test.js.snap +3 -0
- package/src/settings/__snapshots__/IncidentTypeEditPane.test.js.snap +3 -0
- package/src/settings/__snapshots__/IncidentTypesPaneset.test.js.snap +3 -0
- package/src/settings/__snapshots__/LocationsPaneset.test.js.snap +3 -0
- package/src/settings/data/exampleJSON.json +92 -0
- package/src/settings/data/templateTokens.js +396 -0
- package/src/settings/helpers/alphabetize.js +18 -0
- package/src/settings/helpers/getCategoryTitleById.js +13 -0
- package/src/settings/helpers/makeId.js +15 -0
- package/src/settings/index.js +48 -0
- package/stripes.config.js +10 -0
- package/test/jest/__mock__/index.js +8 -0
- package/test/jest/__mock__/intl.mock.js +27 -0
- package/test/jest/__mock__/stripes.mock.js +26 -0
- package/test/jest/__mock__/stripesComponents.mock.js +151 -0
- package/test/jest/__mock__/stripesConfig.mock.js +1 -0
- package/test/jest/__mock__/stripesCore.mock.js +9 -0
- package/test/jest/__mock__/stripesIcon.mock.js +5 -0
- package/test/jest/__mock__/stripesSmartComponents.mock.js +7 -0
- package/test/jest/__mock__/stripesUtils.mock.js +3 -0
- package/test/jest/eslintrc.js +12 -0
- package/test/jest/setupFiles.js +5 -0
- package/translations/ui-security-incident/en_US.json +542 -0
- package/ui-module-acceptance-criteria.md +34 -0
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
import React, { useState, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import DOMPurify from 'dompurify';
|
|
4
|
+
import { decode } from 'html-entities';
|
|
5
|
+
import { FormattedMessage } from 'react-intl';
|
|
6
|
+
import {
|
|
7
|
+
AccordionSet,
|
|
8
|
+
Accordion,
|
|
9
|
+
Button,
|
|
10
|
+
Checkbox,
|
|
11
|
+
Col,
|
|
12
|
+
Datepicker,
|
|
13
|
+
Editor,
|
|
14
|
+
InfoPopover,
|
|
15
|
+
Modal,
|
|
16
|
+
ModalFooter,
|
|
17
|
+
Pane,
|
|
18
|
+
Paneset,
|
|
19
|
+
Row,
|
|
20
|
+
Select,
|
|
21
|
+
TextField,
|
|
22
|
+
AutoSuggest,
|
|
23
|
+
} from '@folio/stripes/components';
|
|
24
|
+
import { useIncidents } from '../../contexts/IncidentContext';
|
|
25
|
+
import GetLocationsInService from '../../settings/GetLocationsInService';
|
|
26
|
+
import GetTrespassReasons from '../../settings/GetTrespassReasons';
|
|
27
|
+
import convertUTCISOToPrettyDate from './helpers/convertUTCISOToPrettyDate';
|
|
28
|
+
import {
|
|
29
|
+
isDeclarationOfServiceEmpty,
|
|
30
|
+
validateTrespass,
|
|
31
|
+
hasTrespassReason
|
|
32
|
+
} from './helpers/validateTrespassDetails';
|
|
33
|
+
import { isSameHtml } from './helpers/isSameHtml.js';
|
|
34
|
+
import css from './ModalStyle.css';
|
|
35
|
+
|
|
36
|
+
const ModalTrespass = ({
|
|
37
|
+
customerID,
|
|
38
|
+
allCustomers, // list of customers in EditPane context use of modal
|
|
39
|
+
setAllCustomers,
|
|
40
|
+
onStagedTrespassUpdate,
|
|
41
|
+
onUpdateDeclaration = () => {}, // Only EditPane passes this prop
|
|
42
|
+
updateDeclarationArray = [], // Only EditPane passes this prop
|
|
43
|
+
modalContext = '', // Only CreatePane passes this prop
|
|
44
|
+
customersWithoutDeclaration = new Set(), // Only EditPane passes this prop
|
|
45
|
+
isNewlySelected
|
|
46
|
+
}) => {
|
|
47
|
+
const {
|
|
48
|
+
isModalTrespass,
|
|
49
|
+
closeModalTrespass,
|
|
50
|
+
selectedCustomers, // list of customers in CreatePane context use of modal
|
|
51
|
+
setSelectedCustomers,
|
|
52
|
+
locationsInService,
|
|
53
|
+
trespassReasons
|
|
54
|
+
} = useIncidents();
|
|
55
|
+
|
|
56
|
+
const allowedReasonIds = useMemo(() => {
|
|
57
|
+
const list = (trespassReasons ?? []).filter(r => !r.isSuppressed);
|
|
58
|
+
return new Set(list.map(r => r.id));
|
|
59
|
+
}, [trespassReasons]);
|
|
60
|
+
|
|
61
|
+
const [localUpdateDeclaration, setLocalUpdateDeclaration] = useState(false);
|
|
62
|
+
const reasonsSectionRef = useRef(null);
|
|
63
|
+
const [trespassData, setTrespassData] = useState({
|
|
64
|
+
dateOfOccurrence: '',
|
|
65
|
+
exclusionOrTrespassBasedOn: [],
|
|
66
|
+
witnessedBy: { witnesses: [] },
|
|
67
|
+
endDateOfTrespass: '',
|
|
68
|
+
declarationOfService: {
|
|
69
|
+
date: '',
|
|
70
|
+
placeSigned: '',
|
|
71
|
+
title: '',
|
|
72
|
+
signature: false,
|
|
73
|
+
},
|
|
74
|
+
description: ''
|
|
75
|
+
});
|
|
76
|
+
const [customersArray, setCustomersArray] = useState([]);
|
|
77
|
+
const [workWithEdit, setWorkWithEdit] = useState(false);
|
|
78
|
+
const [submitOk, setSubmitOk] = useState(false);
|
|
79
|
+
const [useIncidentDesc, setUseIncidentDesc] = useState(true);
|
|
80
|
+
const [formTouched, setFormTouched] = useState(false);
|
|
81
|
+
// const [isNewlySelected, setIsNewlySelected] = useState(false);
|
|
82
|
+
const shouldHideUpdateDeclaration = customersWithoutDeclaration?.has(customerID);
|
|
83
|
+
const initializedByCustomerRef = useRef(new Set()); // remember who we've init
|
|
84
|
+
const [trInputValue, setTrInputValue] = useState(''); // trespass reason input value
|
|
85
|
+
const [trVisibleCount, setTrVisibleCount] = useState(5); // trespass reason vis count
|
|
86
|
+
const [trsHasExpanded, setTrsHasExpanded] = useState(false); // track tresp-reason exp
|
|
87
|
+
const trItems = useMemo(() => {
|
|
88
|
+
const formattedTRitems = trespassReasons
|
|
89
|
+
? trespassReasons
|
|
90
|
+
.filter(tr => !tr.isSuppressed) // exclude suppressed
|
|
91
|
+
.map((tr) => ({
|
|
92
|
+
value: tr.id,
|
|
93
|
+
label: tr.reason,
|
|
94
|
+
isDefault: !!tr.isDefault
|
|
95
|
+
}))
|
|
96
|
+
: [{
|
|
97
|
+
value: '',
|
|
98
|
+
label: <FormattedMessage
|
|
99
|
+
id="search-pane.trespass-reasons-label-no-loaded"
|
|
100
|
+
/>
|
|
101
|
+
}];
|
|
102
|
+
return formattedTRitems;
|
|
103
|
+
}, [trespassReasons]);
|
|
104
|
+
|
|
105
|
+
const defaultReasonObj = useMemo(() => {
|
|
106
|
+
const defaultTR = trespassReasons?.find(r => r.isDefault);
|
|
107
|
+
return defaultTR ?
|
|
108
|
+
{
|
|
109
|
+
id: defaultTR.id,
|
|
110
|
+
reason: defaultTR.reason
|
|
111
|
+
}
|
|
112
|
+
: null;
|
|
113
|
+
}, [trespassReasons]);
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (modalContext !== 'create-mode') return;
|
|
117
|
+
if (!defaultReasonObj) return ;
|
|
118
|
+
if (initializedByCustomerRef.current.has(customerID)) return; // bail if already initialized for this customer
|
|
119
|
+
|
|
120
|
+
const hasSelection = (trespassData.exclusionOrTrespassBasedOn?.length ?? 0) > 0;
|
|
121
|
+
|
|
122
|
+
if (!hasSelection) {
|
|
123
|
+
setTrespassData(prev => ({
|
|
124
|
+
...prev,
|
|
125
|
+
exclusionOrTrespassBasedOn: [defaultReasonObj]
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
}, [
|
|
129
|
+
modalContext,
|
|
130
|
+
defaultReasonObj,
|
|
131
|
+
customerID,
|
|
132
|
+
setTrespassData,
|
|
133
|
+
trespassData.exclusionOrTrespassBasedOn
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
/*
|
|
137
|
+
handle if not in create-mode and customer does NOT have a
|
|
138
|
+
trespass.exclusionOrTrespassBasedOn value, we still set a defaultReasonObj
|
|
139
|
+
*/
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
if (!defaultReasonObj) return ;
|
|
142
|
+
if (initializedByCustomerRef.current.has(customerID)) return;
|
|
143
|
+
const hasSelection = (trespassData.exclusionOrTrespassBasedOn?.length ?? 0) > 0;
|
|
144
|
+
|
|
145
|
+
if (!hasSelection) {
|
|
146
|
+
setTrespassData(prev => ({
|
|
147
|
+
...prev,
|
|
148
|
+
exclusionOrTrespassBasedOn: [defaultReasonObj]
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
}, [
|
|
152
|
+
defaultReasonObj,
|
|
153
|
+
customerID,
|
|
154
|
+
setTrespassData,
|
|
155
|
+
trespassData.exclusionOrTrespassBasedOn
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const allTrespassReasons = useMemo(() => {
|
|
159
|
+
const inVal = (trInputValue || '').toLowerCase();
|
|
160
|
+
return trItems.filter(item => (item.label || '').toLowerCase().includes(inVal));
|
|
161
|
+
}, [trItems, trInputValue]);
|
|
162
|
+
|
|
163
|
+
const sortedTrespassReasons = useMemo(() => {
|
|
164
|
+
// default first, then alpha by label
|
|
165
|
+
const arr = [...allTrespassReasons];
|
|
166
|
+
arr.sort((a, b) => (
|
|
167
|
+
Number(b.isDefault) - Number(a.isDefault)
|
|
168
|
+
) || a.label.localeCompare(b.label));
|
|
169
|
+
return arr;
|
|
170
|
+
}, [allTrespassReasons]);
|
|
171
|
+
|
|
172
|
+
const filteredTrespassReasons = useMemo(() => {
|
|
173
|
+
return sortedTrespassReasons.slice(0, trVisibleCount)
|
|
174
|
+
}, [sortedTrespassReasons, trVisibleCount]);
|
|
175
|
+
|
|
176
|
+
const handleMoreTRsClick = () => {
|
|
177
|
+
setTrVisibleCount((prevCount) => {
|
|
178
|
+
return Math.min(prevCount + 5, sortedTrespassReasons.length)
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const loadMoreTRs = () => {
|
|
183
|
+
handleMoreTRsClick();
|
|
184
|
+
if (!trsHasExpanded) {
|
|
185
|
+
setTrsHasExpanded(true);
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// A customer can only (re)declare if they have at least one current (non-suppressed) reason selected
|
|
190
|
+
const isEligibleToRedeclare = useMemo(() => {
|
|
191
|
+
const arr = trespassData.exclusionOrTrespassBasedOn || [];
|
|
192
|
+
for (const item of arr) {
|
|
193
|
+
const id = typeof item === 'string' ? item : item?.id;
|
|
194
|
+
if (id && allowedReasonIds.has(id)) return true;
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}, [trespassData.exclusionOrTrespassBasedOn, allowedReasonIds]);
|
|
198
|
+
|
|
199
|
+
const showUpdateCheckbox = modalContext !== 'create-mode' &&
|
|
200
|
+
!isNewlySelected && (!shouldHideUpdateDeclaration || localUpdateDeclaration);
|
|
201
|
+
|
|
202
|
+
const selectedObjs = trespassData.exclusionOrTrespassBasedOn || [];
|
|
203
|
+
// const reasonsOk = hasTrespassReason(trespassData);
|
|
204
|
+
// const showReasonError = !isEligibleToRedeclare && formTouched;
|
|
205
|
+
|
|
206
|
+
const handleTRtoggle = (id, reason, checked) => {
|
|
207
|
+
setTrespassData(prev => {
|
|
208
|
+
const prevArr = prev.exclusionOrTrespassBasedOn || [];
|
|
209
|
+
const next = checked
|
|
210
|
+
// add
|
|
211
|
+
? (prevArr.some(x => x?.id === id) ? prevArr : [...prevArr, { id, reason }])
|
|
212
|
+
// remove by id
|
|
213
|
+
: prevArr.filter(x => x?.id !== id);
|
|
214
|
+
|
|
215
|
+
return { ...prev, exclusionOrTrespassBasedOn: next };
|
|
216
|
+
});
|
|
217
|
+
setFormTouched(true);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const handleTRFilterChange = (value) => {
|
|
221
|
+
// console.log("@handleTRFilterChange - value: ", value)
|
|
222
|
+
setTrInputValue(value);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const trContainerStyle = {
|
|
226
|
+
maxHeight: trsHasExpanded ? '175px' : '125px',
|
|
227
|
+
overflowX: 'clip',
|
|
228
|
+
overflowY: 'auto',
|
|
229
|
+
marginTop: '8px'
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// setting customersArray with either allCustomers data OR selectedCustomers data
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
if (allCustomers) {
|
|
235
|
+
setWorkWithEdit(true);
|
|
236
|
+
setCustomersArray(allCustomers); // setting if rendered via @EditPane
|
|
237
|
+
} else if (selectedCustomers) {
|
|
238
|
+
setCustomersArray(selectedCustomers); // setting if rendered via @CreatePane
|
|
239
|
+
}
|
|
240
|
+
}, [selectedCustomers, allCustomers]);
|
|
241
|
+
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
const valid = validateTrespass(trespassData);
|
|
244
|
+
setSubmitOk(valid);
|
|
245
|
+
}, [trespassData]);
|
|
246
|
+
|
|
247
|
+
const rebuildFromParent = () => {
|
|
248
|
+
const currentCustomer = (allCustomers || selectedCustomers || []).find(c => c.id === customerID);
|
|
249
|
+
if (currentCustomer && currentCustomer.trespass) {
|
|
250
|
+
const next = {
|
|
251
|
+
dateOfOccurrence: convertUTCISOToPrettyDate(currentCustomer.trespass.dateOfOccurrence) || '',
|
|
252
|
+
exclusionOrTrespassBasedOn: currentCustomer.trespass.exclusionOrTrespassBasedOn || [],
|
|
253
|
+
endDateOfTrespass: convertUTCISOToPrettyDate(currentCustomer.trespass.endDateOfTrespass) || '',
|
|
254
|
+
declarationOfService: {
|
|
255
|
+
date: convertUTCISOToPrettyDate(currentCustomer.trespass.declarationOfService?.date) || '',
|
|
256
|
+
placeSigned: currentCustomer.trespass.declarationOfService?.placeSigned || '',
|
|
257
|
+
title: currentCustomer.trespass.declarationOfService?.title || '',
|
|
258
|
+
signature: currentCustomer.trespass.declarationOfService?.signature || false,
|
|
259
|
+
},
|
|
260
|
+
description: currentCustomer.trespass.description || ''
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
setTrespassData(next);
|
|
264
|
+
draftRef.current = next.description || '';
|
|
265
|
+
const useDefault = (next.description || '').trim() === '';
|
|
266
|
+
setUseIncidentDesc(useDefault);
|
|
267
|
+
|
|
268
|
+
// recompute validity gating
|
|
269
|
+
const hasAnyCurrentValidReason = (next.exclusionOrTrespassBasedOn || []).some(x => {
|
|
270
|
+
const id = typeof x === 'string' ? x : x?.id;
|
|
271
|
+
return id && allowedReasonIds.has(id);
|
|
272
|
+
});
|
|
273
|
+
setSubmitOk(validateTrespass(next));
|
|
274
|
+
setFormTouched(!hasAnyCurrentValidReason);
|
|
275
|
+
setLocalUpdateDeclaration(updateDeclarationArray.includes(customerID));
|
|
276
|
+
} else {
|
|
277
|
+
const empty = {
|
|
278
|
+
dateOfOccurrence: '',
|
|
279
|
+
exclusionOrTrespassBasedOn: [],
|
|
280
|
+
witnessedBy: { witnesses: [] },
|
|
281
|
+
endDateOfTrespass: '',
|
|
282
|
+
declarationOfService: { date: '', placeSigned: '', title: '', signature: false },
|
|
283
|
+
};
|
|
284
|
+
setTrespassData(empty);
|
|
285
|
+
draftRef.current = '';
|
|
286
|
+
setUseIncidentDesc(true);
|
|
287
|
+
setFormTouched(false);
|
|
288
|
+
setSubmitOk(false);
|
|
289
|
+
setLocalUpdateDeclaration(false);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
if (isModalTrespass) rebuildFromParent();
|
|
295
|
+
}, [isModalTrespass]);
|
|
296
|
+
|
|
297
|
+
useEffect(() => {
|
|
298
|
+
if (isModalTrespass) {
|
|
299
|
+
setLocalUpdateDeclaration(updateDeclarationArray.includes(customerID));
|
|
300
|
+
}
|
|
301
|
+
}, [isModalTrespass, updateDeclarationArray, customerID]);
|
|
302
|
+
|
|
303
|
+
const handleDismiss = () => {
|
|
304
|
+
rebuildFromParent();
|
|
305
|
+
setWorkWithEdit(false);
|
|
306
|
+
closeModalTrespass();
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
useEffect(() => {
|
|
310
|
+
if (formTouched) {
|
|
311
|
+
setSubmitOk(validateTrespass(trespassData))
|
|
312
|
+
}
|
|
313
|
+
}, [formTouched, trespassData]);
|
|
314
|
+
|
|
315
|
+
const locationDataOptions = useMemo(() => {
|
|
316
|
+
const defaultValueLabel = [{
|
|
317
|
+
value: '',
|
|
318
|
+
label: <FormattedMessage
|
|
319
|
+
id="create-pane.locationDataOptions-label-select-location"/>
|
|
320
|
+
}];
|
|
321
|
+
const formattedLocations = locationsInService
|
|
322
|
+
? locationsInService.map((loc) => ({
|
|
323
|
+
value: loc.id,
|
|
324
|
+
label: loc.location
|
|
325
|
+
}))
|
|
326
|
+
: [{
|
|
327
|
+
value: '',
|
|
328
|
+
label: <FormattedMessage
|
|
329
|
+
id="create-pane.locationDataOptions-label-no-loaded"/>
|
|
330
|
+
}];
|
|
331
|
+
|
|
332
|
+
return [
|
|
333
|
+
...defaultValueLabel,
|
|
334
|
+
...formattedLocations,
|
|
335
|
+
];
|
|
336
|
+
}, [locationsInService]);
|
|
337
|
+
|
|
338
|
+
const handleChange = (event) => {
|
|
339
|
+
const { name, value, checked } = event.target;
|
|
340
|
+
if (name === 'exclusionOrTrespassBasedOn') {
|
|
341
|
+
handleExclusionCheckboxChange(event);
|
|
342
|
+
} else if (name === 'declarationOfService.signature') {
|
|
343
|
+
setTrespassData((prevData) => ({
|
|
344
|
+
...prevData,
|
|
345
|
+
declarationOfService: {
|
|
346
|
+
...prevData.declarationOfService,
|
|
347
|
+
signature: checked,
|
|
348
|
+
},
|
|
349
|
+
}));
|
|
350
|
+
} else if (name === 'declarationOfService.placeSigned') {
|
|
351
|
+
setTrespassData((prevData) => ({
|
|
352
|
+
...prevData,
|
|
353
|
+
declarationOfService: {
|
|
354
|
+
...prevData.declarationOfService,
|
|
355
|
+
placeSigned: value,
|
|
356
|
+
},
|
|
357
|
+
}));
|
|
358
|
+
} else if (name === 'declarationOfService.date') {
|
|
359
|
+
setTrespassData((prevData) => ({
|
|
360
|
+
...prevData,
|
|
361
|
+
declarationOfService: {
|
|
362
|
+
...prevData.declarationOfService,
|
|
363
|
+
date: value,
|
|
364
|
+
},
|
|
365
|
+
}));
|
|
366
|
+
} else if (name === 'declarationOfService.title') {
|
|
367
|
+
setTrespassData((prevData) => ({
|
|
368
|
+
...prevData,
|
|
369
|
+
declarationOfService: {
|
|
370
|
+
...prevData.declarationOfService,
|
|
371
|
+
title: value,
|
|
372
|
+
},
|
|
373
|
+
}));
|
|
374
|
+
} else {
|
|
375
|
+
setTrespassData((prevData) => ({
|
|
376
|
+
...prevData,
|
|
377
|
+
[name]: value,
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
setFormTouched(true);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
/*
|
|
384
|
+
Keep current HTML in a ref so keystrokes update w/out setting state.
|
|
385
|
+
This prevents react-quill's cleanup <-> setState feedback loop that otherwise
|
|
386
|
+
causes maximum update depth exceeded error when links are present in editor.
|
|
387
|
+
*/
|
|
388
|
+
// local unsanitized buffer - doesn't trigger React re-renders
|
|
389
|
+
const draftRef = useRef('');
|
|
390
|
+
|
|
391
|
+
// fire on every key-press but only mutautes the ref
|
|
392
|
+
const handleEditorChange = (content) => {
|
|
393
|
+
draftRef.current = content;
|
|
394
|
+
setFormTouched(true);
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
// commits once, with sanitized HTML
|
|
398
|
+
const handleEditorBlur = () => {
|
|
399
|
+
const sanitizedContent = DOMPurify.sanitize(draftRef.current);
|
|
400
|
+
setTrespassData(prev =>
|
|
401
|
+
isSameHtml(prev.description, sanitizedContent)
|
|
402
|
+
? prev
|
|
403
|
+
: { ...prev, description: sanitizedContent}
|
|
404
|
+
);
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
const handleSave = () => {
|
|
408
|
+
const updatedTrespassData = { ...trespassData };
|
|
409
|
+
const updatedCustomerArray = customersArray.map((cust) => {
|
|
410
|
+
if (cust.id === customerID) {
|
|
411
|
+
// if no end date of trespass delete it
|
|
412
|
+
if (trespassData.endDateOfTrespass === '') {
|
|
413
|
+
delete updatedTrespassData.endDateOfTrespass;
|
|
414
|
+
};
|
|
415
|
+
// if no declaration of service delete it
|
|
416
|
+
if (
|
|
417
|
+
isDeclarationOfServiceEmpty(updatedTrespassData.declarationOfService)
|
|
418
|
+
) {
|
|
419
|
+
delete updatedTrespassData.declarationOfService;
|
|
420
|
+
};
|
|
421
|
+
if (useIncidentDesc) {
|
|
422
|
+
// using default, always delete custom override
|
|
423
|
+
delete updatedTrespassData.description;
|
|
424
|
+
} else {
|
|
425
|
+
const sanitizedContent = DOMPurify.sanitize(draftRef.current);
|
|
426
|
+
const rawText = decode(sanitizedContent)
|
|
427
|
+
.replace(/<\/?[^>]+>/g, '') // strip tags
|
|
428
|
+
.trim();
|
|
429
|
+
|
|
430
|
+
if (rawText === '') {
|
|
431
|
+
// Editor visually empty - treat like using default
|
|
432
|
+
delete updatedTrespassData.description;
|
|
433
|
+
} else {
|
|
434
|
+
// Editor has meaningful input - persist
|
|
435
|
+
updatedTrespassData.description = sanitizedContent;
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
// const object = {...cust, trespass: updatedTrespassData};
|
|
439
|
+
|
|
440
|
+
return {
|
|
441
|
+
...cust,
|
|
442
|
+
trespass: updatedTrespassData,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
return cust;
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
onStagedTrespassUpdate?.(customerID, updatedTrespassData);
|
|
449
|
+
const parentHas = updateDeclarationArray.includes(customerID);
|
|
450
|
+
if (localUpdateDeclaration !== parentHas) {
|
|
451
|
+
onUpdateDeclaration(customerID)
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
if (workWithEdit) {
|
|
455
|
+
// setting via @EditPane
|
|
456
|
+
setAllCustomers(updatedCustomerArray);
|
|
457
|
+
} else {
|
|
458
|
+
// setting via @CreatePane
|
|
459
|
+
setSelectedCustomers(updatedCustomerArray);
|
|
460
|
+
};
|
|
461
|
+
setTrespassData({
|
|
462
|
+
dateOfOccurrence: '',
|
|
463
|
+
exclusionOrTrespassBasedOn: [],
|
|
464
|
+
witnessedBy: { witnesses: [] },
|
|
465
|
+
endDateOfTrespass: '',
|
|
466
|
+
declarationOfService: {
|
|
467
|
+
date: '',
|
|
468
|
+
placeSigned: '',
|
|
469
|
+
title: '',
|
|
470
|
+
signature: false,
|
|
471
|
+
},
|
|
472
|
+
description: ''
|
|
473
|
+
})
|
|
474
|
+
draftRef.current = '';
|
|
475
|
+
setWorkWithEdit(false);
|
|
476
|
+
closeModalTrespass();
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
if (!isModalTrespass) {
|
|
480
|
+
return null;
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
const footer = (
|
|
484
|
+
<ModalFooter>
|
|
485
|
+
<Button
|
|
486
|
+
onClick={handleSave}
|
|
487
|
+
buttonStyle="primary"
|
|
488
|
+
marginBottom0
|
|
489
|
+
// must pass validation and have more than 1 current reason selected
|
|
490
|
+
disabled={!(submitOk && isEligibleToRedeclare)}
|
|
491
|
+
>
|
|
492
|
+
<FormattedMessage id="close-continue-button" />
|
|
493
|
+
</Button>
|
|
494
|
+
<Button onClick={handleDismiss}>
|
|
495
|
+
<FormattedMessage id="cancel-button" />
|
|
496
|
+
</Button>
|
|
497
|
+
</ModalFooter>
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
return (
|
|
501
|
+
<Modal
|
|
502
|
+
style={{
|
|
503
|
+
display: 'flex',
|
|
504
|
+
flexDirection: 'column',
|
|
505
|
+
maxHeight: '90vh',
|
|
506
|
+
minHeight: '500px'
|
|
507
|
+
}}
|
|
508
|
+
open
|
|
509
|
+
dismissible
|
|
510
|
+
closeOnBackgroundClick
|
|
511
|
+
label={<FormattedMessage id="modal-trespass-label" />}
|
|
512
|
+
size="large"
|
|
513
|
+
onClose={handleDismiss}
|
|
514
|
+
footer={footer}
|
|
515
|
+
contentClass={css.modalContent}
|
|
516
|
+
>
|
|
517
|
+
<GetLocationsInService />
|
|
518
|
+
<GetTrespassReasons />
|
|
519
|
+
|
|
520
|
+
<Paneset style={{ height: '100%', flexGrow: 1 }}>
|
|
521
|
+
<Pane
|
|
522
|
+
defaultWidth="100%"
|
|
523
|
+
style={{ overflowY: 'auto', flexGrow: 1 }}
|
|
524
|
+
>
|
|
525
|
+
<AccordionSet>
|
|
526
|
+
<Accordion
|
|
527
|
+
label={
|
|
528
|
+
<FormattedMessage id="modal-trespass.accordion-trespass-details-label" />
|
|
529
|
+
}
|
|
530
|
+
>
|
|
531
|
+
<Row>
|
|
532
|
+
<Col xs={4}>
|
|
533
|
+
<AutoSuggest
|
|
534
|
+
value={trInputValue}
|
|
535
|
+
items={[]} // using as filter input
|
|
536
|
+
onChange={handleTRFilterChange}
|
|
537
|
+
menuStyle={{ display: 'none' }}
|
|
538
|
+
renderValue={(val) => val || ''} // render item in input field
|
|
539
|
+
/>
|
|
540
|
+
</Col>
|
|
541
|
+
</Row>
|
|
542
|
+
|
|
543
|
+
<Row xs={12} style={{ marginLeft: '10px' }}>
|
|
544
|
+
<Col>
|
|
545
|
+
<div style={trContainerStyle} ref={reasonsSectionRef}>
|
|
546
|
+
{filteredTrespassReasons.map((item) => (
|
|
547
|
+
<Checkbox
|
|
548
|
+
key={item.value}
|
|
549
|
+
label={item.label}
|
|
550
|
+
value={item.value}
|
|
551
|
+
checked={selectedObjs.some(sel => sel?.id === item.value)}
|
|
552
|
+
onChange={(e) => handleTRtoggle(item.value, item.label, e.target.checked)}
|
|
553
|
+
/>
|
|
554
|
+
))}
|
|
555
|
+
</div>
|
|
556
|
+
|
|
557
|
+
<div style={{ marginTop: '2px' }}>
|
|
558
|
+
{trVisibleCount < allTrespassReasons.length && (
|
|
559
|
+
<Button
|
|
560
|
+
onClick={loadMoreTRs}
|
|
561
|
+
>
|
|
562
|
+
<FormattedMessage id="more-button" />
|
|
563
|
+
</Button>
|
|
564
|
+
)}
|
|
565
|
+
</div>
|
|
566
|
+
</Col>
|
|
567
|
+
</Row>
|
|
568
|
+
|
|
569
|
+
<Row style={{ marginTop: '25px' }}>
|
|
570
|
+
<Col xs={3}>
|
|
571
|
+
<Checkbox
|
|
572
|
+
name="useIncidentDescription"
|
|
573
|
+
label={
|
|
574
|
+
<FormattedMessage id="modal-trespass-checkbox-use-incident-description" />
|
|
575
|
+
}
|
|
576
|
+
checked={useIncidentDesc}
|
|
577
|
+
onChange={() => setUseIncidentDesc(prev => !prev)}
|
|
578
|
+
/>
|
|
579
|
+
</Col>
|
|
580
|
+
<Col xs={1}>
|
|
581
|
+
<InfoPopover
|
|
582
|
+
content="Uncheck this box to provide a Trespass description different than the incident description on the trespass document."
|
|
583
|
+
iconSize='medium'
|
|
584
|
+
/>
|
|
585
|
+
</Col>
|
|
586
|
+
</Row>
|
|
587
|
+
|
|
588
|
+
{!useIncidentDesc && (
|
|
589
|
+
<Row style={{ marginTop: '25px' }}>
|
|
590
|
+
<Col xs={8}>
|
|
591
|
+
<Editor
|
|
592
|
+
label='Trespass description'
|
|
593
|
+
value={draftRef.current}
|
|
594
|
+
onChange={handleEditorChange}
|
|
595
|
+
onBlur={handleEditorBlur}
|
|
596
|
+
/>
|
|
597
|
+
</Col>
|
|
598
|
+
</Row>
|
|
599
|
+
)}
|
|
600
|
+
|
|
601
|
+
<Row style={{ marginTop: '25px' }}>
|
|
602
|
+
<Col xs={3}>
|
|
603
|
+
<Datepicker
|
|
604
|
+
label={
|
|
605
|
+
<FormattedMessage id="modal-trespass.datepicker-end-date-trespass" />
|
|
606
|
+
}
|
|
607
|
+
name="endDateOfTrespass"
|
|
608
|
+
value={trespassData.endDateOfTrespass}
|
|
609
|
+
onChange={handleChange}
|
|
610
|
+
/>
|
|
611
|
+
</Col>
|
|
612
|
+
</Row>
|
|
613
|
+
</Accordion>
|
|
614
|
+
|
|
615
|
+
<Accordion
|
|
616
|
+
label={
|
|
617
|
+
<FormattedMessage id="modal-trespass.accordion-declaration-of-service-label" />
|
|
618
|
+
}
|
|
619
|
+
>
|
|
620
|
+
<Row style={{ marginTop: '25px' }}>
|
|
621
|
+
<Col xs={3}>
|
|
622
|
+
<Datepicker
|
|
623
|
+
label={
|
|
624
|
+
<FormattedMessage id="modal-trespass.datepicker-date-served" />
|
|
625
|
+
}
|
|
626
|
+
name="declarationOfService.date"
|
|
627
|
+
value={
|
|
628
|
+
trespassData.declarationOfService
|
|
629
|
+
? trespassData.declarationOfService.date
|
|
630
|
+
: ''
|
|
631
|
+
}
|
|
632
|
+
onChange={handleChange}
|
|
633
|
+
/>
|
|
634
|
+
</Col>
|
|
635
|
+
<Col xs={3}>
|
|
636
|
+
<Select
|
|
637
|
+
label={
|
|
638
|
+
<FormattedMessage id="modal-trespass.select-place-signed" />
|
|
639
|
+
}
|
|
640
|
+
dataOptions={locationDataOptions}
|
|
641
|
+
name="declarationOfService.placeSigned"
|
|
642
|
+
value={
|
|
643
|
+
trespassData.declarationOfService
|
|
644
|
+
? trespassData.declarationOfService.placeSigned
|
|
645
|
+
: ''
|
|
646
|
+
}
|
|
647
|
+
onChange={handleChange}
|
|
648
|
+
/>
|
|
649
|
+
</Col>
|
|
650
|
+
<Col xs={3}>
|
|
651
|
+
<TextField
|
|
652
|
+
label={
|
|
653
|
+
<FormattedMessage id="modal-trespass.textField-title" />
|
|
654
|
+
}
|
|
655
|
+
name="declarationOfService.title"
|
|
656
|
+
value={
|
|
657
|
+
trespassData.declarationOfService
|
|
658
|
+
? trespassData.declarationOfService.title
|
|
659
|
+
: ''
|
|
660
|
+
}
|
|
661
|
+
onChange={handleChange}
|
|
662
|
+
/>
|
|
663
|
+
</Col>
|
|
664
|
+
</Row>
|
|
665
|
+
|
|
666
|
+
<Row style={{
|
|
667
|
+
marginTop: '25px',
|
|
668
|
+
marginBottom: modalContext === 'create-mode' || isNewlySelected || shouldHideUpdateDeclaration ? '120px' : '0'
|
|
669
|
+
}}>
|
|
670
|
+
<Col xs={3}>
|
|
671
|
+
<Checkbox
|
|
672
|
+
label={
|
|
673
|
+
<FormattedMessage id="modal-trespass.checkbox-signed" />
|
|
674
|
+
}
|
|
675
|
+
name="declarationOfService.signature"
|
|
676
|
+
checked={
|
|
677
|
+
trespassData.declarationOfService
|
|
678
|
+
? trespassData.declarationOfService.signature
|
|
679
|
+
: false
|
|
680
|
+
}
|
|
681
|
+
value={
|
|
682
|
+
trespassData.declarationOfService
|
|
683
|
+
? trespassData.declarationOfService.signature
|
|
684
|
+
: false
|
|
685
|
+
}
|
|
686
|
+
onChange={handleChange}
|
|
687
|
+
/>
|
|
688
|
+
</Col>
|
|
689
|
+
</Row>
|
|
690
|
+
|
|
691
|
+
{showUpdateCheckbox && (
|
|
692
|
+
<Row style={{ marginTop: '5px', marginBottom: '120px' }}>
|
|
693
|
+
<Col xs={3}>
|
|
694
|
+
<Checkbox
|
|
695
|
+
label={
|
|
696
|
+
<FormattedMessage id="modal-trespass.checkbox-update-declaration" />
|
|
697
|
+
}
|
|
698
|
+
// must have a valid, current (non-suppressed) reason AND modal is otherwise valid
|
|
699
|
+
disabled={!submitOk || !isEligibleToRedeclare}
|
|
700
|
+
name="updateDeclaration"
|
|
701
|
+
// checked={updateDeclarationArray.includes(customerID)}
|
|
702
|
+
checked={localUpdateDeclaration}
|
|
703
|
+
// onChange={() => onUpdateDeclaration(customerID)}
|
|
704
|
+
onChange={() => setLocalUpdateDeclaration(prev => !prev)}
|
|
705
|
+
/>
|
|
706
|
+
</Col>
|
|
707
|
+
<Col>
|
|
708
|
+
{!isEligibleToRedeclare && (
|
|
709
|
+
<div style={{ marginTop: 6 }}>
|
|
710
|
+
<InfoPopover
|
|
711
|
+
iconSize="medium"
|
|
712
|
+
content={
|
|
713
|
+
<FormattedMessage
|
|
714
|
+
id="edit-pane.update-declaration-requires-valid-reason"
|
|
715
|
+
/>
|
|
716
|
+
}
|
|
717
|
+
/>
|
|
718
|
+
</div>
|
|
719
|
+
)}
|
|
720
|
+
</Col>
|
|
721
|
+
</Row>
|
|
722
|
+
)}
|
|
723
|
+
</Accordion>
|
|
724
|
+
</AccordionSet>
|
|
725
|
+
</Pane>
|
|
726
|
+
</Paneset>
|
|
727
|
+
</Modal>
|
|
728
|
+
);
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
ModalTrespass.propTypes = {
|
|
732
|
+
customerID: PropTypes.string.isRequired,
|
|
733
|
+
allCustomers: PropTypes.array,
|
|
734
|
+
setAllCustomers: PropTypes.func,
|
|
735
|
+
onStagedTrespassUpdate: PropTypes.func,
|
|
736
|
+
onUpdateDeclaration: PropTypes.func,
|
|
737
|
+
updateDeclarationArray: PropTypes.array,
|
|
738
|
+
modalContext: PropTypes.string,
|
|
739
|
+
customersWithoutDeclaration: PropTypes.instanceOf(Set)
|
|
740
|
+
};
|
|
741
|
+
export default ModalTrespass;
|