@granto-umbrella/umbrella-components 2.3.23 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/umbrella-components.css +1 -1
  2. package/dist/umbrella-components.es.js +42753 -63037
  3. package/dist/umbrella-components.umd.js +2038 -581
  4. package/package.json +9 -4
  5. package/src/assets/_banner_contato.png +0 -0
  6. package/src/assets/_logoUmbrella.svg +34 -0
  7. package/src/assets.d.ts +19 -0
  8. package/src/components/atoms/DropDownMenu/DropdownMenu.styles.tsx +106 -0
  9. package/src/components/atoms/DropDownMenu/DropdownMenu.tsx +48 -0
  10. package/src/components/atoms/DropDownMenu/DropdownMenu.types.ts +15 -0
  11. package/src/components/atoms/DropDownMenu/index.tsx +2 -0
  12. package/src/components/atoms/ErrorMessage/ErrorMessage.styles.tsx +28 -0
  13. package/src/components/atoms/ErrorMessage/ErrorMessage.tsx +12 -0
  14. package/src/components/atoms/ErrorMessage/ErrorMessage.types.ts +6 -0
  15. package/src/components/atoms/ErrorMessage/index.tsx +1 -0
  16. package/src/components/atoms/Footer/Footer.styles.tsx +22 -0
  17. package/src/components/atoms/Footer/Footer.tsx +9 -0
  18. package/src/components/atoms/Footer/Footer.types.tsx +5 -0
  19. package/src/components/atoms/Footer/index.tsx +1 -0
  20. package/src/components/atoms/GenericContainer/GenericContainer.styles.tsx +21 -0
  21. package/src/components/atoms/GenericContainer/GenericContainer.tsx +9 -0
  22. package/src/components/atoms/GenericContainer/GenericContainer.types.ts +5 -0
  23. package/src/components/atoms/GenericContainer/index.tsx +1 -0
  24. package/src/components/atoms/Loading/Loading.styles.tsx +23 -0
  25. package/src/components/atoms/Loading/Loading.tsx +8 -0
  26. package/src/components/atoms/Loading/index.tsx +1 -0
  27. package/src/components/atoms/LogoContainer/LogoContainer.Types.tsx +5 -0
  28. package/src/components/atoms/LogoContainer/LogoContainer.styles.tsx +11 -0
  29. package/src/components/atoms/LogoContainer/LogoContainer.tsx +11 -0
  30. package/src/components/atoms/LogoContainer/index.tsx +1 -0
  31. package/src/components/atoms/ModalAviso/ModalAviso.styles.tsx +54 -0
  32. package/src/components/atoms/ModalAviso/ModalAviso.tsx +37 -0
  33. package/src/components/atoms/ModalAviso/ModalAviso.types.ts +5 -0
  34. package/src/components/atoms/ModalAviso/index.tsx +1 -0
  35. package/src/components/atoms/MultiSelect/MultiSelect.styles.tsx +92 -0
  36. package/src/components/atoms/MultiSelect/MultiSelect.tsx +346 -0
  37. package/src/components/atoms/MultiSelect/MultiSelect.types.ts +38 -0
  38. package/src/components/atoms/MultiSelect/index.tsx +1 -0
  39. package/src/components/atoms/ResendLink/ResendLink.styles.tsx +20 -0
  40. package/src/components/atoms/ResendLink/ResendLink.tsx +16 -0
  41. package/src/components/atoms/ResendLink/ResendLink.types.ts +9 -0
  42. package/src/components/atoms/ResendLink/index.tsx +1 -0
  43. package/src/components/atoms/Subtitle/Subtitle.styles.tsx +21 -0
  44. package/src/components/atoms/Subtitle/Subtitle.tsx +7 -0
  45. package/src/components/atoms/Subtitle/Subtitle.types.ts +5 -0
  46. package/src/components/atoms/Subtitle/index.tsx +1 -0
  47. package/src/components/atoms/Tapbar/Tapbar.styles.tsx +57 -0
  48. package/src/components/atoms/Tapbar/Tapbar.tsx +24 -0
  49. package/src/components/atoms/Tapbar/Tapbar.types.ts +11 -0
  50. package/src/components/atoms/Tapbar/index.tsx +2 -0
  51. package/src/components/atoms/Text/Text.styles.tsx +8 -5
  52. package/src/components/atoms/Text/Text.tsx +1 -0
  53. package/src/components/atoms/Title/Title.styles.tsx +17 -0
  54. package/src/components/atoms/Title/Title.tsx +7 -0
  55. package/src/components/atoms/Title/Title.types.ts +5 -0
  56. package/src/components/atoms/Title/index.tsx +1 -0
  57. package/src/components/molecules/BannerAjuda/BannerAjuda.styles.tsx +9 -0
  58. package/src/components/molecules/BannerAjuda/BannerAjuda.tsx +19 -0
  59. package/src/components/molecules/BannerAjuda/BannerAjuda.types.ts +5 -0
  60. package/src/components/molecules/BannerAjuda/index.tsx +1 -0
  61. package/src/components/molecules/CodeInputContainer/CodeInputContainer.styles.tsx +7 -0
  62. package/src/components/molecules/CodeInputContainer/CodeInputContainer.tsx +32 -0
  63. package/src/components/molecules/CodeInputContainer/CodeInputContainer.types.ts +13 -0
  64. package/src/components/molecules/CodeInputContainer/index.tsx +3 -0
  65. package/src/components/molecules/ExcludeModal/ExcludeModal.styles.tsx +118 -0
  66. package/src/components/molecules/ExcludeModal/ExcludeModal.tsx +48 -0
  67. package/src/components/molecules/ExcludeModal/ExcludeModal.types.ts +10 -0
  68. package/src/components/molecules/ExcludeModal/index.tsx +1 -0
  69. package/src/components/molecules/HighlightsCard/HighlightsCard.styles.tsx +68 -0
  70. package/src/components/molecules/HighlightsCard/HighlightsCard.tsx +26 -0
  71. package/src/components/molecules/HighlightsCard/HighlightsCard.types.ts +10 -0
  72. package/src/components/molecules/HighlightsCard/index.tsx +1 -0
  73. package/src/components/molecules/InsuranceCard/InsuranceCard.styles.tsx +174 -0
  74. package/src/components/molecules/InsuranceCard/InsuranceCard.tsx +418 -0
  75. package/src/components/molecules/InsuranceCard/InsuranceCard.types.ts +32 -0
  76. package/src/components/molecules/InsuranceCard/index.tsx +1 -0
  77. package/src/components/molecules/PieChartComponent/PieChartComponent.styles.tsx +8 -0
  78. package/src/components/molecules/PieChartComponent/PieChartComponent.tsx +73 -0
  79. package/src/components/molecules/PieChartComponent/PieChartComponent.types.ts +11 -0
  80. package/src/components/molecules/PieChartComponent/index.tsx +1 -0
  81. package/src/components/molecules/RadioGroupField/RadioGroupField.styles.tsx +64 -0
  82. package/src/components/molecules/RadioGroupField/RadioGroupField.tsx +69 -0
  83. package/src/components/molecules/RadioGroupField/RadioGroupField.types.ts +17 -0
  84. package/src/components/molecules/RadioGroupField/index.tsx +1 -0
  85. package/src/components/molecules/RefuseModal/RefuseModal.styles.tsx +139 -0
  86. package/src/components/molecules/RefuseModal/RefuseModal.tsx +76 -0
  87. package/src/components/molecules/RefuseModal/RefuseModal.types.ts +15 -0
  88. package/src/components/molecules/RefuseModal/index.tsx +2 -0
  89. package/src/components/molecules/ResultsChart/ResultsChart.styles.tsx +22 -0
  90. package/src/components/molecules/ResultsChart/ResultsChart.tsx +19 -0
  91. package/src/components/molecules/ResultsChart/ResultsChart.types.ts +3 -0
  92. package/src/components/molecules/ResultsChart/index.tsx +2 -0
  93. package/src/components/molecules/TimeLine/TimeLine.styles.ts +118 -0
  94. package/src/components/molecules/TimeLine/TimeLine.tsx +38 -0
  95. package/src/components/molecules/TimeLine/TimeLine.types.ts +35 -0
  96. package/src/components/organisms/DonutEmissionsChart/DonutEmissionsChart.styles.tsx +113 -0
  97. package/src/components/organisms/DonutEmissionsChart/DonutEmissionsChart.tsx +71 -0
  98. package/src/components/organisms/DonutEmissionsChart/DonutEmissionsChart.types.ts +9 -0
  99. package/src/components/organisms/DonutEmissionsChart/index.tsx +2 -0
  100. package/src/components/organisms/ListagemUltimasEmissoes/ListagemUltimasEmissoes.styles.tsx +114 -0
  101. package/src/components/organisms/ListagemUltimasEmissoes/ListagemUltimasEmissoes.tsx +89 -0
  102. package/src/components/organisms/ListagemUltimasEmissoes/ListagemUltimasEmissoes.types.ts +16 -0
  103. package/src/components/organisms/ListagemUltimasEmissoes/index.tsx +1 -0
  104. package/src/components/organisms/TimelineModal/TimelineModal.styles.ts +49 -0
  105. package/src/components/organisms/TimelineModal/TimelineModal.tsx +37 -0
  106. package/src/global.d.ts +6 -0
  107. package/src/index.ts +68 -37
  108. package/src/lib/helpers.ts +17 -0
  109. package/src/styles/tokens/sizes.ts +12 -1
  110. package/src/styles/tokens/typography.ts +1 -1
