@credithub/harlan-components 1.56.0 → 1.58.0

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.
@@ -37,14 +37,68 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  import { formatMoney } from '../../utils/number';
38
38
  import { formatDocument } from '../../utils/string';
39
39
  import XPathUtils from '../../utils/xpath';
40
- import React, { memo, useContext } from 'react';
40
+ import React, { memo, useContext, useState, useEffect } from 'react';
41
41
  import AddItemField from '../common/addItem';
42
42
  import Button from '../common/button';
43
43
  import { ResultContent } from '../interface/result';
44
44
  import { WebService } from '../webservice';
45
45
  import { openFormThenRedirect } from '../../utils/protestosp';
46
+ // Throttling mechanism for API requests
47
+ var activeRequests = 0;
48
+ var MAX_CONCURRENT_REQUESTS = 2;
49
+ var requestQueue = [];
50
+ var processQueue = function () {
51
+ if (requestQueue.length === 0 || activeRequests >= MAX_CONCURRENT_REQUESTS)
52
+ return;
53
+ // Process next request in queue
54
+ var nextRequest = requestQueue.shift();
55
+ if (nextRequest) {
56
+ activeRequests++;
57
+ nextRequest();
58
+ }
59
+ };
60
+ // Elegant three-dot loader component
61
+ var ThreeDotsLoader = function () {
62
+ // CSS for the loader container
63
+ var loaderStyle = {
64
+ display: 'inline-flex',
65
+ alignItems: 'center',
66
+ marginLeft: '5px',
67
+ height: '10px',
68
+ };
69
+ // CSS for each dot
70
+ var dotStyle = function (delay) { return ({
71
+ width: '4px',
72
+ height: '4px',
73
+ margin: '0 2px',
74
+ borderRadius: '50%',
75
+ background: '#aaa',
76
+ opacity: 0.7,
77
+ animation: 'blink 1.4s infinite',
78
+ animationDelay: "".concat(delay, "s"),
79
+ }); };
80
+ // CSS animation keyframes defined as a style block
81
+ var keyframes = "\n @keyframes blink {\n 0% { opacity: 0.2; }\n 20% { opacity: 0.8; }\n 100% { opacity: 0.2; }\n }\n ";
82
+ return (React.createElement("span", { style: loaderStyle },
83
+ React.createElement("style", null, keyframes),
84
+ React.createElement("span", { style: dotStyle(0) }),
85
+ React.createElement("span", { style: dotStyle(0.2) }),
86
+ React.createElement("span", { style: dotStyle(0.4) })));
87
+ };
88
+ // AI Indicator component with tooltip
89
+ var AIIndicator = function () { return (React.createElement("span", { title: "Informa\u00E7\u00E3o obtida utilizando IA", style: {
90
+ color: '#0066cc',
91
+ marginLeft: '3px',
92
+ fontSize: '0.8em',
93
+ cursor: 'help'
94
+ } }, "*")); };
46
95
  export var ProtestoItem = memo(function (_a) {
47
96
  var protesto = _a.protesto;
97
+ var client = useContext(WebService);
98
+ var _b = useState(null), quemApresentou = _b[0], setQuemApresentou = _b[1];
99
+ var _c = useState(false), loading = _c[0], setLoading = _c[1];
100
+ var _d = useState(false), queued = _d[0], setQueued = _d[1];
101
+ var _e = useState(false), isAIData = _e[0], setIsAIData = _e[1];
48
102
  var getField = function (path, formatter) {
49
103
  var value = XPathUtils.select("string(".concat(path, ")"), protesto);
50
104
  return formatter ? formatter(value) : value;
@@ -52,8 +106,112 @@ export var ProtestoItem = memo(function (_a) {
52
106
  var formatBooleanField = function (value) {
53
107
  return value === 'true' ? 'Sim' : 'Não';
54
108
  };
109
+ // Function to fetch Quem Apresentou/Protestou data
110
+ var fetchQuemApresentou = function (nm_chave) { return __awaiter(void 0, void 0, void 0, function () {
111
+ var response, error_1;
112
+ return __generator(this, function (_a) {
113
+ switch (_a.label) {
114
+ case 0:
115
+ if (!nm_chave)
116
+ return [2 /*return*/];
117
+ setLoading(true);
118
+ _a.label = 1;
119
+ case 1:
120
+ _a.trys.push([1, 4, 5, 6]);
121
+ return [4 /*yield*/, client.request("SELECT FROM 'PDFPROTESTO'.'AI'", { nm_chave: nm_chave })];
122
+ case 2: return [4 /*yield*/, (_a.sent()).json()];
123
+ case 3:
124
+ response = _a.sent();
125
+ // Check for "Quem Protestou" first, fallback to "Quem Apresentou"
126
+ if (response) {
127
+ if (response['Quem Protestou']) {
128
+ setQuemApresentou(response['Quem Protestou']);
129
+ setIsAIData(true); // Mark that data came from AI
130
+ }
131
+ else if (response['Quem Apresentou']) {
132
+ setQuemApresentou(response['Quem Apresentou']);
133
+ setIsAIData(true); // Mark that data came from AI
134
+ }
135
+ }
136
+ return [3 /*break*/, 6];
137
+ case 4:
138
+ error_1 = _a.sent();
139
+ console.error('Error fetching protesto data:', error_1);
140
+ return [3 /*break*/, 6];
141
+ case 5:
142
+ setLoading(false);
143
+ activeRequests--;
144
+ processQueue(); // Process next request in queue
145
+ return [7 /*endfinally*/];
146
+ case 6: return [2 /*return*/];
147
+ }
148
+ });
149
+ }); };
150
+ // Function to queue or execute the fetch request
151
+ var queueOrExecuteFetch = function (nm_chave) {
152
+ var executeRequest = function () {
153
+ fetchQuemApresentou(nm_chave);
154
+ };
155
+ if (activeRequests < MAX_CONCURRENT_REQUESTS) {
156
+ // Execute immediately if under threshold
157
+ activeRequests++;
158
+ executeRequest();
159
+ }
160
+ else {
161
+ // Queue the request
162
+ setQueued(true);
163
+ requestQueue.push(function () {
164
+ setQueued(false);
165
+ executeRequest();
166
+ });
167
+ }
168
+ };
169
+ useEffect(function () {
170
+ // Check if nomeCedente is empty
171
+ var nomeCedente = getField('./nomeCedente');
172
+ if (nomeCedente && nomeCedente.trim() !== '')
173
+ return;
174
+ // Get nm_chave and queue/execute the request
175
+ var nm_chave = getField('./nm_chave');
176
+ if (nm_chave) {
177
+ queueOrExecuteFetch(nm_chave);
178
+ }
179
+ // Cleanup function
180
+ return function () {
181
+ // If this component unmounts while in queue, try to remove it from queue
182
+ var queueIndex = requestQueue.findIndex(function (req) {
183
+ return req.toString().includes(nm_chave);
184
+ });
185
+ if (queueIndex !== -1) {
186
+ requestQueue.splice(queueIndex, 1);
187
+ }
188
+ };
189
+ }, []);
190
+ // Get the display value for Quem Protestou field
191
+ var getQuemProtestouDisplay = function () {
192
+ // First check if we have original data from the XML
193
+ var originalValue = getField('./nomeCedente');
194
+ // If we have original data, don't show the loader
195
+ if (originalValue && originalValue.trim() !== '') {
196
+ return originalValue;
197
+ }
198
+ // If we have AI data, show it with the indicator
199
+ if (isAIData && quemApresentou) {
200
+ return React.createElement(React.Fragment, null,
201
+ quemApresentou,
202
+ React.createElement(AIIndicator, null));
203
+ }
204
+ // If we're loading or queued and don't have data yet, show loader
205
+ if ((loading || queued) && (!quemApresentou || quemApresentou.trim() === '')) {
206
+ return React.createElement(React.Fragment, null,
207
+ " ",
208
+ React.createElement(ThreeDotsLoader, null));
209
+ }
210
+ // Fallback to empty string if nothing else applies
211
+ return quemApresentou || '';
212
+ };
55
213
  return (React.createElement(ResultContent, { print: "repeat(7, 1fr)", desktop: "repeat(8, 1fr)", tablet: "repeat(4, 1fr)", mobile: "repeat(2, 1fr)" },
56
- React.createElement(AddItemField, { name: "Quem Protestou", value: getField('./nomeCedente') }),
214
+ React.createElement(AddItemField, { name: "Quem Protestou", value: getQuemProtestouDisplay() }),
57
215
  React.createElement(AddItemField, { name: "Atrav\u00E9s De", value: getField('./nomeApresentante') }),
58
216
  React.createElement(AddItemField, { name: "CPF/CNPJ Protestado", value: formatDocument(getField('./cpfCnpj')) }),
59
217
  React.createElement(AddItemField, { name: "Data Do Protesto", value: getField('./dataProtesto') }),