teraprox-ui-kit 0.1.8 → 0.2.1

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/dist/index.mjs ADDED
@@ -0,0 +1,3992 @@
1
+ // src/buttons/AddButton.tsx
2
+ import { Button } from "react-bootstrap";
3
+ import { GrAdd } from "react-icons/gr";
4
+ import { jsx } from "react/jsx-runtime";
5
+ var AddButton = ({ callback, hiddenBool, size }) => /* @__PURE__ */ jsx(
6
+ Button,
7
+ {
8
+ hidden: hiddenBool || false,
9
+ variant: "outline-primary",
10
+ onClick: () => callback(),
11
+ children: /* @__PURE__ */ jsx(GrAdd, { size: size || 25 })
12
+ }
13
+ );
14
+ var AddButton_default = AddButton;
15
+
16
+ // src/buttons/DeleteButton.tsx
17
+ import { jsx as jsx2 } from "react/jsx-runtime";
18
+ var DeleteButton = ({ title, onDeleteClick }) => {
19
+ return /* @__PURE__ */ jsx2("button", { className: "btn btn-danger", onClick: () => onDeleteClick(), children: title });
20
+ };
21
+ var DeleteButton_default = DeleteButton;
22
+
23
+ // src/buttons/ActionButtons.tsx
24
+ import { useState as useState2, useRef } from "react";
25
+ import { Button as Button3, Form as Form2, ProgressBar } from "react-bootstrap";
26
+ import { FiSave, FiTrash2, FiRotateCcw, FiCopy, FiChevronLeft } from "react-icons/fi";
27
+
28
+ // src/forms/DeleteConfirm.tsx
29
+ import { useState } from "react";
30
+ import { Button as Button2, Modal, Form } from "react-bootstrap";
31
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
32
+ var DeleteConfirm = ({
33
+ show,
34
+ onHide,
35
+ onConfirm,
36
+ title = "Confirma\xE7\xE3o de Exclus\xE3o",
37
+ dialogText,
38
+ payload,
39
+ needExclusionDetails = false
40
+ }) => {
41
+ const [exclusionDetails, setExclusionDetails] = useState("");
42
+ const getDialogContent = () => {
43
+ if (typeof dialogText === "function" && payload) {
44
+ return dialogText(payload);
45
+ }
46
+ return dialogText || "Voc\xEA tem certeza que deseja excluir este item?";
47
+ };
48
+ const isConfirmEnabled = () => {
49
+ if (!needExclusionDetails) return true;
50
+ return exclusionDetails.length >= 8;
51
+ };
52
+ return /* @__PURE__ */ jsxs(Modal, { show, onHide: () => onHide(false), centered: true, children: [
53
+ /* @__PURE__ */ jsx3(Modal.Header, { closeButton: true, children: /* @__PURE__ */ jsx3(Modal.Title, { children: title }) }),
54
+ /* @__PURE__ */ jsx3(Modal.Body, { children: /* @__PURE__ */ jsxs("div", { className: "d-flex flex-column gap-3", children: [
55
+ /* @__PURE__ */ jsx3("div", { children: /* @__PURE__ */ jsx3("strong", { children: getDialogContent() }) }),
56
+ needExclusionDetails && /* @__PURE__ */ jsxs(Form.Group, { children: [
57
+ /* @__PURE__ */ jsx3(Form.Label, { children: "Motivo da Exclus\xE3o (m\xEDn. 8 caracteres)" }),
58
+ /* @__PURE__ */ jsx3(
59
+ Form.Control,
60
+ {
61
+ as: "textarea",
62
+ rows: 3,
63
+ value: exclusionDetails,
64
+ onChange: (e) => setExclusionDetails(e.target.value),
65
+ placeholder: "Descreva o motivo...",
66
+ autoFocus: true
67
+ }
68
+ )
69
+ ] })
70
+ ] }) }),
71
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
72
+ /* @__PURE__ */ jsx3(Button2, { variant: "secondary", onClick: () => onHide(false), children: "Cancelar" }),
73
+ /* @__PURE__ */ jsx3(
74
+ Button2,
75
+ {
76
+ variant: "danger",
77
+ disabled: !isConfirmEnabled(),
78
+ onClick: () => {
79
+ onConfirm(exclusionDetails);
80
+ onHide(false);
81
+ },
82
+ children: "Confirmar Exclus\xE3o"
83
+ }
84
+ )
85
+ ] })
86
+ ] });
87
+ };
88
+
89
+ // src/buttons/ActionButtons.tsx
90
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
91
+ var ActionButtons = ({
92
+ onSave,
93
+ saveLabel = "Salvar",
94
+ saveVariant = "primary",
95
+ disabled = false,
96
+ onDelete,
97
+ deleteLabel = "Excluir",
98
+ deleteConfirmMsg,
99
+ needExclusionDetails = false,
100
+ onBack,
101
+ backLabel = "Voltar",
102
+ onCancelEdit,
103
+ cancelEditLabel = "Cancelar",
104
+ onCopy,
105
+ copyLabel = "Copiar Formul\xE1rio",
106
+ isEditing = false,
107
+ useDelayedDelete = false,
108
+ delayedDeleteTimeout = 3e3,
109
+ PermissionWrapper = ({ children }) => /* @__PURE__ */ jsx4(Fragment, { children })
110
+ }) => {
111
+ const [showConfirm, setShowConfirm] = useState2(false);
112
+ const [isHolding, setIsHolding] = useState2(false);
113
+ const [progress, setProgress] = useState2(0);
114
+ const timeoutRef = useRef(null);
115
+ const intervalRef = useRef(null);
116
+ const startHold = () => {
117
+ if (disabled || !onDelete) return;
118
+ setIsHolding(true);
119
+ setProgress(0);
120
+ const step = 2;
121
+ const tickTime = delayedDeleteTimeout / (100 / step);
122
+ intervalRef.current = setInterval(() => {
123
+ setProgress((prev) => prev >= 100 ? 100 : prev + step);
124
+ }, tickTime);
125
+ timeoutRef.current = setTimeout(() => {
126
+ stopHold();
127
+ onDelete();
128
+ }, delayedDeleteTimeout);
129
+ };
130
+ const stopHold = () => {
131
+ setIsHolding(false);
132
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
133
+ if (intervalRef.current) clearInterval(intervalRef.current);
134
+ setProgress(0);
135
+ };
136
+ const renderDeleteButton = () => {
137
+ if (!onDelete || !isEditing) return null;
138
+ if (useDelayedDelete) {
139
+ return /* @__PURE__ */ jsxs2("div", { style: { position: "relative", display: "inline-block", margin: 2 }, children: [
140
+ /* @__PURE__ */ jsxs2(
141
+ Button3,
142
+ {
143
+ variant: "outline-danger",
144
+ onMouseDown: startHold,
145
+ onMouseUp: stopHold,
146
+ onMouseLeave: stopHold,
147
+ onTouchStart: startHold,
148
+ onTouchEnd: stopHold,
149
+ disabled,
150
+ style: { minWidth: "120px" },
151
+ children: [
152
+ /* @__PURE__ */ jsx4(FiTrash2, { className: "me-2" }),
153
+ isHolding ? "Segure..." : deleteLabel
154
+ ]
155
+ }
156
+ ),
157
+ isHolding && /* @__PURE__ */ jsx4(
158
+ ProgressBar,
159
+ {
160
+ now: progress,
161
+ style: {
162
+ position: "absolute",
163
+ bottom: 0,
164
+ left: 0,
165
+ right: 0,
166
+ height: "4px",
167
+ borderRadius: "0 0 4px 4px"
168
+ },
169
+ variant: "danger"
170
+ }
171
+ )
172
+ ] });
173
+ }
174
+ return /* @__PURE__ */ jsxs2(
175
+ Button3,
176
+ {
177
+ variant: "danger",
178
+ onClick: () => setShowConfirm(true),
179
+ disabled,
180
+ style: { margin: 2 },
181
+ children: [
182
+ /* @__PURE__ */ jsx4(FiTrash2, { className: "me-2" }),
183
+ deleteLabel
184
+ ]
185
+ }
186
+ );
187
+ };
188
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
189
+ /* @__PURE__ */ jsx4(
190
+ DeleteConfirm,
191
+ {
192
+ show: showConfirm,
193
+ onHide: setShowConfirm,
194
+ onConfirm: (details) => onDelete && onDelete(details),
195
+ dialogText: deleteConfirmMsg,
196
+ needExclusionDetails
197
+ }
198
+ ),
199
+ /* @__PURE__ */ jsxs2(Form2.Group, { className: "d-flex flex-wrap align-items-center mt-3 gap-1", children: [
200
+ onBack && /* @__PURE__ */ jsxs2(Button3, { variant: "outline-secondary", onClick: onBack, disabled, style: { margin: 2 }, children: [
201
+ /* @__PURE__ */ jsx4(FiChevronLeft, { className: "me-2" }),
202
+ backLabel
203
+ ] }),
204
+ isEditing && onCancelEdit && /* @__PURE__ */ jsxs2(Button3, { variant: "warning", onClick: onCancelEdit, disabled, style: { margin: 2 }, children: [
205
+ /* @__PURE__ */ jsx4(FiRotateCcw, { className: "me-2" }),
206
+ cancelEditLabel
207
+ ] }),
208
+ /* @__PURE__ */ jsx4(PermissionWrapper, { children: renderDeleteButton() }),
209
+ onSave && /* @__PURE__ */ jsxs2(Button3, { variant: saveVariant, onClick: onSave, disabled, style: { margin: 2 }, children: [
210
+ /* @__PURE__ */ jsx4(FiSave, { className: "me-2" }),
211
+ saveLabel
212
+ ] }),
213
+ isEditing && onCopy && /* @__PURE__ */ jsxs2(Button3, { variant: "outline-primary", onClick: onCopy, disabled, style: { margin: 2 }, children: [
214
+ /* @__PURE__ */ jsx4(FiCopy, { className: "me-2" }),
215
+ copyLabel
216
+ ] })
217
+ ] })
218
+ ] });
219
+ };
220
+
221
+ // src/buttons/ApproveAndReproveButtons.tsx
222
+ import { useEffect } from "react";
223
+ import { Button as Button4 } from "react-bootstrap";
224
+ import { GrCheckmark, GrClose } from "react-icons/gr";
225
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
226
+ var ApproveAndReproveButtons = ({
227
+ buttonSize = 25,
228
+ approveCallback,
229
+ reproveCallback,
230
+ cancelCallback,
231
+ headerText = "Aprovar?",
232
+ approveText,
233
+ repproveText
234
+ }) => {
235
+ useEffect(() => {
236
+ const keyboardHandler = (e) => {
237
+ if (e.key === "Escape") {
238
+ cancelCallback();
239
+ }
240
+ };
241
+ window.document.addEventListener("keydown", keyboardHandler);
242
+ return () => window.document.removeEventListener("keydown", keyboardHandler);
243
+ }, [cancelCallback]);
244
+ return /* @__PURE__ */ jsxs3("div", { children: [
245
+ /* @__PURE__ */ jsx5("strong", { children: headerText }),
246
+ /* @__PURE__ */ jsx5("br", {}),
247
+ /* @__PURE__ */ jsx5(Button4, { onClick: approveCallback, variant: "success", className: "me-1", children: approveText ? approveText : /* @__PURE__ */ jsx5(GrCheckmark, { size: buttonSize }) }),
248
+ /* @__PURE__ */ jsx5(Button4, { onClick: reproveCallback, variant: "danger", children: repproveText ? repproveText : /* @__PURE__ */ jsx5(GrClose, { size: buttonSize }) })
249
+ ] });
250
+ };
251
+
252
+ // src/buttons/AsyncButton.tsx
253
+ import { useState as useState3, useRef as useRef2 } from "react";
254
+ import { Button as Button5 } from "react-bootstrap";
255
+
256
+ // src/progress/LoadingProgress.tsx
257
+ import { Spinner } from "react-bootstrap";
258
+ import { jsx as jsx6 } from "react/jsx-runtime";
259
+ var LoadingProgress = ({ hidden }) => {
260
+ return /* @__PURE__ */ jsx6(Spinner, { hidden, animation: "border", role: "status", children: /* @__PURE__ */ jsx6("span", { className: "visually-hidden", children: "Carregando..." }) });
261
+ };
262
+
263
+ // src/buttons/AsyncButton.tsx
264
+ import { jsx as jsx7 } from "react/jsx-runtime";
265
+ var useAsyncAction = () => {
266
+ const [loading, setLoading] = useState3(false);
267
+ const isMounted = useRef2(true);
268
+ const isProcessing = useRef2(false);
269
+ const execute = async (action) => {
270
+ if (typeof action !== "function") {
271
+ throw new Error("A\xE7\xE3o inv\xE1lida: n\xE3o \xE9 uma fun\xE7\xE3o");
272
+ }
273
+ if (!action || isProcessing.current) return;
274
+ isProcessing.current = true;
275
+ setLoading(true);
276
+ try {
277
+ await action();
278
+ } catch (error) {
279
+ console.error("Async operation failed:", error);
280
+ } finally {
281
+ if (isMounted.current) {
282
+ setLoading(false);
283
+ isProcessing.current = false;
284
+ }
285
+ }
286
+ };
287
+ return { loading, execute };
288
+ };
289
+ var AsyncButton = ({
290
+ onClick,
291
+ children,
292
+ loadingComponent = /* @__PURE__ */ jsx7(LoadingProgress, {}),
293
+ buttonProps
294
+ }) => {
295
+ const { loading, execute } = useAsyncAction();
296
+ return /* @__PURE__ */ jsx7(
297
+ Button5,
298
+ {
299
+ ...buttonProps,
300
+ onClick: () => execute(onClick),
301
+ disabled: loading || buttonProps && buttonProps.disabled,
302
+ children: loading ? loadingComponent : children
303
+ }
304
+ );
305
+ };
306
+
307
+ // src/buttons/BonusButton.tsx
308
+ import { jsx as jsx8 } from "react/jsx-runtime";
309
+ var BonusButton = ({
310
+ renderCondition = true,
311
+ onClickCallback,
312
+ label,
313
+ className = "",
314
+ ...props
315
+ }) => {
316
+ if (!renderCondition) return null;
317
+ return /* @__PURE__ */ jsx8(
318
+ "button",
319
+ {
320
+ className: `bonus-button ${className}`,
321
+ onClick: onClickCallback,
322
+ ...props,
323
+ children: label
324
+ }
325
+ );
326
+ };
327
+
328
+ // src/buttons/ButtonWithDropdown.tsx
329
+ import { Button as Button6, ButtonGroup, Dropdown } from "react-bootstrap";
330
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
331
+ var ButtonWithDropdown = ({
332
+ title,
333
+ onClickButton,
334
+ options,
335
+ menuVariant = "light",
336
+ variant = "primary",
337
+ toggleVariant
338
+ }) => {
339
+ return /* @__PURE__ */ jsxs4(
340
+ Dropdown,
341
+ {
342
+ as: ButtonGroup,
343
+ className: "d-flex w-100",
344
+ style: { flex: 1, minWidth: 0 },
345
+ children: [
346
+ /* @__PURE__ */ jsx9(
347
+ Button6,
348
+ {
349
+ variant,
350
+ onClick: onClickButton,
351
+ className: "flex-grow-1 text-truncate",
352
+ style: { minWidth: 0 },
353
+ children: title
354
+ }
355
+ ),
356
+ /* @__PURE__ */ jsx9(
357
+ Dropdown.Toggle,
358
+ {
359
+ split: true,
360
+ variant: toggleVariant || variant,
361
+ id: "dropdown-split-basic",
362
+ style: {
363
+ flex: "0 0 2.5rem",
364
+ width: "2.5rem",
365
+ padding: "0",
366
+ display: "flex",
367
+ justifyContent: "center",
368
+ alignItems: "center"
369
+ }
370
+ }
371
+ ),
372
+ /* @__PURE__ */ jsx9(Dropdown.Menu, { variant: menuVariant, children: options.map((opt, idx) => /* @__PURE__ */ jsx9(Dropdown.Item, { onClick: opt.callback, children: opt.label }, `${opt.label}-${idx}`)) })
373
+ ]
374
+ }
375
+ );
376
+ };
377
+
378
+ // src/buttons/CheckBox.tsx
379
+ import { Form as Form3, InputGroup } from "react-bootstrap";
380
+ import { TiDelete } from "react-icons/ti";
381
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
382
+ var CheckBox = ({
383
+ opcoes,
384
+ isHover = false,
385
+ isCreator = false,
386
+ updateEvent,
387
+ deleteEvent,
388
+ enterEvent,
389
+ disabled = false,
390
+ className = ""
391
+ }) => {
392
+ if (isHover) {
393
+ return /* @__PURE__ */ jsx10("div", { className, children: opcoes.map((opcao, index) => /* @__PURE__ */ jsxs5(InputGroup, { style: { padding: 12, justifyItems: "center", opacity: disabled ? 0.5 : 1, pointerEvents: disabled ? "none" : "auto" }, children: [
394
+ /* @__PURE__ */ jsx10(InputGroup.Checkbox, {}),
395
+ /* @__PURE__ */ jsx10(
396
+ Form3.Control,
397
+ {
398
+ autoFocus: true,
399
+ onKeyDown: (event) => enterEvent && enterEvent(event, index, opcao),
400
+ style: { border: "none", borderBottom: "solid", borderRadius: 0, borderColor: "gray", borderWidth: "1px" },
401
+ value: isCreator ? "Nova opcao" : String(opcao.valor),
402
+ onChange: (event) => updateEvent && updateEvent(event, index)
403
+ }
404
+ ),
405
+ deleteEvent && /* @__PURE__ */ jsx10("span", { style: { cursor: "pointer" }, children: /* @__PURE__ */ jsx10(TiDelete, { size: "18", className: "delete text-danger", onClick: () => deleteEvent() }) })
406
+ ] }, index)) });
407
+ }
408
+ return /* @__PURE__ */ jsx10("div", { className, style: { textAlign: "start" }, children: opcoes.map((opcao, index) => /* @__PURE__ */ jsx10(
409
+ Form3.Check,
410
+ {
411
+ disabled,
412
+ type: "checkbox",
413
+ label: `${opcao.valor}`
414
+ },
415
+ index
416
+ )) });
417
+ };
418
+
419
+ // src/buttons/Generic3DotMenu.tsx
420
+ import { useState as useState4 } from "react";
421
+ import { Button as Button7, Modal as Modal2 } from "react-bootstrap";
422
+ import { CiMenuKebab } from "react-icons/ci";
423
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
424
+ var MenuEvent = class {
425
+ /**
426
+ * @param label - O texto que aparecerá no botão.
427
+ * @param callback - A função a ser chamada quando o botão for clicado.
428
+ * @param variant - A variante do botão (padrão: 'primary').
429
+ * @param renderCondition - Condição para renderizar o botão.
430
+ * @param section - A seção para organizar os botões (padrão: 'default').
431
+ */
432
+ constructor(label, callback, variant = "primary", renderCondition = true, section = "default") {
433
+ this.label = label;
434
+ this.callback = callback;
435
+ this.variant = variant;
436
+ this.renderCondition = renderCondition;
437
+ this.section = section;
438
+ }
439
+ };
440
+ var Generic3DotMenu = ({
441
+ events,
442
+ tittle = "Op\xE7\xF5es de Controle"
443
+ }) => {
444
+ const [show, setShow] = useState4(false);
445
+ const handleClose = () => setShow(false);
446
+ const handleShow = () => setShow(true);
447
+ const shouldRender = (event) => {
448
+ return typeof event.renderCondition === "function" ? event.renderCondition() : event.renderCondition;
449
+ };
450
+ const groupedEvents = events.reduce((sections, event) => {
451
+ const section = event.section || "default";
452
+ if (!sections[section]) {
453
+ sections[section] = [];
454
+ }
455
+ if (shouldRender(event)) {
456
+ sections[section].push(event);
457
+ }
458
+ return sections;
459
+ }, {});
460
+ return /* @__PURE__ */ jsxs6(Fragment2, { children: [
461
+ /* @__PURE__ */ jsx11(CiMenuKebab, { onClick: handleShow, style: { cursor: "pointer" }, size: 25, title: tittle }),
462
+ /* @__PURE__ */ jsxs6(Modal2, { show, onHide: handleClose, centered: true, children: [
463
+ /* @__PURE__ */ jsx11(Modal2.Header, { closeButton: true, children: /* @__PURE__ */ jsx11(Modal2.Title, { children: tittle }) }),
464
+ /* @__PURE__ */ jsxs6(Modal2.Body, { children: [
465
+ Object.keys(groupedEvents).length === 0 && /* @__PURE__ */ jsx11("div", { className: "text-center text-muted", children: "Nenhuma op\xE7\xE3o dispon\xEDvel." }),
466
+ Object.keys(groupedEvents).map((section, sectionIndex) => /* @__PURE__ */ jsxs6("div", { className: "mb-4", children: [
467
+ /* @__PURE__ */ jsx11("h6", { className: "border-bottom pb-2 mb-3", children: section !== "default" ? section : "Op\xE7\xF5es Principais" }),
468
+ /* @__PURE__ */ jsx11("div", { className: "d-grid gap-2", children: groupedEvents[section].map((event, index) => /* @__PURE__ */ jsx11(
469
+ Button7,
470
+ {
471
+ variant: event.variant || "primary",
472
+ onClick: () => {
473
+ event.callback();
474
+ handleClose();
475
+ },
476
+ children: event.label
477
+ },
478
+ index
479
+ )) })
480
+ ] }, sectionIndex))
481
+ ] }),
482
+ /* @__PURE__ */ jsx11(Modal2.Footer, { children: /* @__PURE__ */ jsx11(Button7, { variant: "secondary", onClick: handleClose, children: "Fechar" }) })
483
+ ] })
484
+ ] });
485
+ };
486
+
487
+ // src/buttons/LoadingButton.tsx
488
+ import { Button as Button8, Spinner as Spinner2 } from "react-bootstrap";
489
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
490
+ var LoadingButton = ({
491
+ onClick,
492
+ loading = false,
493
+ label = "Enviar",
494
+ variant = "primary",
495
+ size,
496
+ disabled = false,
497
+ icon = null,
498
+ className = "",
499
+ loadingLabel = "Carregando...",
500
+ ...props
501
+ }) => {
502
+ return /* @__PURE__ */ jsx12(
503
+ Button8,
504
+ {
505
+ variant,
506
+ size,
507
+ disabled: disabled || loading,
508
+ onClick,
509
+ className: `loading-button ${className}`,
510
+ style: { cursor: loading ? "not-allowed" : "pointer" },
511
+ ...props,
512
+ children: loading ? /* @__PURE__ */ jsxs7("div", { className: "align-items-center", children: [
513
+ /* @__PURE__ */ jsx12(
514
+ Spinner2,
515
+ {
516
+ as: "span",
517
+ animation: "border",
518
+ size: "sm",
519
+ role: "status",
520
+ "aria-hidden": "true",
521
+ className: "me-2"
522
+ }
523
+ ),
524
+ /* @__PURE__ */ jsx12("span", { children: loadingLabel })
525
+ ] }) : /* @__PURE__ */ jsxs7("div", { className: "align-items-center", children: [
526
+ icon && /* @__PURE__ */ jsx12("span", { className: "me-2 d-flex", children: icon }),
527
+ /* @__PURE__ */ jsx12("span", { children: label })
528
+ ] })
529
+ }
530
+ );
531
+ };
532
+
533
+ // src/buttons/NavigateButton.tsx
534
+ import { Button as Button9 } from "react-bootstrap";
535
+ import { jsx as jsx13 } from "react/jsx-runtime";
536
+ var NavigateButton = ({
537
+ displayName,
538
+ path,
539
+ config,
540
+ pageName,
541
+ navigator: navigator2,
542
+ onBeforeNavigate,
543
+ variant = "outline-primary",
544
+ style,
545
+ ...props
546
+ }) => {
547
+ const handleClick = () => {
548
+ if (onBeforeNavigate) {
549
+ onBeforeNavigate();
550
+ }
551
+ navigator2(path, config, pageName);
552
+ };
553
+ return /* @__PURE__ */ jsx13(
554
+ Button9,
555
+ {
556
+ style,
557
+ variant,
558
+ onClick: handleClick,
559
+ ...props,
560
+ children: displayName
561
+ }
562
+ );
563
+ };
564
+
565
+ // src/buttons/StatusBadge.tsx
566
+ import { Form as Form4, Spinner as Spinner3 } from "react-bootstrap";
567
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
568
+ var StatusBadge = ({
569
+ status,
570
+ showCheckbox = false,
571
+ checked = false,
572
+ onToggle = () => {
573
+ },
574
+ loading = false,
575
+ customStatusClasses
576
+ }) => {
577
+ const statusClasses = customStatusClasses || {
578
+ PENDENTE: "bg-warning text-dark",
579
+ EXECUTANDO: "bg-success text-white",
580
+ CONCLUIDO: "bg-secondary text-white",
581
+ CANCELED: "bg-danger text-white"
582
+ };
583
+ const badgeClass = statusClasses[status] || "bg-secondary text-white";
584
+ return /* @__PURE__ */ jsx14("div", { className: "d-flex align-items-center gap-2", children: loading ? /* @__PURE__ */ jsx14(Spinner3, { animation: "border", size: "sm" }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
585
+ showCheckbox && /* @__PURE__ */ jsx14(
586
+ Form4.Check,
587
+ {
588
+ type: "checkbox",
589
+ checked,
590
+ onChange: onToggle,
591
+ className: "me-1"
592
+ }
593
+ ),
594
+ /* @__PURE__ */ jsx14("span", { className: `badge ${badgeClass}`, children: status })
595
+ ] }) });
596
+ };
597
+
598
+ // src/buttons/SwitchOnClick.tsx
599
+ import { useEffect as useEffect2, useState as useState5 } from "react";
600
+ import { FaTimes } from "react-icons/fa";
601
+ import { GrAddCircle } from "react-icons/gr";
602
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
603
+ var SwitchOnClick = ({
604
+ children,
605
+ placeHolder = /* @__PURE__ */ jsx15(
606
+ "div",
607
+ {
608
+ className: "text-center zoom-container",
609
+ style: {
610
+ fontSize: "1.2rem",
611
+ color: "#666"
612
+ },
613
+ children: /* @__PURE__ */ jsx15(
614
+ GrAddCircle,
615
+ {
616
+ size: 25,
617
+ className: "mb-2",
618
+ style: { cursor: "pointer" }
619
+ }
620
+ )
621
+ }
622
+ ),
623
+ onSwitchClick,
624
+ onCancel,
625
+ containerClassName = ""
626
+ }) => {
627
+ const [clicked, setClicked] = useState5(false);
628
+ const handleClick = () => {
629
+ onSwitchClick && onSwitchClick();
630
+ setClicked(!clicked);
631
+ };
632
+ const handleClose = () => {
633
+ setClicked(false);
634
+ onCancel && onCancel();
635
+ };
636
+ useEffect2(() => {
637
+ const handleEscape = (event) => {
638
+ if (event.key === "Escape") {
639
+ handleClose();
640
+ }
641
+ };
642
+ window.addEventListener("keydown", handleEscape);
643
+ return () => window.removeEventListener("keydown", handleEscape);
644
+ }, []);
645
+ if (!clicked) {
646
+ return /* @__PURE__ */ jsx15("div", { onClick: handleClick, style: { cursor: "pointer" }, children: placeHolder });
647
+ }
648
+ return /* @__PURE__ */ jsxs9("div", { className: `switch-on-click-container ${containerClassName}`, children: [
649
+ /* @__PURE__ */ jsx15("div", { className: "close-icon", onClick: handleClose, children: /* @__PURE__ */ jsx15(FaTimes, { title: "Fechar" }) }),
650
+ children({ handleClose })
651
+ ] });
652
+ };
653
+
654
+ // src/charts/GenericChart.tsx
655
+ import { Chart } from "react-google-charts";
656
+ import { jsx as jsx16 } from "react/jsx-runtime";
657
+ var GenericChart = ({
658
+ chartType,
659
+ graphID,
660
+ width = "100%",
661
+ height = "400px",
662
+ columns,
663
+ rows,
664
+ chartEvents,
665
+ options,
666
+ tooltipFormatter
667
+ }) => {
668
+ let datachart = [columns, ...rows];
669
+ if (tooltipFormatter) {
670
+ datachart = datachart.map((row, index) => {
671
+ if (index === 0) return row;
672
+ const formattedTooltip = tooltipFormatter(row);
673
+ return [...row, formattedTooltip];
674
+ });
675
+ datachart[0] = [...columns, { type: "string", role: "tooltip", p: { html: true } }];
676
+ }
677
+ return /* @__PURE__ */ jsx16(
678
+ Chart,
679
+ {
680
+ chartType,
681
+ options: { ...options, tooltip: { isHtml: true } },
682
+ data: datachart,
683
+ graphID,
684
+ width,
685
+ height,
686
+ chartEvents
687
+ }
688
+ );
689
+ };
690
+
691
+ // src/charts/GenericREchart.tsx
692
+ import {
693
+ ResponsiveContainer,
694
+ LineChart,
695
+ Line,
696
+ XAxis,
697
+ YAxis,
698
+ CartesianGrid,
699
+ Tooltip,
700
+ Legend
701
+ } from "recharts";
702
+ import dayjs from "dayjs";
703
+ import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
704
+ var GenericREchart = ({
705
+ data = [],
706
+ lines = [],
707
+ xAxisKey = "data",
708
+ showGrid = true,
709
+ showLegend = true,
710
+ showTooltip = true,
711
+ width = "100%",
712
+ height = 400,
713
+ hideYAxis,
714
+ unit,
715
+ margin = { top: 20, right: 30, left: 20, bottom: 5 },
716
+ YAxisRange = [0, "auto"]
717
+ }) => {
718
+ const sortedData = [...data].sort(
719
+ (a, b) => new Date(a[xAxisKey]).getTime() - new Date(b[xAxisKey]).getTime()
720
+ );
721
+ return /* @__PURE__ */ jsx17("div", { style: { width, height }, children: /* @__PURE__ */ jsx17(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs10(LineChart, { data: sortedData, margin, children: [
722
+ showGrid && /* @__PURE__ */ jsx17(CartesianGrid, { strokeDasharray: "3 3" }),
723
+ /* @__PURE__ */ jsx17(
724
+ XAxis,
725
+ {
726
+ dataKey: xAxisKey,
727
+ reversed: false,
728
+ tickFormatter: (tick) => dayjs(tick).format("DD/MM/YY HH:mm")
729
+ }
730
+ ),
731
+ /* @__PURE__ */ jsx17(YAxis, { domain: YAxisRange, unit, hide: hideYAxis, type: "number" }),
732
+ showTooltip && /* @__PURE__ */ jsx17(
733
+ Tooltip,
734
+ {
735
+ labelFormatter: (label) => dayjs(label).format("DD/MM/YY HH:mm")
736
+ }
737
+ ),
738
+ showLegend && /* @__PURE__ */ jsx17(Legend, {}),
739
+ lines.map((lineCfg, idx) => /* @__PURE__ */ jsx17(Line, { ...lineCfg }, idx))
740
+ ] }) }) });
741
+ };
742
+
743
+ // src/containers/ResponsiveContainer.tsx
744
+ import { Modal as Modal3, ModalBody } from "react-bootstrap";
745
+ import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
746
+ var ResponsiveContainer2 = ({
747
+ title,
748
+ show,
749
+ setShow,
750
+ children,
751
+ onClose,
752
+ scrollable = false
753
+ }) => {
754
+ const handleClose = () => {
755
+ setShow(false);
756
+ if (onClose) onClose();
757
+ };
758
+ return /* @__PURE__ */ jsxs11(Modal3, { size: "lg", show, onHide: handleClose, scrollable, children: [
759
+ /* @__PURE__ */ jsx18(Modal3.Header, { closeButton: true, onClick: handleClose, children: title && /* @__PURE__ */ jsx18(Modal3.Title, { children: title }) }),
760
+ /* @__PURE__ */ jsx18(ModalBody, { children })
761
+ ] });
762
+ };
763
+ var ResponsiveContainer_default = ResponsiveContainer2;
764
+
765
+ // src/containers/ExpandableCard.tsx
766
+ import { useState as useState6 } from "react";
767
+ import { Card, ListGroup } from "react-bootstrap";
768
+ import { FaChevronDown } from "react-icons/fa";
769
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
770
+ var ExpandableCard = ({
771
+ items = [],
772
+ initialVisibleCount = 3,
773
+ expandable = true,
774
+ leftSideContent,
775
+ rightSideContent,
776
+ cardClassName = "",
777
+ cardBodyClassName = "",
778
+ cardBodyStyle,
779
+ isMobile = false
780
+ }) => {
781
+ const [expandedCard, setExpandedCard] = useState6(false);
782
+ const handleToggleExpandCard = () => {
783
+ setExpandedCard(!expandedCard);
784
+ };
785
+ const visibleItems = expandedCard ? items : items.slice(0, initialVisibleCount);
786
+ const shouldShowExpandButton = expandable && items.length > initialVisibleCount;
787
+ const renderContentWithToggle = (content) => {
788
+ return content;
789
+ };
790
+ return /* @__PURE__ */ jsxs12(Card, { className: `expandable-card ${cardClassName}`, children: [
791
+ leftSideContent && /* @__PURE__ */ jsx19("div", { className: "expandable-card-left-side", children: leftSideContent }),
792
+ /* @__PURE__ */ jsx19(Card.Body, { className: `expandable-card-body ${cardBodyClassName}`, style: cardBodyStyle, children: /* @__PURE__ */ jsxs12(ListGroup, { variant: "flush", children: [
793
+ visibleItems.map((item, index) => {
794
+ const isObject = typeof item === "object" && item !== null && "content" in item;
795
+ const itemObj = isObject ? item : { content: item };
796
+ const clickableClass = itemObj.clickable ? "expandable-card-list-item-clickable" : "";
797
+ return /* @__PURE__ */ jsx19(
798
+ ListGroup.Item,
799
+ {
800
+ className: `expandable-card-list-item ${clickableClass}`,
801
+ children: isMobile ? /* @__PURE__ */ jsxs12("div", { className: "expandable-card-item", children: [
802
+ itemObj.label && /* @__PURE__ */ jsx19("div", { className: "expandable-card-item-header", children: /* @__PURE__ */ jsx19("strong", { children: itemObj.label }) }),
803
+ /* @__PURE__ */ jsx19("div", { className: "expandable-card-item-content", children: renderContentWithToggle(itemObj.content) })
804
+ ] }) : /* @__PURE__ */ jsxs12("div", { className: "expandable-card-item-row", children: [
805
+ itemObj.label && /* @__PURE__ */ jsxs12("strong", { className: "expandable-card-item-label", children: [
806
+ itemObj.label,
807
+ ":"
808
+ ] }),
809
+ /* @__PURE__ */ jsx19("span", { className: "expandable-card-item-content", children: renderContentWithToggle(itemObj.content) })
810
+ ] })
811
+ },
812
+ index
813
+ );
814
+ }),
815
+ shouldShowExpandButton && /* @__PURE__ */ jsx19(
816
+ ListGroup.Item,
817
+ {
818
+ className: `expandable-card-toggle ${expandedCard ? "expanded" : ""}`,
819
+ onClick: handleToggleExpandCard,
820
+ children: /* @__PURE__ */ jsx19(FaChevronDown, { className: "expandable-card-toggle-icon" })
821
+ }
822
+ )
823
+ ] }) }),
824
+ rightSideContent && /* @__PURE__ */ jsx19("div", { className: "expandable-card-right-side", children: rightSideContent })
825
+ ] });
826
+ };
827
+
828
+ // src/displays/UuidPill.tsx
829
+ import { useState as useState7, useRef as useRef3 } from "react";
830
+ import { Badge, Overlay, Tooltip as Tooltip2 } from "react-bootstrap";
831
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
832
+ var UuidPill = ({ uuid, bg = "light", textColor = "dark", short = 8 }) => {
833
+ const [copied, setCopied] = useState7(false);
834
+ const ref = useRef3(null);
835
+ const [showTooltip, setShowTooltip] = useState7(false);
836
+ if (!uuid) return /* @__PURE__ */ jsx20("span", { className: "text-muted", children: "\u2014" });
837
+ const shortId = String(uuid).substring(0, short);
838
+ const handleCopy = async (e) => {
839
+ e.stopPropagation();
840
+ try {
841
+ await navigator.clipboard.writeText(uuid);
842
+ } catch (e2) {
843
+ const ta = document.createElement("textarea");
844
+ ta.value = uuid;
845
+ document.body.appendChild(ta);
846
+ ta.select();
847
+ document.execCommand("copy");
848
+ document.body.removeChild(ta);
849
+ }
850
+ setCopied(true);
851
+ setTimeout(() => setCopied(false), 1500);
852
+ };
853
+ return /* @__PURE__ */ jsxs13(Fragment4, { children: [
854
+ /* @__PURE__ */ jsxs13(
855
+ Badge,
856
+ {
857
+ ref,
858
+ bg,
859
+ text: textColor,
860
+ pill: true,
861
+ className: "border px-2 py-1",
862
+ style: { cursor: "pointer", fontFamily: "monospace", fontSize: "0.8rem", userSelect: "none" },
863
+ onClick: handleCopy,
864
+ onMouseEnter: () => setShowTooltip(true),
865
+ onMouseLeave: () => {
866
+ setShowTooltip(false);
867
+ setCopied(false);
868
+ },
869
+ children: [
870
+ shortId,
871
+ "\u2026"
872
+ ]
873
+ }
874
+ ),
875
+ /* @__PURE__ */ jsx20(Overlay, { target: ref.current, show: showTooltip, placement: "top", children: (props) => /* @__PURE__ */ jsx20(Tooltip2, { ...props, children: copied ? /* @__PURE__ */ jsx20("span", { style: { color: "#6f6" }, children: "Copiado!" }) : /* @__PURE__ */ jsxs13("span", { style: { fontFamily: "monospace", fontSize: "0.75rem" }, children: [
876
+ uuid,
877
+ /* @__PURE__ */ jsx20("br", {}),
878
+ /* @__PURE__ */ jsx20("small", { className: "text-muted", children: "Clique para copiar" })
879
+ ] }) }) })
880
+ ] });
881
+ };
882
+ var UuidPill_default = UuidPill;
883
+
884
+ // src/displays/GenericDisplay.tsx
885
+ import React9, { useState as useState8, useEffect as useEffect3 } from "react";
886
+ import { Col, Container, Row } from "react-bootstrap";
887
+ import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
888
+ var ConfigObject = class {
889
+ constructor(dotNotation, style, onClick, onBlur, onHideClick, hidden, mapData, additionalComponents) {
890
+ this.dotNotation = dotNotation;
891
+ this.style = style;
892
+ this.onClick = onClick;
893
+ this.onBlur = onBlur;
894
+ this.onHideClick = onHideClick;
895
+ this.hidden = hidden;
896
+ this.mapData = mapData;
897
+ this.additionalComponents = additionalComponents || [];
898
+ }
899
+ };
900
+ var getRightConfigObjects = (currentPropertieMap, configObjects) => {
901
+ const curreDotNotation = currentPropertieMap.join(".");
902
+ if (!configObjects) return [];
903
+ return configObjects.filter((configObject) => configObject.dotNotation === curreDotNotation);
904
+ };
905
+ var getStyle = (configObjects) => {
906
+ let styleObject = {};
907
+ configObjects.forEach((configObject) => {
908
+ styleObject = { ...styleObject, ...configObject.style };
909
+ });
910
+ return styleObject;
911
+ };
912
+ var getAdditionalComponentes = (configObjects) => {
913
+ const components = [];
914
+ configObjects.forEach((configObject) => {
915
+ if (configObject.additionalComponents) {
916
+ components.push(...configObject.additionalComponents);
917
+ }
918
+ });
919
+ return components;
920
+ };
921
+ var getOnClick = (configObjects) => {
922
+ return () => {
923
+ configObjects.forEach((configObject) => {
924
+ configObject.onClick && configObject.onClick();
925
+ });
926
+ };
927
+ };
928
+ var buildData = (obj, propertiesMap, configObjects, opn, innerArray, dispatch, isRoot, editButtonRenderer) => {
929
+ const newPropertiesMap = [];
930
+ if (opn) newPropertiesMap.push(...propertiesMap, opn);
931
+ else newPropertiesMap.push(...propertiesMap);
932
+ const innerConfigs = getRightConfigObjects(newPropertiesMap, configObjects);
933
+ const styles = getStyle(innerConfigs);
934
+ const onClick = getOnClick(innerConfigs);
935
+ const extraComponents = getAdditionalComponentes(innerConfigs);
936
+ if (Array.isArray(obj)) {
937
+ return /* @__PURE__ */ jsxs14(Container, { onClick, style: { ...styles }, children: [
938
+ opn && /* @__PURE__ */ jsx21("div", { style: { textAlign: "center" }, children: /* @__PURE__ */ jsx21("strong", { children: opn }) }),
939
+ obj.map((o, index) => {
940
+ const mapCopy = [...newPropertiesMap, `[${index}]`];
941
+ return /* @__PURE__ */ jsx21(Row, { style: { padding: 4, ...styles }, children: buildData(o, mapCopy, configObjects, null, true, null, false, editButtonRenderer) }, index);
942
+ })
943
+ ] });
944
+ }
945
+ if (typeof obj === "object" && obj != null) {
946
+ return /* @__PURE__ */ jsxs14(
947
+ Container,
948
+ {
949
+ onClick,
950
+ style: {
951
+ border: innerArray ? "solid" : void 0,
952
+ borderColor: "lightgray",
953
+ borderRadius: innerArray ? 4 : 2,
954
+ borderWidth: 1,
955
+ padding: 4,
956
+ ...styles
957
+ },
958
+ children: [
959
+ opn && /* @__PURE__ */ jsx21("strong", { children: opn }),
960
+ Object.entries(obj).map(
961
+ ([key, value]) => buildData(value, newPropertiesMap, configObjects, key, false, null, false, editButtonRenderer)
962
+ ),
963
+ extraComponents.length > 0 ? extraComponents.map((comp, i) => /* @__PURE__ */ jsx21(React9.Fragment, { children: comp() }, i)) : isRoot && editButtonRenderer ? editButtonRenderer(obj, opn) : null
964
+ ]
965
+ }
966
+ );
967
+ }
968
+ return /* @__PURE__ */ jsxs14(Col, { children: [
969
+ /* @__PURE__ */ jsxs14("strong", { children: [
970
+ opn,
971
+ ": "
972
+ ] }),
973
+ String(obj)
974
+ ] });
975
+ };
976
+ var GenericDisplay = ({
977
+ ops = [],
978
+ loadFunc,
979
+ configObjects,
980
+ rootName,
981
+ context,
982
+ onRefresh,
983
+ editButtonRenderer
984
+ }) => {
985
+ const [innerOptions, setInnerOptions] = useState8();
986
+ const refreshFunc = () => {
987
+ if (loadFunc) {
988
+ loadFunc().then((res) => {
989
+ if (Array.isArray(res)) {
990
+ setInnerOptions(res);
991
+ } else {
992
+ setInnerOptions([res]);
993
+ }
994
+ });
995
+ } else {
996
+ setInnerOptions(ops);
997
+ }
998
+ };
999
+ useEffect3(() => {
1000
+ if (onRefresh) {
1001
+ onRefresh(refreshFunc);
1002
+ } else {
1003
+ refreshFunc();
1004
+ }
1005
+ }, [context]);
1006
+ return /* @__PURE__ */ jsx21(Fragment5, { children: innerOptions && innerOptions.map((cObj, index) => /* @__PURE__ */ jsx21(Container, { style: { padding: 4, border: "solid" }, children: buildData(cObj, [], configObjects, rootName || null, false, null, true, editButtonRenderer) }, index)) });
1007
+ };
1008
+ var GenericDisplay_default = GenericDisplay;
1009
+
1010
+ // src/displays/BranchDropDisplay.tsx
1011
+ import {
1012
+ BranchDropDisplay,
1013
+ BranchDropDisplay as BranchDropDisplay2
1014
+ } from "@teraprox/ui-kit-sgm";
1015
+
1016
+ // src/displays/RateLimitBar.tsx
1017
+ import { useMemo } from "react";
1018
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1019
+ function formatResetIn(windowReset) {
1020
+ const resetAt = new Date(windowReset).getTime();
1021
+ const remaining = Math.max(0, Math.round((resetAt - Date.now()) / 1e3));
1022
+ if (remaining <= 0) return "agora";
1023
+ if (remaining < 60) return `${remaining}s`;
1024
+ return `${Math.round(remaining / 60)}min`;
1025
+ }
1026
+ var RateLimitBar = ({ entry, label, className }) => {
1027
+ const pct = useMemo(() => {
1028
+ if (!entry || entry.limit <= 0) return 0;
1029
+ return Math.min(100, Math.round(entry.used / entry.limit * 100));
1030
+ }, [entry]);
1031
+ if (!entry) return null;
1032
+ const color = entry.exceeded || pct >= 90 ? "#dc3545" : pct >= 70 ? "#ffc107" : "#28a745";
1033
+ const containerStyle = {
1034
+ width: "100%",
1035
+ marginBottom: "4px"
1036
+ };
1037
+ const barTrackStyle = {
1038
+ height: "6px",
1039
+ width: "100%",
1040
+ backgroundColor: "#e9ecef",
1041
+ borderRadius: "3px",
1042
+ overflow: "hidden"
1043
+ };
1044
+ const barFillStyle = {
1045
+ height: "100%",
1046
+ width: `${pct}%`,
1047
+ backgroundColor: color,
1048
+ borderRadius: "3px",
1049
+ transition: "width 0.3s ease, background-color 0.3s ease"
1050
+ };
1051
+ const textStyle = {
1052
+ fontSize: "11px",
1053
+ color: "#6c757d",
1054
+ display: "flex",
1055
+ justifyContent: "space-between",
1056
+ marginBottom: "2px"
1057
+ };
1058
+ return /* @__PURE__ */ jsxs15("div", { style: containerStyle, className, children: [
1059
+ /* @__PURE__ */ jsxs15("div", { style: textStyle, children: [
1060
+ label && /* @__PURE__ */ jsx22("span", { children: label }),
1061
+ /* @__PURE__ */ jsxs15("span", { children: [
1062
+ entry.used,
1063
+ "/",
1064
+ entry.limit,
1065
+ " req",
1066
+ entry.exceeded ? " \u2014 limite atingido" : ` (reset em ${formatResetIn(entry.windowReset)})`
1067
+ ] })
1068
+ ] }),
1069
+ /* @__PURE__ */ jsx22("div", { style: barTrackStyle, children: /* @__PURE__ */ jsx22("div", { style: barFillStyle }) })
1070
+ ] });
1071
+ };
1072
+
1073
+ // src/displays/StatusIndicator.tsx
1074
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
1075
+ var StatusIndicator = ({
1076
+ status,
1077
+ count,
1078
+ containerClassName = "",
1079
+ customLabels
1080
+ }) => {
1081
+ const statusLabels = customLabels || {
1082
+ pendente: "PENDENTE",
1083
+ executando: "EXECUTANDO",
1084
+ concluido: "CONCLU\xCDDA",
1085
+ canceled: "CANCELADA",
1086
+ naoAtribuida: "N\xC3O ATRIBUIDA"
1087
+ };
1088
+ const label = statusLabels[status] || status.toUpperCase();
1089
+ return /* @__PURE__ */ jsxs16("div", { className: `status-flag ${status} ${containerClassName}`, children: [
1090
+ /* @__PURE__ */ jsx23("div", { className: "status-label", children: label }),
1091
+ /* @__PURE__ */ jsx23("div", { className: "status-count", children: count })
1092
+ ] });
1093
+ };
1094
+
1095
+ // src/displays/VerticalItemsDisplay.tsx
1096
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1097
+ var VerticalItemsDisplay = ({
1098
+ item1 = "",
1099
+ item2 = "",
1100
+ item3 = "",
1101
+ className = "",
1102
+ style
1103
+ }) => {
1104
+ return /* @__PURE__ */ jsxs17("div", { className, style, children: [
1105
+ /* @__PURE__ */ jsx24("div", { children: item1 }),
1106
+ /* @__PURE__ */ jsx24("div", { children: item2 }),
1107
+ /* @__PURE__ */ jsx24("div", { children: item3 })
1108
+ ] });
1109
+ };
1110
+
1111
+ // src/displays/StatusLight.tsx
1112
+ import { jsx as jsx25 } from "react/jsx-runtime";
1113
+ var StatusLight = ({
1114
+ active = false,
1115
+ activeLightColor = "green",
1116
+ inactiveLightColor = "gray",
1117
+ size = "20px",
1118
+ className = "",
1119
+ style
1120
+ }) => {
1121
+ const color = active ? activeLightColor : inactiveLightColor;
1122
+ return /* @__PURE__ */ jsx25(
1123
+ "div",
1124
+ {
1125
+ className,
1126
+ style: {
1127
+ backgroundColor: color,
1128
+ borderRadius: "50%",
1129
+ width: size,
1130
+ height: size,
1131
+ display: "inline-block",
1132
+ transition: "background-color 0.3s ease",
1133
+ ...style
1134
+ }
1135
+ }
1136
+ );
1137
+ };
1138
+
1139
+ // src/displays/TimerDisplay.tsx
1140
+ import dayjs2 from "dayjs";
1141
+ import duration from "dayjs/plugin/duration";
1142
+ import { BiTimer } from "react-icons/bi";
1143
+ import { BsPause, BsPlay } from "react-icons/bs";
1144
+ import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
1145
+ dayjs2.extend(duration);
1146
+ var TimerDisplay = ({
1147
+ id,
1148
+ tempo = 0,
1149
+ isStopped = false,
1150
+ pausable = false,
1151
+ playable = false,
1152
+ enableView = true,
1153
+ onPause,
1154
+ onPlay,
1155
+ emptyMessage = "Timer ainda n\xE3o iniciado."
1156
+ }) => {
1157
+ const handlePause = (e) => {
1158
+ e.stopPropagation();
1159
+ if (id && onPause) onPause(id);
1160
+ };
1161
+ const handlePlay = (e) => {
1162
+ e.stopPropagation();
1163
+ if (id && onPlay) onPlay(id);
1164
+ };
1165
+ const formatDuration = (seconds) => {
1166
+ if (!enableView) return "- : - : -";
1167
+ const time = dayjs2.duration(seconds, "seconds");
1168
+ const days = Math.floor(time.asDays());
1169
+ const hours = time.hours().toString().padStart(2, "0");
1170
+ const minutes = time.minutes().toString().padStart(2, "0");
1171
+ const secondsRemaining = time.seconds().toString().padStart(2, "0");
1172
+ return days > 0 ? `${days}d ${hours}:${minutes}:${secondsRemaining}` : `${hours}:${minutes}:${secondsRemaining}`;
1173
+ };
1174
+ return /* @__PURE__ */ jsx26("div", { className: "timer-display-container", children: /* @__PURE__ */ jsx26("div", { className: "timer-display-content", children: id ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
1175
+ /* @__PURE__ */ jsx26(
1176
+ BiTimer,
1177
+ {
1178
+ size: 24,
1179
+ className: "timer-icon",
1180
+ title: "Timer"
1181
+ }
1182
+ ),
1183
+ pausable && !isStopped && /* @__PURE__ */ jsx26(
1184
+ BsPause,
1185
+ {
1186
+ size: 20,
1187
+ className: "timer-icon-action",
1188
+ onClick: handlePause,
1189
+ title: "Pausar"
1190
+ }
1191
+ ),
1192
+ playable && !isStopped && /* @__PURE__ */ jsx26(
1193
+ BsPlay,
1194
+ {
1195
+ size: 20,
1196
+ className: "timer-icon-action",
1197
+ onClick: handlePlay,
1198
+ title: "Iniciar"
1199
+ }
1200
+ ),
1201
+ /* @__PURE__ */ jsx26("span", { className: "timer-display-time", children: formatDuration(tempo) })
1202
+ ] }) : /* @__PURE__ */ jsx26("span", { className: "timer-display-message", children: emptyMessage }) }) });
1203
+ };
1204
+
1205
+ // src/displays/RecursoDisplayer.tsx
1206
+ import {
1207
+ RecursoDisplayer,
1208
+ RecursoDisplayer as RecursoDisplayer2
1209
+ } from "@teraprox/ui-kit-sgm";
1210
+
1211
+ // src/filters/StatusPills.tsx
1212
+ import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
1213
+ var StatusPills = ({
1214
+ statuses,
1215
+ activeKeys,
1216
+ onSelectionChange,
1217
+ multiSelect = true,
1218
+ className = ""
1219
+ }) => {
1220
+ const toggleKey = (key) => {
1221
+ const isActive = activeKeys.includes(key);
1222
+ if (multiSelect) {
1223
+ if (isActive) {
1224
+ onSelectionChange(activeKeys.filter((k) => k !== key));
1225
+ } else {
1226
+ onSelectionChange([...activeKeys, key]);
1227
+ }
1228
+ } else {
1229
+ onSelectionChange(isActive ? [] : [key]);
1230
+ }
1231
+ };
1232
+ return /* @__PURE__ */ jsx27("div", { className: `status-pills-container ${className}`, children: Object.entries(statuses).map(([key, meta]) => {
1233
+ const isActive = activeKeys.includes(key);
1234
+ return /* @__PURE__ */ jsxs19(
1235
+ "button",
1236
+ {
1237
+ type: "button",
1238
+ className: `status-pill ${isActive ? "active" : ""}`,
1239
+ style: { "--status-color": meta.color },
1240
+ onClick: () => toggleKey(key),
1241
+ "aria-pressed": isActive,
1242
+ children: [
1243
+ /* @__PURE__ */ jsx27("span", { className: "status-pill__swatch" }),
1244
+ /* @__PURE__ */ jsx27("span", { className: "status-pill__label", children: meta.label }),
1245
+ meta.count !== void 0 && /* @__PURE__ */ jsx27("span", { className: "status-pill__count", children: meta.count })
1246
+ ]
1247
+ },
1248
+ key
1249
+ );
1250
+ }) });
1251
+ };
1252
+
1253
+ // src/filters/PeriodSelector.tsx
1254
+ import { useState as useState9 } from "react";
1255
+ import { Card as Card2, Form as Form5, Button as Button10 } from "react-bootstrap";
1256
+ import { FaCalendarAlt, FaChevronUp, FaHistory } from "react-icons/fa";
1257
+ import dayjs3 from "dayjs";
1258
+ import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
1259
+ var PeriodSelector = ({
1260
+ startDate,
1261
+ endDate,
1262
+ onStartDateChange,
1263
+ onEndDateChange,
1264
+ onPresetSelect,
1265
+ label = "Per\xEDodo",
1266
+ allowFuture = false,
1267
+ className = ""
1268
+ }) => {
1269
+ const [isExpanded, setIsExpanded] = useState9(false);
1270
+ const formatDisplayRange = (start, end) => {
1271
+ const s = dayjs3(start).format("DD/MM/YY HH:mm");
1272
+ const e = dayjs3(end).format("DD/MM/YY HH:mm");
1273
+ return `${s} at\xE9 ${e}`;
1274
+ };
1275
+ const maxDate = allowFuture ? void 0 : dayjs3().format("YYYY-MM-DDTHH:mm");
1276
+ const presets = [
1277
+ { key: "today", label: "Hoje" },
1278
+ { key: "week", label: "\xDAltima Semana" },
1279
+ { key: "fortnight", label: "Quinzena" },
1280
+ { key: "month", label: "\xDAltimo M\xEAs" },
1281
+ { key: "year", label: "\xDAltimo Ano" }
1282
+ ];
1283
+ return /* @__PURE__ */ jsxs20(Card2, { className: `period-selector-card ${isExpanded ? "expanded" : ""} ${className}`, children: [
1284
+ /* @__PURE__ */ jsxs20("div", { className: "compact-row", onClick: () => setIsExpanded(!isExpanded), children: [
1285
+ /* @__PURE__ */ jsxs20("div", { className: "d-flex align-items-center", children: [
1286
+ /* @__PURE__ */ jsx28(FaCalendarAlt, { className: "me-2 text-primary" }),
1287
+ /* @__PURE__ */ jsx28("span", { className: "date-range-text", children: isExpanded ? label : formatDisplayRange(startDate, endDate) })
1288
+ ] }),
1289
+ /* @__PURE__ */ jsx28("div", { className: "period-icon-btn", children: isExpanded ? /* @__PURE__ */ jsx28(FaChevronUp, {}) : /* @__PURE__ */ jsx28("span", { className: "small text-muted", children: "Editar" }) })
1290
+ ] }),
1291
+ isExpanded && /* @__PURE__ */ jsxs20("div", { className: "expanded-content", children: [
1292
+ onPresetSelect && /* @__PURE__ */ jsxs20(Fragment7, { children: [
1293
+ /* @__PURE__ */ jsxs20("div", { className: "d-flex align-items-center mb-2", children: [
1294
+ /* @__PURE__ */ jsx28(FaHistory, { size: 12, className: "me-1 text-muted" }),
1295
+ /* @__PURE__ */ jsx28("small", { className: "text-muted fw-bold text-uppercase", style: { fontSize: "0.65rem" }, children: "Atalhos" })
1296
+ ] }),
1297
+ /* @__PURE__ */ jsx28("div", { className: "presets-container", children: presets.map((p) => /* @__PURE__ */ jsx28(
1298
+ Button10,
1299
+ {
1300
+ variant: "outline-primary",
1301
+ className: "preset-btn",
1302
+ onClick: (e) => {
1303
+ e.stopPropagation();
1304
+ onPresetSelect(p.key);
1305
+ setIsExpanded(false);
1306
+ },
1307
+ children: p.label
1308
+ },
1309
+ p.key
1310
+ )) })
1311
+ ] }),
1312
+ /* @__PURE__ */ jsxs20("div", { className: "date-inputs-grid", children: [
1313
+ /* @__PURE__ */ jsxs20(Form5.Group, { children: [
1314
+ /* @__PURE__ */ jsx28(Form5.Label, { className: "small text-muted", children: "In\xEDcio" }),
1315
+ /* @__PURE__ */ jsx28(
1316
+ Form5.Control,
1317
+ {
1318
+ type: "datetime-local",
1319
+ size: "sm",
1320
+ value: startDate,
1321
+ max: maxDate,
1322
+ onChange: (e) => onStartDateChange(e.target.value)
1323
+ }
1324
+ )
1325
+ ] }),
1326
+ /* @__PURE__ */ jsxs20(Form5.Group, { children: [
1327
+ /* @__PURE__ */ jsx28(Form5.Label, { className: "small text-muted", children: "Fim" }),
1328
+ /* @__PURE__ */ jsx28(
1329
+ Form5.Control,
1330
+ {
1331
+ type: "datetime-local",
1332
+ size: "sm",
1333
+ value: endDate,
1334
+ min: startDate,
1335
+ max: maxDate,
1336
+ onChange: (e) => onEndDateChange(e.target.value)
1337
+ }
1338
+ )
1339
+ ] })
1340
+ ] }),
1341
+ /* @__PURE__ */ jsx28("div", { className: "mt-3 d-flex justify-content-end", children: /* @__PURE__ */ jsx28(
1342
+ Button10,
1343
+ {
1344
+ variant: "primary",
1345
+ size: "sm",
1346
+ onClick: () => setIsExpanded(false),
1347
+ children: "Aplicar"
1348
+ }
1349
+ ) })
1350
+ ] })
1351
+ ] });
1352
+ };
1353
+
1354
+ // src/filters/AdvancedFilterBar.tsx
1355
+ import { useState as useState10 } from "react";
1356
+ import { Collapse, Button as Button11 } from "react-bootstrap";
1357
+ import { FiFilter, FiChevronDown, FiChevronUp, FiTrash2 as FiTrash22 } from "react-icons/fi";
1358
+ import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
1359
+ var AdvancedFilterBar = ({
1360
+ children,
1361
+ title = "Filtros e Busca",
1362
+ activeFiltersCount = 0,
1363
+ onClearAll,
1364
+ defaultExpanded = false,
1365
+ className = ""
1366
+ }) => {
1367
+ const [expanded, setExpanded] = useState10(defaultExpanded);
1368
+ return /* @__PURE__ */ jsxs21("div", { className: `advanced-filter-bar ${className}`, children: [
1369
+ /* @__PURE__ */ jsxs21(
1370
+ "div",
1371
+ {
1372
+ className: "filter-bar-header",
1373
+ onClick: () => setExpanded(!expanded),
1374
+ children: [
1375
+ /* @__PURE__ */ jsxs21("div", { className: "filter-title-group", children: [
1376
+ /* @__PURE__ */ jsx29(FiFilter, { className: "text-primary" }),
1377
+ /* @__PURE__ */ jsx29("h5", { className: "filter-title", children: title }),
1378
+ activeFiltersCount > 0 && /* @__PURE__ */ jsxs21("span", { className: "filter-count-badge", children: [
1379
+ activeFiltersCount,
1380
+ " ativos"
1381
+ ] })
1382
+ ] }),
1383
+ /* @__PURE__ */ jsx29("div", { className: "filter-chevron", children: expanded ? /* @__PURE__ */ jsx29(FiChevronUp, { size: 20 }) : /* @__PURE__ */ jsx29(FiChevronDown, { size: 20 }) })
1384
+ ]
1385
+ }
1386
+ ),
1387
+ /* @__PURE__ */ jsx29(Collapse, { in: expanded, children: /* @__PURE__ */ jsx29("div", { children: /* @__PURE__ */ jsxs21("div", { className: "filter-bar-content", children: [
1388
+ /* @__PURE__ */ jsx29("div", { className: "filter-grid", children }),
1389
+ (onClearAll || activeFiltersCount > 0) && /* @__PURE__ */ jsxs21("div", { className: "filter-actions", children: [
1390
+ onClearAll && /* @__PURE__ */ jsxs21(
1391
+ Button11,
1392
+ {
1393
+ variant: "link",
1394
+ className: "text-danger text-decoration-none btn-sm d-flex align-items-center",
1395
+ onClick: (e) => {
1396
+ e.stopPropagation();
1397
+ onClearAll();
1398
+ },
1399
+ children: [
1400
+ /* @__PURE__ */ jsx29(FiTrash22, { className: "me-1" }),
1401
+ "Limpar Filtros"
1402
+ ]
1403
+ }
1404
+ ),
1405
+ /* @__PURE__ */ jsx29(
1406
+ Button11,
1407
+ {
1408
+ variant: "primary",
1409
+ size: "sm",
1410
+ onClick: () => setExpanded(false),
1411
+ children: "Aplicar Filtros"
1412
+ }
1413
+ )
1414
+ ] })
1415
+ ] }) }) })
1416
+ ] });
1417
+ };
1418
+
1419
+ // src/filters/UnifiedPeriodSelector.tsx
1420
+ import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useState as useState11 } from "react";
1421
+ import { Button as Button12, Card as Card3, Col as Col3, Form as Form6, Row as Row3 } from "react-bootstrap";
1422
+ import {
1423
+ FaCalendarAlt as FaCalendarAlt2,
1424
+ FaChevronLeft,
1425
+ FaChevronRight,
1426
+ FaClock,
1427
+ FaTimesCircle
1428
+ } from "react-icons/fa";
1429
+ import dayjs4 from "dayjs";
1430
+ import isoWeek from "dayjs/plugin/isoWeek";
1431
+ import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
1432
+ dayjs4.extend(isoWeek);
1433
+ var MONTHS = [
1434
+ "Jan",
1435
+ "Fev",
1436
+ "Mar",
1437
+ "Abr",
1438
+ "Mai",
1439
+ "Jun",
1440
+ "Jul",
1441
+ "Ago",
1442
+ "Set",
1443
+ "Out",
1444
+ "Nov",
1445
+ "Dez"
1446
+ ];
1447
+ var MONTHS_FULL = [
1448
+ "Janeiro",
1449
+ "Fevereiro",
1450
+ "Mar\xE7o",
1451
+ "Abril",
1452
+ "Maio",
1453
+ "Junho",
1454
+ "Julho",
1455
+ "Agosto",
1456
+ "Setembro",
1457
+ "Outubro",
1458
+ "Novembro",
1459
+ "Dezembro"
1460
+ ];
1461
+ var pad2 = (n) => String(n).padStart(2, "0");
1462
+ var startOfMonthISO = (year, m) => `${year}-${pad2(m + 1)}-01T00:00:00`;
1463
+ var endOfMonthISO = (year, m) => {
1464
+ const lastDay = new Date(year, m + 1, 0).getDate();
1465
+ return `${year}-${pad2(m + 1)}-${pad2(lastDay)}T23:59:59`;
1466
+ };
1467
+ var parseDate = (v) => {
1468
+ if (!v) return null;
1469
+ const d = new Date(v);
1470
+ return isNaN(d.getTime()) ? null : d;
1471
+ };
1472
+ var DEFAULT_PRESETS = [
1473
+ {
1474
+ key: "today",
1475
+ label: "Hoje",
1476
+ start: () => dayjs4().startOf("day"),
1477
+ end: () => dayjs4().endOf("day")
1478
+ },
1479
+ {
1480
+ key: "week",
1481
+ label: "Esta semana",
1482
+ start: () => dayjs4().startOf("isoWeek"),
1483
+ end: () => dayjs4().endOf("isoWeek")
1484
+ },
1485
+ {
1486
+ key: "month",
1487
+ label: "Este m\xEAs",
1488
+ start: () => dayjs4().startOf("month"),
1489
+ end: () => dayjs4().endOf("month")
1490
+ },
1491
+ {
1492
+ key: "year",
1493
+ label: "Este ano",
1494
+ start: () => dayjs4().startOf("year"),
1495
+ end: () => dayjs4().endOf("year")
1496
+ }
1497
+ ];
1498
+ var TABS = [
1499
+ { key: "quick", icon: /* @__PURE__ */ jsx30(FaClock, { size: 12 }), label: "R\xE1pido" },
1500
+ { key: "month", icon: /* @__PURE__ */ jsx30(FaCalendarAlt2, { size: 12 }), label: "Meses" },
1501
+ { key: "custom", icon: /* @__PURE__ */ jsx30(FaCalendarAlt2, { size: 12 }), label: "Per\xEDodo" }
1502
+ ];
1503
+ var UnifiedPeriodSelector = ({
1504
+ dataInicio,
1505
+ dataFim,
1506
+ onSelect,
1507
+ defaultTab = "quick",
1508
+ allowFuture = true,
1509
+ quickPresets,
1510
+ className = "",
1511
+ disabled = false,
1512
+ compact = false
1513
+ }) => {
1514
+ const [activeTab, setActiveTab] = useState11(defaultTab);
1515
+ const [isExpanded, setIsExpanded] = useState11(!compact);
1516
+ const [activePresetKey, setActivePresetKey] = useState11(null);
1517
+ const [selectedYear, setSelectedYear] = useState11(() => {
1518
+ const d = parseDate(dataInicio);
1519
+ return d ? d.getFullYear() : (/* @__PURE__ */ new Date()).getFullYear();
1520
+ });
1521
+ const [selectedMonths, setSelectedMonths] = useState11(/* @__PURE__ */ new Set());
1522
+ const [lastClickedMonth, setLastClickedMonth] = useState11(null);
1523
+ const [customStart, setCustomStart] = useState11("");
1524
+ const [customEnd, setCustomEnd] = useState11("");
1525
+ const presets = quickPresets || DEFAULT_PRESETS;
1526
+ useEffect4(() => {
1527
+ const start = parseDate(dataInicio);
1528
+ const end = parseDate(dataFim);
1529
+ if (!start || !end) return;
1530
+ if (start.getFullYear() === selectedYear || end.getFullYear() === selectedYear) {
1531
+ const next = /* @__PURE__ */ new Set();
1532
+ if (start.getFullYear() === end.getFullYear() && start.getFullYear() === selectedYear) {
1533
+ for (let m = start.getMonth(); m <= end.getMonth(); m++) next.add(m);
1534
+ } else {
1535
+ const s = start.getFullYear() === selectedYear ? start.getMonth() : 0;
1536
+ const e = end.getFullYear() === selectedYear ? end.getMonth() : 11;
1537
+ for (let m = s; m <= e; m++) next.add(m);
1538
+ }
1539
+ setSelectedMonths(next);
1540
+ }
1541
+ }, [dataInicio, dataFim, selectedYear]);
1542
+ useEffect4(() => {
1543
+ if (dataInicio) setCustomStart(dayjs4(dataInicio).format("YYYY-MM-DDTHH:mm"));
1544
+ if (dataFim) setCustomEnd(dayjs4(dataFim).format("YYYY-MM-DDTHH:mm"));
1545
+ }, [dataInicio, dataFim]);
1546
+ const displayLabel = useMemo2(() => {
1547
+ const s = parseDate(dataInicio);
1548
+ const e = parseDate(dataFim);
1549
+ if (!s || !e) return "Selecione um per\xEDodo";
1550
+ if (activePresetKey) {
1551
+ const p = presets.find((pr) => pr.key === activePresetKey);
1552
+ if (p) return p.label;
1553
+ }
1554
+ if (s.getFullYear() === e.getFullYear() && s.getMonth() === e.getMonth() && s.getDate() === 1) {
1555
+ return `${MONTHS_FULL[s.getMonth()]} ${s.getFullYear()}`;
1556
+ }
1557
+ return `${dayjs4(s).format("DD/MM/YYYY")} \u2013 ${dayjs4(e).format("DD/MM/YYYY")}`;
1558
+ }, [dataInicio, dataFim, activePresetKey, presets]);
1559
+ const handlePreset = useCallback(
1560
+ (preset) => {
1561
+ if (disabled) return;
1562
+ setActivePresetKey(preset.key);
1563
+ onSelect({
1564
+ dataInicio: preset.start().toISOString(),
1565
+ dataFim: preset.end().toISOString()
1566
+ });
1567
+ },
1568
+ [disabled, onSelect]
1569
+ );
1570
+ const handleMonthClick = useCallback(
1571
+ (index, event) => {
1572
+ if (disabled) return;
1573
+ const ctrl = event.ctrlKey || event.metaKey;
1574
+ const shift = event.shiftKey;
1575
+ setSelectedMonths((prev) => {
1576
+ let next;
1577
+ if (shift && lastClickedMonth !== null) {
1578
+ next = /* @__PURE__ */ new Set();
1579
+ const start = Math.min(index, lastClickedMonth);
1580
+ const end = Math.max(index, lastClickedMonth);
1581
+ for (let m = start; m <= end; m++) next.add(m);
1582
+ } else if (ctrl) {
1583
+ next = new Set(prev);
1584
+ if (next.has(index)) next.delete(index);
1585
+ else next.add(index);
1586
+ } else {
1587
+ next = /* @__PURE__ */ new Set([index]);
1588
+ }
1589
+ if (next.size === 0) {
1590
+ onSelect({ dataInicio: "", dataFim: "" });
1591
+ } else {
1592
+ const arr = Array.from(next).sort((a, b) => a - b);
1593
+ const first = arr[0];
1594
+ const last = arr[arr.length - 1];
1595
+ onSelect({
1596
+ dataInicio: startOfMonthISO(selectedYear, first),
1597
+ dataFim: endOfMonthISO(selectedYear, last)
1598
+ });
1599
+ }
1600
+ setActivePresetKey(null);
1601
+ return next;
1602
+ });
1603
+ setLastClickedMonth(index);
1604
+ },
1605
+ [disabled, lastClickedMonth, onSelect, selectedYear]
1606
+ );
1607
+ const handleYearChange = useCallback(
1608
+ (delta) => {
1609
+ const newYear = selectedYear + delta;
1610
+ setSelectedYear(newYear);
1611
+ if (selectedMonths.size > 0) {
1612
+ const arr = Array.from(selectedMonths).sort((a, b) => a - b);
1613
+ onSelect({
1614
+ dataInicio: startOfMonthISO(newYear, arr[0]),
1615
+ dataFim: endOfMonthISO(newYear, arr[arr.length - 1])
1616
+ });
1617
+ setActivePresetKey(null);
1618
+ }
1619
+ },
1620
+ [selectedYear, selectedMonths, onSelect]
1621
+ );
1622
+ const quickMonthOptions = useMemo2(() => {
1623
+ const now = /* @__PURE__ */ new Date();
1624
+ const opts = [];
1625
+ for (let yearOffset = 0; yearOffset <= 1; yearOffset++) {
1626
+ const year = now.getFullYear() - yearOffset;
1627
+ const lastMonth = yearOffset === 0 ? now.getMonth() : 11;
1628
+ for (let m = lastMonth; m >= 0; m--) {
1629
+ opts.push({
1630
+ value: `${year}-${pad2(m + 1)}`,
1631
+ label: `${MONTHS_FULL[m]} ${year}`,
1632
+ year,
1633
+ month: m
1634
+ });
1635
+ }
1636
+ }
1637
+ return opts;
1638
+ }, []);
1639
+ const quickMonthValue = useMemo2(() => {
1640
+ const s = parseDate(dataInicio);
1641
+ const e = parseDate(dataFim);
1642
+ if (!s || !e) return "";
1643
+ if (s.getFullYear() === e.getFullYear() && s.getMonth() === e.getMonth() && s.getDate() === 1) {
1644
+ return `${s.getFullYear()}-${pad2(s.getMonth() + 1)}`;
1645
+ }
1646
+ return "";
1647
+ }, [dataInicio, dataFim]);
1648
+ const handleQuickMonthChange = useCallback(
1649
+ (value) => {
1650
+ if (disabled || !value) return;
1651
+ const opt = quickMonthOptions.find((o) => o.value === value);
1652
+ if (!opt) return;
1653
+ setActivePresetKey(null);
1654
+ setSelectedYear(opt.year);
1655
+ setSelectedMonths(/* @__PURE__ */ new Set([opt.month]));
1656
+ onSelect({
1657
+ dataInicio: startOfMonthISO(opt.year, opt.month),
1658
+ dataFim: endOfMonthISO(opt.year, opt.month)
1659
+ });
1660
+ },
1661
+ [disabled, onSelect, quickMonthOptions]
1662
+ );
1663
+ const handleCustomApply = useCallback(() => {
1664
+ if (!customStart || !customEnd) return;
1665
+ setActivePresetKey(null);
1666
+ onSelect({
1667
+ dataInicio: dayjs4(customStart).toISOString(),
1668
+ dataFim: dayjs4(customEnd).toISOString()
1669
+ });
1670
+ }, [customStart, customEnd, onSelect]);
1671
+ const handleClear = useCallback(() => {
1672
+ setSelectedMonths(/* @__PURE__ */ new Set());
1673
+ setActivePresetKey(null);
1674
+ setCustomStart("");
1675
+ setCustomEnd("");
1676
+ onSelect({ dataInicio: "", dataFim: "" });
1677
+ }, [onSelect]);
1678
+ const today = /* @__PURE__ */ new Date();
1679
+ const maxDateStr = allowFuture ? void 0 : dayjs4().format("YYYY-MM-DDTHH:mm");
1680
+ if (compact && !isExpanded) {
1681
+ return /* @__PURE__ */ jsx30(
1682
+ Card3,
1683
+ {
1684
+ className: `ups-card ups-card--compact ${className}`,
1685
+ onClick: () => !disabled && setIsExpanded(true),
1686
+ role: "button",
1687
+ tabIndex: 0,
1688
+ children: /* @__PURE__ */ jsxs22("div", { className: "ups-compact-row", children: [
1689
+ /* @__PURE__ */ jsx30(FaCalendarAlt2, { className: "text-primary me-2" }),
1690
+ /* @__PURE__ */ jsx30("span", { className: "ups-display-label", children: displayLabel }),
1691
+ /* @__PURE__ */ jsx30("span", { className: "ups-edit-hint text-muted small", children: "Editar" })
1692
+ ] })
1693
+ }
1694
+ );
1695
+ }
1696
+ return /* @__PURE__ */ jsx30(Card3, { className: `ups-card ${className}`, children: /* @__PURE__ */ jsxs22(Card3.Body, { className: "ups-body", children: [
1697
+ /* @__PURE__ */ jsxs22("div", { className: "ups-header", children: [
1698
+ /* @__PURE__ */ jsxs22("div", { className: "d-flex align-items-center gap-2 flex-grow-1 min-w-0", children: [
1699
+ /* @__PURE__ */ jsx30(FaCalendarAlt2, { className: "text-primary flex-shrink-0" }),
1700
+ /* @__PURE__ */ jsx30("span", { className: "ups-display-label text-truncate", children: displayLabel })
1701
+ ] }),
1702
+ /* @__PURE__ */ jsxs22("div", { className: "d-flex align-items-center gap-1", children: [
1703
+ (dataInicio || dataFim) && /* @__PURE__ */ jsx30(
1704
+ Button12,
1705
+ {
1706
+ variant: "link",
1707
+ size: "sm",
1708
+ className: "p-0 text-muted",
1709
+ onClick: handleClear,
1710
+ title: "Limpar per\xEDodo",
1711
+ disabled,
1712
+ children: /* @__PURE__ */ jsx30(FaTimesCircle, { size: 14 })
1713
+ }
1714
+ ),
1715
+ compact && /* @__PURE__ */ jsx30(
1716
+ Button12,
1717
+ {
1718
+ variant: "link",
1719
+ size: "sm",
1720
+ className: "p-0 text-muted",
1721
+ onClick: () => setIsExpanded(false),
1722
+ children: "Fechar"
1723
+ }
1724
+ )
1725
+ ] })
1726
+ ] }),
1727
+ /* @__PURE__ */ jsx30("div", { className: "ups-tabs", children: TABS.map((tab) => /* @__PURE__ */ jsxs22(
1728
+ "button",
1729
+ {
1730
+ className: `ups-tab ${activeTab === tab.key ? "ups-tab--active" : ""}`,
1731
+ onClick: () => setActiveTab(tab.key),
1732
+ disabled,
1733
+ children: [
1734
+ tab.icon,
1735
+ /* @__PURE__ */ jsx30("span", { children: tab.label })
1736
+ ]
1737
+ },
1738
+ tab.key
1739
+ )) }),
1740
+ /* @__PURE__ */ jsxs22("div", { className: "ups-content", children: [
1741
+ activeTab === "quick" && /* @__PURE__ */ jsxs22(Fragment8, { children: [
1742
+ /* @__PURE__ */ jsx30("div", { className: "ups-quick-grid", children: presets.map((p) => /* @__PURE__ */ jsx30(
1743
+ Button12,
1744
+ {
1745
+ size: "sm",
1746
+ variant: activePresetKey === p.key ? "primary" : "outline-secondary",
1747
+ className: "ups-quick-btn",
1748
+ onClick: () => handlePreset(p),
1749
+ disabled,
1750
+ children: p.label
1751
+ },
1752
+ p.key
1753
+ )) }),
1754
+ /* @__PURE__ */ jsxs22("div", { className: "ups-quick-month", children: [
1755
+ /* @__PURE__ */ jsx30(Form6.Label, { className: "small text-muted mb-1", children: "M\xEAs exato" }),
1756
+ /* @__PURE__ */ jsxs22(
1757
+ Form6.Select,
1758
+ {
1759
+ size: "sm",
1760
+ value: quickMonthValue,
1761
+ onChange: (e) => handleQuickMonthChange(e.target.value),
1762
+ disabled,
1763
+ "aria-label": "Selecionar m\xEAs exato",
1764
+ children: [
1765
+ /* @__PURE__ */ jsx30("option", { value: "", children: "Escolha um m\xEAs\u2026" }),
1766
+ quickMonthOptions.map((o) => /* @__PURE__ */ jsx30("option", { value: o.value, children: o.label }, o.value))
1767
+ ]
1768
+ }
1769
+ )
1770
+ ] })
1771
+ ] }),
1772
+ activeTab === "month" && /* @__PURE__ */ jsxs22("div", { className: "ups-month-section", children: [
1773
+ /* @__PURE__ */ jsxs22("div", { className: "ups-year-nav", children: [
1774
+ /* @__PURE__ */ jsx30(
1775
+ Button12,
1776
+ {
1777
+ variant: "outline-secondary",
1778
+ size: "sm",
1779
+ className: "ups-year-btn",
1780
+ onClick: () => handleYearChange(-1),
1781
+ disabled,
1782
+ children: /* @__PURE__ */ jsx30(FaChevronLeft, { size: 10 })
1783
+ }
1784
+ ),
1785
+ /* @__PURE__ */ jsx30("span", { className: "ups-year-label", children: selectedYear }),
1786
+ /* @__PURE__ */ jsx30(
1787
+ Button12,
1788
+ {
1789
+ variant: "outline-secondary",
1790
+ size: "sm",
1791
+ className: "ups-year-btn",
1792
+ onClick: () => handleYearChange(1),
1793
+ disabled,
1794
+ children: /* @__PURE__ */ jsx30(FaChevronRight, { size: 10 })
1795
+ }
1796
+ )
1797
+ ] }),
1798
+ /* @__PURE__ */ jsx30("div", { className: "ups-month-grid", children: MONTHS.map((label, idx) => {
1799
+ const isSelected = selectedMonths.has(idx);
1800
+ const isCurrent = today.getFullYear() === selectedYear && today.getMonth() === idx;
1801
+ return /* @__PURE__ */ jsx30(
1802
+ "button",
1803
+ {
1804
+ className: [
1805
+ "ups-month-cell",
1806
+ isSelected && "ups-month-cell--selected",
1807
+ isCurrent && !isSelected && "ups-month-cell--current"
1808
+ ].filter(Boolean).join(" "),
1809
+ onClick: (e) => handleMonthClick(idx, e),
1810
+ disabled,
1811
+ title: "Clique: selecionar \xB7 Shift: range \xB7 Ctrl/Cmd: multi",
1812
+ children: label
1813
+ },
1814
+ idx
1815
+ );
1816
+ }) }),
1817
+ /* @__PURE__ */ jsx30("p", { className: "ups-month-hint text-muted", children: "Shift+clique para range \xB7 Ctrl/Cmd+clique para multi-sele\xE7\xE3o" })
1818
+ ] }),
1819
+ activeTab === "custom" && /* @__PURE__ */ jsxs22("div", { className: "ups-custom-section", children: [
1820
+ /* @__PURE__ */ jsxs22(Row3, { className: "g-2", children: [
1821
+ /* @__PURE__ */ jsx30(Col3, { xs: 12, sm: 6, children: /* @__PURE__ */ jsxs22(Form6.Group, { children: [
1822
+ /* @__PURE__ */ jsx30(Form6.Label, { className: "small text-muted mb-1", children: "In\xEDcio" }),
1823
+ /* @__PURE__ */ jsx30(
1824
+ Form6.Control,
1825
+ {
1826
+ type: "datetime-local",
1827
+ size: "sm",
1828
+ value: customStart,
1829
+ max: maxDateStr,
1830
+ onChange: (e) => setCustomStart(e.target.value),
1831
+ disabled
1832
+ }
1833
+ )
1834
+ ] }) }),
1835
+ /* @__PURE__ */ jsx30(Col3, { xs: 12, sm: 6, children: /* @__PURE__ */ jsxs22(Form6.Group, { children: [
1836
+ /* @__PURE__ */ jsx30(Form6.Label, { className: "small text-muted mb-1", children: "Fim" }),
1837
+ /* @__PURE__ */ jsx30(
1838
+ Form6.Control,
1839
+ {
1840
+ type: "datetime-local",
1841
+ size: "sm",
1842
+ value: customEnd,
1843
+ min: customStart,
1844
+ max: maxDateStr,
1845
+ onChange: (e) => setCustomEnd(e.target.value),
1846
+ disabled
1847
+ }
1848
+ )
1849
+ ] }) })
1850
+ ] }),
1851
+ /* @__PURE__ */ jsx30("div", { className: "d-flex justify-content-end mt-2", children: /* @__PURE__ */ jsx30(
1852
+ Button12,
1853
+ {
1854
+ variant: "primary",
1855
+ size: "sm",
1856
+ onClick: handleCustomApply,
1857
+ disabled: disabled || !customStart || !customEnd,
1858
+ children: "Aplicar"
1859
+ }
1860
+ ) })
1861
+ ] })
1862
+ ] })
1863
+ ] }) });
1864
+ };
1865
+
1866
+ // src/forms/MailSender.tsx
1867
+ import { useState as useState12 } from "react";
1868
+ import {
1869
+ Button as Button13,
1870
+ Card as Card4,
1871
+ Col as Col4,
1872
+ Form as Form7,
1873
+ Row as Row4,
1874
+ Spinner as Spinner4,
1875
+ Badge as Badge2,
1876
+ InputGroup as InputGroup2
1877
+ } from "react-bootstrap";
1878
+ import { FiMail, FiSearch, FiUser, FiX, FiPlus, FiSend } from "react-icons/fi";
1879
+ import { Fragment as Fragment9, jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
1880
+ var MailSender = ({
1881
+ htmlContent,
1882
+ companyName,
1883
+ onFetchEmails,
1884
+ onSendEmail,
1885
+ hide = false,
1886
+ renderTrigger
1887
+ }) => {
1888
+ const [opened, setOpened] = useState12(false);
1889
+ const [addingEmail, setAddingEmail] = useState12(false);
1890
+ const [selectedEmails, setSelectedEmails] = useState12([]);
1891
+ const [emails, setEmails] = useState12([]);
1892
+ const [loading, setLoading] = useState12(false);
1893
+ const [postLoading, setPostLoading] = useState12(false);
1894
+ const [customEmail, setCustomEmail] = useState12("");
1895
+ const [emailError, setEmailError] = useState12("");
1896
+ const [searchFilter, setSearchFilter] = useState12("");
1897
+ const handleOpen = async () => {
1898
+ setLoading(true);
1899
+ try {
1900
+ const data = await onFetchEmails();
1901
+ setEmails(data || []);
1902
+ setOpened(true);
1903
+ } catch (err) {
1904
+ console.error("Erro ao buscar e-mails:", err);
1905
+ } finally {
1906
+ setLoading(false);
1907
+ }
1908
+ };
1909
+ const mailListLinter = () => {
1910
+ const result = [];
1911
+ const seen = /* @__PURE__ */ new Set();
1912
+ if (emails) {
1913
+ for (const item of emails) {
1914
+ if (item.email && !seen.has(item.email)) {
1915
+ seen.add(item.email);
1916
+ result.push({ email: item.email });
1917
+ }
1918
+ }
1919
+ }
1920
+ return result;
1921
+ };
1922
+ const filteredEmails = emails ? mailListLinter().filter(
1923
+ (email) => email.email.toLowerCase().includes(searchFilter.toLowerCase()) && !selectedEmails.some((selected) => (selected.email || selected) === email.email)
1924
+ ) : [];
1925
+ const sendEmail = async () => {
1926
+ const emailString = selectedEmails.map((email) => email.email ? email.email : email).join(", ");
1927
+ const emailData = {
1928
+ to: emailString,
1929
+ subject: `Relat\xF3rio - ${companyName}`,
1930
+ text: `Relat\xF3rio de processo da empresa ${companyName}`,
1931
+ html: htmlContent
1932
+ };
1933
+ setPostLoading(true);
1934
+ try {
1935
+ await onSendEmail(emailData);
1936
+ setSelectedEmails([]);
1937
+ setCustomEmail("");
1938
+ setOpened(false);
1939
+ } catch (err) {
1940
+ console.error("Erro ao enviar e-mail:", err);
1941
+ } finally {
1942
+ setPostLoading(false);
1943
+ }
1944
+ };
1945
+ const validateEmail = (email) => {
1946
+ const re = /\S+@\S+\.\S+/;
1947
+ return re.test(email);
1948
+ };
1949
+ const handleEmailAdd = () => {
1950
+ if (!customEmail.trim()) {
1951
+ setEmailError("Por favor, digite um e-mail");
1952
+ return;
1953
+ }
1954
+ if (!validateEmail(customEmail)) {
1955
+ setEmailError("Formato de e-mail inv\xE1lido");
1956
+ return;
1957
+ }
1958
+ if (selectedEmails.some((email) => (email.email || email) === customEmail)) {
1959
+ setEmailError("Este e-mail j\xE1 foi selecionado");
1960
+ return;
1961
+ }
1962
+ setSelectedEmails([...selectedEmails, customEmail]);
1963
+ setCustomEmail("");
1964
+ setEmailError("");
1965
+ setAddingEmail(false);
1966
+ };
1967
+ const handleEmailRemove = (emailToRemove) => {
1968
+ setSelectedEmails(
1969
+ selectedEmails.filter(
1970
+ (email) => (email.email || email) !== (emailToRemove.email || emailToRemove)
1971
+ )
1972
+ );
1973
+ };
1974
+ if (hide) return null;
1975
+ if (!opened) {
1976
+ if (renderTrigger) {
1977
+ return renderTrigger({ onClick: handleOpen, loading });
1978
+ }
1979
+ return /* @__PURE__ */ jsx31(Button13, { disabled: loading, className: "w-100", onClick: handleOpen, children: loading ? "Carregando..." : "Enviar por E-mail" });
1980
+ }
1981
+ return /* @__PURE__ */ jsxs23(
1982
+ "div",
1983
+ {
1984
+ style: {
1985
+ backgroundColor: "#f8f9fa",
1986
+ borderRadius: "12px",
1987
+ overflow: "hidden",
1988
+ border: "1px solid #dee2e6",
1989
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
1990
+ },
1991
+ children: [
1992
+ /* @__PURE__ */ jsx31(
1993
+ "div",
1994
+ {
1995
+ style: {
1996
+ background: "linear-gradient(135deg, #28a745 0%, #20c997 100%)",
1997
+ color: "white",
1998
+ padding: "25px"
1999
+ },
2000
+ children: /* @__PURE__ */ jsxs23("div", { className: "d-flex justify-content-between align-items-center", children: [
2001
+ /* @__PURE__ */ jsxs23("div", { children: [
2002
+ /* @__PURE__ */ jsxs23("h4", { className: "mb-1", style: { fontWeight: "600", fontSize: "22px" }, children: [
2003
+ /* @__PURE__ */ jsx31(FiMail, { className: "me-2", size: 20 }),
2004
+ "Enviar Relat\xF3rio por E-mail"
2005
+ ] }),
2006
+ /* @__PURE__ */ jsxs23("small", { style: { opacity: "0.9", fontSize: "14px" }, children: [
2007
+ "Selecione os destinat\xE1rios para envio do relat\xF3rio de ",
2008
+ companyName
2009
+ ] })
2010
+ ] }),
2011
+ /* @__PURE__ */ jsxs23("div", { className: "d-flex gap-2", children: [
2012
+ /* @__PURE__ */ jsx31(
2013
+ Button13,
2014
+ {
2015
+ variant: "light",
2016
+ onClick: sendEmail,
2017
+ disabled: selectedEmails.length === 0 || postLoading,
2018
+ style: {
2019
+ borderRadius: "8px",
2020
+ fontWeight: "600",
2021
+ minWidth: "130px",
2022
+ height: "40px"
2023
+ },
2024
+ children: postLoading ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
2025
+ /* @__PURE__ */ jsx31(Spinner4, { size: "sm", className: "me-2" }),
2026
+ "Enviando..."
2027
+ ] }) : /* @__PURE__ */ jsxs23(Fragment9, { children: [
2028
+ /* @__PURE__ */ jsx31(FiSend, { className: "me-2", size: 14 }),
2029
+ "Enviar E-mail"
2030
+ ] })
2031
+ }
2032
+ ),
2033
+ /* @__PURE__ */ jsx31(
2034
+ Button13,
2035
+ {
2036
+ variant: "outline-light",
2037
+ onClick: () => setOpened(false),
2038
+ disabled: postLoading,
2039
+ style: { borderRadius: "8px", width: "40px", height: "40px" },
2040
+ children: /* @__PURE__ */ jsx31(FiX, { size: 16 })
2041
+ }
2042
+ )
2043
+ ] })
2044
+ ] })
2045
+ }
2046
+ ),
2047
+ /* @__PURE__ */ jsxs23("div", { style: { padding: "25px" }, children: [
2048
+ /* @__PURE__ */ jsx31(Card4, { className: "mb-4", style: { border: "none", boxShadow: "0 2px 8px rgba(0,0,0,0.05)" }, children: /* @__PURE__ */ jsxs23(Card4.Body, { style: { padding: "20px" }, children: [
2049
+ /* @__PURE__ */ jsxs23(Row4, { className: "align-items-center", children: [
2050
+ /* @__PURE__ */ jsxs23(Col4, { md: 6, children: [
2051
+ /* @__PURE__ */ jsx31("h6", { className: "mb-2", style: { color: "#495057", fontWeight: "600" }, children: "\u{1F527} Filtros e A\xE7\xF5es" }),
2052
+ /* @__PURE__ */ jsxs23(InputGroup2, { style: { maxWidth: "300px" }, children: [
2053
+ /* @__PURE__ */ jsx31(InputGroup2.Text, { style: { backgroundColor: "#f8f9fa", border: "1px solid #dee2e6" }, children: /* @__PURE__ */ jsx31(FiSearch, { size: 14, color: "#6c757d" }) }),
2054
+ /* @__PURE__ */ jsx31(
2055
+ Form7.Control,
2056
+ {
2057
+ type: "text",
2058
+ placeholder: "Buscar e-mails...",
2059
+ value: searchFilter,
2060
+ onChange: (e) => setSearchFilter(e.target.value),
2061
+ style: { border: "1px solid #dee2e6" }
2062
+ }
2063
+ )
2064
+ ] })
2065
+ ] }),
2066
+ /* @__PURE__ */ jsx31(Col4, { md: 6, className: "text-end", children: /* @__PURE__ */ jsx31(
2067
+ Button13,
2068
+ {
2069
+ variant: addingEmail ? "outline-secondary" : "outline-primary",
2070
+ size: "sm",
2071
+ onClick: () => setAddingEmail(!addingEmail),
2072
+ disabled: postLoading,
2073
+ style: { borderRadius: "8px" },
2074
+ children: addingEmail ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
2075
+ /* @__PURE__ */ jsx31(FiX, { className: "me-1", size: 14 }),
2076
+ "Cancelar"
2077
+ ] }) : /* @__PURE__ */ jsxs23(Fragment9, { children: [
2078
+ /* @__PURE__ */ jsx31(FiPlus, { className: "me-1", size: 14 }),
2079
+ "E-mail Personalizado"
2080
+ ] })
2081
+ }
2082
+ ) })
2083
+ ] }),
2084
+ addingEmail && /* @__PURE__ */ jsxs23(
2085
+ "div",
2086
+ {
2087
+ style: {
2088
+ marginTop: "20px",
2089
+ padding: "20px",
2090
+ backgroundColor: "#f8f9ff",
2091
+ borderRadius: "8px",
2092
+ border: "1px solid #e3f2fd"
2093
+ },
2094
+ children: [
2095
+ /* @__PURE__ */ jsx31("h6", { className: "mb-3", style: { color: "#1976d2", fontWeight: "600" }, children: "\u2709\uFE0F Adicionar E-mail Personalizado" }),
2096
+ /* @__PURE__ */ jsxs23(Row4, { className: "align-items-end", children: [
2097
+ /* @__PURE__ */ jsxs23(Col4, { md: 8, children: [
2098
+ /* @__PURE__ */ jsx31(Form7.Label, { style: { fontSize: "13px", color: "#6c757d", fontWeight: "500" }, children: "Endere\xE7o de E-mail" }),
2099
+ /* @__PURE__ */ jsx31(
2100
+ Form7.Control,
2101
+ {
2102
+ type: "email",
2103
+ placeholder: "exemplo@empresa.com",
2104
+ value: customEmail,
2105
+ onChange: (e) => {
2106
+ setCustomEmail(e.target.value);
2107
+ if (emailError) setEmailError("");
2108
+ },
2109
+ isInvalid: !!emailError,
2110
+ disabled: postLoading,
2111
+ style: { borderRadius: "8px" },
2112
+ onKeyPress: (e) => e.key === "Enter" && handleEmailAdd()
2113
+ }
2114
+ ),
2115
+ /* @__PURE__ */ jsx31(Form7.Control.Feedback, { type: "invalid", children: emailError })
2116
+ ] }),
2117
+ /* @__PURE__ */ jsx31(Col4, { md: 4, children: /* @__PURE__ */ jsxs23(
2118
+ Button13,
2119
+ {
2120
+ variant: "success",
2121
+ onClick: handleEmailAdd,
2122
+ disabled: postLoading,
2123
+ style: { borderRadius: "8px", width: "100%" },
2124
+ children: [
2125
+ /* @__PURE__ */ jsx31(FiPlus, { className: "me-1", size: 14 }),
2126
+ "Adicionar"
2127
+ ]
2128
+ }
2129
+ ) })
2130
+ ] })
2131
+ ]
2132
+ }
2133
+ )
2134
+ ] }) }),
2135
+ selectedEmails.length > 0 && /* @__PURE__ */ jsx31(Card4, { className: "mb-4", style: { border: "none", boxShadow: "0 2px 8px rgba(0,0,0,0.05)" }, children: /* @__PURE__ */ jsxs23(Card4.Body, { style: { padding: "20px" }, children: [
2136
+ /* @__PURE__ */ jsxs23("div", { className: "d-flex justify-content-between align-items-center mb-3", children: [
2137
+ /* @__PURE__ */ jsx31("h6", { className: "mb-0", style: { color: "#495057", fontWeight: "600" }, children: "\u{1F4CB} Destinat\xE1rios Selecionados" }),
2138
+ /* @__PURE__ */ jsxs23(Badge2, { bg: "primary", style: { fontSize: "12px", padding: "6px 12px" }, children: [
2139
+ selectedEmails.length,
2140
+ " selecionado",
2141
+ selectedEmails.length > 1 ? "s" : ""
2142
+ ] })
2143
+ ] }),
2144
+ /* @__PURE__ */ jsx31("div", { className: "d-flex flex-wrap gap-2", children: selectedEmails.map((email, index) => /* @__PURE__ */ jsxs23(
2145
+ "div",
2146
+ {
2147
+ style: {
2148
+ background: "linear-gradient(135deg, #e3f2fd 0%, #f3e5f5 100%)",
2149
+ border: "1px solid #bbdefb",
2150
+ borderRadius: "20px",
2151
+ padding: "8px 15px",
2152
+ display: "flex",
2153
+ alignItems: "center",
2154
+ fontSize: "14px",
2155
+ fontWeight: "500"
2156
+ },
2157
+ children: [
2158
+ /* @__PURE__ */ jsx31(FiUser, { size: 12, className: "me-2", color: "#1976d2" }),
2159
+ /* @__PURE__ */ jsx31("span", { children: email.email || email }),
2160
+ /* @__PURE__ */ jsx31(
2161
+ Button13,
2162
+ {
2163
+ variant: "link",
2164
+ size: "sm",
2165
+ onClick: () => handleEmailRemove(email),
2166
+ disabled: postLoading,
2167
+ style: {
2168
+ padding: "0 0 0 8px",
2169
+ color: "#dc3545",
2170
+ textDecoration: "none",
2171
+ fontSize: "16px"
2172
+ },
2173
+ children: /* @__PURE__ */ jsx31(FiX, { size: 14 })
2174
+ }
2175
+ )
2176
+ ]
2177
+ },
2178
+ index
2179
+ )) })
2180
+ ] }) }),
2181
+ /* @__PURE__ */ jsx31(Card4, { style: { border: "none", boxShadow: "0 2px 8px rgba(0,0,0,0.05)" }, children: /* @__PURE__ */ jsxs23(Card4.Body, { style: { padding: "20px" }, children: [
2182
+ /* @__PURE__ */ jsxs23("h6", { className: "mb-3", style: { color: "#495057", fontWeight: "600" }, children: [
2183
+ /* @__PURE__ */ jsx31(FiUser, { className: "me-2", size: 16 }),
2184
+ "E-mails de ",
2185
+ companyName
2186
+ ] }),
2187
+ loading ? /* @__PURE__ */ jsxs23("div", { className: "text-center py-4", children: [
2188
+ /* @__PURE__ */ jsx31(Spinner4, {}),
2189
+ /* @__PURE__ */ jsx31("p", { className: "mt-2 text-muted", children: "Carregando e-mails..." })
2190
+ ] }) : filteredEmails.length === 0 ? /* @__PURE__ */ jsx31("div", { className: "text-center py-4", children: /* @__PURE__ */ jsx31("p", { className: "text-muted mb-0", children: searchFilter ? "Nenhum e-mail encontrado com esse filtro" : "Nenhum e-mail dispon\xEDvel" }) }) : /* @__PURE__ */ jsx31(Row4, { children: filteredEmails.map((email) => /* @__PURE__ */ jsx31(Col4, { xs: 12, sm: 6, lg: 4, className: "mb-3", children: /* @__PURE__ */ jsx31(
2191
+ Card4,
2192
+ {
2193
+ onClick: () => setSelectedEmails([...selectedEmails, email]),
2194
+ style: {
2195
+ cursor: "pointer",
2196
+ border: "1px solid #e9ecef",
2197
+ borderRadius: "10px",
2198
+ transition: "all 0.2s ease",
2199
+ backgroundColor: "#fff"
2200
+ },
2201
+ onMouseEnter: (e) => {
2202
+ e.currentTarget.style.transform = "translateY(-2px)";
2203
+ e.currentTarget.style.boxShadow = "0 4px 12px rgba(0,0,0,0.1)";
2204
+ e.currentTarget.style.borderColor = "#007bff";
2205
+ },
2206
+ onMouseLeave: (e) => {
2207
+ e.currentTarget.style.transform = "translateY(0)";
2208
+ e.currentTarget.style.boxShadow = "none";
2209
+ e.currentTarget.style.borderColor = "#e9ecef";
2210
+ },
2211
+ children: /* @__PURE__ */ jsxs23(Card4.Body, { style: { padding: "15px", textAlign: "center" }, children: [
2212
+ /* @__PURE__ */ jsx31(FiMail, { size: 20, color: "#007bff", className: "mb-2" }),
2213
+ /* @__PURE__ */ jsx31(
2214
+ "div",
2215
+ {
2216
+ style: {
2217
+ fontSize: "14px",
2218
+ fontWeight: "500",
2219
+ color: "#2c3e50",
2220
+ wordBreak: "break-word"
2221
+ },
2222
+ children: email.email
2223
+ }
2224
+ )
2225
+ ] })
2226
+ }
2227
+ ) }, email.email)) })
2228
+ ] }) })
2229
+ ] })
2230
+ ]
2231
+ }
2232
+ );
2233
+ };
2234
+
2235
+ // src/forms/AutoComplete.tsx
2236
+ import { useEffect as useEffect5, useMemo as useMemo3, useState as useState13 } from "react";
2237
+ import { FloatingLabel, Form as Form8, InputGroup as InputGroup3, ListGroup as ListGroup2, Spinner as Spinner5 } from "react-bootstrap";
2238
+ import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
2239
+ var AutoComplete = ({
2240
+ className,
2241
+ ops = [],
2242
+ sortKey,
2243
+ displayKey,
2244
+ displayKeys,
2245
+ onValueChanged,
2246
+ onSelectedClick,
2247
+ value,
2248
+ actionButton,
2249
+ actionButton2,
2250
+ placeH,
2251
+ title,
2252
+ filter,
2253
+ filterField,
2254
+ loadFunc,
2255
+ loadCondition,
2256
+ onBlurEvent,
2257
+ formatationFunc,
2258
+ onEscKeyDown,
2259
+ onEnterKeyDown,
2260
+ margT,
2261
+ margB,
2262
+ hideComponent,
2263
+ disableComponent = false,
2264
+ disableSelect = false,
2265
+ autoFocusConfig,
2266
+ onLoad,
2267
+ cacheKey,
2268
+ minChars = 0,
2269
+ maxItems,
2270
+ showListOnFocus = true,
2271
+ lazyLoad = false,
2272
+ labelPosition = "top"
2273
+ }) => {
2274
+ const [liItem, setListItem] = useState13([]);
2275
+ const [options, setOptions] = useState13([]);
2276
+ const [input, setInput] = useState13("");
2277
+ const [hide, setHide] = useState13(true);
2278
+ const [onLoaded, setOnLoaded] = useState13(false);
2279
+ const [loading, setLoading] = useState13(false);
2280
+ const cacheStore = useMemo3(() => {
2281
+ const win = window;
2282
+ if (!win.__AUTO_COMPLETE_CACHE__) {
2283
+ win.__AUTO_COMPLETE_CACHE__ = /* @__PURE__ */ new Map();
2284
+ }
2285
+ return win.__AUTO_COMPLETE_CACHE__;
2286
+ }, []);
2287
+ const sortOptions = (data, key) => {
2288
+ if (!key || !Array.isArray(data)) return data;
2289
+ return [...data].sort((a, b) => String(a[key]).localeCompare(String(b[key])));
2290
+ };
2291
+ useEffect5(() => {
2292
+ setInput(value || "");
2293
+ }, [value]);
2294
+ useEffect5(() => {
2295
+ if (!Array.isArray(ops) || ops.length === 0) return;
2296
+ const sortedOptions = sortOptions(ops, sortKey);
2297
+ setListItem(sortedOptions);
2298
+ setOptions(sortedOptions);
2299
+ }, [ops, sortKey]);
2300
+ useEffect5(() => {
2301
+ const loadData = async () => {
2302
+ if (!(loadCondition && loadFunc)) return;
2303
+ if (lazyLoad && minChars > 0 && !showListOnFocus && (!value || String(value).length < minChars)) {
2304
+ return;
2305
+ }
2306
+ const key = cacheKey ? `${cacheKey}${filter ? `:${filterField}:${filter}` : ""}` : null;
2307
+ if (key && cacheStore.has(key)) {
2308
+ const cacheEntry = cacheStore.get(key);
2309
+ const data = cacheEntry.promise ? await cacheEntry.promise : cacheEntry.data || cacheEntry;
2310
+ setListItem(data);
2311
+ setOptions(data);
2312
+ triggerOnLoad(data);
2313
+ return;
2314
+ }
2315
+ setLoading(true);
2316
+ try {
2317
+ const requestPromise = loadFunc().then((res) => {
2318
+ let newOps = (res == null ? void 0 : res.content) || res;
2319
+ newOps = Array.isArray(newOps) ? newOps.filter((op) => op != null) : [];
2320
+ if (filter && filterField) {
2321
+ newOps = newOps.filter((op) => op[filterField] === filter);
2322
+ }
2323
+ return sortOptions(newOps, sortKey);
2324
+ });
2325
+ if (key) cacheStore.set(key, { promise: requestPromise });
2326
+ const sortedOptions = await requestPromise;
2327
+ setListItem(sortedOptions);
2328
+ setOptions(sortedOptions);
2329
+ if (key) cacheStore.set(key, { data: sortedOptions });
2330
+ triggerOnLoad(sortedOptions);
2331
+ } catch (error) {
2332
+ if (key) cacheStore.delete(key);
2333
+ setListItem([]);
2334
+ } finally {
2335
+ setLoading(false);
2336
+ }
2337
+ };
2338
+ loadData();
2339
+ }, [loadCondition, filter, filterField, sortKey, cacheKey, lazyLoad, minChars, showListOnFocus]);
2340
+ const triggerOnLoad = (data) => {
2341
+ if (onLoad && !onLoaded) {
2342
+ setOnLoaded(true);
2343
+ onLoad(data);
2344
+ }
2345
+ };
2346
+ const keysJoinner = (li) => {
2347
+ if (!displayKeys || !Array.isArray(displayKeys)) return "";
2348
+ return displayKeys.map((key) => `${li[key]} `).join("").trim();
2349
+ };
2350
+ const getDisplayText = (item) => {
2351
+ if (formatationFunc) return formatationFunc(item);
2352
+ if (displayKey) return item[displayKey];
2353
+ if (displayKeys) return keysJoinner(item);
2354
+ return String(item);
2355
+ };
2356
+ const onFieldUpdate = (val) => {
2357
+ const search = val.toLowerCase();
2358
+ const canSearch = search.length >= minChars;
2359
+ if (canSearch && Array.isArray(options)) {
2360
+ const filtered = options.filter((item) => {
2361
+ const text = getDisplayText(item);
2362
+ return String(text).toLowerCase().includes(search);
2363
+ });
2364
+ setListItem(filtered);
2365
+ } else {
2366
+ setListItem(options || []);
2367
+ }
2368
+ onValueChanged == null ? void 0 : onValueChanged(val);
2369
+ setInput(val);
2370
+ setHide(!canSearch && options.length === 0);
2371
+ };
2372
+ return /* @__PURE__ */ jsxs24(
2373
+ "div",
2374
+ {
2375
+ className,
2376
+ style: { marginTop: margT != null ? margT : 4, marginBottom: margB != null ? margB : 4, position: "relative" },
2377
+ onBlur: (e) => {
2378
+ setTimeout(() => {
2379
+ onBlurEvent == null ? void 0 : onBlurEvent(e, input);
2380
+ setHide(true);
2381
+ }, 200);
2382
+ },
2383
+ onKeyDown: (e) => {
2384
+ if (e.key === "Escape") {
2385
+ setHide(true);
2386
+ onEscKeyDown == null ? void 0 : onEscKeyDown();
2387
+ }
2388
+ if (e.key === "Enter" && onEnterKeyDown) {
2389
+ onEnterKeyDown(input);
2390
+ }
2391
+ },
2392
+ onMouseLeave: () => setHide(true),
2393
+ children: [
2394
+ !hideComponent && /* @__PURE__ */ jsxs24(Fragment10, { children: [
2395
+ labelPosition === "top" && title && /* @__PURE__ */ jsx32(Form8.Label, { className: "fw-semibold small mb-1", children: title }),
2396
+ /* @__PURE__ */ jsxs24(InputGroup3, { children: [
2397
+ labelPosition === "floating" ? /* @__PURE__ */ jsx32(FloatingLabel, { controlId: "floatingInput", label: title, style: { zIndex: 0, flex: 1 }, children: /* @__PURE__ */ jsx32(
2398
+ Form8.Control,
2399
+ {
2400
+ autoFocus: autoFocusConfig,
2401
+ disabled: disableComponent || disableSelect,
2402
+ placeholder: placeH,
2403
+ autoComplete: "off",
2404
+ value: input,
2405
+ onClickCapture: () => {
2406
+ const canOpen = showListOnFocus && input.length >= minChars;
2407
+ setHide(!canOpen);
2408
+ },
2409
+ onChange: (e) => onFieldUpdate(e.currentTarget.value),
2410
+ type: "text"
2411
+ }
2412
+ ) }) : /* @__PURE__ */ jsx32(
2413
+ Form8.Control,
2414
+ {
2415
+ autoFocus: autoFocusConfig,
2416
+ disabled: disableComponent || disableSelect,
2417
+ placeholder: placeH || title,
2418
+ autoComplete: "off",
2419
+ value: input,
2420
+ onClickCapture: () => {
2421
+ const canOpen = showListOnFocus && input.length >= minChars;
2422
+ setHide(!canOpen);
2423
+ },
2424
+ onChange: (e) => onFieldUpdate(e.currentTarget.value),
2425
+ type: "text"
2426
+ }
2427
+ ),
2428
+ loading && /* @__PURE__ */ jsx32(InputGroup3.Text, { children: /* @__PURE__ */ jsx32(Spinner5, { animation: "border", size: "sm" }) }),
2429
+ !disableComponent && (actionButton == null ? void 0 : actionButton(() => setInput(""))),
2430
+ !disableComponent && (actionButton2 == null ? void 0 : actionButton2(input))
2431
+ ] })
2432
+ ] }),
2433
+ /* @__PURE__ */ jsx32(
2434
+ ListGroup2,
2435
+ {
2436
+ className: "listgroup-autocomplete shadow-sm",
2437
+ hidden: hide || liItem.length === 0,
2438
+ style: {
2439
+ position: "absolute",
2440
+ top: "100%",
2441
+ left: 0,
2442
+ width: "100%",
2443
+ maxHeight: "250px",
2444
+ overflowY: "auto",
2445
+ zIndex: 1050,
2446
+ backgroundColor: "#fff"
2447
+ },
2448
+ children: (maxItems ? liItem.slice(0, maxItems) : liItem).map((li, index) => /* @__PURE__ */ jsx32(
2449
+ ListGroup2.Item,
2450
+ {
2451
+ action: true,
2452
+ onClick: () => {
2453
+ const text = getDisplayText(li);
2454
+ setInput(text);
2455
+ onSelectedClick(li, index, liItem);
2456
+ setHide(true);
2457
+ },
2458
+ children: getDisplayText(li)
2459
+ },
2460
+ index
2461
+ ))
2462
+ }
2463
+ )
2464
+ ]
2465
+ }
2466
+ );
2467
+ };
2468
+
2469
+ // src/forms/GenericForm.tsx
2470
+ import { useState as useState14 } from "react";
2471
+ import { Button as Button14, Form as Form9 } from "react-bootstrap";
2472
+ import { jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
2473
+ var GenericForm = ({ fields, onSubmit, renderCustomSelect }) => {
2474
+ const [formValues, setFormValues] = useState14({});
2475
+ const [errors, setErrors] = useState14({});
2476
+ const handleChange = (key, value) => {
2477
+ setFormValues({
2478
+ ...formValues,
2479
+ [key]: value
2480
+ });
2481
+ };
2482
+ const validate = () => {
2483
+ const newErrors = {};
2484
+ fields.forEach((field) => {
2485
+ if (field.required && !formValues[field.key]) {
2486
+ newErrors[field.key] = `${field.label} \xE9 obrigat\xF3rio`;
2487
+ }
2488
+ });
2489
+ setErrors(newErrors);
2490
+ return Object.keys(newErrors).length === 0;
2491
+ };
2492
+ const handleSubmit = (e) => {
2493
+ e.preventDefault();
2494
+ if (validate()) {
2495
+ onSubmit(formValues);
2496
+ }
2497
+ };
2498
+ const renderField = (field) => {
2499
+ const { label, key, type, options, placeholder } = field;
2500
+ const value = formValues[key] || "";
2501
+ switch (type) {
2502
+ case "text":
2503
+ case "number":
2504
+ return /* @__PURE__ */ jsxs25(Form9.Group, { className: "mb-3", children: [
2505
+ /* @__PURE__ */ jsx33(Form9.Label, { children: label }),
2506
+ /* @__PURE__ */ jsx33(
2507
+ Form9.Control,
2508
+ {
2509
+ type,
2510
+ placeholder,
2511
+ value,
2512
+ onChange: (e) => handleChange(key, e.target.value),
2513
+ isInvalid: !!errors[key]
2514
+ }
2515
+ ),
2516
+ /* @__PURE__ */ jsx33(Form9.Control.Feedback, { type: "invalid", children: errors[key] })
2517
+ ] }, key);
2518
+ case "select": {
2519
+ const orderedOptions = (options || []).filter((opt) => opt && opt.value !== void 0 && opt.label !== void 0).sort((a, b) => a.label.localeCompare(b.label));
2520
+ return /* @__PURE__ */ jsxs25(Form9.Group, { className: "mb-3", children: [
2521
+ /* @__PURE__ */ jsx33(Form9.Label, { children: label }),
2522
+ /* @__PURE__ */ jsxs25(
2523
+ Form9.Select,
2524
+ {
2525
+ value,
2526
+ onChange: (e) => handleChange(key, e.target.value),
2527
+ isInvalid: !!errors[key],
2528
+ children: [
2529
+ /* @__PURE__ */ jsx33("option", { value: "", children: "Selecione..." }),
2530
+ orderedOptions.map((option) => /* @__PURE__ */ jsx33("option", { value: option.value, children: option.label }, String(option.value)))
2531
+ ]
2532
+ }
2533
+ ),
2534
+ /* @__PURE__ */ jsx33(Form9.Control.Feedback, { type: "invalid", children: errors[key] })
2535
+ ] }, key);
2536
+ }
2537
+ case "custom-select":
2538
+ if (renderCustomSelect) {
2539
+ return /* @__PURE__ */ jsxs25("div", { children: [
2540
+ renderCustomSelect({
2541
+ label,
2542
+ value,
2543
+ options,
2544
+ onChange: (v) => handleChange(key, v),
2545
+ placeholder
2546
+ }),
2547
+ errors[key] && /* @__PURE__ */ jsx33("div", { className: "invalid-feedback d-block", children: errors[key] })
2548
+ ] }, key);
2549
+ }
2550
+ return null;
2551
+ case "date":
2552
+ return /* @__PURE__ */ jsxs25(Form9.Group, { className: "mb-3", children: [
2553
+ /* @__PURE__ */ jsx33(Form9.Label, { children: label }),
2554
+ /* @__PURE__ */ jsx33(
2555
+ Form9.Control,
2556
+ {
2557
+ type: "date",
2558
+ value,
2559
+ onChange: (e) => handleChange(key, e.target.value),
2560
+ isInvalid: !!errors[key]
2561
+ }
2562
+ ),
2563
+ /* @__PURE__ */ jsx33(Form9.Control.Feedback, { type: "invalid", children: errors[key] })
2564
+ ] }, key);
2565
+ default:
2566
+ return null;
2567
+ }
2568
+ };
2569
+ return /* @__PURE__ */ jsxs25(Form9, { onSubmit: handleSubmit, children: [
2570
+ fields.map((field) => renderField(field)),
2571
+ /* @__PURE__ */ jsx33("div", { className: "d-grid", children: /* @__PURE__ */ jsx33(Button14, { variant: "primary", type: "submit", children: "Salvar" }) })
2572
+ ] });
2573
+ };
2574
+ var GenericForm_default = GenericForm;
2575
+
2576
+ // src/forms/GenericSelect.tsx
2577
+ import { useEffect as useEffect6, useState as useState15 } from "react";
2578
+ import { Form as Form10, InputGroup as InputGroup4 } from "react-bootstrap";
2579
+ import { Fragment as Fragment11, jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
2580
+ var GenericSelectOps = class {
2581
+ constructor(noLabel, title, onChange, ops, selection, returnType, displayType, filter, filterField, valueType, loadFunc, loadCondition, actionClick, locked) {
2582
+ this.noLabel = noLabel;
2583
+ this.title = title;
2584
+ this.onChange = onChange;
2585
+ this.ops = ops;
2586
+ this.selection = selection;
2587
+ this.returnType = returnType;
2588
+ this.displayType = displayType;
2589
+ this.filter = filter;
2590
+ this.filterField = filterField;
2591
+ this.valueType = valueType;
2592
+ this.loadFunc = loadFunc;
2593
+ this.loadCondition = loadCondition;
2594
+ this.actionClick = actionClick;
2595
+ this.locked = locked;
2596
+ }
2597
+ };
2598
+ var GenericSelect = ({
2599
+ noLabel,
2600
+ title,
2601
+ onChange,
2602
+ ops,
2603
+ selection,
2604
+ returnType,
2605
+ displayType,
2606
+ filter,
2607
+ filterField,
2608
+ valueType,
2609
+ loadFunc,
2610
+ loadCondition = true,
2611
+ actionClick,
2612
+ locked,
2613
+ isBold,
2614
+ ...restProps
2615
+ }) => {
2616
+ const [options, setOptions] = useState15(ops || []);
2617
+ useEffect6(() => {
2618
+ const loadFunction = async () => {
2619
+ if (loadCondition && loadFunc) {
2620
+ loadFunc().then((res) => {
2621
+ let newOps = res.content ? res.content : res;
2622
+ if (filter && filterField) {
2623
+ newOps = res.filter((op) => op[filterField] == filter);
2624
+ }
2625
+ setOptions(newOps);
2626
+ });
2627
+ }
2628
+ };
2629
+ loadFunction().catch((error) => console.log(error));
2630
+ }, [loadCondition]);
2631
+ const getTrueValue = (clickedIndex) => {
2632
+ const returnValue = options.filter((_op, index) => index == clickedIndex - 1)[0];
2633
+ if (returnType == "index") {
2634
+ onChange(clickedIndex);
2635
+ } else if (returnType) {
2636
+ onChange(returnValue[returnType]);
2637
+ } else {
2638
+ onChange(returnValue);
2639
+ }
2640
+ };
2641
+ const defaultPlaceholder = (restProps == null ? void 0 : restProps.default) || "Seleciona uma Op\xE7\xE3o";
2642
+ const selectContent = /* @__PURE__ */ jsxs26(
2643
+ Form10.Control,
2644
+ {
2645
+ disabled: locked,
2646
+ as: "select",
2647
+ value: selection,
2648
+ onChange: (event) => getTrueValue(event.target.selectedIndex),
2649
+ children: [
2650
+ /* @__PURE__ */ jsxs26("option", { value: void 0, children: [
2651
+ "-- ",
2652
+ defaultPlaceholder,
2653
+ " --"
2654
+ ] }, 0),
2655
+ (options == null ? void 0 : options.length) > 0 && options.map((op, index) => {
2656
+ const val = valueType && op[valueType] || op.id || op;
2657
+ let fill = displayType && op[displayType] || op;
2658
+ if (typeof fill == "object") fill = "";
2659
+ return /* @__PURE__ */ jsx34("option", { value: val, children: fill }, op.id || index);
2660
+ })
2661
+ ]
2662
+ }
2663
+ );
2664
+ if (actionClick) {
2665
+ return /* @__PURE__ */ jsxs26(Fragment11, { children: [
2666
+ /* @__PURE__ */ jsx34(Form10.Label, { style: { fontWeight: isBold ? "bold" : void 0 }, hidden: noLabel, children: title }),
2667
+ /* @__PURE__ */ jsxs26(InputGroup4, { children: [
2668
+ selectContent,
2669
+ actionClick()
2670
+ ] })
2671
+ ] });
2672
+ }
2673
+ return /* @__PURE__ */ jsxs26(Fragment11, { children: [
2674
+ /* @__PURE__ */ jsx34(Form10.Label, { style: { fontWeight: isBold ? "bold" : void 0 }, hidden: noLabel, children: title }),
2675
+ selectContent
2676
+ ] });
2677
+ };
2678
+ var GenericSelect_default = GenericSelect;
2679
+
2680
+ // src/forms/FormField.tsx
2681
+ import { FloatingLabel as FloatingLabel2, Form as Form11, InputGroup as InputGroup5 } from "react-bootstrap";
2682
+ import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2683
+ var FormField = ({
2684
+ val,
2685
+ onValueUpdate,
2686
+ onBlur,
2687
+ label,
2688
+ labelPosition = "top",
2689
+ ty,
2690
+ actionClick,
2691
+ actionClick2,
2692
+ reference,
2693
+ others,
2694
+ styleObj,
2695
+ locked,
2696
+ hide,
2697
+ onMouseLv,
2698
+ onEnterPress,
2699
+ className,
2700
+ isInvalid,
2701
+ feedback,
2702
+ onFocus,
2703
+ rows,
2704
+ asTextArea,
2705
+ controlId
2706
+ }) => {
2707
+ const onKeyDownHandler = (event) => {
2708
+ if (event.code === "Enter" || event.key === "Enter") {
2709
+ onEnterPress && onEnterPress(event.target.value);
2710
+ }
2711
+ };
2712
+ const onFocusHandler = (value) => {
2713
+ onFocus && onFocus(value);
2714
+ };
2715
+ const renderField = () => {
2716
+ const fieldProps = {
2717
+ autoComplete: "off",
2718
+ isInvalid,
2719
+ className,
2720
+ ...others,
2721
+ onBlur: (event) => onBlur && onBlur(event.target.value, event),
2722
+ disabled: locked,
2723
+ style: styleObj,
2724
+ ref: reference,
2725
+ placeholder: (others == null ? void 0 : others.placeholder) || label,
2726
+ type: ty || "text",
2727
+ value: val != null ? val : "",
2728
+ onChange: (event) => onValueUpdate && onValueUpdate(event.target.value, event)
2729
+ };
2730
+ if (asTextArea) {
2731
+ fieldProps.as = "textarea";
2732
+ fieldProps.rows = rows || 3;
2733
+ }
2734
+ return /* @__PURE__ */ jsx35(Form11.Control, { ...fieldProps });
2735
+ };
2736
+ if (hide) return null;
2737
+ const useFloating = labelPosition === "floating" && !asTextArea;
2738
+ return /* @__PURE__ */ jsxs27(
2739
+ Form11.Group,
2740
+ {
2741
+ onFocusCapture: (e) => onFocusHandler(e.target.value),
2742
+ onMouseLeave: onMouseLv,
2743
+ onKeyDown: onKeyDownHandler,
2744
+ style: { marginTop: 4, marginBottom: 4, width: "100%" },
2745
+ controlId: !useFloating ? controlId : void 0,
2746
+ children: [
2747
+ !useFloating && label && /* @__PURE__ */ jsx35(Form11.Label, { className: "fw-semibold small mb-1", children: label }),
2748
+ /* @__PURE__ */ jsxs27(InputGroup5, { children: [
2749
+ useFloating ? /* @__PURE__ */ jsx35(FloatingLabel2, { style: { zIndex: 0, flex: 1 }, label, controlId: controlId || "floatingInput", children: renderField() }) : renderField(),
2750
+ actionClick && actionClick(),
2751
+ actionClick2 && actionClick2()
2752
+ ] }),
2753
+ feedback && isInvalid && /* @__PURE__ */ jsx35(Form11.Control.Feedback, { type: "invalid", style: { display: "block" }, children: feedback })
2754
+ ]
2755
+ }
2756
+ );
2757
+ };
2758
+
2759
+ // src/forms/ClickToWriteField.tsx
2760
+ import { useState as useState16, useEffect as useEffect7, useRef as useRef4 } from "react";
2761
+ import { Button as Button15 } from "react-bootstrap";
2762
+ import { jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
2763
+ var ClickToWriteField = ({
2764
+ buttonDisplay,
2765
+ fieldType = "text",
2766
+ fieldLabel = "",
2767
+ buttonProps,
2768
+ fieldProps,
2769
+ onFieldValueUpdate,
2770
+ enableFieldActionButton = false,
2771
+ fieldActionButtonIcon,
2772
+ fieldActionButtonProps,
2773
+ fieldActionButtonCallback = () => {
2774
+ },
2775
+ onEnterPress,
2776
+ cleanRef
2777
+ }) => {
2778
+ const [showClick, setShowClick] = useState16(false);
2779
+ const inputRef = useRef4(null);
2780
+ useEffect7(() => {
2781
+ if (showClick) {
2782
+ setTimeout(() => {
2783
+ if (inputRef.current) {
2784
+ inputRef.current.focus();
2785
+ cleanRef && cleanRef(inputRef);
2786
+ }
2787
+ }, 100);
2788
+ }
2789
+ }, [showClick, cleanRef]);
2790
+ const handleShowClick = () => {
2791
+ setShowClick(!showClick);
2792
+ };
2793
+ const resolveButtonDisplay = () => {
2794
+ if (typeof buttonDisplay === "function") return buttonDisplay();
2795
+ return buttonDisplay;
2796
+ };
2797
+ const renderFieldActionButtonIcon = () => {
2798
+ if (fieldActionButtonIcon) return fieldActionButtonIcon();
2799
+ return "OK";
2800
+ };
2801
+ const closeOnEscape = (e) => {
2802
+ if (e.key === "Escape") {
2803
+ setShowClick(false);
2804
+ }
2805
+ if (e.key === "Enter" && onEnterPress) {
2806
+ onEnterPress(inputRef);
2807
+ }
2808
+ };
2809
+ return /* @__PURE__ */ jsxs28("div", { style: { display: "flex", width: "100%", margin: 0, padding: 0 }, children: [
2810
+ !showClick && /* @__PURE__ */ jsx36(
2811
+ Button15,
2812
+ {
2813
+ style: { flexGrow: 1 },
2814
+ onClick: handleShowClick,
2815
+ ...buttonProps,
2816
+ children: resolveButtonDisplay()
2817
+ }
2818
+ ),
2819
+ showClick && /* @__PURE__ */ jsx36(
2820
+ FormField,
2821
+ {
2822
+ reference: inputRef,
2823
+ others: { ...fieldProps, onKeyUp: closeOnEscape },
2824
+ hide: !showClick,
2825
+ ty: fieldType,
2826
+ label: fieldLabel,
2827
+ onValueUpdate: onFieldValueUpdate,
2828
+ onBlur: () => setShowClick(false),
2829
+ actionClick: () => enableFieldActionButton ? /* @__PURE__ */ jsx36(
2830
+ Button15,
2831
+ {
2832
+ ...fieldActionButtonProps,
2833
+ onClick: () => fieldActionButtonCallback(inputRef),
2834
+ children: renderFieldActionButtonIcon()
2835
+ }
2836
+ ) : null
2837
+ }
2838
+ )
2839
+ ] });
2840
+ };
2841
+
2842
+ // src/forms/ColorPicker.tsx
2843
+ import { Card as Card5, Form as Form12, Row as Row5, Col as Col5 } from "react-bootstrap";
2844
+ import { FaPalette } from "react-icons/fa";
2845
+ import { jsx as jsx37, jsxs as jsxs29 } from "react/jsx-runtime";
2846
+ var ColorPicker = ({
2847
+ selectedColor,
2848
+ onColorChange,
2849
+ defaultColor,
2850
+ setCor,
2851
+ presetColors = ["#ff0000", "#ffd700", "#008000", "#0000ff", "#800080"],
2852
+ title = "Cor de Identifica\xE7\xE3o"
2853
+ }) => {
2854
+ var _a, _b;
2855
+ const safeSelectedColor = (_b = (_a = selectedColor != null ? selectedColor : defaultColor) != null ? _a : presetColors[0]) != null ? _b : "#000000";
2856
+ const handleColorChange = (color) => {
2857
+ onColorChange == null ? void 0 : onColorChange(color);
2858
+ setCor == null ? void 0 : setCor(color);
2859
+ };
2860
+ return /* @__PURE__ */ jsxs29(
2861
+ Card5,
2862
+ {
2863
+ className: "shadow-sm border-primary-hover mb-3",
2864
+ style: { maxWidth: "320px", transition: "0.3s" },
2865
+ children: [
2866
+ /* @__PURE__ */ jsxs29(Card5.Header, { className: "bg-light d-flex align-items-center", children: [
2867
+ /* @__PURE__ */ jsx37(FaPalette, { className: "me-2 text-primary" }),
2868
+ /* @__PURE__ */ jsx37("span", { className: "fw-medium", children: title })
2869
+ ] }),
2870
+ /* @__PURE__ */ jsxs29(Card5.Body, { children: [
2871
+ /* @__PURE__ */ jsxs29(Row5, { className: "g-3 align-items-center mb-3", children: [
2872
+ /* @__PURE__ */ jsx37(Col5, { xs: "auto", children: /* @__PURE__ */ jsx37(
2873
+ "div",
2874
+ {
2875
+ className: "rounded-circle shadow-sm border",
2876
+ style: {
2877
+ width: "40px",
2878
+ height: "40px",
2879
+ backgroundColor: safeSelectedColor,
2880
+ cursor: "pointer",
2881
+ border: "2px solid #dee2e6"
2882
+ },
2883
+ onClick: () => {
2884
+ const el = document.getElementById("color-input-hidden");
2885
+ if (el) el.click();
2886
+ },
2887
+ title: "Clique para abrir o seletor"
2888
+ }
2889
+ ) }),
2890
+ /* @__PURE__ */ jsx37(Col5, { children: /* @__PURE__ */ jsx37(
2891
+ Form12.Control,
2892
+ {
2893
+ type: "color",
2894
+ id: "color-input-hidden",
2895
+ value: safeSelectedColor,
2896
+ onChange: (e) => handleColorChange(e.target.value),
2897
+ className: "form-control-color-lg",
2898
+ style: { width: "100%", height: "40px", cursor: "pointer" }
2899
+ }
2900
+ ) })
2901
+ ] }),
2902
+ /* @__PURE__ */ jsx37(Row5, { className: "g-2 justify-content-start", children: presetColors.map((cor) => /* @__PURE__ */ jsx37(Col5, { xs: "auto", children: /* @__PURE__ */ jsx37(
2903
+ "div",
2904
+ {
2905
+ className: "rounded-1 shadow-sm",
2906
+ style: {
2907
+ width: "28px",
2908
+ height: "28px",
2909
+ backgroundColor: cor,
2910
+ cursor: "pointer",
2911
+ border: cor.toLowerCase() === safeSelectedColor.toLowerCase() ? "2px solid #0d6efd" : "1px solid #dee2e6"
2912
+ },
2913
+ onClick: () => handleColorChange(cor)
2914
+ }
2915
+ ) }, cor)) })
2916
+ ] })
2917
+ ]
2918
+ }
2919
+ );
2920
+ };
2921
+
2922
+ // src/forms/Switch.tsx
2923
+ import { Form as Form13 } from "react-bootstrap";
2924
+ import { jsx as jsx38 } from "react/jsx-runtime";
2925
+ var Switch = ({
2926
+ label,
2927
+ onSwitchChange,
2928
+ value,
2929
+ disabled = false,
2930
+ defaultChecked,
2931
+ ...props
2932
+ }) => {
2933
+ return /* @__PURE__ */ jsx38(
2934
+ Form13.Check,
2935
+ {
2936
+ ...props,
2937
+ disabled,
2938
+ type: "switch",
2939
+ label,
2940
+ checked: value,
2941
+ defaultChecked,
2942
+ onChange: (event) => onSwitchChange && onSwitchChange(event.target.checked)
2943
+ }
2944
+ );
2945
+ };
2946
+
2947
+ // src/forms/UploadArea.tsx
2948
+ import { useCallback as useCallback2 } from "react";
2949
+ import { useDropzone } from "react-dropzone";
2950
+ import { FiUploadCloud, FiCheckCircle } from "react-icons/fi";
2951
+ import { Fragment as Fragment12, jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
2952
+ var UploadArea = ({
2953
+ onFilePut,
2954
+ anexo,
2955
+ accept = { "image/jpeg": [], "image/png": [] },
2956
+ maxSize = 50 * 1024 * 1024
2957
+ }) => {
2958
+ const onDrop = useCallback2(
2959
+ (acceptedFiles) => {
2960
+ const file = acceptedFiles[0];
2961
+ if (file && typeof onFilePut === "function") {
2962
+ onFilePut(file);
2963
+ }
2964
+ },
2965
+ [onFilePut]
2966
+ );
2967
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
2968
+ onDrop,
2969
+ maxSize,
2970
+ accept
2971
+ });
2972
+ const hasAnexo = Boolean(anexo);
2973
+ return /* @__PURE__ */ jsxs30(
2974
+ "div",
2975
+ {
2976
+ ...getRootProps(),
2977
+ className: `upload-area
2978
+ ${isDragActive ? "drag-active" : ""}
2979
+ ${hasAnexo ? "upload-has-file" : ""}
2980
+ `,
2981
+ children: [
2982
+ /* @__PURE__ */ jsx39("input", { ...getInputProps() }),
2983
+ /* @__PURE__ */ jsxs30("div", { className: "upload-content", children: [
2984
+ /* @__PURE__ */ jsx39("span", { className: "upload-icon", children: hasAnexo ? /* @__PURE__ */ jsx39(FiCheckCircle, { size: 24 }) : /* @__PURE__ */ jsx39(FiUploadCloud, { size: 24 }) }),
2985
+ hasAnexo ? /* @__PURE__ */ jsxs30(Fragment12, { children: [
2986
+ /* @__PURE__ */ jsx39("p", { className: "upload-link", children: "Arquivo anexado" }),
2987
+ /* @__PURE__ */ jsx39("p", { className: "upload-info", children: anexo == null ? void 0 : anexo.name })
2988
+ ] }) : /* @__PURE__ */ jsxs30(Fragment12, { children: [
2989
+ /* @__PURE__ */ jsxs30("p", { children: [
2990
+ /* @__PURE__ */ jsx39("span", { className: "upload-link", children: "Adicione" }),
2991
+ " ou arraste arquivos aqui"
2992
+ ] }),
2993
+ /* @__PURE__ */ jsxs30("p", { className: "upload-info", children: [
2994
+ "Formatos aceitos: ",
2995
+ /* @__PURE__ */ jsx39("b", { children: Object.keys(accept).map((t) => t.split("/")[1].toUpperCase()).join(", ") }),
2996
+ " | Tamanho m\xE1ximo:",
2997
+ " ",
2998
+ /* @__PURE__ */ jsxs30("b", { children: [
2999
+ (maxSize / (1024 * 1024)).toFixed(0),
3000
+ "MB"
3001
+ ] })
3002
+ ] })
3003
+ ] })
3004
+ ] })
3005
+ ]
3006
+ }
3007
+ );
3008
+ };
3009
+
3010
+ // src/index.ts
3011
+ import {
3012
+ AnexoManager
3013
+ } from "@teraprox/ui-kit-core";
3014
+
3015
+ // src/forms/FindRecursoByTagField.tsx
3016
+ import {
3017
+ FindRecursoByTagField,
3018
+ FindRecursoByTagField as FindRecursoByTagField2
3019
+ } from "@teraprox/ui-kit-sgm";
3020
+
3021
+ // src/forms/SectorSelector.tsx
3022
+ import { useState as useState17, useEffect as useEffect8 } from "react";
3023
+ import { Form as Form14 } from "react-bootstrap";
3024
+ import { BsChevronDown, BsChevronUp } from "react-icons/bs";
3025
+ import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
3026
+ var SectorSelector = ({
3027
+ setores,
3028
+ onSectorSelect,
3029
+ selectionLabel = "Selecione o Setor",
3030
+ selectionPlaceholder = "Selecione o setor",
3031
+ hideComponent = false,
3032
+ defaultSectorName = false,
3033
+ allowAll = false
3034
+ }) => {
3035
+ const [expanded, setExpanded] = useState17(false);
3036
+ const [selectedSector, setSelectedSector] = useState17(null);
3037
+ useEffect8(() => {
3038
+ if (defaultSectorName && setores.length > 0) {
3039
+ const setor = setores.find((s) => s.nome === defaultSectorName);
3040
+ if (setor && setor.id !== (selectedSector == null ? void 0 : selectedSector.id)) {
3041
+ setSelectedSector(setor);
3042
+ }
3043
+ } else if (!defaultSectorName) {
3044
+ setSelectedSector(null);
3045
+ }
3046
+ }, [defaultSectorName, setores]);
3047
+ const handleSelectSetor = (setor) => {
3048
+ setSelectedSector(setor);
3049
+ onSectorSelect(setor);
3050
+ setExpanded(false);
3051
+ };
3052
+ const toggleExpand = () => {
3053
+ setExpanded(!expanded);
3054
+ };
3055
+ if (hideComponent) return null;
3056
+ const setorOptions = allowAll ? [{ id: "all", nome: "Todos" }, ...setores] : [...setores];
3057
+ return /* @__PURE__ */ jsxs31(Form14.Floating, { className: "sector-selector-floating", children: [
3058
+ /* @__PURE__ */ jsxs31("div", { className: "custom-select-container", onClick: toggleExpand, children: [
3059
+ /* @__PURE__ */ jsx40("span", { className: "selected-sector-label mt-1", children: (selectedSector == null ? void 0 : selectedSector.nome) || selectionPlaceholder }),
3060
+ /* @__PURE__ */ jsx40("div", { className: "zoom-container", children: expanded ? /* @__PURE__ */ jsx40(BsChevronUp, {}) : /* @__PURE__ */ jsx40(BsChevronDown, {}) })
3061
+ ] }),
3062
+ (selectedSector == null ? void 0 : selectedSector.nome) && /* @__PURE__ */ jsx40("label", { htmlFor: "floatingInputCustom", children: selectionLabel }),
3063
+ expanded && /* @__PURE__ */ jsxs31(
3064
+ "div",
3065
+ {
3066
+ className: "custom-dropdown-menu",
3067
+ onMouseLeave: () => setExpanded(false),
3068
+ children: [
3069
+ setorOptions.sort((a, b) => a.nome.localeCompare(b.nome)).map((setor, idx) => /* @__PURE__ */ jsx40(
3070
+ "div",
3071
+ {
3072
+ className: `dropdown-option ${setor.nome === (selectedSector == null ? void 0 : selectedSector.nome) ? "selected-option" : ""}`,
3073
+ onClick: () => handleSelectSetor(setor),
3074
+ children: setor.nome === "default" ? "Nenhum" : setor.nome
3075
+ },
3076
+ idx
3077
+ )),
3078
+ setores.length === 0 && /* @__PURE__ */ jsx40("div", { className: "dropdown-option text-muted italic", children: "Carregando setores..." })
3079
+ ]
3080
+ }
3081
+ )
3082
+ ] });
3083
+ };
3084
+
3085
+ // src/forms/UnidadeMaterialForm.tsx
3086
+ import { Button as Button16 } from "react-bootstrap";
3087
+ import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
3088
+ var UnidadeMaterialForm = ({
3089
+ value,
3090
+ onMaterialSelected,
3091
+ onQuantidadeUpdate,
3092
+ onUnidadeSelected,
3093
+ onNavigateToCreateMaterial,
3094
+ onNavigateToCreateUnidade,
3095
+ loadMaterialsFunc,
3096
+ loadUnidadesFunc,
3097
+ materialLabel = "Materia Prima",
3098
+ hideMaterial = false,
3099
+ hideQuantidade = false,
3100
+ hideUnidade = false,
3101
+ className = ""
3102
+ }) => {
3103
+ var _a, _b, _c;
3104
+ const renderNewMaterialButton = () => /* @__PURE__ */ jsx41(Button16, { onClick: onNavigateToCreateMaterial, size: "sm", variant: "outline-primary", children: "Novo Material" });
3105
+ const renderNewUnidadeButton = () => /* @__PURE__ */ jsx41(Button16, { onClick: onNavigateToCreateUnidade, size: "sm", variant: "outline-primary", children: "Nova Unidade" });
3106
+ return /* @__PURE__ */ jsxs32("div", { className: `unidade-material-form ${className}`, children: [
3107
+ !hideMaterial && /* @__PURE__ */ jsx41(
3108
+ AutoComplete,
3109
+ {
3110
+ displayKey: "nome",
3111
+ value: ((_a = value == null ? void 0 : value.material) == null ? void 0 : _a.nome) || "",
3112
+ loadCondition: true,
3113
+ title: materialLabel,
3114
+ loadFunc: loadMaterialsFunc,
3115
+ onSelectedClick: onMaterialSelected,
3116
+ actionButton: onNavigateToCreateMaterial ? renderNewMaterialButton : void 0
3117
+ }
3118
+ ),
3119
+ !hideQuantidade && /* @__PURE__ */ jsx41(
3120
+ FormField,
3121
+ {
3122
+ label: "Quantidade",
3123
+ val: (_b = value == null ? void 0 : value.quantidade) != null ? _b : "",
3124
+ onValueUpdate: onQuantidadeUpdate,
3125
+ ty: "number"
3126
+ }
3127
+ ),
3128
+ !hideUnidade && /* @__PURE__ */ jsx41(
3129
+ AutoComplete,
3130
+ {
3131
+ displayKey: "nome",
3132
+ value: ((_c = value == null ? void 0 : value.unidade) == null ? void 0 : _c.nome) || "",
3133
+ loadCondition: true,
3134
+ title: "Unidade",
3135
+ loadFunc: loadUnidadesFunc,
3136
+ onSelectedClick: onUnidadeSelected,
3137
+ actionButton: onNavigateToCreateUnidade ? renderNewUnidadeButton : void 0
3138
+ }
3139
+ )
3140
+ ] });
3141
+ };
3142
+
3143
+ // src/icons/IconLabelItem.tsx
3144
+ import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
3145
+ var IconLabelItem = ({
3146
+ icon,
3147
+ label,
3148
+ containerClassName = "",
3149
+ labelClassName = "",
3150
+ onClick,
3151
+ style
3152
+ }) => {
3153
+ return /* @__PURE__ */ jsxs33("div", { className: containerClassName, onClick, style: { ...style, cursor: onClick ? "pointer" : "default" }, children: [
3154
+ icon,
3155
+ /* @__PURE__ */ jsx42("span", { className: labelClassName, children: label })
3156
+ ] });
3157
+ };
3158
+
3159
+ // src/icons/IconLabelList.tsx
3160
+ import { jsx as jsx43 } from "react/jsx-runtime";
3161
+ var IconLabelList = ({ items, className = "" }) => {
3162
+ return /* @__PURE__ */ jsx43("div", { className: `icon-label-list ${className}`, children: items.map((item, index) => /* @__PURE__ */ jsx43(
3163
+ IconLabelItem,
3164
+ {
3165
+ labelClassName: "icon-label",
3166
+ containerClassName: "icon-label-item",
3167
+ icon: item.icon,
3168
+ label: item.label,
3169
+ onClick: item.onClick
3170
+ },
3171
+ index
3172
+ )) });
3173
+ };
3174
+
3175
+ // src/icons/NotificationItem.tsx
3176
+ import { useState as useState18 } from "react";
3177
+ import { Modal as Modal4, Button as Button17, OverlayTrigger, Tooltip as Tooltip3 } from "react-bootstrap";
3178
+ import { FiClock, FiCheck, FiTrash2 as FiTrash23 } from "react-icons/fi";
3179
+ import dayjs5 from "dayjs";
3180
+ import { Fragment as Fragment13, jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
3181
+ var NotificationItem = ({
3182
+ notification,
3183
+ onRead,
3184
+ onDismiss,
3185
+ emptyContentLabel = "Sem conte\xFAdo adicional dispon\xEDvel."
3186
+ }) => {
3187
+ const [showModal, setShowModal] = useState18(false);
3188
+ const { context, contextId, content, status, createdAt, readAt } = notification;
3189
+ const handleOpenModal = (e) => {
3190
+ e.stopPropagation();
3191
+ setShowModal(true);
3192
+ };
3193
+ const handleCloseModal = () => setShowModal(false);
3194
+ const handleReadAndClose = () => {
3195
+ onRead(notification);
3196
+ handleCloseModal();
3197
+ };
3198
+ const handleDismiss = (e) => {
3199
+ e.stopPropagation();
3200
+ onDismiss(notification);
3201
+ };
3202
+ const displayTitle = contextId ? `${context} - ${contextId}` : context || "Notifica\xE7\xE3o";
3203
+ return /* @__PURE__ */ jsxs34(Fragment13, { children: [
3204
+ /* @__PURE__ */ jsxs34(
3205
+ "div",
3206
+ {
3207
+ className: `notification-item-modern ${status === "unread" ? "unread" : ""}`,
3208
+ onClick: handleOpenModal,
3209
+ children: [
3210
+ /* @__PURE__ */ jsx44("div", { className: `notification-status-indicator ${status}`, children: status === "unread" ? /* @__PURE__ */ jsx44(FiClock, { size: 14 }) : /* @__PURE__ */ jsx44(FiCheck, { size: 14 }) }),
3211
+ /* @__PURE__ */ jsxs34("div", { className: "notification-main-content", children: [
3212
+ /* @__PURE__ */ jsx44("div", { className: "notification-header-row", children: /* @__PURE__ */ jsxs34("div", { className: "notification-title-modern", children: [
3213
+ /* @__PURE__ */ jsx44("span", { className: "notification-context", children: context }),
3214
+ contextId && /* @__PURE__ */ jsxs34(Fragment13, { children: [
3215
+ /* @__PURE__ */ jsx44("span", { className: "notification-separator", children: "/" }),
3216
+ /* @__PURE__ */ jsx44("span", { className: "notification-context-id", children: contextId })
3217
+ ] })
3218
+ ] }) }),
3219
+ /* @__PURE__ */ jsx44("div", { className: "notification-preview", children: /* @__PURE__ */ jsx44("p", { className: "notification-content-preview", children: content || "Nova mensagem recebida" }) }),
3220
+ /* @__PURE__ */ jsxs34("div", { className: "notification-meta", children: [
3221
+ /* @__PURE__ */ jsxs34("div", { className: "notification-timestamp", children: [
3222
+ /* @__PURE__ */ jsx44(FiClock, { size: 12, className: "me-1" }),
3223
+ /* @__PURE__ */ jsx44("small", { children: dayjs5(createdAt).format("DD/MM/YYYY HH:mm") })
3224
+ ] }),
3225
+ readAt && /* @__PURE__ */ jsxs34("div", { className: "notification-read-time", children: [
3226
+ /* @__PURE__ */ jsx44(FiCheck, { size: 12, className: "me-1" }),
3227
+ /* @__PURE__ */ jsxs34("small", { children: [
3228
+ "Lida em ",
3229
+ dayjs5(readAt).format("DD/MM HH:mm")
3230
+ ] })
3231
+ ] })
3232
+ ] })
3233
+ ] }),
3234
+ /* @__PURE__ */ jsx44("div", { className: "notification-quick-actions", children: status === "unread" && /* @__PURE__ */ jsx44(
3235
+ OverlayTrigger,
3236
+ {
3237
+ placement: "top",
3238
+ overlay: /* @__PURE__ */ jsx44(Tooltip3, { children: "Descartar" }),
3239
+ children: /* @__PURE__ */ jsx44(
3240
+ "button",
3241
+ {
3242
+ className: "notification-action-btn notification-dismiss-btn",
3243
+ onClick: handleDismiss,
3244
+ "aria-label": "Descartar notifica\xE7\xE3o",
3245
+ children: /* @__PURE__ */ jsx44(FiTrash23, { size: 14 })
3246
+ }
3247
+ )
3248
+ }
3249
+ ) })
3250
+ ]
3251
+ }
3252
+ ),
3253
+ /* @__PURE__ */ jsxs34(
3254
+ Modal4,
3255
+ {
3256
+ show: showModal,
3257
+ onHide: handleCloseModal,
3258
+ centered: true,
3259
+ className: "notification-modal",
3260
+ children: [
3261
+ /* @__PURE__ */ jsx44(Modal4.Header, { closeButton: true, className: "notification-modal-header", children: /* @__PURE__ */ jsx44(Modal4.Title, { className: "notification-modal-title", children: /* @__PURE__ */ jsxs34("div", { className: "d-flex align-items-center", children: [
3262
+ status === "unread" ? /* @__PURE__ */ jsx44(FiClock, { className: "me-2 text-warning" }) : /* @__PURE__ */ jsx44(FiCheck, { className: "me-2 text-success" }),
3263
+ "Detalhes da Notifica\xE7\xE3o"
3264
+ ] }) }) }),
3265
+ /* @__PURE__ */ jsx44(Modal4.Body, { className: "notification-modal-body", children: /* @__PURE__ */ jsxs34("div", { className: "notification-modal-content", children: [
3266
+ /* @__PURE__ */ jsxs34("div", { className: "notification-modal-meta", children: [
3267
+ /* @__PURE__ */ jsx44("h6", { className: "notification-modal-source", children: displayTitle }),
3268
+ /* @__PURE__ */ jsxs34("div", { className: "notification-modal-timestamps", children: [
3269
+ /* @__PURE__ */ jsxs34("small", { className: "text-muted", children: [
3270
+ /* @__PURE__ */ jsx44(FiClock, { size: 12, className: "me-1" }),
3271
+ "Criada em ",
3272
+ dayjs5(createdAt).format("DD/MM/YYYY [\xE0s] HH:mm")
3273
+ ] }),
3274
+ readAt && /* @__PURE__ */ jsxs34("small", { className: "text-muted ms-3", children: [
3275
+ /* @__PURE__ */ jsx44(FiCheck, { size: 12, className: "me-1" }),
3276
+ "Lida em ",
3277
+ dayjs5(readAt).format("DD/MM/YYYY [\xE0s] HH:mm")
3278
+ ] })
3279
+ ] })
3280
+ ] }),
3281
+ /* @__PURE__ */ jsx44("div", { className: "notification-modal-message", children: /* @__PURE__ */ jsx44("p", { className: "mb-0", children: content || emptyContentLabel }) })
3282
+ ] }) }),
3283
+ /* @__PURE__ */ jsxs34(Modal4.Footer, { className: "notification-modal-footer", children: [
3284
+ /* @__PURE__ */ jsx44(Button17, { variant: "outline-secondary", onClick: handleCloseModal, children: "Fechar" }),
3285
+ status === "unread" && /* @__PURE__ */ jsx44(Button17, { variant: "primary", onClick: handleReadAndClose, children: "Marcar como lida" })
3286
+ ] })
3287
+ ]
3288
+ }
3289
+ )
3290
+ ] });
3291
+ };
3292
+
3293
+ // src/icons/NotificationBell.tsx
3294
+ import { Dropdown as Dropdown2, Badge as Badge3 } from "react-bootstrap";
3295
+ import { FiBell } from "react-icons/fi";
3296
+ import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
3297
+ var NotificationBell = ({
3298
+ notifications,
3299
+ onItemRead,
3300
+ onItemDismiss,
3301
+ onMarkAllRead,
3302
+ size = 20,
3303
+ className = ""
3304
+ }) => {
3305
+ const unreadCount = notifications.filter((n) => n.status === "unread").length;
3306
+ return /* @__PURE__ */ jsxs35(Dropdown2, { align: "end", className: `notification-bell-dropdown ${className}`, children: [
3307
+ /* @__PURE__ */ jsxs35(Dropdown2.Toggle, { as: "div", className: "position-relative cursor-pointer p-2", children: [
3308
+ /* @__PURE__ */ jsx45(FiBell, { size }),
3309
+ unreadCount > 0 && /* @__PURE__ */ jsx45(
3310
+ Badge3,
3311
+ {
3312
+ pill: true,
3313
+ bg: "danger",
3314
+ className: "position-absolute",
3315
+ style: { top: 0, right: 0, fontSize: "0.65rem" },
3316
+ children: unreadCount > 99 ? "99+" : unreadCount
3317
+ }
3318
+ )
3319
+ ] }),
3320
+ /* @__PURE__ */ jsxs35(
3321
+ Dropdown2.Menu,
3322
+ {
3323
+ className: "shadow-lg border-0",
3324
+ style: { width: "320px", padding: 0, maxHeight: "500px", overflowY: "auto" },
3325
+ children: [
3326
+ /* @__PURE__ */ jsxs35("div", { className: "p-3 border-bottom d-flex justify-content-between align-items-center bg-light", children: [
3327
+ /* @__PURE__ */ jsx45("h6", { className: "mb-0 fw-bold", children: "Notifica\xE7\xF5es" }),
3328
+ unreadCount > 0 && onMarkAllRead && /* @__PURE__ */ jsx45(
3329
+ "button",
3330
+ {
3331
+ className: "btn btn-link btn-sm p-0 text-decoration-none",
3332
+ onClick: (e) => {
3333
+ e.stopPropagation();
3334
+ onMarkAllRead();
3335
+ },
3336
+ children: "Limpar tudo"
3337
+ }
3338
+ )
3339
+ ] }),
3340
+ /* @__PURE__ */ jsx45("div", { className: "notification-list", children: notifications.length > 0 ? notifications.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()).map((n) => /* @__PURE__ */ jsx45(
3341
+ NotificationItem,
3342
+ {
3343
+ notification: n,
3344
+ onRead: onItemRead,
3345
+ onDismiss: onItemDismiss
3346
+ },
3347
+ n.id
3348
+ )) : /* @__PURE__ */ jsxs35("div", { className: "p-4 text-center text-muted", children: [
3349
+ /* @__PURE__ */ jsx45(FiBell, { size: 24, className: "mb-2 opacity-25" }),
3350
+ /* @__PURE__ */ jsx45("p", { className: "mb-0 small", children: "Nenhuma notifica\xE7\xE3o por aqui." })
3351
+ ] }) }),
3352
+ notifications.length > 0 && /* @__PURE__ */ jsx45("div", { className: "p-2 border-top text-center bg-light", children: /* @__PURE__ */ jsxs35("small", { className: "text-muted", children: [
3353
+ "Total: ",
3354
+ notifications.length,
3355
+ " notifica\xE7\xF5es"
3356
+ ] }) })
3357
+ ]
3358
+ }
3359
+ )
3360
+ ] });
3361
+ };
3362
+
3363
+ // src/modals/ModalBasicTemplate.tsx
3364
+ import { Modal as Modal5, Button as Button18 } from "react-bootstrap";
3365
+ import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
3366
+ var ModalBasicTemplate = ({
3367
+ show,
3368
+ closeFunc,
3369
+ body,
3370
+ header,
3371
+ footer,
3372
+ props = {}
3373
+ }) => {
3374
+ const { bodyStyle, dialogStyle, ...modalProps } = props;
3375
+ const renderPart = (part) => {
3376
+ if (typeof part === "function") return part();
3377
+ return part;
3378
+ };
3379
+ return /* @__PURE__ */ jsxs36(
3380
+ Modal5,
3381
+ {
3382
+ show,
3383
+ onHide: closeFunc,
3384
+ centered: true,
3385
+ style: dialogStyle,
3386
+ ...modalProps,
3387
+ children: [
3388
+ header && /* @__PURE__ */ jsx46(Modal5.Header, { closeButton: true, children: /* @__PURE__ */ jsx46(Modal5.Title, { children: renderPart(header) }) }),
3389
+ /* @__PURE__ */ jsx46(Modal5.Body, { style: bodyStyle, children: renderPart(body) }),
3390
+ footer && /* @__PURE__ */ jsxs36(Modal5.Footer, { children: [
3391
+ renderPart(footer),
3392
+ !footer && /* @__PURE__ */ jsx46(Button18, { variant: "secondary", onClick: closeFunc, children: "Fechar" })
3393
+ ] })
3394
+ ]
3395
+ }
3396
+ );
3397
+ };
3398
+ var ModalBasicTemplate_default = ModalBasicTemplate;
3399
+
3400
+ // src/modals/SelectDateModal.tsx
3401
+ import { useState as useState19 } from "react";
3402
+ import { Modal as Modal6, Button as Button19, Form as Form15 } from "react-bootstrap";
3403
+ import dayjs6 from "dayjs";
3404
+ import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
3405
+ var SelectDateModal = ({
3406
+ show,
3407
+ onClose,
3408
+ onSelect,
3409
+ title = "Selecionar Data",
3410
+ label = "Escolha a data",
3411
+ initialDate,
3412
+ allowFuture = true
3413
+ }) => {
3414
+ const [selectedDate, setSelectedDate] = useState19(
3415
+ initialDate || dayjs6().format("YYYY-MM-DDTHH:mm")
3416
+ );
3417
+ const handleConfirm = () => {
3418
+ onSelect(selectedDate);
3419
+ onClose();
3420
+ };
3421
+ return /* @__PURE__ */ jsxs37(Modal6, { show, onHide: onClose, centered: true, size: "sm", children: [
3422
+ /* @__PURE__ */ jsx47(Modal6.Header, { closeButton: true, children: /* @__PURE__ */ jsx47(Modal6.Title, { children: title }) }),
3423
+ /* @__PURE__ */ jsx47(Modal6.Body, { children: /* @__PURE__ */ jsxs37(Form15.Group, { children: [
3424
+ /* @__PURE__ */ jsx47(Form15.Label, { children: label }),
3425
+ /* @__PURE__ */ jsx47(
3426
+ Form15.Control,
3427
+ {
3428
+ type: "datetime-local",
3429
+ value: selectedDate,
3430
+ max: allowFuture ? void 0 : dayjs6().format("YYYY-MM-DDTHH:mm"),
3431
+ onChange: (e) => setSelectedDate(e.target.value)
3432
+ }
3433
+ )
3434
+ ] }) }),
3435
+ /* @__PURE__ */ jsxs37(Modal6.Footer, { children: [
3436
+ /* @__PURE__ */ jsx47(Button19, { variant: "outline-secondary", onClick: onClose, children: "Cancelar" }),
3437
+ /* @__PURE__ */ jsx47(Button19, { variant: "primary", onClick: handleConfirm, children: "Confirmar" })
3438
+ ] })
3439
+ ] });
3440
+ };
3441
+
3442
+ // src/modals/JustificativaModal.tsx
3443
+ import { useState as useState20, useEffect as useEffect9 } from "react";
3444
+ import { Modal as Modal7, Button as Button20, Form as Form16, ListGroup as ListGroup3, Badge as Badge4, OverlayTrigger as OverlayTrigger2, Tooltip as Tooltip4 } from "react-bootstrap";
3445
+ import { FaTrashAlt, FaUndo } from "react-icons/fa";
3446
+ import dayjs7 from "dayjs";
3447
+ import { jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
3448
+ var JustificativaModal = ({
3449
+ show,
3450
+ onClose,
3451
+ justificativas: initialJustificativas = [],
3452
+ currentUserId,
3453
+ currentUserName,
3454
+ onUpdateJustificativas
3455
+ }) => {
3456
+ const [localJustificativas, setLocalJustificativas] = useState20(initialJustificativas);
3457
+ const [novaDescricao, setNovaDescricao] = useState20("");
3458
+ const [editandoId, setEditandoId] = useState20(null);
3459
+ useEffect9(() => {
3460
+ setLocalJustificativas(initialJustificativas);
3461
+ }, [initialJustificativas]);
3462
+ const handleAddOrEdit = async () => {
3463
+ if (!novaDescricao.trim()) return;
3464
+ let updatedList = [];
3465
+ if (editandoId) {
3466
+ updatedList = localJustificativas.map(
3467
+ (j) => j.id === editandoId ? { ...j, descricao: novaDescricao } : j
3468
+ );
3469
+ setEditandoId(null);
3470
+ } else {
3471
+ const nova = {
3472
+ id: Math.random().toString(36).substr(2, 9),
3473
+ // Simples ID local se uuid não estiver disp.
3474
+ descricao: novaDescricao,
3475
+ user: { userId: currentUserId, firstName: currentUserName },
3476
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
3477
+ isNew: true
3478
+ };
3479
+ updatedList = [...localJustificativas, nova];
3480
+ }
3481
+ setNovaDescricao("");
3482
+ await onUpdateJustificativas(updatedList);
3483
+ setLocalJustificativas(updatedList);
3484
+ };
3485
+ const handleRemove = async (id) => {
3486
+ const updated = localJustificativas.map((j) => j.id === id ? { ...j, removed: true } : j);
3487
+ await onUpdateJustificativas(updated);
3488
+ setLocalJustificativas(updated);
3489
+ };
3490
+ const handleUndoRemove = async (id) => {
3491
+ const updated = localJustificativas.map((j) => j.id === id ? { ...j, removed: false } : j);
3492
+ await onUpdateJustificativas(updated);
3493
+ setLocalJustificativas(updated);
3494
+ };
3495
+ return /* @__PURE__ */ jsxs38(Modal7, { show, onHide: onClose, centered: true, size: "lg", children: [
3496
+ /* @__PURE__ */ jsx48(Modal7.Header, { closeButton: true, children: /* @__PURE__ */ jsx48(Modal7.Title, { children: "Justificativas / Coment\xE1rios" }) }),
3497
+ /* @__PURE__ */ jsxs38(Modal7.Body, { children: [
3498
+ /* @__PURE__ */ jsxs38(Form16, { className: "mb-4", children: [
3499
+ /* @__PURE__ */ jsxs38(Form16.Group, { controlId: "justificativaInput", className: "mb-2", children: [
3500
+ /* @__PURE__ */ jsx48(Form16.Label, { className: "small text-muted fw-bold", children: "NOVO REGISTRO" }),
3501
+ /* @__PURE__ */ jsx48(
3502
+ Form16.Control,
3503
+ {
3504
+ as: "textarea",
3505
+ rows: 2,
3506
+ value: novaDescricao,
3507
+ onChange: (e) => setNovaDescricao(e.target.value),
3508
+ placeholder: "Descreva o motivo ou informa\xE7\xE3o adicional..."
3509
+ }
3510
+ )
3511
+ ] }),
3512
+ /* @__PURE__ */ jsx48("div", { className: "d-flex justify-content-end", children: /* @__PURE__ */ jsx48(Button20, { variant: "primary", size: "sm", onClick: handleAddOrEdit, children: editandoId ? "Salvar Edi\xE7\xE3o" : "Adicionar Justificativa" }) })
3513
+ ] }),
3514
+ /* @__PURE__ */ jsx48(ListGroup3, { className: "border-0", children: localJustificativas.map((j) => {
3515
+ var _a, _b, _c;
3516
+ const isMe = ((_a = j.user) == null ? void 0 : _a.userId) === currentUserId;
3517
+ return /* @__PURE__ */ jsxs38(
3518
+ ListGroup3.Item,
3519
+ {
3520
+ className: "border-0 px-0",
3521
+ style: {
3522
+ opacity: j.removed ? 0.5 : 1,
3523
+ display: "flex",
3524
+ flexDirection: "column",
3525
+ alignItems: isMe ? "flex-start" : "flex-end",
3526
+ backgroundColor: "transparent"
3527
+ },
3528
+ children: [
3529
+ /* @__PURE__ */ jsxs38("div", { className: "d-flex align-items-center mb-1", style: { width: "100%", justifyContent: isMe ? "flex-start" : "flex-end" }, children: [
3530
+ /* @__PURE__ */ jsx48("span", { className: "small fw-bold text-dark me-2", children: isMe ? "Voc\xEA" : ((_b = j.user) == null ? void 0 : _b.userName) || ((_c = j.user) == null ? void 0 : _c.firstName) || "Usu\xE1rio" }),
3531
+ /* @__PURE__ */ jsx48(Badge4, { bg: "secondary", style: { fontSize: "0.65rem" }, children: dayjs7(j.createdAt).format("DD/MM [\xE0s] HH:mm") })
3532
+ ] }),
3533
+ /* @__PURE__ */ jsx48(
3534
+ "div",
3535
+ {
3536
+ onClick: () => !j.removed && isMe && (setNovaDescricao(j.descricao), setEditandoId(j.id)),
3537
+ style: {
3538
+ maxWidth: "85%",
3539
+ alignSelf: isMe ? "flex-start" : "flex-end",
3540
+ backgroundColor: j.removed ? "#f8d7da" : isMe ? "#e3f2fd" : "#f8f9fa",
3541
+ color: "#333",
3542
+ padding: "12px 16px",
3543
+ borderRadius: "12px",
3544
+ cursor: isMe && !j.removed ? "pointer" : "default",
3545
+ textDecoration: j.removed ? "line-through" : "none",
3546
+ boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
3547
+ border: isMe ? "1px solid #bbdefb" : "1px solid #e0e0e0"
3548
+ },
3549
+ children: j.descricao
3550
+ }
3551
+ ),
3552
+ isMe && /* @__PURE__ */ jsx48("div", { className: "mt-1 d-flex gap-2", children: j.removed ? /* @__PURE__ */ jsx48(OverlayTrigger2, { placement: "top", overlay: /* @__PURE__ */ jsx48(Tooltip4, { children: "Desfazer" }), children: /* @__PURE__ */ jsx48(
3553
+ FaUndo,
3554
+ {
3555
+ onClick: () => handleUndoRemove(j.id),
3556
+ className: "text-success cursor-pointer",
3557
+ size: 14
3558
+ }
3559
+ ) }) : /* @__PURE__ */ jsx48(OverlayTrigger2, { placement: "top", overlay: /* @__PURE__ */ jsx48(Tooltip4, { children: "Remover" }), children: /* @__PURE__ */ jsx48(
3560
+ FaTrashAlt,
3561
+ {
3562
+ onClick: () => handleRemove(j.id),
3563
+ className: "text-danger cursor-pointer",
3564
+ size: 14
3565
+ }
3566
+ ) }) })
3567
+ ]
3568
+ },
3569
+ j.id
3570
+ );
3571
+ }) })
3572
+ ] }),
3573
+ /* @__PURE__ */ jsx48(Modal7.Footer, { children: /* @__PURE__ */ jsx48(Button20, { variant: "outline-secondary", onClick: onClose, children: "Fechar" }) })
3574
+ ] });
3575
+ };
3576
+
3577
+ // src/modals/ImageViewModal.tsx
3578
+ import { useState as useState21, useEffect as useEffect10 } from "react";
3579
+ import { Button as Button21 } from "react-bootstrap";
3580
+ import { jsx as jsx49, jsxs as jsxs39 } from "react/jsx-runtime";
3581
+ var ImageViewModal = ({
3582
+ show,
3583
+ onHide,
3584
+ imagesData = [],
3585
+ initialImageData,
3586
+ imageAltText = "Visualiza\xE7\xE3o de imagem",
3587
+ resolveImageUrl
3588
+ }) => {
3589
+ const [selectedImageKey, setSelectedImageKey] = useState21(null);
3590
+ const [imageSrc, setImageSrc] = useState21(null);
3591
+ const [currentAuthor, setCurrentAuthor] = useState21("Desconhecido");
3592
+ useEffect10(() => {
3593
+ if (show && initialImageData) {
3594
+ setSelectedImageKey(initialImageData.key);
3595
+ setCurrentAuthor(initialImageData.author || "Desconhecido");
3596
+ } else if (show && imagesData.length > 0) {
3597
+ setSelectedImageKey(imagesData[0].key);
3598
+ setCurrentAuthor(imagesData[0].author || "Desconhecido");
3599
+ }
3600
+ }, [show, initialImageData]);
3601
+ useEffect10(() => {
3602
+ if (show && selectedImageKey) {
3603
+ setImageSrc(null);
3604
+ const file = imagesData.find((f) => f.key === selectedImageKey);
3605
+ if (file == null ? void 0 : file.signedUrl) {
3606
+ setImageSrc(file.signedUrl);
3607
+ } else if (resolveImageUrl) {
3608
+ setImageSrc(resolveImageUrl(selectedImageKey));
3609
+ }
3610
+ }
3611
+ }, [show, selectedImageKey]);
3612
+ const renderImageSelector = () => {
3613
+ if (imagesData.length <= 1) return null;
3614
+ return /* @__PURE__ */ jsx49("div", { className: "mb-3 d-flex flex-wrap justify-content-center gap-2", children: imagesData.map((img, idx) => /* @__PURE__ */ jsx49(
3615
+ Button21,
3616
+ {
3617
+ variant: selectedImageKey === img.key ? "primary" : "outline-secondary",
3618
+ size: "sm",
3619
+ onClick: () => {
3620
+ setSelectedImageKey(img.key);
3621
+ setCurrentAuthor(img.author || "Desconhecido");
3622
+ },
3623
+ children: img.dataContext ? `${img.dataContext}-${img.dataId}` : `Imagem ${idx + 1}`
3624
+ },
3625
+ idx
3626
+ )) });
3627
+ };
3628
+ const body = /* @__PURE__ */ jsxs39("div", { className: "text-center", children: [
3629
+ renderImageSelector(),
3630
+ imageSrc ? /* @__PURE__ */ jsx49(
3631
+ "img",
3632
+ {
3633
+ src: imageSrc,
3634
+ alt: imageAltText,
3635
+ className: "img-fluid rounded shadow-sm",
3636
+ style: { maxHeight: "75vh", objectFit: "contain" }
3637
+ }
3638
+ ) : /* @__PURE__ */ jsx49("div", { className: "p-5 text-muted", children: "Aguardando imagem..." })
3639
+ ] });
3640
+ return /* @__PURE__ */ jsx49(
3641
+ ModalBasicTemplate_default,
3642
+ {
3643
+ header: "Visualiza\xE7\xE3o de Imagem",
3644
+ closeFunc: onHide,
3645
+ show,
3646
+ body,
3647
+ props: { size: "lg" },
3648
+ footer: () => /* @__PURE__ */ jsxs39("div", { className: "w-100 d-flex justify-content-between align-items-center", children: [
3649
+ /* @__PURE__ */ jsxs39("small", { className: "text-muted", children: [
3650
+ "Enviado por: ",
3651
+ /* @__PURE__ */ jsx49("strong", { children: currentAuthor })
3652
+ ] }),
3653
+ /* @__PURE__ */ jsx49(Button21, { variant: "outline-secondary", size: "sm", onClick: onHide, children: "Fechar" })
3654
+ ] })
3655
+ }
3656
+ );
3657
+ };
3658
+
3659
+ // src/qr/QrReader.tsx
3660
+ import QrScanner from "qr-scanner";
3661
+ import { useEffect as useEffect11, useRef as useRef5, useState as useState22 } from "react";
3662
+ import { jsx as jsx50, jsxs as jsxs40 } from "react/jsx-runtime";
3663
+ var QrReader = ({ callback }) => {
3664
+ const scanner = useRef5(null);
3665
+ const videoEl = useRef5(null);
3666
+ const qrBoxEl = useRef5(null);
3667
+ const [qrOn, setQrOn] = useState22(true);
3668
+ const [scannedResult, setScannedResult] = useState22("");
3669
+ const onScanSuccess = (result) => {
3670
+ setScannedResult(result.data);
3671
+ callback(result.data);
3672
+ };
3673
+ const onScanFail = (err) => {
3674
+ if (typeof err === "string" && !err.includes("No QR code found")) {
3675
+ console.error("QR Scanner Error:", err);
3676
+ }
3677
+ };
3678
+ useEffect11(() => {
3679
+ if (videoEl.current && !scanner.current) {
3680
+ scanner.current = new QrScanner(videoEl.current, onScanSuccess, {
3681
+ onDecodeError: onScanFail,
3682
+ preferredCamera: "environment",
3683
+ highlightScanRegion: true,
3684
+ highlightCodeOutline: true,
3685
+ overlay: qrBoxEl.current || void 0
3686
+ });
3687
+ scanner.current.start().then(() => setQrOn(true)).catch((err) => {
3688
+ console.error("Failed to start QR Scanner:", err);
3689
+ setQrOn(false);
3690
+ });
3691
+ }
3692
+ return () => {
3693
+ if (scanner.current) {
3694
+ scanner.current.stop();
3695
+ scanner.current.destroy();
3696
+ scanner.current = null;
3697
+ }
3698
+ };
3699
+ }, []);
3700
+ useEffect11(() => {
3701
+ if (!qrOn) {
3702
+ alert(
3703
+ "C\xE2mera est\xE1 bloqueada ou inacess\xEDvel. Por favor, habilite a c\xE2mera nas permiss\xF5es do seu navegador e recarregue a p\xE1gina."
3704
+ );
3705
+ }
3706
+ }, [qrOn]);
3707
+ return /* @__PURE__ */ jsxs40("div", { className: "qr-reader", style: { position: "relative", width: "100%", maxWidth: "500px", margin: "0 auto" }, children: [
3708
+ /* @__PURE__ */ jsx50("video", { ref: videoEl, style: { width: "100%", borderRadius: "8px" } }),
3709
+ /* @__PURE__ */ jsx50("div", { ref: qrBoxEl, className: "qr-box" }),
3710
+ scannedResult && /* @__PURE__ */ jsxs40(
3711
+ "div",
3712
+ {
3713
+ style: {
3714
+ position: "absolute",
3715
+ top: 10,
3716
+ left: 10,
3717
+ zIndex: 10,
3718
+ background: "rgba(0,0,0,0.6)",
3719
+ color: "white",
3720
+ padding: "4px 8px",
3721
+ borderRadius: "4px",
3722
+ fontSize: "0.8rem"
3723
+ },
3724
+ children: [
3725
+ "Lido: ",
3726
+ scannedResult
3727
+ ]
3728
+ }
3729
+ )
3730
+ ] });
3731
+ };
3732
+
3733
+ // src/qr/QrCodeScanButton.tsx
3734
+ import { useState as useState23 } from "react";
3735
+ import { BsQrCode } from "react-icons/bs";
3736
+ import { jsx as jsx51, jsxs as jsxs41 } from "react/jsx-runtime";
3737
+ var QrCodeScanButton = ({ callback, size = 25 }) => {
3738
+ const [showQr, setShowQr] = useState23(false);
3739
+ const toggleQr = () => {
3740
+ setShowQr((prev) => !prev);
3741
+ };
3742
+ return /* @__PURE__ */ jsxs41(
3743
+ "div",
3744
+ {
3745
+ className: "hoverable-div",
3746
+ style: {
3747
+ border: "solid",
3748
+ borderTopRightRadius: "3px",
3749
+ borderBottomRightRadius: "3px",
3750
+ padding: "8px",
3751
+ borderLeft: "none",
3752
+ borderColor: "#ccc",
3753
+ borderWidth: "1px",
3754
+ cursor: "pointer",
3755
+ display: "flex",
3756
+ alignItems: "center"
3757
+ },
3758
+ onClick: toggleQr,
3759
+ children: [
3760
+ /* @__PURE__ */ jsx51(BsQrCode, { size }),
3761
+ showQr && /* @__PURE__ */ jsx51(
3762
+ "div",
3763
+ {
3764
+ style: {
3765
+ position: "fixed",
3766
+ top: 0,
3767
+ left: 0,
3768
+ right: 0,
3769
+ bottom: 0,
3770
+ backgroundColor: "rgba(0,0,0,0.8)",
3771
+ zIndex: 9999,
3772
+ display: "flex",
3773
+ flexDirection: "column",
3774
+ alignItems: "center",
3775
+ justifyContent: "center",
3776
+ padding: "20px"
3777
+ },
3778
+ onClick: (e) => e.stopPropagation(),
3779
+ children: /* @__PURE__ */ jsxs41("div", { style: { width: "100%", maxWidth: "500px", backgroundColor: "#fff", borderRadius: "12px", padding: "20px", position: "relative" }, children: [
3780
+ /* @__PURE__ */ jsx51(
3781
+ "div",
3782
+ {
3783
+ onClick: toggleQr,
3784
+ style: { position: "absolute", top: "10px", right: "15px", fontSize: "1.5rem", cursor: "pointer", zIndex: 10001 },
3785
+ children: "\xD7"
3786
+ }
3787
+ ),
3788
+ /* @__PURE__ */ jsx51("h5", { className: "mb-3 text-center", children: "Escaneie o QR Code" }),
3789
+ /* @__PURE__ */ jsx51(
3790
+ QrReader,
3791
+ {
3792
+ callback: (v) => {
3793
+ toggleQr();
3794
+ callback(v);
3795
+ }
3796
+ }
3797
+ ),
3798
+ /* @__PURE__ */ jsx51("p", { className: "mt-3 text-muted text-center small", children: "Aponte a c\xE2mera para o c\xF3digo" })
3799
+ ] })
3800
+ }
3801
+ )
3802
+ ]
3803
+ }
3804
+ );
3805
+ };
3806
+
3807
+ // src/tables/ReusableTableWithModal.tsx
3808
+ import { useState as useState24, useEffect as useEffect12 } from "react";
3809
+ import { Table, Button as Button22, Modal as Modal8 } from "react-bootstrap";
3810
+ import { Fragment as Fragment14, jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
3811
+ var ReusableTableWithModal = ({
3812
+ fetchDataCallback,
3813
+ modalButtonCallback,
3814
+ configureColumnsCallback,
3815
+ headers,
3816
+ modalContent,
3817
+ confirmLabel = "Aceitar",
3818
+ onFetchData
3819
+ }) => {
3820
+ const [data, setData] = useState24([]);
3821
+ const [selectedItem, setSelectedItem] = useState24(null);
3822
+ const [showModal, setShowModal] = useState24(false);
3823
+ const [loading, setLoading] = useState24(false);
3824
+ const [tableDataRows, setTableDataRows] = useState24([]);
3825
+ const fetchData = async () => {
3826
+ setLoading(true);
3827
+ try {
3828
+ const response = await fetchDataCallback();
3829
+ onFetchData && onFetchData(response);
3830
+ setData(response);
3831
+ const items = Array.isArray(response) ? response : [response];
3832
+ const tabData = items.map((r) => configureColumnsCallback(r));
3833
+ setTableDataRows(tabData);
3834
+ } catch (error) {
3835
+ console.error("Erro ao buscar dados na ReusableTable:", error);
3836
+ } finally {
3837
+ setLoading(false);
3838
+ }
3839
+ };
3840
+ useEffect12(() => {
3841
+ fetchData();
3842
+ }, []);
3843
+ const handleRowClick = (td) => {
3844
+ setSelectedItem(td.dataObj);
3845
+ setShowModal(true);
3846
+ };
3847
+ const handleCloseModal = () => {
3848
+ setShowModal(false);
3849
+ setSelectedItem(null);
3850
+ };
3851
+ return /* @__PURE__ */ jsxs42(Fragment14, { children: [
3852
+ /* @__PURE__ */ jsxs42(Table, { striped: true, bordered: true, hover: true, responsive: true, children: [
3853
+ /* @__PURE__ */ jsx52("thead", { children: /* @__PURE__ */ jsx52("tr", { children: headers.map((col, index) => /* @__PURE__ */ jsx52("th", { children: col }, index)) }) }),
3854
+ /* @__PURE__ */ jsx52("tbody", { children: loading ? /* @__PURE__ */ jsx52("tr", { children: /* @__PURE__ */ jsx52("td", { colSpan: headers.length, className: "text-center py-4", children: "Carregando..." }) }) : tableDataRows.length > 0 ? tableDataRows.map((td, index) => /* @__PURE__ */ jsx52(
3855
+ "tr",
3856
+ {
3857
+ onClick: () => handleRowClick(td),
3858
+ style: { cursor: "pointer" },
3859
+ children: td.columns.map((col, colIndex) => /* @__PURE__ */ jsx52("td", { children: col || "N/A" }, colIndex))
3860
+ },
3861
+ index
3862
+ )) : /* @__PURE__ */ jsx52("tr", { children: /* @__PURE__ */ jsx52("td", { colSpan: headers.length, className: "text-center py-4", children: "Nenhum dado encontrado." }) }) })
3863
+ ] }),
3864
+ /* @__PURE__ */ jsxs42(Modal8, { show: showModal, onHide: handleCloseModal, centered: true, children: [
3865
+ /* @__PURE__ */ jsx52(Modal8.Header, { closeButton: true, children: /* @__PURE__ */ jsx52(Modal8.Title, { children: "Detalhes" }) }),
3866
+ /* @__PURE__ */ jsx52(Modal8.Body, { children: selectedItem && /* @__PURE__ */ jsx52("div", { children: modalContent ? modalContent(selectedItem) : "Visualizando detalhes do item." }) }),
3867
+ /* @__PURE__ */ jsxs42(Modal8.Footer, { children: [
3868
+ /* @__PURE__ */ jsx52(Button22, { variant: "outline-secondary", onClick: handleCloseModal, children: "Fechar" }),
3869
+ modalButtonCallback && /* @__PURE__ */ jsx52(
3870
+ Button22,
3871
+ {
3872
+ variant: "primary",
3873
+ onClick: () => {
3874
+ modalButtonCallback(selectedItem);
3875
+ handleCloseModal();
3876
+ },
3877
+ children: confirmLabel
3878
+ }
3879
+ )
3880
+ ] })
3881
+ ] })
3882
+ ] });
3883
+ };
3884
+
3885
+ // src/text/TextWithMore.tsx
3886
+ import { useState as useState25 } from "react";
3887
+ import { Button as Button23 } from "react-bootstrap";
3888
+ import { Fragment as Fragment15, jsx as jsx53, jsxs as jsxs43 } from "react/jsx-runtime";
3889
+ var TextWithMore = ({
3890
+ text = "Carregando...",
3891
+ maxLength,
3892
+ moreLabel = "ver mais",
3893
+ lessLabel = "ver menos"
3894
+ }) => {
3895
+ const [expanded, setExpanded] = useState25(false);
3896
+ const handleToggleExpand = () => {
3897
+ setExpanded(!expanded);
3898
+ };
3899
+ const isTruncated = text.length > maxLength;
3900
+ const displayText = isTruncated && !expanded ? text.slice(0, maxLength) + "\u2026" : text;
3901
+ return /* @__PURE__ */ jsxs43(Fragment15, { children: [
3902
+ /* @__PURE__ */ jsx53("span", { className: "text-with-more-content", children: displayText }),
3903
+ isTruncated && /* @__PURE__ */ jsx53(
3904
+ Button23,
3905
+ {
3906
+ variant: "link",
3907
+ className: "p-0 ms-2",
3908
+ style: { fontSize: "0.85rem", textDecoration: "none" },
3909
+ onClick: handleToggleExpand,
3910
+ children: expanded ? lessLabel : moreLabel
3911
+ }
3912
+ )
3913
+ ] });
3914
+ };
3915
+
3916
+ // src/index.ts
3917
+ import {
3918
+ CalculoCorrecao,
3919
+ CalculadoraCorrecaoModal,
3920
+ UnidadeMaterialCard,
3921
+ TarefaUnidadeForm,
3922
+ FrequenciaFormV2,
3923
+ CampoDeVerificacaoV2
3924
+ } from "@teraprox/ui-kit-sgp";
3925
+ export {
3926
+ ActionButtons,
3927
+ AddButton_default as AddButton,
3928
+ AdvancedFilterBar,
3929
+ AnexoManager,
3930
+ ApproveAndReproveButtons,
3931
+ AsyncButton,
3932
+ AutoComplete,
3933
+ BonusButton,
3934
+ BranchDropDisplay,
3935
+ ButtonWithDropdown,
3936
+ CalculadoraCorrecaoModal,
3937
+ CalculoCorrecao,
3938
+ CampoDeVerificacaoV2,
3939
+ CheckBox,
3940
+ ClickToWriteField,
3941
+ ColorPicker,
3942
+ ConfigObject,
3943
+ DeleteButton_default as DeleteButton,
3944
+ DeleteConfirm,
3945
+ ExpandableCard,
3946
+ FindRecursoByTagField,
3947
+ FormField,
3948
+ FrequenciaFormV2,
3949
+ Generic3DotMenu,
3950
+ GenericChart,
3951
+ GenericDisplay_default as GenericDisplay,
3952
+ GenericForm_default as GenericForm,
3953
+ GenericREchart,
3954
+ GenericSelect_default as GenericSelect,
3955
+ GenericSelectOps,
3956
+ IconLabelItem,
3957
+ IconLabelList,
3958
+ ImageViewModal,
3959
+ JustificativaModal,
3960
+ LoadingButton,
3961
+ LoadingProgress,
3962
+ MailSender,
3963
+ MenuEvent,
3964
+ ModalBasicTemplate,
3965
+ NavigateButton,
3966
+ NotificationBell,
3967
+ NotificationItem,
3968
+ PeriodSelector,
3969
+ QrCodeScanButton,
3970
+ QrReader,
3971
+ RateLimitBar,
3972
+ RecursoDisplayer,
3973
+ ResponsiveContainer_default as ResponsiveContainer,
3974
+ ReusableTableWithModal,
3975
+ SectorSelector,
3976
+ SelectDateModal,
3977
+ StatusBadge,
3978
+ StatusIndicator,
3979
+ StatusLight,
3980
+ StatusPills,
3981
+ Switch,
3982
+ SwitchOnClick,
3983
+ TarefaUnidadeForm,
3984
+ TextWithMore,
3985
+ TimerDisplay,
3986
+ UnidadeMaterialCard,
3987
+ UnidadeMaterialForm,
3988
+ UnifiedPeriodSelector,
3989
+ UploadArea,
3990
+ UuidPill_default as UuidPill,
3991
+ VerticalItemsDisplay
3992
+ };