@@ -0,0 +1,418 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ FileText,
4
+ CreditCard,
5
+ Download,
6
+ PlusCircle,
7
+ ChevronDown,
8
+ ChevronUp,
9
+ Loader2,
10
+ } from "lucide-react";
11
+ import {
12
+ CardContainer,
13
+ HeaderRow,
14
+ InfoRow,
15
+ InfoLabel,
16
+ TruncatedValue,
17
+ Actions,
18
+ DropdownWrapper,
19
+ DropdownMenu,
20
+ StyledMenuItem,
21
+ Text,
22
+ BodyRow,
23
+ InfoSubValue,
24
+ ProdValue,
25
+ ProcessValue,
26
+ ActionButton,
27
+ } from "./InsuranceCard.styles";
28
+ import { InsuranceCardProps, MenuItemProps, StatusVariant } from "./InsuranceCard.types";
29
+
30
+ import Pill from "../../atoms/Pill/Pill";
31
+
32
+
33
+
34
+
35
+ const applyMask = (value: string, mask: string): string => {
36
+ let result = "";
37
+ let valueIndex = 0;
38
+
39
+ for (let i = 0; i < mask.length && valueIndex < value.length; i++) {
40
+ if (mask[i] === "0") {
41
+ result += value[valueIndex];
42
+ valueIndex++;
43
+ } else {
44
+ result += mask[i];
45
+ }
46
+ }
47
+
48
+ return result;
49
+ };
50
+
51
+
52
+ const isValidCNPJ = (value: string): boolean => {
53
+ const cleanValue = value.replace(/\D/g, "");
54
+ return cleanValue.length === 14;
55
+ };
56
+
57
+
58
+ const formatDate = (isoDate: string): string => {
59
+ const date = new Date(isoDate);
60
+ const day = String(date.getDate()).padStart(2, "0");
61
+ const month = String(date.getMonth() + 1).padStart(2, "0");
62
+ const year = date.getFullYear();
63
+ return `${day}/${month}/${year}`;
64
+ };
65
+
66
+
67
+ const product_list = [
68
+ { value: "001", label: "Seguro Garantia" },
69
+ { value: "002", label: "Seguro Fiança" },
70
+
71
+ ];
72
+
73
+ const formatProduct = (modality: string) => {
74
+ const type = modality.at(2);
75
+ const result = [];
76
+
77
+ switch (type) {
78
+ case "1":
79
+ result.push("Tradicional");
80
+ break;
81
+ case "2":
82
+ result.push("Judicial");
83
+ break;
84
+ default:
85
+ result.push("Desconhecido");
86
+ break;
87
+ }
88
+
89
+ result.push(
90
+ product_list.find((item) => item.value === modality)?.label ??
91
+ "Desconhecido"
92
+ );
93
+ return result;
94
+ };
95
+
96
+ // Ícones do phosphor-react substituídos por componentes inline
97
+ const ArrowCircleUpRight = ({ size = 16 }: { size?: number }) => (
98
+ <svg width={size} height={size} viewBox="0 0 256 256" fill="currentColor">
99
+ <path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z" />
100
+ </svg>
101
+ );
102
+
103
+ const Cube = ({ size = 16 }: { size?: number }) => (
104
+ <svg width={size} height={size} viewBox="0 0 256 256" fill="currentColor">
105
+ <path d="M223.68,66.15,135.68,18a15.88,15.88,0,0,0-15.36,0l-88,48.17a16,16,0,0,0-8.32,14v95.64a16,16,0,0,0,8.32,14l88,48.17a15.88,15.88,0,0,0,15.36,0l88-48.17a16,16,0,0,0,8.32-14V80.18A16,16,0,0,0,223.68,66.15ZM128,32l80.34,44L128,120,47.66,76ZM40,90l80,43.78v85.79L40,175.82Zm176,85.78h0l-80,43.79V133.82l80-43.78Z" />
106
+ </svg>
107
+ );
108
+
109
+ const XCircle = ({ size = 16 }: { size?: number }) => (
110
+ <svg width={size} height={size} viewBox="0 0 256 256" fill="currentColor">
111
+ <path d="M165.66,101.66,139.31,128l26.35,26.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z" />
112
+ </svg>
113
+ );
114
+
115
+ // ===== COMPONENTE PRINCIPAL =====
116
+
117
+ export const InsuranceCard: React.FC<InsuranceCardProps> = ({
118
+ idGranto,
119
+ idOrder,
120
+ idInsurance,
121
+ idInterno,
122
+ isSupply,
123
+ hasMinute,
124
+ statusLabel,
125
+ statusVariant,
126
+ seguradoName,
127
+ seguradoCnpj,
128
+ product,
129
+ issuedDate,
130
+ totalValue,
131
+ processId,
132
+ activeIndex,
133
+ testId,
134
+ openCardId,
135
+ setOpenCardId,
136
+
137
+ }) => {
138
+ const [loadingItem, setLoadingItem] = useState<string | null>(null);
139
+ const isOpen = openCardId === idOrder;
140
+
141
+ const toggleOpen = () => {
142
+ setOpenCardId(isOpen ? null : idOrder);
143
+ };
144
+
145
+ const handleClick = async (
146
+ key: string,
147
+ callback: () => Promise<void> | void
148
+ ) => {
149
+ setLoadingItem(key);
150
+ await Promise.resolve(callback());
151
+ setLoadingItem(null);
152
+ };
153
+
154
+ const [productTitle, productDescription] = formatProduct(product);
155
+
156
+ // Mock das funções (você ajustará quando os hooks existirem)
157
+ const downloadFile = (type: string, flag: boolean) => {
158
+ console.log(`Download ${type}:`, flag);
159
+ };
160
+
161
+ const searchCerts = (insurance: string, order: string) => {
162
+ console.log(`Search certs for ${insurance}, ${order}`);
163
+ };
164
+
165
+ const onEndorsementClick = (company: string, insurance: string) => {
166
+ console.log(`Endorsement for ${company}, ${insurance}`);
167
+ };
168
+
169
+ const irParaContinuarEmissao = () => {
170
+ console.log("Continuar emissão");
171
+ // Implementar navegação quando disponível
172
+ };
173
+
174
+ const abrirModalExcluirProposta = () => {
175
+ console.log("Abrir modal excluir");
176
+ // Modal será implementado depois
177
+ };
178
+
179
+ const abrirModalRecusarProposta = () => {
180
+ console.log("Abrir modal recusar");
181
+ // Modal será implementado depois
182
+ };
183
+
184
+ return (
185
+ <CardContainer
186
+ data-testid={testId}
187
+ id={testId}
188
+ $variant={statusVariant as StatusVariant}
189
+ >
190
+ <HeaderRow>
191
+ {isSupply && (
192
+ <Pill size={"sm"} variant="supply">
193
+ <Cube />
194
+ Supply
195
+ </Pill>
196
+ )}
197
+ <Text>ID Granto: {idGranto}</Text>
198
+ <Text>ID interno: {idInterno}</Text>
199
+ <Text $variant={statusVariant as StatusVariant}>
200
+ {activeIndex === 0 ? "Etapa" : "Status"}: {statusLabel}
201
+ </Text>
202
+ </HeaderRow>
203
+ <BodyRow>
204
+ <InfoRow>
205
+ <InfoLabel>Segurado</InfoLabel>
206
+ <TruncatedValue>{seguradoName}</TruncatedValue>
207
+ <InfoSubValue>
208
+ {applyMask(
209
+ seguradoCnpj,
210
+ isValidCNPJ(seguradoCnpj)
211
+ ? "00.000.000/0000-00"
212
+ : "000.000.000-00"
213
+ )}
214
+ </InfoSubValue>
215
+ </InfoRow>
216
+ <InfoRow>
217
+ <InfoLabel>Produto</InfoLabel>
218
+ <ProdValue>{productTitle}</ProdValue>
219
+ <InfoSubValue>{productDescription}</InfoSubValue>
220
+ </InfoRow>
221
+ <InfoRow>
222
+ <InfoLabel>
223
+ {activeIndex === 0 ? "Iniciado em" : "Emitido em"}
224
+ </InfoLabel>
225
+ <InfoSubValue>{formatDate(issuedDate)}</InfoSubValue>
226
+ </InfoRow>
227
+ <InfoRow>
228
+ <InfoLabel>
229
+ {activeIndex === 0 ? "Valor a ser pago" : "Valor pago"}
230
+ </InfoLabel>
231
+ <InfoSubValue>{totalValue}</InfoSubValue>
232
+ </InfoRow>
233
+ <InfoRow>
234
+ <InfoLabel>Processo</InfoLabel>
235
+ <ProcessValue>
236
+ {processId
237
+ ? applyMask(processId || "", "0000000-00.0000.0.00.0000")
238
+ : "-"}
239
+ </ProcessValue>
240
+ </InfoRow>
241
+ <Actions>
242
+ <DropdownWrapper>
243
+ <ActionButton
244
+ data-testid={`btn_minhas_emissoes_mais_informacoes_${processId}`}
245
+ id={`btn_minhas_emissoes_mais_informacoes_${processId}`}
246
+ onClick={toggleOpen}
247
+ >
248
+ Mais informações{" "}
249
+ {isOpen ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
250
+ </ActionButton>
251
+ {isOpen && activeIndex === 0 && (
252
+ <DropdownMenu>
253
+ <MenuItem
254
+ data-testid={`btn_minhas_emissoes_continuar_emissao_${processId}`}
255
+ id={`btn_minhas_emissoes_continuar_emissao_${processId}`}
256
+ icon={
257
+ loadingItem === "continuar_emissao" ? (
258
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
259
+ ) : (
260
+ <ArrowCircleUpRight size={16} />
261
+ )
262
+ }
263
+ onClick={() =>
264
+ handleClick("continuar_emissao", irParaContinuarEmissao)
265
+ }
266
+ >
267
+ Continuar emissão
268
+ </MenuItem>
269
+ {hasMinute && (
270
+ <MenuItem
271
+ data-testid={`btn_minhas_emissoes_baixar_minuta_${processId}`}
272
+ id={`btn_minhas_emissoes_baixar_minuta_${processId}`}
273
+ icon={
274
+ loadingItem === "minuta" ? (
275
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
276
+ ) : (
277
+ <Download size={16} />
278
+ )
279
+ }
280
+ onClick={() =>
281
+ handleClick("minuta", () => downloadFile("MINUTE", true))
282
+ }
283
+ >
284
+ Baixar minuta
285
+ </MenuItem>
286
+ )}
287
+ {statusLabel === "Aguardando aprovação" && (
288
+ <MenuItem
289
+ danger
290
+ data-testid={`btn_minhas_emissoes_recusar_proposta_${processId}`}
291
+ id={`btn_minhas_emissoes_recusar_proposta_${processId}`}
292
+ icon={
293
+ loadingItem === "recusar_proposta" ? (
294
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
295
+ ) : (
296
+ <XCircle size={16} />
297
+ )
298
+ }
299
+ onClick={() =>
300
+ handleClick("recusar_proposta", abrirModalRecusarProposta)
301
+ }
302
+ >
303
+ Recusar proposta
304
+ </MenuItem>
305
+ )}
306
+ {statusLabel === "Proposta recusada" && (
307
+ <MenuItem
308
+ danger
309
+ data-testid={`btn_minhas_emissoes_excluir_proposta_${processId}`}
310
+ id={`btn_minhas_emissoes_excluir_proposta_${processId}`}
311
+ icon={
312
+ loadingItem === "excluir_proposta" ? (
313
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
314
+ ) : (
315
+ <XCircle size={16} />
316
+ )
317
+ }
318
+ onClick={() =>
319
+ handleClick("excluir_proposta", abrirModalExcluirProposta)
320
+ }
321
+ >
322
+ Excluir proposta
323
+ </MenuItem>
324
+ )}
325
+ </DropdownMenu>
326
+ )}
327
+ {isOpen && activeIndex === 1 && (
328
+ <DropdownMenu>
329
+ <MenuItem
330
+ data-testid={`btn_minhas_emissoes_baixar_apolice_${processId}`}
331
+ id={`btn_minhas_emissoes_baixar_apolice_${processId}`}
332
+ icon={
333
+ loadingItem === "apolice" ? (
334
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
335
+ ) : (
336
+ <FileText size={16} />
337
+ )
338
+ }
339
+ onClick={() =>
340
+ handleClick("apolice", () => downloadFile("POLICY", true))
341
+ }
342
+ >
343
+ Baixar apólice
344
+ </MenuItem>
345
+ <MenuItem
346
+ data-testid={`btn_minhas_emissoes_baixar_boleto_${processId}`}
347
+ id={`btn_minhas_emissoes_baixar_boleto_${processId}`}
348
+ icon={
349
+ loadingItem === "boleto" ? (
350
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
351
+ ) : (
352
+ <CreditCard size={16} />
353
+ )
354
+ }
355
+ onClick={() =>
356
+ handleClick("boleto", () => downloadFile("SLIP", true))
357
+ }
358
+ >
359
+ Baixar boleto
360
+ </MenuItem>
361
+ <MenuItem
362
+ data-testid={`btn_minhas_emissoes_baixar_certidoes_${processId}`}
363
+ id={`btn_minhas_emissoes_baixar_certidoes_${processId}`}
364
+ icon={
365
+ loadingItem === "certidoes" ? (
366
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
367
+ ) : (
368
+ <Download size={16} />
369
+ )
370
+ }
371
+ onClick={() =>
372
+ handleClick("certidoes", () =>
373
+ searchCerts(idInsurance!, idOrder)
374
+ )
375
+ }
376
+ >
377
+ Baixar certidões
378
+ </MenuItem>
379
+ <MenuItem
380
+ data-testid={`btn_minhas_emissoes_solicitar_endosso_${processId}`}
381
+ id={`btn_minhas_emissoes_solicitar_endosso_${processId}`}
382
+ icon={
383
+ loadingItem === "endosso" ? (
384
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
385
+ ) : (
386
+ <PlusCircle size={16} />
387
+ )
388
+ }
389
+ onClick={() =>
390
+ handleClick("endosso", () =>
391
+ onEndorsementClick("Umbrela Corp", idInsurance!)
392
+ )
393
+ }
394
+ >
395
+ Solicitar endosso
396
+ </MenuItem>
397
+ </DropdownMenu>
398
+ )}
399
+ </DropdownWrapper>
400
+ </Actions>
401
+ </BodyRow>
402
+ </CardContainer>
403
+ );
404
+ };
405
+
406
+ const MenuItem: React.FC<MenuItemProps> = ({
407
+ icon,
408
+ danger,
409
+ children,
410
+ ...rest
411
+ }) => {
412
+ return (
413
+ <StyledMenuItem {...rest} $danger={danger}>
414
+ {icon}
415
+ {children}
416
+ </StyledMenuItem>
417
+ );
418
+ };
@@ -0,0 +1,32 @@
1
+ export type StatusVariant = "primary" | "success" | "warning" | "danger";
2
+
3
+ export interface InsuranceCardProps {
4
+ idGranto: string;
5
+ idOrder: string;
6
+ idInsurance?: string;
7
+ idInterno: string;
8
+ isSupply: boolean;
9
+ hasMinute: boolean;
10
+ statusLabel: string;
11
+ statusVariant: StatusVariant;
12
+ seguradoName: string;
13
+ seguradoCnpj: string;
14
+ product: string;
15
+ issuedDate: string;
16
+ totalValue: string;
17
+ processId?: string;
18
+ activeIndex: number;
19
+ testId?: string;
20
+ openCardId: string | null;
21
+ setOpenCardId: (id: string | null) => void;
22
+ runQuery: () => void;
23
+ }
24
+
25
+ export interface MenuItemProps {
26
+ icon: React.ReactNode;
27
+ danger?: boolean;
28
+ children: React.ReactNode;
29
+ onClick?: () => void;
30
+ id?: string;
31
+ "data-testid"?: string;
32
+ }
@@ -0,0 +1 @@
1
+ export { InsuranceCard } from "./InsuranceCard";
@@ -0,0 +1,8 @@
1
+ import styled from "styled-components";
2
+
3
+ export const StyledPieChart = styled.div`
4
+ .recharts-wrapper {
5
+ margin: auto;
6
+ }
7
+ `;
8
+
@@ -0,0 +1,73 @@
1
+ import { useMemo } from "react";
2
+ import { PieChart, Pie, Label, Tooltip } from "recharts";
3
+ import { StyledPieChart } from "./PieChartComponent.styles";
4
+ import { PieChartComponentProps } from "./PieChartComponent.types";
5
+ import {
6
+ semanticColors,
7
+ typographyTokens,
8
+ } from "../../../styles/tokens";
9
+
10
+ const PieChartComponent = ({ data }: PieChartComponentProps) => {
11
+ const totalEmissoes = useMemo(
12
+ () => data.reduce((acc, curr) => acc + curr.value, 0),
13
+ [data]
14
+ );
15
+
16
+ return (
17
+ <StyledPieChart>
18
+ <PieChart width={155} height={155}>
19
+ <Tooltip cursor={false} />
20
+ <Pie
21
+ data={data}
22
+ dataKey="value"
23
+ nameKey="name"
24
+ innerRadius={52}
25
+ outerRadius={62}
26
+ stroke="none"
27
+ paddingAngle={2}
28
+ >
29
+ <Label
30
+ content={({ viewBox }) => {
31
+ if (viewBox && "cx" in viewBox && "cy" in viewBox) {
32
+ const { cx, cy } = viewBox;
33
+ return (
34
+ <text
35
+ x={cx}
36
+ y={cy}
37
+ textAnchor="middle"
38
+ dominantBaseline="middle"
39
+ >
40
+ <tspan
41
+ x={cx}
42
+ y={(cy ?? 0) - 8}
43
+ style={{
44
+ fontSize: typographyTokens.fontSizes.displayL,
45
+ fontWeight: typographyTokens.fontWeights.bold,
46
+ fill: semanticColors.base.text,
47
+ }}
48
+ >
49
+ {totalEmissoes}
50
+ </tspan>
51
+ <tspan
52
+ x={cx}
53
+ y={(cy ?? 0) + 16}
54
+ style={{
55
+ fontSize: typographyTokens.fontSizes.bodyS,
56
+ fill: semanticColors.base.text,
57
+ }}
58
+ >
59
+ emissões
60
+ </tspan>
61
+ </text>
62
+ );
63
+ }
64
+ return null;
65
+ }}
66
+ />
67
+ </Pie>
68
+ </PieChart>
69
+ </StyledPieChart>
70
+ );
71
+ };
72
+
73
+ export { PieChartComponent };
@@ -0,0 +1,11 @@
1
+ export interface PieChartData {
2
+ name: string;
3
+ value: number;
4
+ fill: string;
5
+
6
+ [key: string]: string | number;
7
+ }
8
+
9
+ export interface PieChartComponentProps {
10
+ data: PieChartData[];
11
+ }
@@ -0,0 +1 @@
1
+ export { PieChartComponent } from "./PieChartComponent";
@@ -0,0 +1,64 @@
1
+ import styled from "styled-components";
2
+ import {
3
+ semanticColors,
4
+ semanticRadius,
5
+ semanticSizes,
6
+ typographyTokens,
7
+ } from "../../../styles/tokens";
8
+
9
+ export const RadioGroupContainer = styled.div`
10
+ display: flex;
11
+ flex-wrap: wrap;
12
+ gap: ${semanticSizes.global.gap.md};
13
+ width: 100%;
14
+ `;
15
+
16
+ export const RadioButton = styled.div<{ isSelected: boolean }>`
17
+ min-width: 274px;
18
+ padding: ${semanticSizes.global.padding.md} ${semanticSizes.global.padding["2xl"]};
19
+ height: 40px;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ cursor: pointer;
24
+ border-radius: ${semanticRadius.global.radius.md2};
25
+ transition: all 0.2s;
26
+ font-size: ${typographyTokens.fontSizes.bodyS};
27
+ font-weight: ${typographyTokens.fontWeights.regular};
28
+
29
+ ${({ isSelected }) =>
30
+ isSelected
31
+ ? `
32
+ background-color: ${semanticColors.branding.surface.enabled};
33
+ color: ${semanticColors.branding.text.onSurfaceAccent.enabled};
34
+ border: none;
35
+ `
36
+ : `
37
+ background-color: ${semanticColors.base.background};
38
+ color: ${semanticColors.neutral[700]};
39
+ border: 1px solid ${semanticColors.global.border.default};
40
+
41
+ &:hover {
42
+ border-color: ${semanticColors.global.border.medium};
43
+ }
44
+ `}
45
+
46
+ &:disabled {
47
+ cursor: not-allowed;
48
+ opacity: 0.5;
49
+ }
50
+ `;
51
+
52
+ export const RadioLabel = styled.label`
53
+ display: inline-flex;
54
+ align-items: center;
55
+ gap: ${semanticSizes.global.gap.lg};
56
+ cursor: pointer;
57
+ margin: 0;
58
+ `;
59
+
60
+ export const HiddenRadioInput = styled.input`
61
+ position: absolute;
62
+ opacity: 0;
63
+ pointer-events: none;
64
+ `;
@@ -0,0 +1,69 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ RadioGroupContainer,
4
+ RadioButton,
5
+ RadioLabel,
6
+ HiddenRadioInput,
7
+ } from "./RadioGroupField.styles";
8
+ import { RadioGroupFieldProps } from "./RadioGroupField.types";
9
+
10
+ const RadioGroupField: React.FC<RadioGroupFieldProps> = ({
11
+ options,
12
+ value: controlledValue,
13
+ defaultValue,
14
+ onChange,
15
+ name = "radio-group",
16
+ disabled = false,
17
+ }) => {
18
+ const [internalValue, setInternalValue] = useState(defaultValue || "");
19
+
20
+ // Componente controlado ou não-controlado
21
+ const isControlled = controlledValue !== undefined;
22
+ const currentValue = isControlled ? controlledValue : internalValue;
23
+
24
+ const handleChange = (optionValue: string) => {
25
+ if (disabled) return;
26
+
27
+ if (!isControlled) {
28
+ setInternalValue(optionValue);
29
+ }
30
+
31
+ onChange?.(optionValue);
32
+ };
33
+
34
+ return (
35
+ <RadioGroupContainer>
36
+ {options.map((option) => {
37
+ const isSelected = currentValue === option.value;
38
+
39
+ return (
40
+ <RadioButton
41
+ key={option.value}
42
+ isSelected={isSelected}
43
+ onClick={() => handleChange(option.value)}
44
+ role="radio"
45
+ aria-checked={isSelected}
46
+ aria-disabled={disabled}
47
+ >
48
+ <RadioLabel>
49
+ <HiddenRadioInput
50
+ type="radio"
51
+ name={name}
52
+ value={option.value}
53
+ checked={isSelected}
54
+ onChange={() => handleChange(option.value)}
55
+ disabled={disabled}
56
+ />
57
+
58
+ {isSelected ? option.iconActive : option.iconInactive}
59
+
60
+ <span>{option.label}</span>
61
+ </RadioLabel>
62
+ </RadioButton>
63
+ );
64
+ })}
65
+ </RadioGroupContainer>
66
+ );
67
+ };
68
+
69
+ export { RadioGroupField };
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from "react";
2
+
3
+ export interface RadioOption {
4
+ value: string;
5
+ label: string;
6
+ iconActive?: ReactNode;
7
+ iconInactive?: ReactNode;
8
+ }
9
+
10
+ export interface RadioGroupFieldProps {
11
+ options: RadioOption[];
12
+ value?: string;
13
+ defaultValue?: string;
14
+ onChange?: (value: string) => void;
15
+ name?: string;
16
+ disabled?: boolean;
17
+ }