@controleonline/ui-customers 1.0.81

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.
Files changed (102) hide show
  1. package/.github/agents/developer.agent.md +30 -0
  2. package/.github/agents/devops.agent.md +30 -0
  3. package/.github/agents/qa.agent.md +30 -0
  4. package/.github/agents/security.agent.md +30 -0
  5. package/.scrutinizer.yml +20 -0
  6. package/AGENTS.md +50 -0
  7. package/FUNDING.yml +1 -0
  8. package/README.md +23 -0
  9. package/docs/technical/Client-Details-Franquia-Filial.md +18 -0
  10. package/docs/technical/Client-Details-People-Name-Case.md +103 -0
  11. package/docs/technical/Cliente-Vendedor-Vinculo-e-Permissoes.md +152 -0
  12. package/docs/wiki.md +1 -0
  13. package/package.json +32 -0
  14. package/scripts/validate-wiki-pointer.cjs +13 -0
  15. package/src/react/components/tabs/AddressesTab.js +494 -0
  16. package/src/react/components/tabs/CategoriesTab.js +196 -0
  17. package/src/react/components/tabs/ClassificationChips.js +494 -0
  18. package/src/react/components/tabs/ContactTab.js +621 -0
  19. package/src/react/components/tabs/ContactTab.styles.js +119 -0
  20. package/src/react/components/tabs/ContractsTab.js +13 -0
  21. package/src/react/components/tabs/DocumentsTab.js +463 -0
  22. package/src/react/components/tabs/DocumentsTab.styles.js +133 -0
  23. package/src/react/components/tabs/EmployeeContactRow.js +83 -0
  24. package/src/react/components/tabs/EmployeesTab.js +454 -0
  25. package/src/react/components/tabs/EmployeesTab.styles.js +172 -0
  26. package/src/react/components/tabs/FiscalTab.js +6 -0
  27. package/src/react/components/tabs/FranchiseCommissionSection.js +307 -0
  28. package/src/react/components/tabs/FranchiseLinksManageModal.js +215 -0
  29. package/src/react/components/tabs/FranchiseLinksTab.js +282 -0
  30. package/src/react/components/tabs/GeneralTab.js +466 -0
  31. package/src/react/components/tabs/GeneralTab.styles.js +101 -0
  32. package/src/react/components/tabs/MediaTab.js +356 -0
  33. package/src/react/components/tabs/PeopleCategoriesPanel.js +601 -0
  34. package/src/react/components/tabs/ProductsTab.js +236 -0
  35. package/src/react/components/tabs/ProductsTab.styles.js +143 -0
  36. package/src/react/components/tabs/SalesmanCommissionBlock.js +120 -0
  37. package/src/react/components/tabs/SalesmanManageModal.js +208 -0
  38. package/src/react/components/tabs/SalesmanTab.js +436 -0
  39. package/src/react/components/tabs/SalesmanTab.styles.js +4 -0
  40. package/src/react/components/tabs/UserApiKeyModal.js +90 -0
  41. package/src/react/components/tabs/UserFormModal.js +301 -0
  42. package/src/react/components/tabs/UsersTab.js +426 -0
  43. package/src/react/components/tabs/UsersTab.styles.js +283 -0
  44. package/src/react/components/tabs/UsersTab.styles.test.js +42 -0
  45. package/src/react/components/tabs/contactMutationMessage.js +18 -0
  46. package/src/react/components/tabs/employeeContacts.js +214 -0
  47. package/src/react/components/tabs/employeeUnlink.js +68 -0
  48. package/src/react/components/tabs/employeesTabHelpers.js +227 -0
  49. package/src/react/components/tabs/franchiseCommissionHelpers.js +134 -0
  50. package/src/react/components/tabs/franchiseLinksTab.helpers.js +247 -0
  51. package/src/react/components/tabs/generalTabHelpers.js +120 -0
  52. package/src/react/components/tabs/salesmanTab.helpers.js +114 -0
  53. package/src/react/components/tabs/salesmanTabHelpers.js +173 -0
  54. package/src/react/components/tabs/salesmanTabMedia.js +55 -0
  55. package/src/react/components/tabs/salesmanTabSession.js +39 -0
  56. package/src/react/components/tabs/useEmployeeUnlink.js +58 -0
  57. package/src/react/components/tabs/useFranchiseLinksManage.js +215 -0
  58. package/src/react/components/tabs/useSalesmanManage.js +222 -0
  59. package/src/react/components/tabs/usersTabHelpers.js +221 -0
  60. package/src/react/domain/productSupplierFlow.js +37 -0
  61. package/src/react/index.js +4 -0
  62. package/src/react/pages/ClientDetailsSkeleton.js +84 -0
  63. package/src/react/pages/clientDetailsHelpers.js +17 -0
  64. package/src/react/pages/clients.js +27 -0
  65. package/src/react/pages/details.js +529 -0
  66. package/src/react/pages/details.page.styles.js +105 -0
  67. package/src/react/pages/details.styles.js +15 -0
  68. package/src/react/pages/employees.js +69 -0
  69. package/src/react/pages/franchisees.js +30 -0
  70. package/src/react/pages/prospects.js +21 -0
  71. package/src/react/pages/provider.js +21 -0
  72. package/src/react/router/routes.js +104 -0
  73. package/src/react/styles/details.js +571 -0
  74. package/src/store/people_categories/index.js +72 -0
  75. package/src/tests/browser/manager/client-details-create-user.spec.js +321 -0
  76. package/src/tests/browser/manager/client-details-employee-unlink.spec.js +215 -0
  77. package/src/tests/browser/manager/client-details-employees-refresh.spec.js +271 -0
  78. package/src/tests/browser/manager/client-details-enable.spec.js +241 -0
  79. package/src/tests/browser/manager/client-details-fiscal-tabs.spec.js +410 -0
  80. package/src/tests/browser/manager/client-details-franchise-commission.spec.js +318 -0
  81. package/src/tests/browser/manager/client-details-franchise-links.spec.js +365 -0
  82. package/src/tests/browser/manager/client-details-media.spec.js +405 -0
  83. package/src/tests/browser/manager/client-details-relationships.spec.js +313 -0
  84. package/src/tests/browser/manager/client-details-salesman-commission.spec.js +291 -0
  85. package/src/tests/browser/manager/client-details-salesman-manage.spec.js +448 -0
  86. package/src/tests/react/components/tabs/contactMutationMessage.test.js +25 -0
  87. package/src/tests/react/components/tabs/employeeContacts.test.js +266 -0
  88. package/src/tests/react/components/tabs/employeeUnlink.test.js +67 -0
  89. package/src/tests/react/components/tabs/employeesTabHelpers.media.test.js +78 -0
  90. package/src/tests/react/components/tabs/employeesTabHelpers.test.js +64 -0
  91. package/src/tests/react/components/tabs/fiscalTabContract.test.mjs +29 -0
  92. package/src/tests/react/components/tabs/franchiseCommissionHelpers.test.js +128 -0
  93. package/src/tests/react/components/tabs/franchiseLinksTab.helpers.test.mjs +166 -0
  94. package/src/tests/react/components/tabs/generalTabHelpers.test.js +130 -0
  95. package/src/tests/react/components/tabs/peopleMediaTabs.test.js +322 -0
  96. package/src/tests/react/components/tabs/salesmanTab.helpers.test.mjs +75 -0
  97. package/src/tests/react/components/tabs/salesmanTabHelpers.test.js +142 -0
  98. package/src/tests/react/components/tabs/salesmanTabHelpers.test.mjs +92 -0
  99. package/src/tests/react/components/tabs/usersTabHelpers.test.js +59 -0
  100. package/src/tests/react/domain/productSupplierFlow.test.mjs +55 -0
  101. package/src/tests/react/pages/clientDetailsHelpers.test.js +98 -0
  102. package/src/tests/react/pages/employees.test.js +44 -0
