@credithub/harlan-components 1.104.1 → 1.106.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.
@@ -13,13 +13,25 @@ import ProtestosIcon from '../../assets/icones/protestos';
13
13
  import { useGlobalData } from '../../contexts/globalDataContext';
14
14
  import { formatMoney } from '../../utils/number';
15
15
  import { formatDocument } from '../../utils/string';
16
- import React, { useEffect, useMemo, useRef } from 'react';
16
+ import React, { memo, useEffect, useMemo, useRef } from 'react';
17
17
  import AddItemField from '../common/addItem';
18
- import { ResultContent } from '../interface/result';
18
+ import { Result, ResultContent } from '../interface/result';
19
19
  import StatusMessage from '../interface/statusMessage';
20
20
  import Section from '../section';
21
21
  import { RequestStatus } from '../webservice';
22
22
  import { adaptToUI, buildChartSeries } from './adaptToChart';
23
+ // Componente individual para cada protesto pago/baixado
24
+ var ProtestoHistoricoItemComponent = memo(function (_a) {
25
+ var protesto = _a.protesto;
26
+ return (React.createElement(ResultContent, { print: "repeat(7, 1fr)", desktop: "repeat(8, 1fr)", tablet: "repeat(4, 1fr)", mobile: "repeat(2, 1fr)" },
27
+ React.createElement(AddItemField, { name: "Quem Protestou", value: protesto.nomeCedente }),
28
+ React.createElement(AddItemField, { name: "Atrav\u00E9s De", value: protesto.nomeApresentante }),
29
+ React.createElement(AddItemField, { name: "CPF/CNPJ Protestado", value: formatDocument(protesto.cpfCnpj) }),
30
+ React.createElement(AddItemField, { name: "Data Do Protesto", value: protesto.dataProtesto }),
31
+ React.createElement(AddItemField, { name: "Possui Anu\u00EAncia / Protesto Pago", value: protesto.temAnuencia ? 'Sim' : 'Não' }),
32
+ React.createElement(AddItemField, { name: "Valor Do Protesto", value: formatMoney(protesto.valor) })));
33
+ });
34
+ ProtestoHistoricoItemComponent.displayName = 'ProtestoHistoricoItemComponent';
23
35
  var ProtestosPagosBaixados = function (_a) {
24
36
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
25
37
  var _p = _a.isFinancial, isFinancial = _p === void 0 ? false : _p;
@@ -74,12 +86,13 @@ var ProtestosPagosBaixados = function (_a) {
74
86
  ? 'Não foram encontradas ocorrências'
75
87
  : ((_j = (_h = data === null || data === void 0 ? void 0 : data.protestosPagosBaixados) === null || _h === void 0 ? void 0 : _h.protestos) === null || _j === void 0 ? void 0 : _j.length) === 1
76
88
  ? 'Foi encontrado um protesto'
77
- : "Foram encontrados ".concat((_l = (_k = data === null || data === void 0 ? void 0 : data.protestosPagosBaixados) === null || _k === void 0 ? void 0 : _k.protestos) === null || _l === void 0 ? void 0 : _l.length, " protestos")), variant: ((_o = (_m = data === null || data === void 0 ? void 0 : data.protestosPagosBaixados) === null || _m === void 0 ? void 0 : _m.protestos) === null || _o === void 0 ? void 0 : _o.length) ? 'error' : 'default', icon: ProtestosIcon, onSuccess: function () { return (React.createElement("div", null, adaptToUI(items).map(function (protesto) { return (React.createElement(ResultContent, { key: protesto.chave, print: "repeat(7, 1fr)", desktop: "repeat(8, 1fr)", tablet: "repeat(4, 1fr)", mobile: "repeat(2, 1fr)" },
78
- React.createElement(AddItemField, { name: "Quem Protestou", value: protesto.nomeCedente }),
79
- React.createElement(AddItemField, { name: "Atrav\u00E9s De", value: protesto.nomeApresentante }),
80
- React.createElement(AddItemField, { name: "CPF/CNPJ Protestado", value: formatDocument(protesto.cpfCnpj) }),
81
- React.createElement(AddItemField, { name: "Data Do Protesto", value: protesto.dataProtesto }),
82
- React.createElement(AddItemField, { name: "Possui Anu\u00EAncia / Protesto Pago", value: protesto.temAnuencia ? 'Sim' : 'Não' }),
83
- React.createElement(AddItemField, { name: "Valor Do Protesto", value: formatMoney(protesto.valor) }))); }))); } }));
89
+ : "Foram encontrados ".concat((_l = (_k = data === null || data === void 0 ? void 0 : data.protestosPagosBaixados) === null || _k === void 0 ? void 0 : _k.protestos) === null || _l === void 0 ? void 0 : _l.length, " protestos")), variant: ((_o = (_m = data === null || data === void 0 ? void 0 : data.protestosPagosBaixados) === null || _m === void 0 ? void 0 : _m.protestos) === null || _o === void 0 ? void 0 : _o.length) ? 'error' : 'default', icon: ProtestosIcon, onSuccess: function () {
90
+ var protestosAdaptados = adaptToUI(items);
91
+ var totalProtestos = protestosAdaptados.length;
92
+ var children = totalProtestos ? (React.createElement(Result, null, protestosAdaptados.map(function (protesto) { return (React.createElement(ProtestoHistoricoItemComponent, { key: protesto.chave, protesto: protesto })); }))) : null;
93
+ return {
94
+ children: children
95
+ };
96
+ } }));
84
97
  };
