@snksergio/design-system 0.62.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/ai/blocos/chart/budget-breakdown.tsx +174 -0
- package/dist-lib/ai/blocos/indice.md +43 -0
- package/dist-lib/ai/blocos/paneldetail/detalhe-com-tabela.tsx +450 -0
- package/dist-lib/ai/blocos/paneldetail/detalhe-de-tarefa-com-abas.tsx +570 -0
- package/dist-lib/ai/blocos/paneldetail/detalhe-do-registro.tsx +555 -0
- package/dist-lib/ai/componentes/DataTable.md +2 -1
- package/dist-lib/ai/componentes/TableToolbar.md +1 -1
- package/dist-lib/ai/exemplos/app-shell/app-shell-example.tsx +140 -0
- package/dist-lib/ai/exemplos/app-shell/index.ts +3 -0
- package/dist-lib/ai/exemplos/app-shell/nav-data.ts +97 -0
- package/dist-lib/ai/exemplos/app-shell/routes.tsx +75 -0
- package/dist-lib/ai/exemplos/chat/chat-screen.tsx +152 -0
- package/dist-lib/ai/exemplos/chat/chat-v2-mocks.ts +171 -0
- package/dist-lib/ai/exemplos/chat/chat-v2.styles.ts +23 -0
- package/dist-lib/ai/exemplos/chat/chat-v2.types.ts +81 -0
- package/dist-lib/ai/exemplos/chat/components/ChannelDot/channel-dot.tsx +28 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/conversation-actions-menu.tsx +83 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/index.ts +4 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.styles.ts +22 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.tsx +203 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.types.ts +10 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationColumn/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.styles.ts +55 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.tsx +52 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.types.ts +7 -0
- package/dist-lib/ai/exemplos/chat/components/ConversationListItem/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/DateSeparator/date-separator.tsx +18 -0
- package/dist-lib/ai/exemplos/chat/components/DetailField/detail-field.tsx +23 -0
- package/dist-lib/ai/exemplos/chat/components/DetailSection/detail-section.tsx +41 -0
- package/dist-lib/ai/exemplos/chat/components/DetailSection/index.ts +1 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.styles.ts +30 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.tsx +142 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.types.ts +16 -0
- package/dist-lib/ai/exemplos/chat/components/DetailsColumn/index.ts +5 -0
- package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.styles.ts +37 -0
- package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.tsx +45 -0
- package/dist-lib/ai/exemplos/chat/components/FilterRow/index.ts +1 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.styles.ts +27 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.tsx +66 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.types.ts +13 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-rail.tsx +38 -0
- package/dist-lib/ai/exemplos/chat/components/FiltersColumn/index.ts +6 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.styles.ts +37 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.tsx +29 -0
- package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.types.ts +5 -0
- package/dist-lib/ai/exemplos/chat/components/PersonAvatar/index.ts +5 -0
- package/dist-lib/ai/exemplos/chat/components/PersonAvatar/person-avatar.tsx +31 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/index.ts +2 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.styles.ts +19 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.tsx +140 -0
- package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.types.ts +13 -0
- package/dist-lib/ai/exemplos/chat/components/RailItem/index.ts +1 -0
- package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.styles.ts +30 -0
- package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.tsx +42 -0
- package/dist-lib/ai/exemplos/chat/hooks/use-resizable.ts +98 -0
- package/dist-lib/ai/exemplos/chat/index.ts +1 -0
- package/dist-lib/ai/exemplos/clientes/_table-data.ts +59 -0
- package/dist-lib/ai/exemplos/clientes/clientes-screen.tsx +505 -0
- package/dist-lib/ai/exemplos/clientes/clientes-showcase-mocks.ts +117 -0
- package/dist-lib/ai/exemplos/clientes/clientes-showcase.styles.ts +13 -0
- package/dist-lib/ai/exemplos/clientes/clientes-showcase.types.ts +16 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.styles.ts +28 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.tsx +303 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.types.ts +14 -0
- package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/index.ts +2 -0
- package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/index.ts +2 -0
- package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
- package/dist-lib/ai/exemplos/clientes/index.ts +1 -0
- package/dist-lib/ai/exemplos/edit-page/components/StepNav.tsx +81 -0
- package/dist-lib/ai/exemplos/edit-page/components/section-card.tsx +85 -0
- package/dist-lib/ai/exemplos/edit-page/edit-page-screen.tsx +234 -0
- package/dist-lib/ai/exemplos/edit-page/index.ts +1 -0
- package/dist-lib/ai/exemplos/finance/_table-data.ts +57 -0
- package/dist-lib/ai/exemplos/finance/clientes-financeiro-mocks.ts +227 -0
- package/dist-lib/ai/exemplos/finance/clientes-financeiro.types.ts +75 -0
- package/dist-lib/ai/exemplos/finance/clientes-showcase-mocks.ts +117 -0
- package/dist-lib/ai/exemplos/finance/clientes-showcase.styles.ts +13 -0
- package/dist-lib/ai/exemplos/finance/clientes-showcase.types.ts +16 -0
- package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/editar-finance-drawer.tsx +241 -0
- package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/index.ts +5 -0
- package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/extrato-expansion.tsx +172 -0
- package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/index.ts +1 -0
- package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/finance-detail-panel.tsx +241 -0
- package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/index.ts +2 -0
- package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/index.ts +2 -0
- package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
- package/dist-lib/ai/exemplos/finance/components/SacarDialog/index.ts +2 -0
- package/dist-lib/ai/exemplos/finance/components/SacarDialog/sacar-dialog.tsx +346 -0
- package/dist-lib/ai/exemplos/finance/finance-screen.tsx +821 -0
- package/dist-lib/ai/exemplos/finance/index.ts +1 -0
- package/dist-lib/ai/exemplos/gantt/_gantt-data.tsx +402 -0
- package/dist-lib/ai/exemplos/gantt/gantt-screen.tsx +512 -0
- package/dist-lib/ai/exemplos/gantt/index.ts +1 -0
- package/dist-lib/ai/exemplos/login/index.ts +1 -0
- package/dist-lib/ai/exemplos/login/login-screen.tsx +246 -0
- package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/consultor-detail-panel.tsx +158 -0
- package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/index.ts +2 -0
- package/dist-lib/ai/exemplos/mapa-rede/index.ts +1 -0
- package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede-mocks.ts +655 -0
- package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede.types.ts +53 -0
- package/dist-lib/ai/exemplos/mapa-rede/mapa-rede-screen.tsx +227 -0
- package/dist-lib/ai/exemplos/order-detail/components/ActivityTab.tsx +77 -0
- package/dist-lib/ai/exemplos/order-detail/components/AttachmentsTab.tsx +45 -0
- package/dist-lib/ai/exemplos/order-detail/components/CommentsTab.tsx +111 -0
- package/dist-lib/ai/exemplos/order-detail/components/DetailsTab.tsx +189 -0
- package/dist-lib/ai/exemplos/order-detail/components/OverviewTab.tsx +200 -0
- package/dist-lib/ai/exemplos/order-detail/components/section-card.tsx +85 -0
- package/dist-lib/ai/exemplos/order-detail/index.ts +1 -0
- package/dist-lib/ai/exemplos/order-detail/order-detail-screen.tsx +119 -0
- package/dist-lib/ai/exemplos/order-detail/order-mocks.ts +186 -0
- package/dist-lib/ai/exemplos/order-detail/order.types.ts +118 -0
- package/dist-lib/ai/global/componentes.md +7 -0
- package/dist-lib/ai/indice.json +30 -15
- package/dist-lib/ai/manifest.json +32 -6
- package/dist-lib/ai/roteiros/app-builder/roteiro.md +155 -0
- package/dist-lib/ai/roteiros/auth-builder/roteiro.md +42 -0
- package/dist-lib/ai/roteiros/cards/roteiro.md +34 -0
- package/dist-lib/ai/roteiros/charts/roteiro.md +32 -0
- package/dist-lib/ai/roteiros/chat/roteiro.md +31 -0
- package/dist-lib/ai/roteiros/crud-builder/blueprint.md +63 -0
- package/dist-lib/ai/roteiros/crud-builder/entrevista.md +146 -0
- package/dist-lib/ai/roteiros/crud-builder/geracao.md +113 -0
- package/dist-lib/ai/roteiros/crud-builder/roteiro.md +89 -0
- package/dist-lib/ai/roteiros/drawers/roteiro.md +41 -0
- package/dist-lib/ai/roteiros/list-builder/blueprint.md +94 -0
- package/dist-lib/ai/roteiros/list-builder/entrevista.md +193 -0
- package/dist-lib/ai/roteiros/list-builder/geracao.md +63 -0
- package/dist-lib/ai/roteiros/list-builder/roteiro.md +91 -0
- package/dist-lib/ai/roteiros/module-replicator/roteiro.md +56 -0
- package/dist-lib/ai/roteiros/page-detail/roteiro.md +32 -0
- package/dist-lib/ai/roteiros/page-edit/roteiro.md +31 -0
- package/dist-lib/ai/roteiros/screen-composer/roteiro.md +95 -0
- package/dist-lib/chunks/{panel-B-liPlxr.mjs → panel-CN0ChoHM.mjs} +5 -2
- package/dist-lib/chunks/{panel-B-liPlxr.mjs.map → panel-CN0ChoHM.mjs.map} +1 -1
- package/dist-lib/chunks/{panel-DoNbjeqX.cjs → panel-Cpq1xHck.cjs} +5 -2
- package/dist-lib/chunks/{panel-DoNbjeqX.cjs.map → panel-Cpq1xHck.cjs.map} +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/index.mjs +2 -2
- package/dist-lib/preview/clientes.cjs +1 -1
- package/dist-lib/preview/clientes.mjs +1 -1
- package/dist-lib/src/components/ui/DataTable/data-table.d.ts.map +1 -1
- package/dist-lib/src/components/ui/DataTable/data-table.types.d.ts +20 -2
- package/dist-lib/src/components/ui/DataTable/data-table.types.d.ts.map +1 -1
- package/package.json +1 -1
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/blueprint.md +0 -0
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/entrevista.md +0 -0
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/geracao.md +0 -0
- /package/dist-lib/ai/roteiros/{dashboard → dashboard-builder}/roteiro.md +0 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { Mail, Phone } from "lucide-react";
|
|
2
|
+
import { Avatar } from "@/components/ui/avatar-ig";
|
|
3
|
+
import { Chip } from "@/components/ui/Chip";
|
|
4
|
+
import { SectionCard, SectionDivider } from "./section-card";
|
|
5
|
+
import { formatBRL } from "../order-mocks";
|
|
6
|
+
import type { Order } from "../order.types";
|
|
7
|
+
|
|
8
|
+
export function OverviewTab({ order }: { order: Order }) {
|
|
9
|
+
const c = order.customer;
|
|
10
|
+
const addr = order.shippingAddress;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className="grid grid-cols-1 gap-gp-2xl lg:grid-cols-3">
|
|
14
|
+
{/* Coluna principal */}
|
|
15
|
+
<div className="flex flex-col gap-gp-2xl lg:col-span-2">
|
|
16
|
+
{/* Produtos */}
|
|
17
|
+
<SectionCard title="Produtos do pedido">
|
|
18
|
+
<ul className="flex flex-col">
|
|
19
|
+
{order.items.map((item, i) => (
|
|
20
|
+
<li
|
|
21
|
+
key={item.id}
|
|
22
|
+
className={
|
|
23
|
+
"flex items-center gap-gp-lg py-pad-lg" +
|
|
24
|
+
(i > 0 ? " border-t border-border-subtle" : "")
|
|
25
|
+
}
|
|
26
|
+
>
|
|
27
|
+
<span
|
|
28
|
+
className="size-12 shrink-0 rounded-radius-md"
|
|
29
|
+
style={{ backgroundColor: `${item.thumb}1f` }}
|
|
30
|
+
aria-hidden="true"
|
|
31
|
+
/>
|
|
32
|
+
<div className="min-w-0 flex-1">
|
|
33
|
+
<p className="text-body-md font-semibold text-fg-default">
|
|
34
|
+
{item.name}
|
|
35
|
+
</p>
|
|
36
|
+
<p className="text-caption-sm text-fg-muted">
|
|
37
|
+
SKU: {item.sku}
|
|
38
|
+
</p>
|
|
39
|
+
</div>
|
|
40
|
+
<div className="shrink-0 text-right">
|
|
41
|
+
<p className="text-body-md font-semibold text-fg-default [font-variant-numeric:tabular-nums]">
|
|
42
|
+
{formatBRL(item.price)}
|
|
43
|
+
</p>
|
|
44
|
+
<p className="text-caption-sm text-fg-muted">
|
|
45
|
+
Qtd: {item.qty}
|
|
46
|
+
</p>
|
|
47
|
+
</div>
|
|
48
|
+
</li>
|
|
49
|
+
))}
|
|
50
|
+
</ul>
|
|
51
|
+
</SectionCard>
|
|
52
|
+
|
|
53
|
+
{/* Pagamento */}
|
|
54
|
+
<SectionCard
|
|
55
|
+
title="Pagamento"
|
|
56
|
+
action={
|
|
57
|
+
<Chip color="success" variant="soft" size="sm" shape="pill">
|
|
58
|
+
Pago
|
|
59
|
+
</Chip>
|
|
60
|
+
}
|
|
61
|
+
>
|
|
62
|
+
<dl className="flex flex-col gap-gp-md">
|
|
63
|
+
<Row label="Subtotal" value={formatBRL(order.subtotal)} />
|
|
64
|
+
<Row label="Frete" value={formatBRL(order.shipping)} />
|
|
65
|
+
<Row label="Impostos" value={formatBRL(order.tax)} />
|
|
66
|
+
{order.discountValue != null && (
|
|
67
|
+
<Row
|
|
68
|
+
label={`Desconto (${order.discountCode})`}
|
|
69
|
+
value={`- ${formatBRL(order.discountValue)}`}
|
|
70
|
+
accent
|
|
71
|
+
/>
|
|
72
|
+
)}
|
|
73
|
+
<div className="mt-gp-xs flex items-center justify-between border-t border-border-subtle pt-pad-lg">
|
|
74
|
+
<dt className="text-body-md font-semibold text-fg-default">
|
|
75
|
+
Total
|
|
76
|
+
</dt>
|
|
77
|
+
<dd className="text-body-md font-semibold text-fg-default [font-variant-numeric:tabular-nums]">
|
|
78
|
+
{formatBRL(order.total)}
|
|
79
|
+
</dd>
|
|
80
|
+
</div>
|
|
81
|
+
<div className="flex items-center justify-between">
|
|
82
|
+
<dt className="text-title-md font-semibold text-fg-default">
|
|
83
|
+
Pago pelo cliente
|
|
84
|
+
</dt>
|
|
85
|
+
<dd className="text-title-md font-semibold text-fg-default [font-variant-numeric:tabular-nums]">
|
|
86
|
+
{formatBRL(order.total)}
|
|
87
|
+
</dd>
|
|
88
|
+
</div>
|
|
89
|
+
</dl>
|
|
90
|
+
</SectionCard>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
{/* Coluna lateral */}
|
|
94
|
+
<div className="flex flex-col gap-gp-2xl">
|
|
95
|
+
<SectionCard title="Cliente">
|
|
96
|
+
<div className="flex items-center gap-gp-md">
|
|
97
|
+
<Avatar size="lg" colorHex={c.colorHex} aria-label={`${c.firstName} ${c.lastName}`}>
|
|
98
|
+
{c.initials}
|
|
99
|
+
</Avatar>
|
|
100
|
+
<div className="min-w-0">
|
|
101
|
+
<p className="text-body-md font-semibold text-fg-default">
|
|
102
|
+
{c.firstName} {c.lastName}
|
|
103
|
+
</p>
|
|
104
|
+
<p className="text-caption-sm text-fg-muted">
|
|
105
|
+
{c.previousOrders} pedidos anteriores
|
|
106
|
+
</p>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<SectionDivider className="my-gp-2xl" />
|
|
111
|
+
|
|
112
|
+
<div className="flex flex-col gap-gp-md">
|
|
113
|
+
<a
|
|
114
|
+
href={`mailto:${c.email}`}
|
|
115
|
+
className="flex items-center gap-gp-sm text-body-sm text-fg-default hover:text-fg-brand"
|
|
116
|
+
>
|
|
117
|
+
<Mail className="size-icon-sm shrink-0 text-fg-muted" />
|
|
118
|
+
<span className="truncate">{c.email}</span>
|
|
119
|
+
</a>
|
|
120
|
+
<span className="flex items-center gap-gp-sm text-body-sm text-fg-default">
|
|
121
|
+
<Phone className="size-icon-sm shrink-0 text-fg-muted" />
|
|
122
|
+
{c.phone}
|
|
123
|
+
</span>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<SectionDivider className="my-gp-2xl" />
|
|
127
|
+
|
|
128
|
+
<AddressBlock
|
|
129
|
+
title="Endereço de entrega"
|
|
130
|
+
lines={[
|
|
131
|
+
addr.line1,
|
|
132
|
+
addr.line2,
|
|
133
|
+
`${addr.city} — ${addr.state}`,
|
|
134
|
+
addr.zip,
|
|
135
|
+
addr.country,
|
|
136
|
+
]}
|
|
137
|
+
/>
|
|
138
|
+
|
|
139
|
+
<SectionDivider className="my-gp-2xl" />
|
|
140
|
+
|
|
141
|
+
<AddressBlock
|
|
142
|
+
title="Endereço de cobrança"
|
|
143
|
+
lines={[
|
|
144
|
+
order.billing.address,
|
|
145
|
+
order.billing.cityState,
|
|
146
|
+
order.billing.country,
|
|
147
|
+
]}
|
|
148
|
+
/>
|
|
149
|
+
</SectionCard>
|
|
150
|
+
|
|
151
|
+
<SectionCard title="Observação do cliente">
|
|
152
|
+
<p className="text-body-sm leading-relaxed text-fg-muted">
|
|
153
|
+
{order.note}
|
|
154
|
+
</p>
|
|
155
|
+
</SectionCard>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function Row({
|
|
162
|
+
label,
|
|
163
|
+
value,
|
|
164
|
+
accent,
|
|
165
|
+
}: {
|
|
166
|
+
label: string;
|
|
167
|
+
value: string;
|
|
168
|
+
accent?: boolean;
|
|
169
|
+
}) {
|
|
170
|
+
return (
|
|
171
|
+
<div className="flex items-center justify-between">
|
|
172
|
+
<dt className="text-body-sm text-fg-muted">{label}</dt>
|
|
173
|
+
<dd
|
|
174
|
+
className={
|
|
175
|
+
"text-body-sm [font-variant-numeric:tabular-nums] " +
|
|
176
|
+
(accent ? "text-fg-success" : "text-fg-default")
|
|
177
|
+
}
|
|
178
|
+
>
|
|
179
|
+
{value}
|
|
180
|
+
</dd>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function AddressBlock({ title, lines }: { title: string; lines: (string | undefined)[] }) {
|
|
186
|
+
return (
|
|
187
|
+
<div>
|
|
188
|
+
<p className="mb-gp-xs text-caption-sm font-semibold uppercase tracking-wider text-fg-muted">
|
|
189
|
+
{title}
|
|
190
|
+
</p>
|
|
191
|
+
<address className="not-italic text-body-sm leading-relaxed text-fg-default">
|
|
192
|
+
{lines.filter(Boolean).map((l, i) => (
|
|
193
|
+
<span key={i} className="block">
|
|
194
|
+
{l}
|
|
195
|
+
</span>
|
|
196
|
+
))}
|
|
197
|
+
</address>
|
|
198
|
+
</div>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Card de seção flat — bg-surface + borda sutil, sem elevação pesada.
|
|
6
|
+
* Espelha o visual dos blocos da referência (Products ordered, Customer, etc).
|
|
7
|
+
* Composição local do showcase consumindo tokens DS via classes.
|
|
8
|
+
*/
|
|
9
|
+
export function SectionCard({
|
|
10
|
+
title,
|
|
11
|
+
icon,
|
|
12
|
+
action,
|
|
13
|
+
children,
|
|
14
|
+
className,
|
|
15
|
+
bodyClassName,
|
|
16
|
+
}: {
|
|
17
|
+
title?: ReactNode;
|
|
18
|
+
icon?: ReactNode;
|
|
19
|
+
action?: ReactNode;
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
className?: string;
|
|
22
|
+
bodyClassName?: string;
|
|
23
|
+
}) {
|
|
24
|
+
const hasHeader = !!(title || action);
|
|
25
|
+
const header = hasHeader && (
|
|
26
|
+
// Header: padding 16px (pad-2xl) + divider full-bleed embaixo.
|
|
27
|
+
<header className="flex items-center justify-between gap-gp-md border-b border-border-subtle bg-bg-subtle p-pad-2xl">
|
|
28
|
+
{/* gap ícone↔título = 12px (gap-gp-md) */}
|
|
29
|
+
<div className="flex items-center gap-gp-md">
|
|
30
|
+
{icon && (
|
|
31
|
+
<span className="grid size-8 shrink-0 place-items-center rounded-radius-md bg-bg-muted text-fg-muted">
|
|
32
|
+
{icon}
|
|
33
|
+
</span>
|
|
34
|
+
)}
|
|
35
|
+
{title && (
|
|
36
|
+
<h2 className="text-title-md font-semibold text-fg-default">
|
|
37
|
+
{title}
|
|
38
|
+
</h2>
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
41
|
+
{action}
|
|
42
|
+
</header>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<section className={cn("overflow-hidden rounded-radius-lg border border-border-subtle bg-bg-surface shadow-sh-sm", className)}>
|
|
47
|
+
{header}
|
|
48
|
+
{/* body: padding 16px (pad-2xl) — uniforme; abaixo do divider quando há header */}
|
|
49
|
+
<div className={cn("p-pad-2xl", bodyClassName)}>{children}</div>
|
|
50
|
+
</section>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Divisória sutil de seção. `my` controla o respiro vertical (default md). */
|
|
55
|
+
export function SectionDivider({ className }: { className?: string }) {
|
|
56
|
+
return <div className={cn("h-px bg-border-subtle", className)} />;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Par label-uppercase + valor (grid de Customer/Shipping/Billing Information). */
|
|
60
|
+
export function Field({
|
|
61
|
+
label,
|
|
62
|
+
value,
|
|
63
|
+
accent,
|
|
64
|
+
}: {
|
|
65
|
+
label: string;
|
|
66
|
+
value: ReactNode;
|
|
67
|
+
/** Destaca o valor com a cor de marca (links, ids de transação, etc). */
|
|
68
|
+
accent?: boolean;
|
|
69
|
+
}) {
|
|
70
|
+
return (
|
|
71
|
+
<div className="flex flex-col gap-gp-2xs">
|
|
72
|
+
<span className="text-caption-sm font-medium uppercase tracking-wider text-fg-muted">
|
|
73
|
+
{label}
|
|
74
|
+
</span>
|
|
75
|
+
<span
|
|
76
|
+
className={cn(
|
|
77
|
+
"text-body-md",
|
|
78
|
+
accent ? "text-fg-brand" : "text-fg-default",
|
|
79
|
+
)}
|
|
80
|
+
>
|
|
81
|
+
{value}
|
|
82
|
+
</span>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { OrderDetailScreen, default } from "./order-detail-screen";
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
ChevronLeft,
|
|
4
|
+
ChevronRight,
|
|
5
|
+
MoreHorizontal,
|
|
6
|
+
Pencil,
|
|
7
|
+
RotateCcw,
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
import { Button } from "@/components/ui/Button/button";
|
|
10
|
+
import { Chip } from "@/components/ui/Chip";
|
|
11
|
+
import { PageHeader } from "@/components/ui/PageHeader";
|
|
12
|
+
import { Tabs, TabsList, TabsTrigger } from "@/components/shadcn/tabs";
|
|
13
|
+
import { ORDER } from "./order-mocks";
|
|
14
|
+
import { OverviewTab } from "./components/OverviewTab";
|
|
15
|
+
import { DetailsTab } from "./components/DetailsTab";
|
|
16
|
+
import { ActivityTab } from "./components/ActivityTab";
|
|
17
|
+
import { CommentsTab } from "./components/CommentsTab";
|
|
18
|
+
import { AttachmentsTab } from "./components/AttachmentsTab";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* OrderDetailScreen — conteúdo da página de detalhe de pedido consumindo o DS:
|
|
22
|
+
* PageHeader (título + status + ações) + Tabs (Visão geral / Detalhes /
|
|
23
|
+
* Atividade / Comentários / Anexos). Domínio iGreen (energia solar).
|
|
24
|
+
*
|
|
25
|
+
* Sem shell — embrulhe no seu AppShell/layout. O parent precisa dar altura
|
|
26
|
+
* (h-full/flex) pro conteúdo preencher.
|
|
27
|
+
*/
|
|
28
|
+
export function OrderDetailScreen() {
|
|
29
|
+
const [tab, setTab] = useState("overview");
|
|
30
|
+
|
|
31
|
+
const order = ORDER;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className="flex flex-col h-full min-h-0 gap-gp-2xl">
|
|
35
|
+
<PageHeader
|
|
36
|
+
title={`Pedido #${order.id}`}
|
|
37
|
+
description={order.placedAt}
|
|
38
|
+
hideTextOnMobile={false}
|
|
39
|
+
badge={
|
|
40
|
+
<span className="flex items-center gap-gp-sm">
|
|
41
|
+
<Chip color="success" variant="soft" size="sm" shape="pill">
|
|
42
|
+
Pago
|
|
43
|
+
</Chip>
|
|
44
|
+
<Chip color="info" variant="soft" size="sm" shape="pill">
|
|
45
|
+
Enviado
|
|
46
|
+
</Chip>
|
|
47
|
+
</span>
|
|
48
|
+
}
|
|
49
|
+
actions={
|
|
50
|
+
<>
|
|
51
|
+
<Button
|
|
52
|
+
variant="outline"
|
|
53
|
+
color="secondary"
|
|
54
|
+
size="md"
|
|
55
|
+
iconLeft={<RotateCcw />}
|
|
56
|
+
>
|
|
57
|
+
Reabastecer
|
|
58
|
+
</Button>
|
|
59
|
+
<Button
|
|
60
|
+
variant="outline"
|
|
61
|
+
color="secondary"
|
|
62
|
+
size="md"
|
|
63
|
+
iconLeft={<Pencil />}
|
|
64
|
+
>
|
|
65
|
+
Editar
|
|
66
|
+
</Button>
|
|
67
|
+
<Button
|
|
68
|
+
variant="outline"
|
|
69
|
+
color="secondary"
|
|
70
|
+
size="icon-md"
|
|
71
|
+
aria-label="Mais ações"
|
|
72
|
+
>
|
|
73
|
+
<MoreHorizontal />
|
|
74
|
+
</Button>
|
|
75
|
+
<Button
|
|
76
|
+
variant="outline"
|
|
77
|
+
color="secondary"
|
|
78
|
+
size="icon-md"
|
|
79
|
+
aria-label="Pedido anterior"
|
|
80
|
+
>
|
|
81
|
+
<ChevronLeft />
|
|
82
|
+
</Button>
|
|
83
|
+
<Button
|
|
84
|
+
variant="outline"
|
|
85
|
+
color="secondary"
|
|
86
|
+
size="icon-md"
|
|
87
|
+
aria-label="Próximo pedido"
|
|
88
|
+
>
|
|
89
|
+
<ChevronRight />
|
|
90
|
+
</Button>
|
|
91
|
+
</>
|
|
92
|
+
}
|
|
93
|
+
>
|
|
94
|
+
<Tabs value={tab} onValueChange={setTab}>
|
|
95
|
+
<TabsList>
|
|
96
|
+
<TabsTrigger value="overview">Visão geral</TabsTrigger>
|
|
97
|
+
<TabsTrigger value="details">Detalhes</TabsTrigger>
|
|
98
|
+
<TabsTrigger value="activity">Atividade</TabsTrigger>
|
|
99
|
+
<TabsTrigger value="comments">
|
|
100
|
+
Comentários
|
|
101
|
+
<Chip color="danger" variant="soft" size="sm" shape="pill">
|
|
102
|
+
{order.comments.length}
|
|
103
|
+
</Chip>
|
|
104
|
+
</TabsTrigger>
|
|
105
|
+
<TabsTrigger value="attachments">Anexos</TabsTrigger>
|
|
106
|
+
</TabsList>
|
|
107
|
+
</Tabs>
|
|
108
|
+
</PageHeader>
|
|
109
|
+
|
|
110
|
+
{tab === "overview" && <OverviewTab order={order} />}
|
|
111
|
+
{tab === "details" && <DetailsTab order={order} />}
|
|
112
|
+
{tab === "activity" && <ActivityTab order={order} />}
|
|
113
|
+
{tab === "comments" && <CommentsTab order={order} />}
|
|
114
|
+
{tab === "attachments" && <AttachmentsTab order={order} />}
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export default OrderDetailScreen;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { Order } from "./order.types";
|
|
2
|
+
|
|
3
|
+
/** Formata número como BRL. */
|
|
4
|
+
export const formatBRL = (v: number): string =>
|
|
5
|
+
v.toLocaleString("pt-BR", { style: "currency", currency: "BRL" });
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Pedido mock no domínio iGreen (energia solar). Espelha a estrutura da
|
|
9
|
+
* referência (Overview / Details / Activity / Comments / Attachments) com
|
|
10
|
+
* dados coerentes ao resto do showcase.
|
|
11
|
+
*/
|
|
12
|
+
export const ORDER: Order = {
|
|
13
|
+
id: "84021",
|
|
14
|
+
status: "paid",
|
|
15
|
+
fulfillment: "fulfilled",
|
|
16
|
+
placedAt: "8 de janeiro de 2024 às 21:48 · via Pedidos rascunho",
|
|
17
|
+
source: "Pedidos rascunho",
|
|
18
|
+
|
|
19
|
+
items: [
|
|
20
|
+
{
|
|
21
|
+
id: "SOL-4KWP-098",
|
|
22
|
+
name: "Kit Solar Residencial 4 kWp",
|
|
23
|
+
sku: "SOL-4KWP-098",
|
|
24
|
+
price: 12480,
|
|
25
|
+
qty: 1,
|
|
26
|
+
thumb: "#22A06B",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "INV-5KW-336",
|
|
30
|
+
name: "Inversor Híbrido 5 kW",
|
|
31
|
+
sku: "INV-5KW-336",
|
|
32
|
+
price: 4890,
|
|
33
|
+
qty: 1,
|
|
34
|
+
thumb: "#3B82F6",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "PNL-550-368",
|
|
38
|
+
name: "Painel Monocristalino 550 W",
|
|
39
|
+
sku: "PNL-550-368",
|
|
40
|
+
price: 689,
|
|
41
|
+
qty: 8,
|
|
42
|
+
thumb: "#F59E0B",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
subtotal: 22882,
|
|
46
|
+
shipping: 320,
|
|
47
|
+
tax: 1373,
|
|
48
|
+
discountCode: "INVERNO2024",
|
|
49
|
+
discountLabel: "-10%",
|
|
50
|
+
discountValue: 2288.2,
|
|
51
|
+
total: 22286.8,
|
|
52
|
+
|
|
53
|
+
customer: {
|
|
54
|
+
firstName: "Helena",
|
|
55
|
+
middleName: "Rocha",
|
|
56
|
+
lastName: "Martins",
|
|
57
|
+
initials: "HM",
|
|
58
|
+
colorHex: "#22A06B",
|
|
59
|
+
email: "helena.martins@example.com",
|
|
60
|
+
phone: "+55 (31) 99845-2014",
|
|
61
|
+
customerId: "#CLI-52365",
|
|
62
|
+
accountType: "Premium",
|
|
63
|
+
registeredAt: "17/12/2023",
|
|
64
|
+
active: true,
|
|
65
|
+
previousOrders: 11,
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
shippingAddress: {
|
|
69
|
+
line1: "Rua das Acácias, 2780",
|
|
70
|
+
line2: "Sala 4",
|
|
71
|
+
city: "Belo Horizonte",
|
|
72
|
+
state: "Minas Gerais",
|
|
73
|
+
zip: "30513-200",
|
|
74
|
+
country: "Brasil",
|
|
75
|
+
carrier: "Correios SEDEX",
|
|
76
|
+
tracking: "BR7489204588 31",
|
|
77
|
+
eta: "12 de janeiro de 2024",
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
billing: {
|
|
81
|
+
address: "Rua das Acácias, 2780, Sala 4",
|
|
82
|
+
cityState: "Belo Horizonte, Minas Gerais 30513-200",
|
|
83
|
+
country: "Brasil",
|
|
84
|
+
method: "Visa terminando em 4242",
|
|
85
|
+
transactionId: "TXN-8847291",
|
|
86
|
+
paymentDate: "8 de janeiro de 2024",
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
note: "Caso haja qualquer atraso ou problema com meu pedido, por favor me avise. Valorizo uma comunicação clara e a atenção aos detalhes.",
|
|
90
|
+
internalNote:
|
|
91
|
+
"Cliente solicitou embalagem reforçada para todos os itens. A etiqueta de envio deve incluir a nota \"Frágil — manusear com cuidado\". Prioridade confirmada pelo status de conta Premium.",
|
|
92
|
+
|
|
93
|
+
tags: [
|
|
94
|
+
{ label: "Cliente verificado", color: "success" },
|
|
95
|
+
{ label: "Premium", color: "info" },
|
|
96
|
+
{ label: "Alta prioridade", color: "warning" },
|
|
97
|
+
{ label: "Recorrente", color: "neutral" },
|
|
98
|
+
{ label: "Frágil", color: "danger" },
|
|
99
|
+
],
|
|
100
|
+
|
|
101
|
+
activity: [
|
|
102
|
+
{
|
|
103
|
+
id: "a1",
|
|
104
|
+
dateGroup: "Domingo, 06 de março",
|
|
105
|
+
title: "Pedido entregue",
|
|
106
|
+
description: "Recebido por: Helena Martins",
|
|
107
|
+
time: "14:05",
|
|
108
|
+
done: true,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "a2",
|
|
112
|
+
dateGroup: "Domingo, 06 de março",
|
|
113
|
+
title: "Saiu para entrega",
|
|
114
|
+
time: "09:12",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: "a3",
|
|
118
|
+
dateGroup: "Domingo, 06 de março",
|
|
119
|
+
title: "Chegou ao centro de distribuição",
|
|
120
|
+
time: "22:15",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "a4",
|
|
124
|
+
dateGroup: "Sexta, 04 de março",
|
|
125
|
+
title: "Coletado pela transportadora",
|
|
126
|
+
time: "03:43",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "a5",
|
|
130
|
+
dateGroup: "Sexta, 04 de março",
|
|
131
|
+
title: "Saiu do centro de distribuição",
|
|
132
|
+
time: "01:12",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: "a6",
|
|
136
|
+
dateGroup: "Quinta, 03 de março",
|
|
137
|
+
title: "Em preparação para envio",
|
|
138
|
+
time: "23:30",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: "a7",
|
|
142
|
+
dateGroup: "Quinta, 03 de março",
|
|
143
|
+
title: "Pedido confirmado",
|
|
144
|
+
description: "Pagamento recebido via cartão de crédito",
|
|
145
|
+
time: "21:15",
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
|
|
149
|
+
comments: [
|
|
150
|
+
{
|
|
151
|
+
id: "c1",
|
|
152
|
+
author: "Helena Martins",
|
|
153
|
+
initials: "HM",
|
|
154
|
+
colorHex: "#22A06B",
|
|
155
|
+
when: "2 dias atrás",
|
|
156
|
+
text: "Vocês conseguem atualizar o endereço de entrega? Mudei recentemente e esqueci de alterar antes de fazer o pedido.",
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: "c2",
|
|
160
|
+
author: "Suporte iGreen",
|
|
161
|
+
initials: "SI",
|
|
162
|
+
colorHex: "#3B82F6",
|
|
163
|
+
when: "1 dia atrás",
|
|
164
|
+
text: "Claro! Atualizei o endereço para Rua das Acácias, 2780, Sala 4, Belo Horizonte/MG. Pode confirmar se está correto?",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: "c3",
|
|
168
|
+
author: "Helena Martins",
|
|
169
|
+
initials: "HM",
|
|
170
|
+
colorHex: "#22A06B",
|
|
171
|
+
when: "1 dia atrás",
|
|
172
|
+
text: "Isso mesmo, muito obrigada pela agilidade!",
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
|
|
176
|
+
attachments: [
|
|
177
|
+
{ id: "f1", name: "nota_fiscal_84021.pdf", kind: "pdf", size: "245 KB" },
|
|
178
|
+
{ id: "f2", name: "etiqueta_envio.png", kind: "image", size: "128 KB" },
|
|
179
|
+
{
|
|
180
|
+
id: "f3",
|
|
181
|
+
name: "comprovante_pagamento.pdf",
|
|
182
|
+
kind: "pdf",
|
|
183
|
+
size: "89 KB",
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
};
|