@controleonline/ui-customers 1.0.81 → 1.0.83
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/.github/workflows/integration-source-gate.yml +68 -0
- package/.github/workflows/publish-npm.yml +91 -0
- package/AGENTS.md +12 -6
- package/docs/technical/Client-Details-Criar-Usuario.md +113 -0
- package/package.json +5 -4
- package/src/react/components/tabs/AddressesTab.js +240 -335
- package/src/react/components/tabs/DocumentAttachments.js +270 -0
- package/src/react/components/tabs/DocumentsTab.js +355 -463
- package/src/react/components/tabs/DocumentsTab.styles.js +123 -0
- package/src/react/components/tabs/EmployeeCreateFormFields.js +203 -0
- package/src/react/components/tabs/EmployeesTab.js +17 -171
- package/src/react/components/tabs/EmployeesTab.styles.js +220 -172
- package/src/react/components/tabs/GeneralTab.js +84 -46
- package/src/react/components/tabs/GeneralTab.styles.js +81 -77
- package/src/react/components/tabs/MediaTab.js +50 -5
- package/src/react/components/tabs/PeopleCategoriesPanel.js +161 -78
- package/src/react/components/tabs/SalesmanTab.js +1 -1
- package/src/react/components/tabs/UserFormModal.js +26 -2
- package/src/react/components/tabs/UsersTab.js +30 -19
- package/src/react/components/tabs/UsersTab.styles.js +257 -257
- package/src/react/components/tabs/UsersTabApiKeyModal.js +115 -0
- package/src/react/components/tabs/UsersTabUserModal.js +222 -0
- package/src/react/components/tabs/addressesTabHelpers.js +190 -0
- package/src/react/components/tabs/documentsTabHelpers.js +142 -0
- package/src/react/components/tabs/employeeContacts.js +3 -23
- package/src/react/components/tabs/employeeUnlink.js +7 -4
- package/src/react/components/tabs/employeesTabHelpers.js +33 -9
- package/src/react/components/tabs/generalTabHelpers.js +30 -8
- package/src/react/components/tabs/useGeneralTabPeopleLink.js +68 -0
- package/src/react/components/tabs/usersTabHelpers.js +24 -23
- package/src/react/pages/details.page.styles.js +114 -100
- package/src/react/pages/employees.js +4 -0
- package/src/react/utils/humanCompanyLinkTypes.js +28 -0
- package/src/tests/browser/manager/client-details-add-user-modal.spec.js +281 -0
- package/src/tests/browser/manager/client-details-address-create-coords.spec.js +414 -0
- package/src/tests/browser/manager/client-details-address-edit.spec.js +331 -0
- package/src/tests/browser/manager/client-details-contact-edit.spec.js +198 -0
- package/src/tests/browser/manager/client-details-create-contact.spec.js +306 -0
- package/src/tests/browser/manager/client-details-documents.spec.js +346 -0
- package/src/tests/browser/manager/client-details-identity-case.spec.js +227 -0
- package/src/tests/browser/manager/client-details-people-type.manifest.md +18 -0
- package/src/tests/browser/manager/client-details-people-type.spec.js +345 -0
- package/src/tests/browser/manager/client-details-supplier-product-create.spec.js +334 -0
- package/src/tests/browser/manager/client-details-users-tab-load.spec.js +194 -0
- package/src/tests/browser/manager/employees-salesman-after-sales.spec.js +441 -0
- package/src/tests/react/components/SalesmanTab.company.test.js +40 -0
- package/src/tests/react/components/tabs/UsersTab.styles.test.js +39 -0
- package/src/tests/react/components/tabs/addressesTabHelpers.test.js +78 -0
- package/src/tests/react/components/tabs/documentsTabContract.test.mjs +37 -0
- package/src/tests/react/components/tabs/documentsTabHelpers.test.mjs +93 -0
- package/src/tests/react/components/tabs/employeeContacts.test.js +46 -4
- package/src/tests/react/components/tabs/employeeLinkTypes.contract.test.mjs +52 -0
- package/src/tests/react/components/tabs/employeeUnlink.test.js +11 -11
- package/src/tests/react/components/tabs/employeesTabHelpers.media.test.js +2 -23
- package/src/tests/react/components/tabs/employeesTabHelpers.test.js +59 -0
- package/src/tests/react/components/tabs/generalTabHelpers.test.js +35 -0
- package/src/tests/react/components/tabs/peopleMediaTabs.test.js +217 -217
- package/src/tests/react/components/tabs/peopleType.contract.test.mjs +47 -0
- package/src/tests/react/components/tabs/resolveSeededLinkType.test.mjs +20 -0
- package/src/tests/react/components/tabs/salesmanTabMedia.no-redeclare.test.mjs +33 -0
- package/src/tests/react/components/tabs/usersTabHelpers.test.js +20 -0
- package/src/tests/react/components/tabs/usersTabHelpers.test.mjs +63 -0
- package/src/tests/react/pages/employees.test.js +2 -0
- package/src/tests/react/utils/humanCompanyLinkTypes.test.js +50 -0
|
@@ -17,194 +17,90 @@ import {
|
|
|
17
17
|
buildNavigationMapQuery,
|
|
18
18
|
buildWazeNavigationUrl,
|
|
19
19
|
} from '@controleonline/ui-common/src/react/utils/mapNavigation';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return nestedIri;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const id = extractId(person?.id || person?.people?.id || rawIri || nestedIri);
|
|
36
|
-
return id ? `/people/${id}` : '';
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const normalizeString = value => {
|
|
40
|
-
const text = String(value || '').trim();
|
|
41
|
-
return text.length > 0 ? text : undefined;
|
|
42
|
-
};
|
|
43
|
-
const normalizeZipCode = value =>
|
|
44
|
-
String(value || '')
|
|
45
|
-
.replace(/\D/g, '')
|
|
46
|
-
.slice(0, 8);
|
|
47
|
-
|
|
48
|
-
const buildAddressMapQuery = address => {
|
|
49
|
-
const streetLine = [normalizeString(address?.street), normalizeString(address?.number)]
|
|
50
|
-
.filter(Boolean)
|
|
51
|
-
.join(', ');
|
|
52
|
-
const cityStateLine = [normalizeString(address?.city), normalizeString(address?.state)]
|
|
53
|
-
.filter(Boolean)
|
|
54
|
-
.join(' - ');
|
|
55
|
-
|
|
56
|
-
return buildNavigationMapQuery([
|
|
57
|
-
streetLine,
|
|
58
|
-
normalizeString(address?.district),
|
|
59
|
-
cityStateLine,
|
|
60
|
-
normalizeString(address?.country),
|
|
61
|
-
normalizeZipCode(address?.zipCode),
|
|
62
|
-
normalizeString(address?.complement),
|
|
63
|
-
]);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const buildAddressPrimaryLine = address =>
|
|
67
|
-
[normalizeString(address?.street), normalizeString(address?.number)]
|
|
68
|
-
.filter(Boolean)
|
|
69
|
-
.join(', ');
|
|
70
|
-
|
|
71
|
-
const buildAddressSecondaryLine = address =>
|
|
72
|
-
[
|
|
73
|
-
normalizeString(address?.district),
|
|
74
|
-
[normalizeString(address?.city), normalizeString(address?.state)]
|
|
75
|
-
.filter(Boolean)
|
|
76
|
-
.join(' - '),
|
|
77
|
-
normalizeString(address?.country),
|
|
78
|
-
]
|
|
79
|
-
.filter(Boolean)
|
|
80
|
-
.join(' • ');
|
|
81
|
-
|
|
82
|
-
const normalizeAddress = address => ({
|
|
83
|
-
id: normalizeId(address?.id || address?.['@id']),
|
|
84
|
-
street: address?.street?.street || address?.street || '',
|
|
85
|
-
number: String(address?.number || '').trim(),
|
|
86
|
-
city:
|
|
87
|
-
address?.street?.district?.city?.city ||
|
|
88
|
-
address?.street?.city?.city ||
|
|
89
|
-
address?.city ||
|
|
90
|
-
'',
|
|
91
|
-
state:
|
|
92
|
-
address?.street?.district?.city?.state?.uf ||
|
|
93
|
-
address?.street?.district?.city?.state?.state ||
|
|
94
|
-
address?.street?.city?.state?.uf ||
|
|
95
|
-
address?.street?.city?.state?.state ||
|
|
96
|
-
address?.state ||
|
|
97
|
-
'',
|
|
98
|
-
zipCode:
|
|
99
|
-
(typeof address?.zipCode === 'object'
|
|
100
|
-
? address?.zipCode?.cep
|
|
101
|
-
: address?.zipCode) ||
|
|
102
|
-
address?.street?.cep?.cep ||
|
|
103
|
-
address?.postal_code ||
|
|
104
|
-
address?.cep ||
|
|
105
|
-
'',
|
|
106
|
-
complement: address?.complement || '',
|
|
107
|
-
district:
|
|
108
|
-
address?.street?.district?.district ||
|
|
109
|
-
address?.district ||
|
|
110
|
-
'',
|
|
111
|
-
country:
|
|
112
|
-
address?.street?.district?.city?.state?.country?.countrycode ||
|
|
113
|
-
address?.street?.district?.city?.state?.country?.countryname ||
|
|
114
|
-
address?.street?.city?.state?.country?.countrycode ||
|
|
115
|
-
address?.street?.city?.state?.country?.countryname ||
|
|
116
|
-
address?.country ||
|
|
117
|
-
'',
|
|
118
|
-
nickname: address?.nickname || '',
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const mapAddressesForClient = list =>
|
|
122
|
-
list.map(item => ({
|
|
123
|
-
id: item.id,
|
|
124
|
-
'@id': String(item?.id || '').startsWith('/addresses/')
|
|
125
|
-
? String(item.id)
|
|
126
|
-
: `/addresses/${extractId(item.id || '')}`,
|
|
127
|
-
street: item.street,
|
|
128
|
-
number: item.number,
|
|
129
|
-
complement: item.complement,
|
|
130
|
-
district: item.district,
|
|
131
|
-
city: item.city,
|
|
132
|
-
state: item.state,
|
|
133
|
-
zipCode: item.zipCode,
|
|
134
|
-
country: item.country,
|
|
135
|
-
nickname: item.nickname,
|
|
136
|
-
}));
|
|
137
|
-
|
|
138
|
-
const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
139
|
-
const {showError, showSuccess, showDialog} = useMessage();
|
|
20
|
+
import {
|
|
21
|
+
buildAddressMapQueryParts,
|
|
22
|
+
buildAddressPrimaryLine,
|
|
23
|
+
buildAddressSecondaryLine,
|
|
24
|
+
mapAddressesForClient,
|
|
25
|
+
normalizeAddress,
|
|
26
|
+
resolveAddressSaveId,
|
|
27
|
+
toPeopleIri,
|
|
28
|
+
} from './addressesTabHelpers';
|
|
29
|
+
|
|
30
|
+
const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
31
|
+
const {showError, showSuccess, showDialog} = useMessage();
|
|
140
32
|
const [addresses, setAddresses] = useState([]);
|
|
141
33
|
const [showModal, setShowModal] = useState(false);
|
|
142
34
|
const [editingItem, setEditingItem] = useState(null);
|
|
143
35
|
const [showNavigationModal, setShowNavigationModal] = useState(false);
|
|
144
36
|
const [navigationAddress, setNavigationAddress] = useState(null);
|
|
145
|
-
|
|
146
|
-
const addressStore = useStores(state => state.address) || {};
|
|
147
|
-
const actions = addressStore.actions || {};
|
|
148
|
-
const peopleIri = useMemo(() => toPeopleIri(client), [client]);
|
|
149
|
-
|
|
150
|
-
useEffect(() => {
|
|
151
|
-
const rawAddresses = Array.isArray(client?.address)
|
|
152
|
-
? client.address.map(item => normalizeAddress(item))
|
|
153
|
-
: [];
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const normalizedItem = item ? normalizeAddress(item) : {};
|
|
160
|
-
setEditingItem(item ? normalizedItem : null);
|
|
37
|
+
|
|
38
|
+
const addressStore = useStores(state => state.address) || {};
|
|
39
|
+
const actions = addressStore.actions || {};
|
|
40
|
+
const peopleIri = useMemo(() => toPeopleIri(client), [client]);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const rawAddresses = Array.isArray(client?.address)
|
|
44
|
+
? client.address.map(item => normalizeAddress(item))
|
|
45
|
+
: [];
|
|
46
|
+
setAddresses(rawAddresses);
|
|
47
|
+
}, [client]);
|
|
48
|
+
|
|
49
|
+
const openModal = item => {
|
|
50
|
+
setEditingItem(item ? normalizeAddress(item) : null);
|
|
161
51
|
setShowModal(true);
|
|
162
52
|
};
|
|
163
|
-
|
|
164
|
-
const closeModal = () => {
|
|
53
|
+
|
|
54
|
+
const closeModal = () => {
|
|
165
55
|
setShowModal(false);
|
|
166
56
|
setEditingItem(null);
|
|
167
57
|
};
|
|
168
|
-
|
|
169
|
-
const closeNavigationModal = () => {
|
|
170
|
-
setShowNavigationModal(false);
|
|
171
|
-
setNavigationAddress(null);
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
const openNavigationModal = address => {
|
|
175
|
-
const normalizedAddress = normalizeAddress(address);
|
|
176
|
-
const mapQuery =
|
|
177
|
-
|
|
178
|
-
if (!mapQuery) {
|
|
179
|
-
showError('Nao foi possivel montar a navegacao para este endereco.');
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
setNavigationAddress(normalizedAddress);
|
|
184
|
-
setShowNavigationModal(true);
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const handleOpenNavigation = async appName => {
|
|
188
|
-
const mapQuery =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
58
|
+
|
|
59
|
+
const closeNavigationModal = () => {
|
|
60
|
+
setShowNavigationModal(false);
|
|
61
|
+
setNavigationAddress(null);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const openNavigationModal = address => {
|
|
65
|
+
const normalizedAddress = normalizeAddress(address);
|
|
66
|
+
const mapQuery = buildNavigationMapQuery(buildAddressMapQueryParts(normalizedAddress));
|
|
67
|
+
|
|
68
|
+
if (!mapQuery) {
|
|
69
|
+
showError('Nao foi possivel montar a navegacao para este endereco.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
setNavigationAddress(normalizedAddress);
|
|
74
|
+
setShowNavigationModal(true);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const handleOpenNavigation = async appName => {
|
|
78
|
+
const mapQuery = buildNavigationMapQuery(
|
|
79
|
+
buildAddressMapQueryParts(navigationAddress),
|
|
80
|
+
);
|
|
81
|
+
const url =
|
|
82
|
+
appName === 'waze'
|
|
83
|
+
? buildWazeNavigationUrl({mapQuery})
|
|
84
|
+
: buildGoogleMapsNavigationUrl({mapQuery});
|
|
85
|
+
|
|
86
|
+
if (!url) {
|
|
87
|
+
showError('Nao foi possivel montar a navegacao para este endereco.');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
closeNavigationModal();
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
await Linking.openURL(url);
|
|
95
|
+
} catch {
|
|
96
|
+
showError('Nao foi possivel abrir o aplicativo de navegacao.');
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Always attach a numeric id when editing so the default store issues PUT
|
|
102
|
+
* (update) instead of POST (create). Root cause of app-community#282.
|
|
103
|
+
*/
|
|
208
104
|
const saveAddress = async payload => {
|
|
209
105
|
if (!actions?.save) {
|
|
210
106
|
throw new Error('Servico de enderecos indisponivel no momento.');
|
|
@@ -214,17 +110,25 @@ const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
|
214
110
|
throw new Error('Nao foi possivel identificar o cliente para salvar o endereco.');
|
|
215
111
|
}
|
|
216
112
|
|
|
217
|
-
|
|
113
|
+
const body = {
|
|
218
114
|
...payload,
|
|
219
115
|
people: peopleIri,
|
|
220
|
-
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const editId = resolveAddressSaveId(editingItem, payload);
|
|
119
|
+
if (editId) {
|
|
120
|
+
body.id = editId;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return actions.save(body);
|
|
221
124
|
};
|
|
222
125
|
|
|
223
126
|
const handleAddressSaved = saved => {
|
|
224
127
|
const normalizedSaved = normalizeAddress(saved || {});
|
|
225
|
-
const
|
|
128
|
+
const editId = resolveAddressSaveId(editingItem);
|
|
129
|
+
const updatedAddresses = editId
|
|
226
130
|
? addresses.map(item =>
|
|
227
|
-
item
|
|
131
|
+
resolveAddressSaveId(item) === editId ? normalizedSaved : item,
|
|
228
132
|
)
|
|
229
133
|
: [...addresses, normalizedSaved];
|
|
230
134
|
|
|
@@ -232,44 +136,49 @@ const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
|
232
136
|
onUpdateClient?.('address', mapAddressesForClient(updatedAddresses));
|
|
233
137
|
|
|
234
138
|
showSuccess(
|
|
235
|
-
|
|
139
|
+
editId
|
|
236
140
|
? 'Endereco atualizado com sucesso!'
|
|
237
141
|
: 'Endereco criado com sucesso!',
|
|
238
142
|
);
|
|
239
143
|
closeModal();
|
|
240
144
|
};
|
|
241
|
-
|
|
242
|
-
const handleDelete = id => {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
145
|
+
|
|
146
|
+
const handleDelete = id => {
|
|
147
|
+
const deleteId = resolveAddressSaveId({id});
|
|
148
|
+
showDialog({
|
|
149
|
+
title: 'Confirmar exclusao',
|
|
150
|
+
message: 'Deseja realmente remover este item?',
|
|
151
|
+
confirmLabel: 'Remover',
|
|
152
|
+
cancelLabel: 'Cancelar',
|
|
153
|
+
onConfirm: async () => {
|
|
154
|
+
try {
|
|
155
|
+
if (!actions?.remove || !deleteId) {
|
|
156
|
+
showError('Servico de enderecos indisponivel no momento.');
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
await actions.remove(deleteId);
|
|
160
|
+
const updatedAddresses = addresses.filter(
|
|
161
|
+
item => resolveAddressSaveId(item) !== deleteId,
|
|
162
|
+
);
|
|
163
|
+
setAddresses(updatedAddresses);
|
|
164
|
+
onUpdateClient?.('address', mapAddressesForClient(updatedAddresses));
|
|
165
|
+
showSuccess('Endereco removido com sucesso!');
|
|
166
|
+
} catch {
|
|
167
|
+
showError('Falha ao remover endereco. Tente novamente.');
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
266
173
|
const renderModal = () => (
|
|
267
174
|
<Modal visible={showModal} transparent animationType="slide">
|
|
268
175
|
<View style={[customStyles.modalOverlay, addressModalStyles.overlay]}>
|
|
269
176
|
<View style={addressModalStyles.container}>
|
|
270
177
|
<View style={addressModalStyles.header}>
|
|
271
178
|
<Text style={[customStyles.modalTitle, addressModalStyles.title]}>
|
|
272
|
-
{editingItem
|
|
179
|
+
{editingItem
|
|
180
|
+
? global.t?.t('address', 'title', 'editAddress')
|
|
181
|
+
: global.t?.t('address', 'title', 'address')}
|
|
273
182
|
</Text>
|
|
274
183
|
<TouchableOpacity
|
|
275
184
|
onPress={closeModal}
|
|
@@ -278,15 +187,23 @@ const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
|
278
187
|
</TouchableOpacity>
|
|
279
188
|
</View>
|
|
280
189
|
<DefaultAddress
|
|
281
|
-
mode={
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
190
|
+
mode={
|
|
191
|
+
editingItem && resolveAddressSaveId(editingItem) ? 'edit' : 'create'
|
|
192
|
+
}
|
|
193
|
+
row={
|
|
194
|
+
editingItem && resolveAddressSaveId(editingItem)
|
|
195
|
+
? {
|
|
196
|
+
...editingItem,
|
|
197
|
+
id: resolveAddressSaveId(editingItem),
|
|
198
|
+
'@id':
|
|
199
|
+
editingItem['@id'] ||
|
|
200
|
+
`/addresses/${resolveAddressSaveId(editingItem)}`,
|
|
201
|
+
cep: editingItem.zipCode,
|
|
202
|
+
uf: editingItem.state,
|
|
203
|
+
country: editingItem.country,
|
|
204
|
+
}
|
|
205
|
+
: null
|
|
206
|
+
}
|
|
290
207
|
peopleIri={peopleIri}
|
|
291
208
|
saveAction={saveAddress}
|
|
292
209
|
onCancel={closeModal}
|
|
@@ -296,74 +213,76 @@ const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
|
296
213
|
</View>
|
|
297
214
|
</View>
|
|
298
215
|
</Modal>
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
const renderNavigationModal = () => {
|
|
302
|
-
const primaryLine = buildAddressPrimaryLine(navigationAddress);
|
|
303
|
-
const secondaryLine = buildAddressSecondaryLine(navigationAddress);
|
|
304
|
-
|
|
305
|
-
return (
|
|
306
|
-
<Modal
|
|
307
|
-
visible={showNavigationModal}
|
|
308
|
-
transparent
|
|
309
|
-
animationType="fade"
|
|
310
|
-
onRequestClose={closeNavigationModal}>
|
|
311
|
-
<View style={customStyles.modalOverlay}>
|
|
312
|
-
<View style={customStyles.modalContainer}>
|
|
313
|
-
<Text style={customStyles.modalTitle}>Abrir endereco</Text>
|
|
314
|
-
<Text style={customStyles.navigationModalDescription}>
|
|
315
|
-
Escolha qual aplicativo deseja usar para navegar ate este endereco.
|
|
316
|
-
</Text>
|
|
317
|
-
<View style={customStyles.navigationAddressCard}>
|
|
318
|
-
<Text style={customStyles.navigationAddressTitle}>
|
|
319
|
-
{primaryLine || 'Endereco'}
|
|
320
|
-
</Text>
|
|
321
|
-
{secondaryLine ? (
|
|
322
|
-
<Text style={customStyles.navigationAddressSubtitle}>
|
|
323
|
-
{secondaryLine}
|
|
324
|
-
</Text>
|
|
325
|
-
) : null}
|
|
326
|
-
</View>
|
|
327
|
-
<View style={customStyles.navigationOptions}>
|
|
328
|
-
<TouchableOpacity
|
|
329
|
-
style={[
|
|
330
|
-
customStyles.navigationOptionButton,
|
|
331
|
-
customStyles.navigationOptionButtonPrimary,
|
|
332
|
-
]}
|
|
333
|
-
onPress={() => handleOpenNavigation('google')}>
|
|
334
|
-
<Text
|
|
335
|
-
style={[
|
|
336
|
-
customStyles.navigationOptionButtonText,
|
|
337
|
-
customStyles.navigationOptionButtonTextPrimary,
|
|
338
|
-
]}>
|
|
339
|
-
Google Maps
|
|
340
|
-
</Text>
|
|
341
|
-
</TouchableOpacity>
|
|
342
|
-
<TouchableOpacity
|
|
343
|
-
style={customStyles.navigationOptionButton}
|
|
344
|
-
onPress={() => handleOpenNavigation('waze')}>
|
|
345
|
-
<Text style={customStyles.navigationOptionButtonText}>
|
|
346
|
-
Waze
|
|
347
|
-
</Text>
|
|
348
|
-
</TouchableOpacity>
|
|
349
|
-
</View>
|
|
350
|
-
<TouchableOpacity
|
|
351
|
-
style={customStyles.modalCancelButton}
|
|
352
|
-
onPress={closeNavigationModal}>
|
|
353
|
-
<Text style={customStyles.modalCancelText}>Cancelar</Text>
|
|
354
|
-
</TouchableOpacity>
|
|
355
|
-
</View>
|
|
356
|
-
</View>
|
|
357
|
-
</Modal>
|
|
358
|
-
);
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
return (
|
|
362
|
-
<>
|
|
363
|
-
<View style={customStyles.tabContent}>
|
|
364
|
-
<View style={customStyles.section}>
|
|
365
|
-
<View style={customStyles.sectionHeader}>
|
|
366
|
-
<Text style={customStyles.sectionTitle}>
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const renderNavigationModal = () => {
|
|
219
|
+
const primaryLine = buildAddressPrimaryLine(navigationAddress);
|
|
220
|
+
const secondaryLine = buildAddressSecondaryLine(navigationAddress);
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<Modal
|
|
224
|
+
visible={showNavigationModal}
|
|
225
|
+
transparent
|
|
226
|
+
animationType="fade"
|
|
227
|
+
onRequestClose={closeNavigationModal}>
|
|
228
|
+
<View style={customStyles.modalOverlay}>
|
|
229
|
+
<View style={customStyles.modalContainer}>
|
|
230
|
+
<Text style={customStyles.modalTitle}>Abrir endereco</Text>
|
|
231
|
+
<Text style={customStyles.navigationModalDescription}>
|
|
232
|
+
Escolha qual aplicativo deseja usar para navegar ate este endereco.
|
|
233
|
+
</Text>
|
|
234
|
+
<View style={customStyles.navigationAddressCard}>
|
|
235
|
+
<Text style={customStyles.navigationAddressTitle}>
|
|
236
|
+
{primaryLine || 'Endereco'}
|
|
237
|
+
</Text>
|
|
238
|
+
{secondaryLine ? (
|
|
239
|
+
<Text style={customStyles.navigationAddressSubtitle}>
|
|
240
|
+
{secondaryLine}
|
|
241
|
+
</Text>
|
|
242
|
+
) : null}
|
|
243
|
+
</View>
|
|
244
|
+
<View style={customStyles.navigationOptions}>
|
|
245
|
+
<TouchableOpacity
|
|
246
|
+
style={[
|
|
247
|
+
customStyles.navigationOptionButton,
|
|
248
|
+
customStyles.navigationOptionButtonPrimary,
|
|
249
|
+
]}
|
|
250
|
+
onPress={() => handleOpenNavigation('google')}>
|
|
251
|
+
<Text
|
|
252
|
+
style={[
|
|
253
|
+
customStyles.navigationOptionButtonText,
|
|
254
|
+
customStyles.navigationOptionButtonTextPrimary,
|
|
255
|
+
]}>
|
|
256
|
+
Google Maps
|
|
257
|
+
</Text>
|
|
258
|
+
</TouchableOpacity>
|
|
259
|
+
<TouchableOpacity
|
|
260
|
+
style={customStyles.navigationOptionButton}
|
|
261
|
+
onPress={() => handleOpenNavigation('waze')}>
|
|
262
|
+
<Text style={customStyles.navigationOptionButtonText}>
|
|
263
|
+
Waze
|
|
264
|
+
</Text>
|
|
265
|
+
</TouchableOpacity>
|
|
266
|
+
</View>
|
|
267
|
+
<TouchableOpacity
|
|
268
|
+
style={customStyles.modalCancelButton}
|
|
269
|
+
onPress={closeNavigationModal}>
|
|
270
|
+
<Text style={customStyles.modalCancelText}>Cancelar</Text>
|
|
271
|
+
</TouchableOpacity>
|
|
272
|
+
</View>
|
|
273
|
+
</View>
|
|
274
|
+
</Modal>
|
|
275
|
+
);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<>
|
|
280
|
+
<View style={customStyles.tabContent}>
|
|
281
|
+
<View style={customStyles.section}>
|
|
282
|
+
<View style={customStyles.sectionHeader}>
|
|
283
|
+
<Text style={customStyles.sectionTitle}>
|
|
284
|
+
{global.t?.t('address', 'title', 'addresses')}
|
|
285
|
+
</Text>
|
|
367
286
|
{isEditing && (
|
|
368
287
|
<TouchableOpacity
|
|
369
288
|
onPress={() => openModal(null)}
|
|
@@ -376,46 +295,32 @@ const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
|
376
295
|
</TouchableOpacity>
|
|
377
296
|
)}
|
|
378
297
|
</View>
|
|
379
|
-
{addresses.length === 0 ? (
|
|
380
|
-
<Text style={customStyles.emptyText}>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
customStyles.listItemWithActions,
|
|
388
|
-
]}>
|
|
298
|
+
{addresses.length === 0 ? (
|
|
299
|
+
<Text style={customStyles.emptyText}>
|
|
300
|
+
{global.t?.t('address', 'empty', 'noAddresses') ||
|
|
301
|
+
'Nenhum endereco cadastrado.'}
|
|
302
|
+
</Text>
|
|
303
|
+
) : (
|
|
304
|
+
addresses.map(address => (
|
|
305
|
+
<View key={address.id || address['@id']} style={customStyles.itemCard}>
|
|
389
306
|
<View style={customStyles.itemContent}>
|
|
390
|
-
<
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
<Text style={customStyles.itemSubtext}>
|
|
408
|
-
{address.district ? `${address.district}, ` : ''}
|
|
409
|
-
{address.city}
|
|
410
|
-
{address.state ? ` - ${address.state}` : ''}
|
|
411
|
-
{address.country ? ` (${address.country})` : ''}
|
|
412
|
-
{address.complement ? `\n${address.complement}` : ''}
|
|
413
|
-
{address.nickname && address.nickname !== 'DEFAULT'
|
|
414
|
-
? `\n${address.nickname}`
|
|
415
|
-
: ''}
|
|
416
|
-
</Text>
|
|
417
|
-
</View>
|
|
418
|
-
</View>
|
|
307
|
+
<View style={{flex: 1}}>
|
|
308
|
+
<Text style={customStyles.itemTitle}>
|
|
309
|
+
{[address.street, address.number].filter(Boolean).join(', ') ||
|
|
310
|
+
'Endereco'}
|
|
311
|
+
</Text>
|
|
312
|
+
<Text style={customStyles.itemSubtitle}>
|
|
313
|
+
{address.district ? `${address.district}\n` : ''}
|
|
314
|
+
{address.city}
|
|
315
|
+
{address.state ? ` - ${address.state}` : ''}
|
|
316
|
+
{address.country ? ` (${address.country})` : ''}
|
|
317
|
+
{address.complement ? `\n${address.complement}` : ''}
|
|
318
|
+
{address.nickname && address.nickname !== 'DEFAULT'
|
|
319
|
+
? `\n${address.nickname}`
|
|
320
|
+
: ''}
|
|
321
|
+
</Text>
|
|
322
|
+
</View>
|
|
323
|
+
</View>
|
|
419
324
|
{isEditing && (
|
|
420
325
|
<View
|
|
421
326
|
style={[
|
|
@@ -440,16 +345,16 @@ const AddressesTab = ({client, customStyles, isEditing, onUpdateClient}) => {
|
|
|
440
345
|
color={customStyles.iconButtonGhostIcon.color}
|
|
441
346
|
/>
|
|
442
347
|
</TouchableOpacity>
|
|
443
|
-
</View>
|
|
444
|
-
)}
|
|
445
|
-
</View>
|
|
446
|
-
))
|
|
447
|
-
)}
|
|
448
|
-
</View>
|
|
449
|
-
</View>
|
|
450
|
-
{renderModal()}
|
|
451
|
-
{renderNavigationModal()}
|
|
452
|
-
</>
|
|
348
|
+
</View>
|
|
349
|
+
)}
|
|
350
|
+
</View>
|
|
351
|
+
))
|
|
352
|
+
)}
|
|
353
|
+
</View>
|
|
354
|
+
</View>
|
|
355
|
+
{renderModal()}
|
|
356
|
+
{renderNavigationModal()}
|
|
357
|
+
</>
|
|
453
358
|
);
|
|
454
359
|
};
|
|
455
360
|
|