85
98
  export default ProtestosPagosBaixados;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Utility functions for calculating business days (Monday-Friday, excluding Brazilian national holidays)
3
+ */
4
+ /**
5
+ * Check if a date is a business day (Monday-Friday, not a holiday)
6
+ */
7
+ export declare const isBusinessDay: (date: Date) => boolean;
8
+ /**
9
+ * Calculate the number of business days between two dates
10
+ * @param fromDate Start date (inclusive)
11
+ * @param toDate End date (exclusive)
12
+ * @returns Number of business days
13
+ */
14
+ export declare const calculateBusinessDays: (fromDate: Date, toDate: Date) => number;
15
+ /**
16
+ * Parse various date formats from edital data
17
+ */
18
+ export declare const parseEditalDate: (dateStr: string) => Date | null;
19
+ /**
20
+ * Calculate remaining business days until deadline (3 business days for protest)
21
+ * @param cadastroDate Date when the edital was registered
22
+ * @returns Number of business days remaining (max 3, can be negative if expired)
23
+ */
24
+ export declare const calculateRemainingBusinessDays: (cadastroDate: Date) => number;
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Utility functions for calculating business days (Monday-Friday, excluding Brazilian national holidays)
3
+ */
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
13
+ var __generator = (this && this.__generator) || function (thisArg, body) {
14
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
15
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
16
+ function verb(n) { return function (v) { return step([n, v]); }; }
17
+ function step(op) {
18
+ if (f) throw new TypeError("Generator is already executing.");
19
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
20
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
21
+ if (y = 0, t) op = [op[0] & 2, t.value];
22
+ switch (op[0]) {
23
+ case 0: case 1: t = op; break;
24
+ case 4: _.label++; return { value: op[1], done: false };
25
+ case 5: _.label++; y = op[1]; op = [0]; continue;
26
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
27
+ default:
28
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
29
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
30
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
31
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
32
+ if (t[2]) _.ops.pop();
33
+ _.trys.pop(); continue;
34
+ }
35
+ op = body.call(thisArg, _);
36
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
37
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
38
+ }
39
+ };
40
+ /**
41
+ * Brazilian national holidays for 2024-2026 (static fallback)
42
+ * Format: 'YYYY-MM-DD'
43
+ */
44
+ var STATIC_BRAZILIAN_HOLIDAYS = [
45
+ // 2024
46
+ '2024-01-01', // Ano Novo
47
+ '2024-02-13', // Carnaval
48
+ '2024-03-29', // Sexta-feira Santa
49
+ '2024-04-21', // Tiradentes
50
+ '2024-05-01', // Dia do Trabalho
51
+ '2024-05-30', // Corpus Christi
52
+ '2024-09-07', // Independência do Brasil
53
+ '2024-10-12', // Nossa Senhora Aparecida
54
+ '2024-11-02', // Finados
55
+ '2024-11-15', // Proclamação da República
56
+ '2024-11-20', // Dia da Consciência Negra
57
+ '2024-12-25', // Natal
58
+ // 2025
59
+ '2025-01-01', // Ano Novo
60
+ '2025-03-04', // Carnaval
61
+ '2025-04-18', // Sexta-feira Santa
62
+ '2025-04-21', // Tiradentes
63
+ '2025-05-01', // Dia do Trabalho
64
+ '2025-06-19', // Corpus Christi
65
+ '2025-09-07', // Independência do Brasil
66
+ '2025-10-12', // Nossa Senhora Aparecida
67
+ '2025-11-02', // Finados
68
+ '2025-11-15', // Proclamação da República
69
+ '2025-11-20', // Dia da Consciência Negra
70
+ '2025-12-25', // Natal
71
+ // 2026
72
+ '2026-01-01', // Ano Novo
73
+ '2026-02-17', // Carnaval
74
+ '2026-04-03', // Sexta-feira Santa
75
+ '2026-04-21', // Tiradentes
76
+ '2026-05-01', // Dia do Trabalho
77
+ '2026-06-04', // Corpus Christi
78
+ '2026-09-07', // Independência do Brasil
79
+ '2026-10-12', // Nossa Senhora Aparecida
80
+ '2026-11-02', // Finados
81
+ '2026-11-15', // Proclamação da República
82
+ '2026-11-20', // Dia da Consciência Negra
83
+ '2026-12-25' // Natal
84
+ ];
85
+ var holidayCache = {};
86
+ /**
87
+ * Flag to control if we should use holidays or only weekends
88
+ * Set to false if API fails, falling back to weekend-only validation
89
+ */
90
+ var useHolidaysValidation = true;
91
+ /**
92
+ * Format date as 'YYYY-MM-DD'
93
+ */
94
+ var formatDateKey = function (date) {
95
+ var year = date.getFullYear();
96
+ var month = String(date.getMonth() + 1).padStart(2, '0');
97
+ var day = String(date.getDate()).padStart(2, '0');
98
+ return "".concat(year, "-").concat(month, "-").concat(day);
99
+ };
100
+ /**
101
+ * Fetch holidays from Brasil API for a given year
102
+ */
103
+ var fetchHolidaysFromAPI = function (year) { return __awaiter(void 0, void 0, void 0, function () {
104
+ var response, holidays, error_1;
105
+ return __generator(this, function (_a) {
106
+ switch (_a.label) {
107
+ case 0:
108
+ _a.trys.push([0, 3, , 4]);
109
+ return [4 /*yield*/, fetch("https://brasilapi.com.br/api/feriados/v1/".concat(year), {
110
+ method: 'GET',
111
+ headers: { 'Content-Type': 'application/json' }
112
+ })];
113
+ case 1:
114
+ response = _a.sent();
115
+ if (!response.ok) {
116
+ throw new Error("API response status: ".concat(response.status));
117
+ }
118
+ return [4 /*yield*/, response.json()];
119
+ case 2:
120
+ holidays = _a.sent();
121
+ return [2 /*return*/, holidays.map(function (h) { return h.date; })];
122
+ case 3:
123
+ error_1 = _a.sent();
124
+ console.warn("Failed to fetch holidays for ".concat(year, " from Brasil API:"), error_1);
125
+ return [2 /*return*/, []];
126
+ case 4: return [2 /*return*/];
127
+ }
128
+ });
129
+ }); };
130
+ /**
131
+ * Get holidays for a given year (with caching and fallbacks)
132
+ */
133
+ var getHolidaysForYear = function (year) { return __awaiter(void 0, void 0, void 0, function () {
134
+ var apiHolidays, staticHolidays;
135
+ return __generator(this, function (_a) {
136
+ switch (_a.label) {
137
+ case 0:
138
+ // Check cache first
139
+ if (holidayCache[year]) {
140
+ return [2 /*return*/, holidayCache[year]];
141
+ }
142
+ return [4 /*yield*/, fetchHolidaysFromAPI(year)];
143
+ case 1:
144
+ apiHolidays = _a.sent();
145
+ if (apiHolidays.length > 0) {
146
+ holidayCache[year] = apiHolidays;
147
+ return [2 /*return*/, apiHolidays];
148
+ }
149
+ staticHolidays = STATIC_BRAZILIAN_HOLIDAYS.filter(function (h) {
150
+ return h.startsWith("".concat(year, "-"));
151
+ });
152
+ if (staticHolidays.length > 0) {
153
+ holidayCache[year] = staticHolidays;
154
+ return [2 /*return*/, staticHolidays];
155
+ }
156
+ // If everything fails, disable holiday validation
157
+ useHolidaysValidation = false;
158
+ console.warn("No holidays found for ".concat(year, ". Falling back to weekend-only validation."));
159
+ return [2 /*return*/, []];
160
+ }
161
+ });
162
+ }); };
163
+ /**
164
+ * Initialize holiday cache for current and relevant years
165
+ */
166
+ var initializeHolidayCache = function () { return __awaiter(void 0, void 0, void 0, function () {
167
+ var currentYear, years, error_2;
168
+ return __generator(this, function (_a) {
169
+ switch (_a.label) {
170
+ case 0:
171
+ currentYear = new Date().getFullYear();
172
+ years = [currentYear - 1, currentYear, currentYear + 1];
173
+ _a.label = 1;
174
+ case 1:
175
+ _a.trys.push([1, 3, , 4]);
176
+ return [4 /*yield*/, Promise.all(years.map(function (year) { return getHolidaysForYear(year); }))];
177
+ case 2:
178
+ _a.sent();
179
+ return [3 /*break*/, 4];
180
+ case 3:
181
+ error_2 = _a.sent();
182
+ console.warn('Failed to initialize holiday cache:', error_2);
183
+ useHolidaysValidation = false;
184
+ return [3 /*break*/, 4];
185
+ case 4: return [2 /*return*/];
186
+ }
187
+ });
188
+ }); };
189
+ // Initialize cache on module load (fire and forget)
190
+ initializeHolidayCache().catch(function () {
191
+ // Silently fail and use fallback
192
+ });
193
+ /**
194
+ * Check if a date is a Brazilian national holiday
195
+ */
196
+ var isHoliday = function (date) {
197
+ if (!useHolidaysValidation)
198
+ return false;
199
+ var dateKey = formatDateKey(date);
200
+ var year = date.getFullYear();
201
+ // Check cache
202
+ var yearHolidays = holidayCache[year];
203
+ if (yearHolidays) {
204
+ return yearHolidays.includes(dateKey);
205
+ }
206
+ // Fallback to static holidays if cache not available
207
+ return STATIC_BRAZILIAN_HOLIDAYS.includes(dateKey);
208
+ };
209
+ /**
210
+ * Check if a date is a weekend (Saturday or Sunday)
211
+ */
212
+ var isWeekend = function (date) {
213
+ var dayOfWeek = date.getDay();
214
+ return dayOfWeek === 0 || dayOfWeek === 6; // 0 = Sunday, 6 = Saturday
215
+ };
216
+ /**
217
+ * Check if a date is a business day (Monday-Friday, not a holiday)
218
+ */
219
+ export var isBusinessDay = function (date) {
220
+ return !isWeekend(date) && !isHoliday(date);
221
+ };
222
+ /**
223
+ * Calculate the number of business days between two dates
224
+ * @param fromDate Start date (inclusive)
225
+ * @param toDate End date (exclusive)
226
+ * @returns Number of business days
227
+ */
228
+ export var calculateBusinessDays = function (fromDate, toDate) {
229
+ var count = 0;
230
+ var current = new Date(fromDate);
231
+ current.setHours(0, 0, 0, 0);
232
+ var end = new Date(toDate);
233
+ end.setHours(0, 0, 0, 0);
234
+ while (current < end) {
235
+ if (isBusinessDay(current)) {
236
+ count++;
237
+ }
238
+ current.setDate(current.getDate() + 1);
239
+ }
240
+ return count;
241
+ };
242
+ /**
243
+ * Parse various date formats from edital data
244
+ */
245
+ export var parseEditalDate = function (dateStr) {
246
+ if (!dateStr)
247
+ return null;
248
+ // Try ISO format: "2025-10-20" or "2025-10-20 12:34:56"
249
+ if (/^\d{4}-\d{2}-\d{2}/.test(dateStr)) {
250
+ var date = new Date(dateStr);
251
+ if (!isNaN(date.getTime()))
252
+ return date;
253
+ }
254
+ // Try "Oct 10 2025 12:00:00:AM" format
255
+ if (dateStr.includes(' ')) {
256
+ var date = new Date(dateStr);
257
+ if (!isNaN(date.getTime()))
258
+ return date;
259
+ }
260
+ // Try dd/mm/yyyy format
261
+ if (/^\d{2}\/\d{2}\/\d{4}/.test(dateStr)) {
262
+ var _a = dateStr.split('/').map(Number), day = _a[0], month = _a[1], year = _a[2];
263
+ var date = new Date(year, month - 1, day);
264
+ if (!isNaN(date.getTime()))
265
+ return date;
266
+ }
267
+ return null;
268
+ };
269
+ /**
270
+ * Calculate remaining business days until deadline (3 business days for protest)
271
+ * @param cadastroDate Date when the edital was registered
272
+ * @returns Number of business days remaining (max 3, can be negative if expired)
273
+ */
274
+ export var calculateRemainingBusinessDays = function (cadastroDate) {
275
+ var today = new Date();
276
+ today.setHours(0, 0, 0, 0);
277
+ var businessDaysPassed = calculateBusinessDays(cadastroDate, today);
278
+ var deadline = 3; // 3 business days deadline
279
+ var remaining = deadline - businessDaysPassed;
280
+ return remaining;
281
+ };