teraprox-ui-kit 0.1.8 → 0.1.10

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