@granto-umbrella/umbrella-components 3.0.56 → 3.0.57
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/umbrella-components.es.js +23668 -23512
- package/dist/umbrella-components.umd.js +592 -569
- package/package.json +141 -141
- package/src/components/atoms/EditableDurationSelect/EditableDurationSelect.styles.ts +50 -0
- package/src/components/atoms/EditableDurationSelect/EditableDurationSelect.tsx +136 -0
- package/src/components/atoms/EditableDurationSelect/EditableDurationSelect.types.ts +18 -0
- package/src/components/atoms/EditableDurationSelect/index.tsx +1 -0
- package/src/components/molecules/TimeLine/TimeLine.mapper.ts +86 -86
- package/src/components/molecules/TimeLine/TimeLine.registry.ts +66 -41
- package/src/components/molecules/TimeLine/TimeLine.styles.ts +184 -184
- package/src/components/molecules/TimeLine/TimeLine.tsx +100 -100
- package/src/components/molecules/TimeLine/TimeLine.types.ts +65 -65
- package/src/index.ts +3 -1
|
@@ -1,41 +1,66 @@
|
|
|
1
|
-
import { EventIdKey, TimelineVariant } from './TimeLine.types';
|
|
2
|
-
|
|
3
|
-
type TimelineEventConfig = {
|
|
4
|
-
labelPtBr: string;
|
|
5
|
-
variant: TimelineVariant;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'
|
|
17
|
-
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
'
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
1
|
+
import { EventIdKey, TimelineVariant } from './TimeLine.types';
|
|
2
|
+
|
|
3
|
+
type TimelineEventConfig = {
|
|
4
|
+
labelPtBr: string;
|
|
5
|
+
variant: TimelineVariant;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Fonte única de verdade:
|
|
10
|
+
* - id (eventId) => label PT-BR + variant
|
|
11
|
+
* - Alterou aqui, reflete em tudo.
|
|
12
|
+
*/
|
|
13
|
+
export const TIMELINE_EVENT_REGISTRY: Record<EventIdKey, TimelineEventConfig> =
|
|
14
|
+
{
|
|
15
|
+
'15101': { labelPtBr: 'Proposta criada', variant: 'info' },
|
|
16
|
+
'15102': { labelPtBr: 'Proposta subscrita', variant: 'info' },
|
|
17
|
+
'15103': { labelPtBr: 'Proposta atualizada', variant: 'info' },
|
|
18
|
+
'15104': { labelPtBr: 'Foi feito o download da proposta', variant: 'info' },
|
|
19
|
+
'15105': { labelPtBr: 'Apólice emitida', variant: 'issue' },
|
|
20
|
+
|
|
21
|
+
'15120': { labelPtBr: 'Categoria criada', variant: 'info' },
|
|
22
|
+
|
|
23
|
+
'20001': { labelPtBr: 'Unidade de Negócio criada', variant: 'info' },
|
|
24
|
+
'20002': { labelPtBr: 'Unidade de Negócio atualizada', variant: 'info' },
|
|
25
|
+
'20003': { labelPtBr: 'Unidade de Negócio removida', variant: 'deleted' },
|
|
26
|
+
'20004': {
|
|
27
|
+
labelPtBr: 'Usuário adicionado à Unidade de Negócio',
|
|
28
|
+
variant: 'info',
|
|
29
|
+
},
|
|
30
|
+
'20005': {
|
|
31
|
+
labelPtBr: 'Usuário removido da Unidade de Negócio',
|
|
32
|
+
variant: 'info',
|
|
33
|
+
},
|
|
34
|
+
'20006': {
|
|
35
|
+
labelPtBr: 'Empresa adicionada à Unidade de Negócio',
|
|
36
|
+
variant: 'info',
|
|
37
|
+
},
|
|
38
|
+
'20007': {
|
|
39
|
+
labelPtBr: 'Empresa removida da Unidade de Negócio',
|
|
40
|
+
variant: 'deleted',
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Se você quer um "alias" tipo EventIds.ProposalCreated:
|
|
46
|
+
* ele também nasce do registry e não vira duplicação.
|
|
47
|
+
*/
|
|
48
|
+
export const EventIds = {
|
|
49
|
+
ProposalCreated: '15101',
|
|
50
|
+
ProposalSubscribed: '15102',
|
|
51
|
+
ProposalUpdated: '15103',
|
|
52
|
+
ProposalFileDownloaded: '15104',
|
|
53
|
+
ProposalInsuranceIssued: '15105',
|
|
54
|
+
CategoryCreated: '15120',
|
|
55
|
+
HoldingGroupCreated: '20001',
|
|
56
|
+
HoldingGroupUpdated: '20002',
|
|
57
|
+
HoldingGroupDeleted: '20003',
|
|
58
|
+
HoldingGroupUserAdded: '20004',
|
|
59
|
+
HoldingGroupUserRemoved: '20005',
|
|
60
|
+
HoldingGroupCompanyAdded: '20006',
|
|
61
|
+
HoldingGroupCompanyRemoved: '20007',
|
|
62
|
+
} as const satisfies Record<string, EventIdKey>;
|
|
63
|
+
|
|
64
|
+
export function resolveTimelineConfig(eventIdKey: EventIdKey) {
|
|
65
|
+
return TIMELINE_EVENT_REGISTRY[eventIdKey];
|
|
66
|
+
}
|
|
@@ -1,184 +1,184 @@
|
|
|
1
|
-
import {
|
|
2
|
-
primitiveColors,
|
|
3
|
-
semanticColors,
|
|
4
|
-
typographyTokens,
|
|
5
|
-
} from '../../../styles/tokens';
|
|
6
|
-
import styled, { css } from 'styled-components';
|
|
7
|
-
import { TimelineVariant } from './TimeLine.types';
|
|
8
|
-
|
|
9
|
-
export const Time = styled.time`
|
|
10
|
-
color: #6b7280;
|
|
11
|
-
font-size: 0.78rem;
|
|
12
|
-
`;
|
|
13
|
-
|
|
14
|
-
export const ItemWrap = styled.li`
|
|
15
|
-
display: grid;
|
|
16
|
-
grid-template-columns: 24px 1fr;
|
|
17
|
-
gap: 12px;
|
|
18
|
-
position: relative;
|
|
19
|
-
padding-bottom: 16px;
|
|
20
|
-
&:last-child {
|
|
21
|
-
padding-bottom: 0;
|
|
22
|
-
}
|
|
23
|
-
&:not(:last-child)::before {
|
|
24
|
-
content: '';
|
|
25
|
-
position: absolute;
|
|
26
|
-
left: 11px;
|
|
27
|
-
top: 34px;
|
|
28
|
-
bottom: 0;
|
|
29
|
-
width: 3px;
|
|
30
|
-
height: 100%;
|
|
31
|
-
background-color: ${primitiveColors.gray[200]};
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
export const Dot = styled.span<{ $variant?: TimelineVariant | string }>`
|
|
36
|
-
width: 24px;
|
|
37
|
-
height: 24px;
|
|
38
|
-
border-radius: 50%;
|
|
39
|
-
border: 1px solid;
|
|
40
|
-
display: inline-block;
|
|
41
|
-
margin-top: 0.2rem;
|
|
42
|
-
|
|
43
|
-
${({ $variant = 'continued' }) => {
|
|
44
|
-
const v = ($variant as TimelineVariant) || 'continued';
|
|
45
|
-
|
|
46
|
-
const bgMap: Partial<Record<TimelineVariant, ReturnType<typeof css>>> = {
|
|
47
|
-
continued: css`
|
|
48
|
-
background: ${semanticColors.branding.surface.disabled};
|
|
49
|
-
`,
|
|
50
|
-
accepted: css`
|
|
51
|
-
background: ${semanticColors.global.surface.status.online};
|
|
52
|
-
`,
|
|
53
|
-
rejected: css`
|
|
54
|
-
background: ${semanticColors.global.surface.status.notification};
|
|
55
|
-
`,
|
|
56
|
-
download: css`
|
|
57
|
-
background: ${semanticColors.branding.surface.disabled};
|
|
58
|
-
`,
|
|
59
|
-
issue: css`
|
|
60
|
-
background: ${semanticColors.global.surface.status.online};
|
|
61
|
-
`,
|
|
62
|
-
order: css`
|
|
63
|
-
background: ${semanticColors.global.surface.status.online};
|
|
64
|
-
`,
|
|
65
|
-
created: css`
|
|
66
|
-
background: ${semanticColors.global.surface.status.online};
|
|
67
|
-
`,
|
|
68
|
-
updated: css`
|
|
69
|
-
background: ${semanticColors.global.surface.status.online};
|
|
70
|
-
`,
|
|
71
|
-
deleted: css`
|
|
72
|
-
background: ${semanticColors.global.surface.status.notification};
|
|
73
|
-
`,
|
|
74
|
-
info: css`
|
|
75
|
-
background: ${semanticColors.branding.surface.disabled};
|
|
76
|
-
`,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return bgMap[v] ?? bgMap.continued!;
|
|
80
|
-
}}
|
|
81
|
-
|
|
82
|
-
${({ $variant = 'continued' }) => {
|
|
83
|
-
const v = ($variant as TimelineVariant) || 'continued';
|
|
84
|
-
|
|
85
|
-
const borderMap: Partial<Record<TimelineVariant, ReturnType<typeof css>>> =
|
|
86
|
-
{
|
|
87
|
-
continued: css`
|
|
88
|
-
border-color: ${semanticColors.branding.surface.enabled};
|
|
89
|
-
`,
|
|
90
|
-
accepted: css`
|
|
91
|
-
border-color: ${semanticColors.global.border.feedback.success};
|
|
92
|
-
`,
|
|
93
|
-
rejected: css`
|
|
94
|
-
border-color: ${semanticColors.global.border.feedback.error};
|
|
95
|
-
`,
|
|
96
|
-
download: css`
|
|
97
|
-
border-color: ${semanticColors.branding.surface.enabled};
|
|
98
|
-
`,
|
|
99
|
-
issue: css`
|
|
100
|
-
border-color: ${semanticColors.global.border.feedback.success};
|
|
101
|
-
`,
|
|
102
|
-
order: css`
|
|
103
|
-
border-color: ${semanticColors.global.border.feedback.success};
|
|
104
|
-
`,
|
|
105
|
-
created: css`
|
|
106
|
-
border-color: ${semanticColors.global.border.feedback.success};
|
|
107
|
-
`,
|
|
108
|
-
updated: css`
|
|
109
|
-
border-color: ${semanticColors.global.border.feedback.success};
|
|
110
|
-
`,
|
|
111
|
-
deleted: css`
|
|
112
|
-
border-color: ${semanticColors.global.border.feedback.error};
|
|
113
|
-
`,
|
|
114
|
-
info: css`
|
|
115
|
-
border-color: ${semanticColors.branding.surface.enabled};
|
|
116
|
-
`,
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
return borderMap[v] ?? borderMap.continued!;
|
|
120
|
-
}}
|
|
121
|
-
`;
|
|
122
|
-
|
|
123
|
-
export const Card = styled.div`
|
|
124
|
-
background: #fff;
|
|
125
|
-
padding: 0px 8px;
|
|
126
|
-
margin-top: -4px;
|
|
127
|
-
`;
|
|
128
|
-
|
|
129
|
-
export const Title = styled.h4`
|
|
130
|
-
margin: 0 0 4px 0;
|
|
131
|
-
font-size: ${typographyTokens.fontSizes.headingL};
|
|
132
|
-
color: ${semanticColors.global.text.default.enabled};
|
|
133
|
-
font-weight: ${typographyTokens.fontWeights.semibold};
|
|
134
|
-
`;
|
|
135
|
-
|
|
136
|
-
export const Sub = styled.div`
|
|
137
|
-
color: ${semanticColors.global.text.subtitle.enabled};
|
|
138
|
-
font-size: 14px;
|
|
139
|
-
`;
|
|
140
|
-
|
|
141
|
-
export const Row = styled.div`
|
|
142
|
-
display: flex;
|
|
143
|
-
flex-wrap: wrap;
|
|
144
|
-
gap: 8px;
|
|
145
|
-
align-items: center;
|
|
146
|
-
`;
|
|
147
|
-
|
|
148
|
-
export const List = styled.ol`
|
|
149
|
-
list-style: none;
|
|
150
|
-
margin: 0;
|
|
151
|
-
padding: 0;
|
|
152
|
-
gap: 8px;
|
|
153
|
-
display: flex;
|
|
154
|
-
flex-direction: column;
|
|
155
|
-
`;
|
|
156
|
-
|
|
157
|
-
export const Empty = styled.div`
|
|
158
|
-
display: grid;
|
|
159
|
-
gap: 12px;
|
|
160
|
-
justify-items: start;
|
|
161
|
-
background: #fff;
|
|
162
|
-
border: 1px dashed ${primitiveColors.gray[300]};
|
|
163
|
-
border-radius: 12px;
|
|
164
|
-
padding: 16px;
|
|
165
|
-
color: ${semanticColors.global.text.subtitle.enabled};
|
|
166
|
-
`;
|
|
167
|
-
|
|
168
|
-
export const RetryButton = styled.button`
|
|
169
|
-
appearance: none;
|
|
170
|
-
border: 1px solid ${semanticColors.branding.surface.enabled};
|
|
171
|
-
background: ${semanticColors.branding.surface.enabled};
|
|
172
|
-
color: ${primitiveColors.base.white};
|
|
173
|
-
border-radius: 10px;
|
|
174
|
-
padding: 8px 12px;
|
|
175
|
-
font-size: ${typographyTokens.fontSizes.bodyM};
|
|
176
|
-
cursor: pointer;
|
|
177
|
-
|
|
178
|
-
&:hover {
|
|
179
|
-
filter: brightness(0.95);
|
|
180
|
-
}
|
|
181
|
-
&:active {
|
|
182
|
-
filter: brightness(0.9);
|
|
183
|
-
}
|
|
184
|
-
`;
|
|
1
|
+
import {
|
|
2
|
+
primitiveColors,
|
|
3
|
+
semanticColors,
|
|
4
|
+
typographyTokens,
|
|
5
|
+
} from '../../../styles/tokens';
|
|
6
|
+
import styled, { css } from 'styled-components';
|
|
7
|
+
import { TimelineVariant } from './TimeLine.types';
|
|
8
|
+
|
|
9
|
+
export const Time = styled.time`
|
|
10
|
+
color: #6b7280;
|
|
11
|
+
font-size: 0.78rem;
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
export const ItemWrap = styled.li`
|
|
15
|
+
display: grid;
|
|
16
|
+
grid-template-columns: 24px 1fr;
|
|
17
|
+
gap: 12px;
|
|
18
|
+
position: relative;
|
|
19
|
+
padding-bottom: 16px;
|
|
20
|
+
&:last-child {
|
|
21
|
+
padding-bottom: 0;
|
|
22
|
+
}
|
|
23
|
+
&:not(:last-child)::before {
|
|
24
|
+
content: '';
|
|
25
|
+
position: absolute;
|
|
26
|
+
left: 11px;
|
|
27
|
+
top: 34px;
|
|
28
|
+
bottom: 0;
|
|
29
|
+
width: 3px;
|
|
30
|
+
height: 100%;
|
|
31
|
+
background-color: ${primitiveColors.gray[200]};
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
export const Dot = styled.span<{ $variant?: TimelineVariant | string }>`
|
|
36
|
+
width: 24px;
|
|
37
|
+
height: 24px;
|
|
38
|
+
border-radius: 50%;
|
|
39
|
+
border: 1px solid;
|
|
40
|
+
display: inline-block;
|
|
41
|
+
margin-top: 0.2rem;
|
|
42
|
+
|
|
43
|
+
${({ $variant = 'continued' }) => {
|
|
44
|
+
const v = ($variant as TimelineVariant) || 'continued';
|
|
45
|
+
|
|
46
|
+
const bgMap: Partial<Record<TimelineVariant, ReturnType<typeof css>>> = {
|
|
47
|
+
continued: css`
|
|
48
|
+
background: ${semanticColors.branding.surface.disabled};
|
|
49
|
+
`,
|
|
50
|
+
accepted: css`
|
|
51
|
+
background: ${semanticColors.global.surface.status.online};
|
|
52
|
+
`,
|
|
53
|
+
rejected: css`
|
|
54
|
+
background: ${semanticColors.global.surface.status.notification};
|
|
55
|
+
`,
|
|
56
|
+
download: css`
|
|
57
|
+
background: ${semanticColors.branding.surface.disabled};
|
|
58
|
+
`,
|
|
59
|
+
issue: css`
|
|
60
|
+
background: ${semanticColors.global.surface.status.online};
|
|
61
|
+
`,
|
|
62
|
+
order: css`
|
|
63
|
+
background: ${semanticColors.global.surface.status.online};
|
|
64
|
+
`,
|
|
65
|
+
created: css`
|
|
66
|
+
background: ${semanticColors.global.surface.status.online};
|
|
67
|
+
`,
|
|
68
|
+
updated: css`
|
|
69
|
+
background: ${semanticColors.global.surface.status.online};
|
|
70
|
+
`,
|
|
71
|
+
deleted: css`
|
|
72
|
+
background: ${semanticColors.global.surface.status.notification};
|
|
73
|
+
`,
|
|
74
|
+
info: css`
|
|
75
|
+
background: ${semanticColors.branding.surface.disabled};
|
|
76
|
+
`,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return bgMap[v] ?? bgMap.continued!;
|
|
80
|
+
}}
|
|
81
|
+
|
|
82
|
+
${({ $variant = 'continued' }) => {
|
|
83
|
+
const v = ($variant as TimelineVariant) || 'continued';
|
|
84
|
+
|
|
85
|
+
const borderMap: Partial<Record<TimelineVariant, ReturnType<typeof css>>> =
|
|
86
|
+
{
|
|
87
|
+
continued: css`
|
|
88
|
+
border-color: ${semanticColors.branding.surface.enabled};
|
|
89
|
+
`,
|
|
90
|
+
accepted: css`
|
|
91
|
+
border-color: ${semanticColors.global.border.feedback.success};
|
|
92
|
+
`,
|
|
93
|
+
rejected: css`
|
|
94
|
+
border-color: ${semanticColors.global.border.feedback.error};
|
|
95
|
+
`,
|
|
96
|
+
download: css`
|
|
97
|
+
border-color: ${semanticColors.branding.surface.enabled};
|
|
98
|
+
`,
|
|
99
|
+
issue: css`
|
|
100
|
+
border-color: ${semanticColors.global.border.feedback.success};
|
|
101
|
+
`,
|
|
102
|
+
order: css`
|
|
103
|
+
border-color: ${semanticColors.global.border.feedback.success};
|
|
104
|
+
`,
|
|
105
|
+
created: css`
|
|
106
|
+
border-color: ${semanticColors.global.border.feedback.success};
|
|
107
|
+
`,
|
|
108
|
+
updated: css`
|
|
109
|
+
border-color: ${semanticColors.global.border.feedback.success};
|
|
110
|
+
`,
|
|
111
|
+
deleted: css`
|
|
112
|
+
border-color: ${semanticColors.global.border.feedback.error};
|
|
113
|
+
`,
|
|
114
|
+
info: css`
|
|
115
|
+
border-color: ${semanticColors.branding.surface.enabled};
|
|
116
|
+
`,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return borderMap[v] ?? borderMap.continued!;
|
|
120
|
+
}}
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
export const Card = styled.div`
|
|
124
|
+
background: #fff;
|
|
125
|
+
padding: 0px 8px;
|
|
126
|
+
margin-top: -4px;
|
|
127
|
+
`;
|
|
128
|
+
|
|
129
|
+
export const Title = styled.h4`
|
|
130
|
+
margin: 0 0 4px 0;
|
|
131
|
+
font-size: ${typographyTokens.fontSizes.headingL};
|
|
132
|
+
color: ${semanticColors.global.text.default.enabled};
|
|
133
|
+
font-weight: ${typographyTokens.fontWeights.semibold};
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
export const Sub = styled.div`
|
|
137
|
+
color: ${semanticColors.global.text.subtitle.enabled};
|
|
138
|
+
font-size: 14px;
|
|
139
|
+
`;
|
|
140
|
+
|
|
141
|
+
export const Row = styled.div`
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-wrap: wrap;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
align-items: center;
|
|
146
|
+
`;
|
|
147
|
+
|
|
148
|
+
export const List = styled.ol`
|
|
149
|
+
list-style: none;
|
|
150
|
+
margin: 0;
|
|
151
|
+
padding: 0;
|
|
152
|
+
gap: 8px;
|
|
153
|
+
display: flex;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
export const Empty = styled.div`
|
|
158
|
+
display: grid;
|
|
159
|
+
gap: 12px;
|
|
160
|
+
justify-items: start;
|
|
161
|
+
background: #fff;
|
|
162
|
+
border: 1px dashed ${primitiveColors.gray[300]};
|
|
163
|
+
border-radius: 12px;
|
|
164
|
+
padding: 16px;
|
|
165
|
+
color: ${semanticColors.global.text.subtitle.enabled};
|
|
166
|
+
`;
|
|
167
|
+
|
|
168
|
+
export const RetryButton = styled.button`
|
|
169
|
+
appearance: none;
|
|
170
|
+
border: 1px solid ${semanticColors.branding.surface.enabled};
|
|
171
|
+
background: ${semanticColors.branding.surface.enabled};
|
|
172
|
+
color: ${primitiveColors.base.white};
|
|
173
|
+
border-radius: 10px;
|
|
174
|
+
padding: 8px 12px;
|
|
175
|
+
font-size: ${typographyTokens.fontSizes.bodyM};
|
|
176
|
+
cursor: pointer;
|
|
177
|
+
|
|
178
|
+
&:hover {
|
|
179
|
+
filter: brightness(0.95);
|
|
180
|
+
}
|
|
181
|
+
&:active {
|
|
182
|
+
filter: brightness(0.9);
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
ItemWrap,
|
|
4
|
-
Card,
|
|
5
|
-
Sub,
|
|
6
|
-
Row,
|
|
7
|
-
Dot,
|
|
8
|
-
List,
|
|
9
|
-
Title,
|
|
10
|
-
Empty,
|
|
11
|
-
RetryButton,
|
|
12
|
-
} from './TimeLine.styles';
|
|
13
|
-
import { TimelineProps } from './TimeLine.types';
|
|
14
|
-
import { Skeleton } from '../../atoms/Skeleton/Skeleton';
|
|
15
|
-
|
|
16
|
-
function formatDateTimePtBr(iso: string) {
|
|
17
|
-
const d = new Date(iso);
|
|
18
|
-
if (Number.isNaN(d.getTime())) return { dateStr: '', timeStr: '' };
|
|
19
|
-
|
|
20
|
-
const dateStr = d.toLocaleDateString('pt-BR');
|
|
21
|
-
const timeStr = d.toLocaleTimeString('pt-BR', {
|
|
22
|
-
hour: '2-digit',
|
|
23
|
-
minute: '2-digit',
|
|
24
|
-
});
|
|
25
|
-
return { dateStr, timeStr };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const Timeline: React.FC<TimelineProps> = ({
|
|
29
|
-
items,
|
|
30
|
-
loading = false,
|
|
31
|
-
onRetry,
|
|
32
|
-
emptyLabel = 'Nenhum evento encontrado.',
|
|
33
|
-
skeletonItems = 3,
|
|
34
|
-
}) => {
|
|
35
|
-
if (loading) {
|
|
36
|
-
return (
|
|
37
|
-
<List aria-label="Linha do tempo (carregando)">
|
|
38
|
-
{Array.from({ length: skeletonItems }).map((_, i) => (
|
|
39
|
-
<ItemWrap key={`sk-${i}`}>
|
|
40
|
-
<Skeleton
|
|
41
|
-
variant="circle"
|
|
42
|
-
width={24}
|
|
43
|
-
height={24}
|
|
44
|
-
ariaLabel="Carregando ponto da linha do tempo"
|
|
45
|
-
/>
|
|
46
|
-
|
|
47
|
-
<Card>
|
|
48
|
-
<Title>
|
|
49
|
-
<Skeleton variant="text" width="60%" height={32} />
|
|
50
|
-
</Title>
|
|
51
|
-
|
|
52
|
-
<Sub>
|
|
53
|
-
<Skeleton variant="text" width="40%" height={18} />
|
|
54
|
-
</Sub>
|
|
55
|
-
</Card>
|
|
56
|
-
</ItemWrap>
|
|
57
|
-
))}
|
|
58
|
-
</List>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!items?.length) {
|
|
63
|
-
return (
|
|
64
|
-
<Empty role="status" aria-live="polite">
|
|
65
|
-
<div>{emptyLabel}</div>
|
|
66
|
-
{onRetry && (
|
|
67
|
-
<RetryButton type="button" onClick={onRetry}>
|
|
68
|
-
Tentar novamente
|
|
69
|
-
</RetryButton>
|
|
70
|
-
)}
|
|
71
|
-
</Empty>
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<List aria-label="Linha do tempo">
|
|
77
|
-
{items.map((it) => {
|
|
78
|
-
const { dateStr, timeStr } = formatDateTimePtBr(it.timestamp);
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<ItemWrap key={it.id}>
|
|
82
|
-
<Dot aria-hidden $variant={it.type} />
|
|
83
|
-
<Card>
|
|
84
|
-
<Row style={{ justifyContent: 'space-between' }}>
|
|
85
|
-
<Title>{it.title}</Title>
|
|
86
|
-
</Row>
|
|
87
|
-
|
|
88
|
-
<Sub>
|
|
89
|
-
<div>
|
|
90
|
-
Por: {it.actor.displayName} no dia{' '}
|
|
91
|
-
{dateStr ? `${dateStr} às ${timeStr}` : ''}
|
|
92
|
-
</div>
|
|
93
|
-
</Sub>
|
|
94
|
-
</Card>
|
|
95
|
-
</ItemWrap>
|
|
96
|
-
);
|
|
97
|
-
})}
|
|
98
|
-
</List>
|
|
99
|
-
);
|
|
100
|
-
};
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ItemWrap,
|
|
4
|
+
Card,
|
|
5
|
+
Sub,
|
|
6
|
+
Row,
|
|
7
|
+
Dot,
|
|
8
|
+
List,
|
|
9
|
+
Title,
|
|
10
|
+
Empty,
|
|
11
|
+
RetryButton,
|
|
12
|
+
} from './TimeLine.styles';
|
|
13
|
+
import { TimelineProps } from './TimeLine.types';
|
|
14
|
+
import { Skeleton } from '../../atoms/Skeleton/Skeleton';
|
|
15
|
+
|
|
16
|
+
function formatDateTimePtBr(iso: string) {
|
|
17
|
+
const d = new Date(iso);
|
|
18
|
+
if (Number.isNaN(d.getTime())) return { dateStr: '', timeStr: '' };
|
|
19
|
+
|
|
20
|
+
const dateStr = d.toLocaleDateString('pt-BR');
|
|
21
|
+
const timeStr = d.toLocaleTimeString('pt-BR', {
|
|
22
|
+
hour: '2-digit',
|
|
23
|
+
minute: '2-digit',
|
|
24
|
+
});
|
|
25
|
+
return { dateStr, timeStr };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Timeline: React.FC<TimelineProps> = ({
|
|
29
|
+
items,
|
|
30
|
+
loading = false,
|
|
31
|
+
onRetry,
|
|
32
|
+
emptyLabel = 'Nenhum evento encontrado.',
|
|
33
|
+
skeletonItems = 3,
|
|
34
|
+
}) => {
|
|
35
|
+
if (loading) {
|
|
36
|
+
return (
|
|
37
|
+
<List aria-label="Linha do tempo (carregando)">
|
|
38
|
+
{Array.from({ length: skeletonItems }).map((_, i) => (
|
|
39
|
+
<ItemWrap key={`sk-${i}`}>
|
|
40
|
+
<Skeleton
|
|
41
|
+
variant="circle"
|
|
42
|
+
width={24}
|
|
43
|
+
height={24}
|
|
44
|
+
ariaLabel="Carregando ponto da linha do tempo"
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
<Card>
|
|
48
|
+
<Title>
|
|
49
|
+
<Skeleton variant="text" width="60%" height={32} />
|
|
50
|
+
</Title>
|
|
51
|
+
|
|
52
|
+
<Sub>
|
|
53
|
+
<Skeleton variant="text" width="40%" height={18} />
|
|
54
|
+
</Sub>
|
|
55
|
+
</Card>
|
|
56
|
+
</ItemWrap>
|
|
57
|
+
))}
|
|
58
|
+
</List>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!items?.length) {
|
|
63
|
+
return (
|
|
64
|
+
<Empty role="status" aria-live="polite">
|
|
65
|
+
<div>{emptyLabel}</div>
|
|
66
|
+
{onRetry && (
|
|
67
|
+
<RetryButton type="button" onClick={onRetry}>
|
|
68
|
+
Tentar novamente
|
|
69
|
+
</RetryButton>
|
|
70
|
+
)}
|
|
71
|
+
</Empty>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<List aria-label="Linha do tempo">
|
|
77
|
+
{items.map((it) => {
|
|
78
|
+
const { dateStr, timeStr } = formatDateTimePtBr(it.timestamp);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<ItemWrap key={it.id}>
|
|
82
|
+
<Dot aria-hidden $variant={it.type} />
|
|
83
|
+
<Card>
|
|
84
|
+
<Row style={{ justifyContent: 'space-between' }}>
|
|
85
|
+
<Title>{it.title}</Title>
|
|
86
|
+
</Row>
|
|
87
|
+
|
|
88
|
+
<Sub>
|
|
89
|
+
<div>
|
|
90
|
+
Por: {it.actor.displayName} no dia{' '}
|
|
91
|
+
{dateStr ? `${dateStr} às ${timeStr}` : ''}
|
|
92
|
+
</div>
|
|
93
|
+
</Sub>
|
|
94
|
+
</Card>
|
|
95
|
+
</ItemWrap>
|
|
96
|
+
);
|
|
97
|
+
})}
|
|
98
|
+
</List>
|
|
99
|
+
);
|
|
100
|
+
};
|