@@ -0,0 +1,291 @@
1
+ const {expect, test} = require('playwright/test');
2
+ const {API_ORIGIN} = require('../../../../../../../src/tests/browser/apiOrigin');
3
+ const {version: appVersion} = require('../../../../../../../package.json');
4
+
5
+ const CORS_HEADERS = {
6
+ 'access-control-allow-origin': '*',
7
+ 'access-control-allow-headers':
8
+ 'API-TOKEN, APP-DOMAIN, DEVICE, ACCEPT, CONTENT-TYPE, X-Requested-With',
9
+ 'access-control-allow-methods': 'GET,POST,PUT,PATCH,DELETE,OPTIONS',
10
+ };
11
+
12
+ const jsonHeaders = () => ({
13
+ ...CORS_HEADERS,
14
+ 'content-type': 'application/ld+json; charset=utf-8',
15
+ });
16
+
17
+ const collection = member => ({
18
+ member,
19
+ 'hydra:member': member,
20
+ totalItems: member.length,
21
+ 'hydra:totalItems': member.length,
22
+ });
23
+
24
+ const themeColors = {
25
+ primary: '#1C8FBD',
26
+ secondary: '#0169D9',
27
+ background: '#F3F7FB',
28
+ text: '#0F172A',
29
+ textSecondary: '#6C7787',
30
+ border: '#D7E1EC',
31
+ headerBackground: '#F3F7FB',
32
+ headerBorder: '#D7E1EC',
33
+ headerText: '#0F172A',
34
+ cardBackground: '#FFFFFF',
35
+ cardBorder: '#D7E1EC',
36
+ cardText: '#0F172A',
37
+ cardIcon: '#1C8FBD',
38
+ cardShadow: '#1C8FBD',
39
+ listItemBackground: '#F1F8FB',
40
+ listItemText: '#0F172A',
41
+ listItemSubtitleText: '#6C7787',
42
+ loadingSpinner: '#1C8FBD',
43
+ buttonBackground: '#1C8FBD',
44
+ buttonBorder: '#1C8FBD',
45
+ buttonIcon: '#FFFFFF',
46
+ buttonText: '#FFFFFF',
47
+ buttonShadow: '#1C8FBD',
48
+ buttonBackgroundSecondary: '#FFFFFF',
49
+ buttonBorderSecondary: '#D7E1EC',
50
+ buttonIconSecondary: '#0169D9',
51
+ buttonTextSecondary: '#0169D9',
52
+ buttonDisabledBackground: '#CBD5E1',
53
+ tabBarBackground: '#FFFFFF',
54
+ tabBarBorder: '#D7E1EC',
55
+ menuSelectedBorder: '#1C8FBD',
56
+ menuSelectedText: '#1C8FBD',
57
+ pageBackground: '#F3F7FB',
58
+ modalOverlay: 'rgba(15,23,42,0.45)',
59
+ modalBackground: '#FFFFFF',
60
+ modalText: '#0F172A',
61
+ modalShadow: '#1C8FBD',
62
+ inputBackground: '#FFFFFF',
63
+ inputBorder: '#D7E1EC',
64
+ };
65
+
66
+ const company = {
67
+ '@id': '/people/2',
68
+ id: 2,
69
+ name: 'CONTROLE ONLINE',
70
+ alias: 'CONTROLE ONLINE',
71
+ panel_enabled: true,
72
+ enabled: true,
73
+ commercial_enabled: true,
74
+ theme: {colors: themeColors},
75
+ configs: {},
76
+ };
77
+
78
+ const client = {
79
+ '@id': '/people/29',
80
+ id: 29,
81
+ name: 'LAVE GO FRANQUIAS LTDA',
82
+ alias: 'LAVE-GO',
83
+ peopleType: 'J',
84
+ enable: true,
85
+ };
86
+
87
+ const sellerDefault = {
88
+ '@id': '/people/40',
89
+ id: 40,
90
+ name: 'VENDEDOR PADRAO',
91
+ alias: 'PADRAO',
92
+ peopleType: 'F',
93
+ };
94
+
95
+ const sellerOverride = {
96
+ '@id': '/people/41',
97
+ id: 41,
98
+ name: 'VENDEDOR OVERRIDE',
99
+ alias: 'OVERRIDE',
100
+ peopleType: 'F',
101
+ };
102
+
103
+ const mockManagerApi = async (page, {roles = ['ROLE_SUPER']} = {}) => {
104
+ await page.route(`${API_ORIGIN}/**`, async route => {
105
+ const request = route.request();
106
+ const url = new URL(request.url());
107
+ const pathname = url.pathname.replace(/^\/+/, '');
108
+
109
+ if (request.method() === 'OPTIONS') {
110
+ return route.fulfill({status: 204, headers: CORS_HEADERS, body: ''});
111
+ }
112
+
113
+ if (pathname === 'people/29' || pathname === 'people/29/') {
114
+ return route.fulfill({
115
+ status: 200,
116
+ headers: jsonHeaders(),
117
+ body: JSON.stringify(client),
118
+ });
119
+ }
120
+
121
+ if (pathname === 'people' || pathname.startsWith('people?')) {
122
+ return route.fulfill({
123
+ status: 200,
124
+ headers: jsonHeaders(),
125
+ body: JSON.stringify(collection([client])),
126
+ });
127
+ }
128
+
129
+ if (pathname === 'people_links' || pathname.startsWith('people_links')) {
130
+ const query = Object.fromEntries(url.searchParams);
131
+ if (query.linkType === 'sellers-client') {
132
+ return route.fulfill({
133
+ status: 200,
134
+ headers: jsonHeaders(),
135
+ body: JSON.stringify(
136
+ collection([
137
+ {
138
+ '@id': '/people_links/501',
139
+ id: 501,
140
+ company: sellerDefault,
141
+ people: client,
142
+ linkType: 'sellers-client',
143
+ comission: null,
144
+ minimum_comission: null,
145
+ },
146
+ {
147
+ '@id': '/people_links/502',
148
+ id: 502,
149
+ company: sellerOverride,
150
+ people: client,
151
+ linkType: 'sellers-client',
152
+ comission: 15,
153
+ minimum_comission: 5,
154
+ },
155
+ ]),
156
+ ),
157
+ });
158
+ }
159
+ if (query.linkType === 'salesman') {
160
+ return route.fulfill({
161
+ status: 200,
162
+ headers: jsonHeaders(),
163
+ body: JSON.stringify(
164
+ collection([
165
+ {
166
+ '@id': '/people_links/601',
167
+ id: 601,
168
+ company: company,
169
+ people: sellerDefault,
170
+ linkType: 'salesman',
171
+ comission: 10,
172
+ minimum_comission: 2,
173
+ },
174
+ {
175
+ '@id': '/people_links/602',
176
+ id: 602,
177
+ company: company,
178
+ people: sellerOverride,
179
+ linkType: 'salesman',
180
+ comission: 10,
181
+ minimum_comission: 2,
182
+ },
183
+ ]),
184
+ ),
185
+ });
186
+ }
187
+ return route.fulfill({
188
+ status: 200,
189
+ headers: jsonHeaders(),
190
+ body: JSON.stringify(collection([])),
191
+ });
192
+ }
193
+
194
+ if (pathname.startsWith('people_links/') && request.method() === 'PUT') {
195
+ const body = request.postDataJSON?.() || {};
196
+ return route.fulfill({
197
+ status: 200,
198
+ headers: jsonHeaders(),
199
+ body: JSON.stringify({
200
+ '@id': `/people_links/${pathname.split('/').pop()}`,
201
+ id: Number(pathname.split('/').pop()),
202
+ ...body,
203
+ }),
204
+ });
205
+ }
206
+
207
+ if (pathname.includes('people_media') || pathname.includes('people-media')) {
208
+ return route.fulfill({
209
+ status: 200,
210
+ headers: jsonHeaders(),
211
+ body: JSON.stringify(collection([])),
212
+ });
213
+ }
214
+
215
+ if (pathname === 'menus-people') {
216
+ return route.fulfill({
217
+ status: 200,
218
+ headers: jsonHeaders(),
219
+ body: JSON.stringify({modules: {}}),
220
+ });
221
+ }
222
+
223
+ if (pathname === 'configs/discovery-configs') {
224
+ return route.fulfill({
225
+ status: 200,
226
+ headers: jsonHeaders(),
227
+ body: JSON.stringify({configs: {}}),
228
+ });
229
+ }
230
+
231
+ return route.fulfill({
232
+ status: 200,
233
+ headers: jsonHeaders(),
234
+ body: JSON.stringify(collection([])),
235
+ });
236
+ });
237
+
238
+ await page.addInitScript(
239
+ ({version, roles}) => {
240
+ localStorage.setItem(
241
+ 'session',
242
+ JSON.stringify({
243
+ id: 19,
244
+ people: '/people/19',
245
+ api_key: 'test-api-key',
246
+ active: 1,
247
+ mycompany: 2,
248
+ roles,
249
+ }),
250
+ );
251
+ localStorage.setItem('app-type', 'MANAGER');
252
+ localStorage.setItem('config', JSON.stringify({language: 'pt-br'}));
253
+ localStorage.setItem(
254
+ 'device',
255
+ JSON.stringify({
256
+ id: 'web-manager',
257
+ device: 'web-manager',
258
+ type: 'WEB',
259
+ appName: 'Browser Manager',
260
+ appVersion: version,
261
+ buildNumber: version,
262
+ systemName: 'web',
263
+ systemVersion: 'web',
264
+ deviceType: 'web',
265
+ metadata: {},
266
+ }),
267
+ );
268
+ },
269
+ {version: appVersion, roles},
270
+ );
271
+ };
272
+
273
+ test.describe('manager client salesman commission', () => {
274
+ test('shows default and override commissions; edit for ROLE_SUPER', async ({page}) => {
275
+ await mockManagerApi(page, {roles: ['ROLE_SUPER']});
276
+ await page.goto('/client-details?clientId=29&contextKey=client&initialTab=sellers');
277
+
278
+ await expect(page.getByTestId('salesman-commission-501')).toBeVisible({timeout: 15000});
279
+ await expect(page.getByTestId('salesman-commission-label-501')).toContainText('padrão');
280
+ await expect(page.getByTestId('salesman-commission-label-502')).toContainText('override');
281
+ await expect(page.getByTestId('salesman-commission-edit-btn-502')).toBeVisible();
282
+ });
283
+
284
+ test('hides edit control for non-owner/non-super roles', async ({page}) => {
285
+ await mockManagerApi(page, {roles: ['ROLE_EMPLOYEE']});
286
+ await page.goto('/client-details?clientId=29&contextKey=client&initialTab=sellers');
287
+
288
+ await expect(page.getByTestId('salesman-commission-502')).toBeVisible({timeout: 15000});
289
+ await expect(page.getByTestId('salesman-commission-edit-btn-502')).toHaveCount(0);
290
+ });
291
+ });