@snksergio/design-system 0.61.0 → 0.63.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/AlertModal.md +47 -0
- package/dist-lib/ai/componentes/AppShell.md +117 -0
- package/dist-lib/ai/componentes/Breadcrumb.md +187 -0
- package/dist-lib/ai/componentes/Button.md +116 -0
- package/dist-lib/ai/componentes/ButtonGroup.md +162 -0
- package/dist-lib/ai/componentes/CardCheckbox.md +99 -0
- package/dist-lib/ai/componentes/CardOption.md +133 -0
- package/dist-lib/ai/componentes/Chart.md +93 -0
- package/dist-lib/ai/componentes/Chip.md +68 -0
- package/dist-lib/ai/componentes/ChoroplethMap.md +118 -0
- package/dist-lib/ai/componentes/ColorPicker.md +70 -0
- package/dist-lib/ai/componentes/Combobox.md +51 -0
- package/dist-lib/ai/componentes/ConversationListItem.md +90 -0
- package/dist-lib/ai/componentes/DataList.md +111 -0
- package/dist-lib/ai/componentes/DataTable.md +867 -0
- package/dist-lib/ai/componentes/DatePicker.md +84 -0
- package/dist-lib/ai/componentes/DateSeparatorChip.md +59 -0
- package/dist-lib/ai/componentes/EmptyState.md +72 -0
- package/dist-lib/ai/componentes/FileUploadField.md +95 -0
- package/dist-lib/ai/componentes/FloatingPanel.md +118 -0
- package/dist-lib/ai/componentes/FooterTable.md +62 -0
- package/dist-lib/ai/componentes/FormField.md +110 -0
- package/dist-lib/ai/componentes/Gantt.md +552 -0
- package/dist-lib/ai/componentes/Header.md +98 -0
- package/dist-lib/ai/componentes/Icon.md +65 -0
- package/dist-lib/ai/componentes/Kanban.md +343 -0
- package/dist-lib/ai/componentes/Kpi.md +103 -0
- package/dist-lib/ai/componentes/List.md +61 -0
- package/dist-lib/ai/componentes/MarkdownText.md +59 -0
- package/dist-lib/ai/componentes/MenuSidebar.md +128 -0
- package/dist-lib/ai/componentes/MessageAck.md +53 -0
- package/dist-lib/ai/componentes/MessageBubble.md +115 -0
- package/dist-lib/ai/componentes/MessageComposer.md +80 -0
- package/dist-lib/ai/componentes/MessageVariablesPicker.md +104 -0
- package/dist-lib/ai/componentes/Modal.md +88 -0
- package/dist-lib/ai/componentes/MonthYearPicker.md +49 -0
- package/dist-lib/ai/componentes/PageHeader.md +129 -0
- package/dist-lib/ai/componentes/Panel.md +84 -0
- package/dist-lib/ai/componentes/Scheduler.md +421 -0
- package/dist-lib/ai/componentes/ScreenLoader.md +60 -0
- package/dist-lib/ai/componentes/SingleMenuSidebar.md +171 -0
- package/dist-lib/ai/componentes/Spinner.md +52 -0
- package/dist-lib/ai/componentes/Table.md +192 -0
- package/dist-lib/ai/componentes/TableToolbar.md +87 -0
- package/dist-lib/ai/componentes/TabsNavigation.md +152 -0
- package/dist-lib/ai/componentes/Toast.md +49 -0
- package/dist-lib/ai/componentes/_primitivos.md +74 -0
- package/dist-lib/ai/componentes/avatar-ig.md +181 -0
- package/dist-lib/ai/componentes/indice.json +49 -0
- 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/dashboard/dashboard-brazil-map.ts +33 -0
- package/dist-lib/ai/exemplos/dashboard/dashboard-screen.tsx +1110 -0
- package/dist-lib/ai/exemplos/dashboard/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 +217 -0
- package/dist-lib/ai/global/composicao.md +182 -0
- package/dist-lib/ai/indice.json +192 -0
- package/dist-lib/ai/lint/ds-lint-patterns.mjs +115 -0
- package/dist-lib/ai/manifest.json +42 -0
- package/dist-lib/ai/regras/design.md +88 -0
- package/dist-lib/ai/regras/temas.md +192 -0
- package/dist-lib/ai/regras-por-componente.json +103 -0
- 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 +139 -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/dashboard-builder/blueprint.md +47 -0
- package/dist-lib/ai/roteiros/dashboard-builder/entrevista.md +62 -0
- package/dist-lib/ai/roteiros/dashboard-builder/geracao.md +88 -0
- package/dist-lib/ai/roteiros/dashboard-builder/roteiro.md +88 -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 +188 -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/package.json +4 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ArrowDownLeft,
|
|
3
|
+
ArrowUpRight,
|
|
4
|
+
Mail,
|
|
5
|
+
MapPin,
|
|
6
|
+
Phone,
|
|
7
|
+
Wallet,
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
import { Avatar } from "@/components/ui/avatar-ig";
|
|
10
|
+
import { Chip } from "@/components/ui/Chip";
|
|
11
|
+
import {
|
|
12
|
+
ACCOUNT_STATUS,
|
|
13
|
+
BANKS,
|
|
14
|
+
formatBRL,
|
|
15
|
+
formatDateTimeShort,
|
|
16
|
+
} from "../../clientes-financeiro-mocks";
|
|
17
|
+
import type { FinanceClientRow } from "../../clientes-financeiro.types";
|
|
18
|
+
|
|
19
|
+
/* ── Linha do extrato ───────────────────────────────────────────── */
|
|
20
|
+
|
|
21
|
+
function TransactionRow({
|
|
22
|
+
date,
|
|
23
|
+
type,
|
|
24
|
+
amount,
|
|
25
|
+
description,
|
|
26
|
+
}: FinanceClientRow["transactions"][number]) {
|
|
27
|
+
const isIn = type === "in";
|
|
28
|
+
return (
|
|
29
|
+
<li className="flex items-center gap-gp-md py-pad-sm">
|
|
30
|
+
<span
|
|
31
|
+
className={`grid place-items-center size-form-md shrink-0 rounded-radius-md ${
|
|
32
|
+
isIn
|
|
33
|
+
? "bg-bg-success-muted text-fg-success"
|
|
34
|
+
: "bg-bg-danger-muted text-fg-danger"
|
|
35
|
+
}`}
|
|
36
|
+
aria-hidden="true"
|
|
37
|
+
>
|
|
38
|
+
{isIn ? (
|
|
39
|
+
<ArrowDownLeft className="size-icon-sm" strokeWidth={2} />
|
|
40
|
+
) : (
|
|
41
|
+
<ArrowUpRight className="size-icon-sm" strokeWidth={2} />
|
|
42
|
+
)}
|
|
43
|
+
</span>
|
|
44
|
+
<div className="flex flex-col min-w-0 flex-1">
|
|
45
|
+
<span className="text-body-sm font-medium text-fg-default truncate">
|
|
46
|
+
{description}
|
|
47
|
+
</span>
|
|
48
|
+
<span className="text-caption-md text-fg-muted tabular-nums">
|
|
49
|
+
{formatDateTimeShort(date)}
|
|
50
|
+
</span>
|
|
51
|
+
</div>
|
|
52
|
+
<span
|
|
53
|
+
className={`text-body-sm font-semibold tabular-nums shrink-0 ${
|
|
54
|
+
isIn ? "text-fg-success" : "text-fg-danger"
|
|
55
|
+
}`}
|
|
56
|
+
>
|
|
57
|
+
{isIn ? "+" : "−"} {formatBRL(amount)}
|
|
58
|
+
</span>
|
|
59
|
+
</li>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ── Item label/valor das colunas laterais ─────────────────────── */
|
|
64
|
+
|
|
65
|
+
function InfoRow({
|
|
66
|
+
icon: Icon,
|
|
67
|
+
label,
|
|
68
|
+
children,
|
|
69
|
+
}: {
|
|
70
|
+
icon: React.ComponentType<{ className?: string; strokeWidth?: number }>;
|
|
71
|
+
label: string;
|
|
72
|
+
children: React.ReactNode;
|
|
73
|
+
}) {
|
|
74
|
+
return (
|
|
75
|
+
<div className="flex items-start gap-gp-sm">
|
|
76
|
+
<Icon className="size-icon-sm text-fg-muted mt-[2px] shrink-0" strokeWidth={1.8} />
|
|
77
|
+
<div className="flex flex-col gap-gp-2xs min-w-0">
|
|
78
|
+
<span className="text-body-sm text-fg-strong break-words">{children}</span>
|
|
79
|
+
<span className="text-body-xs font-normal text-fg-muted">{label}</span>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ── Painel de expansão da row ──────────────────────────────────── */
|
|
86
|
+
|
|
87
|
+
export function ExtratoExpansion({ row }: { row: FinanceClientRow }) {
|
|
88
|
+
const status = ACCOUNT_STATUS[row.accountStatus];
|
|
89
|
+
const bank = BANKS[row.bankAccount.bank];
|
|
90
|
+
// Extrato exibe as 5 movimentações mais recentes (transactions já vem ordenado desc).
|
|
91
|
+
const recent = row.transactions.slice(0, 5);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div className="w-full p-pad-4xl bg-bg-subtle">
|
|
95
|
+
<div className="grid grid-cols-1 lg:grid-cols-[1.5fr_1fr] gap-gp-4xl lg:gap-gp-6xl max-w-[1100px]">
|
|
96
|
+
{/* Extrato */}
|
|
97
|
+
<section className="flex flex-col gap-gp-lg">
|
|
98
|
+
<header className="flex items-center justify-between gap-gp-md">
|
|
99
|
+
<h4 className="m-0 text-body-md font-semibold text-fg-muted uppercase tracking-wider">
|
|
100
|
+
Extrato recente
|
|
101
|
+
</h4>
|
|
102
|
+
<Chip color={status.color} variant="soft" size="sm" shape="pill">
|
|
103
|
+
{status.label}
|
|
104
|
+
</Chip>
|
|
105
|
+
</header>
|
|
106
|
+
<ul className="flex flex-col divide-y divide-border-subtle m-0 p-0 list-none">
|
|
107
|
+
{recent.map((tx) => (
|
|
108
|
+
<TransactionRow key={tx.id} {...tx} />
|
|
109
|
+
))}
|
|
110
|
+
</ul>
|
|
111
|
+
</section>
|
|
112
|
+
|
|
113
|
+
{/* Dados bancários + contato + resumo — separados do extrato por
|
|
114
|
+
divisória sutil + respiro (evita poluição visual de "grudado"). */}
|
|
115
|
+
<div className="flex flex-col gap-gp-3xl lg:pl-gp-6xl lg:border-l lg:border-border-subtle">
|
|
116
|
+
<section className="flex flex-col gap-gp-md">
|
|
117
|
+
<h4 className="m-0 text-body-md font-semibold text-fg-muted uppercase tracking-wider">
|
|
118
|
+
Conta bancária
|
|
119
|
+
</h4>
|
|
120
|
+
<div className="flex items-center gap-gp-md">
|
|
121
|
+
<Avatar size="lg" colorHex={bank.color} className="text-caption-md font-bold">
|
|
122
|
+
{bank.initials}
|
|
123
|
+
</Avatar>
|
|
124
|
+
<div className="flex flex-col min-w-0">
|
|
125
|
+
<span className="text-body-sm font-medium text-fg-default truncate">
|
|
126
|
+
{row.bankAccount.bankName}
|
|
127
|
+
</span>
|
|
128
|
+
<span className="text-caption-md text-fg-muted tabular-nums">
|
|
129
|
+
Ag {row.bankAccount.agency} · {row.bankAccount.account}
|
|
130
|
+
</span>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</section>
|
|
134
|
+
|
|
135
|
+
<section className="flex flex-col gap-gp-md">
|
|
136
|
+
<h4 className="m-0 text-body-md font-semibold text-fg-muted uppercase tracking-wider">
|
|
137
|
+
Contato
|
|
138
|
+
</h4>
|
|
139
|
+
<InfoRow icon={Mail} label="Email">{row.email}</InfoRow>
|
|
140
|
+
<InfoRow icon={Phone} label="Telefone">{row.phone}</InfoRow>
|
|
141
|
+
<InfoRow icon={MapPin} label="Localização">{row.location}</InfoRow>
|
|
142
|
+
</section>
|
|
143
|
+
|
|
144
|
+
<section className="flex flex-col gap-gp-md">
|
|
145
|
+
<h4 className="m-0 text-body-md font-semibold text-fg-muted uppercase tracking-wider">
|
|
146
|
+
Resumo financeiro
|
|
147
|
+
</h4>
|
|
148
|
+
<InfoRow icon={Wallet} label="Saldo disponível">
|
|
149
|
+
<span className="font-semibold tabular-nums text-fg-success">
|
|
150
|
+
{formatBRL(row.availableBalance)}
|
|
151
|
+
</span>
|
|
152
|
+
</InfoRow>
|
|
153
|
+
<div className="flex gap-gp-2xl">
|
|
154
|
+
<div className="flex flex-col gap-gp-2xs">
|
|
155
|
+
<span className="text-body-sm font-medium text-fg-default tabular-nums">
|
|
156
|
+
{formatBRL(row.monthlyVolume)}
|
|
157
|
+
</span>
|
|
158
|
+
<span className="text-body-xs font-normal text-fg-muted">Volume mensal</span>
|
|
159
|
+
</div>
|
|
160
|
+
<div className="flex flex-col gap-gp-2xs">
|
|
161
|
+
<span className="text-body-sm font-medium text-fg-default tabular-nums">
|
|
162
|
+
{row.commissionRate.toLocaleString("pt-BR", { minimumFractionDigits: 1 })}%
|
|
163
|
+
</span>
|
|
164
|
+
<span className="text-body-xs font-normal text-fg-muted">Comissão</span>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</section>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ExtratoExpansion } from "./extrato-expansion";
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { Banknote, Pencil } from "lucide-react";
|
|
2
|
+
import {
|
|
3
|
+
FloatingPanel,
|
|
4
|
+
FloatingPanelSection,
|
|
5
|
+
FloatingPanelField,
|
|
6
|
+
} from "@/components/ui/FloatingPanel";
|
|
7
|
+
import { Avatar } from "@/components/ui/avatar-ig";
|
|
8
|
+
import { Button } from "@/components/ui/Button/button";
|
|
9
|
+
import { Chip } from "@/components/ui/Chip";
|
|
10
|
+
import { AGENTS } from "../../_table-data";
|
|
11
|
+
import {
|
|
12
|
+
ACCOUNT_STATUS,
|
|
13
|
+
BANKS,
|
|
14
|
+
formatBRL,
|
|
15
|
+
formatRelativeDays,
|
|
16
|
+
} from "../../clientes-financeiro-mocks";
|
|
17
|
+
import type {
|
|
18
|
+
FinanceClientRow,
|
|
19
|
+
PaymentMethod,
|
|
20
|
+
} from "../../clientes-financeiro.types";
|
|
21
|
+
|
|
22
|
+
const PAYMENT_METHOD_LABEL: Record<PaymentMethod, string> = {
|
|
23
|
+
pix: "PIX",
|
|
24
|
+
ted: "TED",
|
|
25
|
+
boleto: "Boleto",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function formatLongDate(ms: number): string {
|
|
29
|
+
if (!ms) return "—";
|
|
30
|
+
return new Date(ms).toLocaleDateString("pt-BR", {
|
|
31
|
+
day: "numeric",
|
|
32
|
+
month: "long",
|
|
33
|
+
year: "numeric",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type FinanceDetailPanelProps = {
|
|
38
|
+
row: FinanceClientRow | null;
|
|
39
|
+
onClose: () => void;
|
|
40
|
+
onEdit?: (row: FinanceClientRow) => void;
|
|
41
|
+
onSacar?: (row: FinanceClientRow) => void;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export function FinanceDetailPanel({
|
|
45
|
+
row,
|
|
46
|
+
onClose,
|
|
47
|
+
onEdit,
|
|
48
|
+
onSacar,
|
|
49
|
+
}: FinanceDetailPanelProps) {
|
|
50
|
+
if (!row) return null;
|
|
51
|
+
|
|
52
|
+
const status = ACCOUNT_STATUS[row.accountStatus];
|
|
53
|
+
const bank = BANKS[row.bankAccount.bank];
|
|
54
|
+
const agent = AGENTS[row.agentId as keyof typeof AGENTS];
|
|
55
|
+
const blocked = row.accountStatus === "bloqueado";
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<FloatingPanel
|
|
59
|
+
open={row !== null}
|
|
60
|
+
onOpenChange={(open) => {
|
|
61
|
+
if (!open) onClose();
|
|
62
|
+
}}
|
|
63
|
+
side="right"
|
|
64
|
+
size="md"
|
|
65
|
+
resizable
|
|
66
|
+
maximizable
|
|
67
|
+
// Sections gerenciam o próprio padding edge-to-edge (divisórias full-width).
|
|
68
|
+
bodyPadded={false}
|
|
69
|
+
resizableStorageKey="clientes-financeiro.detail-panel.width"
|
|
70
|
+
titleSlot={
|
|
71
|
+
<div className="flex items-center gap-gp-md min-w-0">
|
|
72
|
+
<Avatar size="lg" colorHex={row.avatarColor} className="shrink-0">
|
|
73
|
+
{row.initials}
|
|
74
|
+
</Avatar>
|
|
75
|
+
<div className="flex flex-col min-w-0 flex-1">
|
|
76
|
+
<div className="text-body-md font-semibold text-fg-default truncate">
|
|
77
|
+
{row.name}
|
|
78
|
+
</div>
|
|
79
|
+
<div className="flex items-center gap-gp-sm mt-[2px] text-body-xs font-normal text-fg-muted">
|
|
80
|
+
<span className="tabular-nums">{row.id}</span>
|
|
81
|
+
<span className="opacity-50">·</span>
|
|
82
|
+
<Chip color={status.color} variant="soft" size="sm" shape="pill">
|
|
83
|
+
{status.label}
|
|
84
|
+
</Chip>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
}
|
|
89
|
+
headerActions={
|
|
90
|
+
<>
|
|
91
|
+
<Button
|
|
92
|
+
variant="soft"
|
|
93
|
+
color="secondary"
|
|
94
|
+
size="icon-sm"
|
|
95
|
+
aria-label="Editar dados"
|
|
96
|
+
onClick={() => onEdit?.(row)}
|
|
97
|
+
>
|
|
98
|
+
<Pencil />
|
|
99
|
+
</Button>
|
|
100
|
+
<Button
|
|
101
|
+
variant="soft"
|
|
102
|
+
color="primary"
|
|
103
|
+
size="icon-sm"
|
|
104
|
+
aria-label="Realizar saque"
|
|
105
|
+
disabled={blocked}
|
|
106
|
+
onClick={() => onSacar?.(row)}
|
|
107
|
+
>
|
|
108
|
+
<Banknote />
|
|
109
|
+
</Button>
|
|
110
|
+
</>
|
|
111
|
+
}
|
|
112
|
+
footer={
|
|
113
|
+
<>
|
|
114
|
+
<Button variant="outline" color="secondary" size="sm" onClick={onClose}>
|
|
115
|
+
Fechar
|
|
116
|
+
</Button>
|
|
117
|
+
<Button
|
|
118
|
+
variant="filled"
|
|
119
|
+
color="primary"
|
|
120
|
+
size="sm"
|
|
121
|
+
disabled={blocked}
|
|
122
|
+
onClick={() => onSacar?.(row)}
|
|
123
|
+
>
|
|
124
|
+
Realizar saque
|
|
125
|
+
</Button>
|
|
126
|
+
</>
|
|
127
|
+
}
|
|
128
|
+
>
|
|
129
|
+
{/* Saldo em destaque — gutter próprio (body não tem padding). */}
|
|
130
|
+
<div className="px-[18px] pt-pad-xl pb-pad-md">
|
|
131
|
+
<div className="flex flex-col gap-gp-2xs p-pad-2xl bg-bg-success-muted rounded-radius-lg">
|
|
132
|
+
<span className="text-caption-sm text-fg-muted">Saldo disponível</span>
|
|
133
|
+
<span className="text-body-2xl font-bold text-fg-success leading-none tabular-nums">
|
|
134
|
+
{formatBRL(row.availableBalance)}
|
|
135
|
+
</span>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<FloatingPanelSection title="Empresa">
|
|
140
|
+
<FloatingPanelField label="Razão Social" value={row.companyName} />
|
|
141
|
+
<FloatingPanelField
|
|
142
|
+
label="CNPJ"
|
|
143
|
+
value={<span className="tabular-nums">{row.cnpj}</span>}
|
|
144
|
+
/>
|
|
145
|
+
</FloatingPanelSection>
|
|
146
|
+
|
|
147
|
+
<FloatingPanelSection title="Conta bancária">
|
|
148
|
+
<div className="flex items-center gap-gp-md">
|
|
149
|
+
<Avatar size="lg" colorHex={bank.color} className="text-caption-md font-bold">
|
|
150
|
+
{bank.initials}
|
|
151
|
+
</Avatar>
|
|
152
|
+
<div className="flex flex-col min-w-0">
|
|
153
|
+
<span className="text-body-sm font-medium text-fg-default truncate">
|
|
154
|
+
{row.bankAccount.bankName}
|
|
155
|
+
</span>
|
|
156
|
+
<span className="text-caption-md text-fg-muted tabular-nums">
|
|
157
|
+
Ag {row.bankAccount.agency} · {row.bankAccount.account}
|
|
158
|
+
</span>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</FloatingPanelSection>
|
|
162
|
+
|
|
163
|
+
<FloatingPanelSection title="Financeiro">
|
|
164
|
+
<FloatingPanelField
|
|
165
|
+
label="Volume mensal"
|
|
166
|
+
value={<span className="tabular-nums">{formatBRL(row.monthlyVolume)}</span>}
|
|
167
|
+
/>
|
|
168
|
+
<FloatingPanelField
|
|
169
|
+
label="Comissão"
|
|
170
|
+
value={
|
|
171
|
+
<span className="tabular-nums">
|
|
172
|
+
{row.commissionRate.toLocaleString("pt-BR", { minimumFractionDigits: 1 })}%
|
|
173
|
+
</span>
|
|
174
|
+
}
|
|
175
|
+
/>
|
|
176
|
+
<FloatingPanelField
|
|
177
|
+
label="Saque automático"
|
|
178
|
+
value={row.autoWithdraw ? "Ativado" : "Desativado"}
|
|
179
|
+
/>
|
|
180
|
+
<FloatingPanelField
|
|
181
|
+
label="Métodos"
|
|
182
|
+
value={
|
|
183
|
+
<span className="inline-flex flex-wrap gap-gp-2xs justify-end">
|
|
184
|
+
{row.paymentMethods.map((m) => (
|
|
185
|
+
<Chip key={m} color="neutral" variant="soft" size="sm" shape="rounded">
|
|
186
|
+
{PAYMENT_METHOD_LABEL[m]}
|
|
187
|
+
</Chip>
|
|
188
|
+
))}
|
|
189
|
+
</span>
|
|
190
|
+
}
|
|
191
|
+
/>
|
|
192
|
+
</FloatingPanelSection>
|
|
193
|
+
|
|
194
|
+
<FloatingPanelSection title="Contato">
|
|
195
|
+
<FloatingPanelField
|
|
196
|
+
label="Email"
|
|
197
|
+
value={
|
|
198
|
+
<a href={`mailto:${row.email}`} className="text-fg-brand hover:underline">
|
|
199
|
+
{row.email}
|
|
200
|
+
</a>
|
|
201
|
+
}
|
|
202
|
+
/>
|
|
203
|
+
<FloatingPanelField
|
|
204
|
+
label="Telefone"
|
|
205
|
+
value={
|
|
206
|
+
<a
|
|
207
|
+
href={`tel:${row.phone.replace(/\D/g, "")}`}
|
|
208
|
+
className="text-fg-brand hover:underline"
|
|
209
|
+
>
|
|
210
|
+
{row.phone}
|
|
211
|
+
</a>
|
|
212
|
+
}
|
|
213
|
+
/>
|
|
214
|
+
<FloatingPanelField label="Localização" value={row.location} />
|
|
215
|
+
</FloatingPanelSection>
|
|
216
|
+
|
|
217
|
+
<FloatingPanelSection title="Gestão">
|
|
218
|
+
<FloatingPanelField
|
|
219
|
+
label="Gestor da conta"
|
|
220
|
+
value={
|
|
221
|
+
agent ? (
|
|
222
|
+
<span className="inline-flex items-center gap-gp-sm">
|
|
223
|
+
<Avatar size="xs" colorHex={agent.color}>
|
|
224
|
+
{agent.initials}
|
|
225
|
+
</Avatar>
|
|
226
|
+
{agent.name}
|
|
227
|
+
</span>
|
|
228
|
+
) : (
|
|
229
|
+
"—"
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
/>
|
|
233
|
+
<FloatingPanelField label="Cliente desde" value={formatLongDate(row.createdAt)} />
|
|
234
|
+
<FloatingPanelField
|
|
235
|
+
label="Última movimentação"
|
|
236
|
+
value={formatRelativeDays(row.lastMovement)}
|
|
237
|
+
/>
|
|
238
|
+
</FloatingPanelSection>
|
|
239
|
+
</FloatingPanel>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { Panel } from "@/components/ui/Panel";
|
|
3
|
+
import { Button } from "@/components/ui/Button/button";
|
|
4
|
+
import {
|
|
5
|
+
FormField,
|
|
6
|
+
FormFieldInput,
|
|
7
|
+
FormFieldSelect,
|
|
8
|
+
FormFieldTextarea,
|
|
9
|
+
} from "@/components/ui/FormField";
|
|
10
|
+
import { ChipGroup, ChipGroupItem } from "@/components/ui/Chip";
|
|
11
|
+
import { STATUSES, CATEGORIES } from "../../_table-data";
|
|
12
|
+
import { CITIES, STATUS_DOT } from "../../clientes-showcase-mocks";
|
|
13
|
+
import { drawerFormStyles } from "../../clientes-showcase.styles";
|
|
14
|
+
import type { NovoClienteFormData } from "../../clientes-showcase.types";
|
|
15
|
+
|
|
16
|
+
const INITIAL_FORM: NovoClienteFormData = {
|
|
17
|
+
name: "",
|
|
18
|
+
email: "",
|
|
19
|
+
whatsapp: "",
|
|
20
|
+
statusId: "active",
|
|
21
|
+
categoryId: "lead",
|
|
22
|
+
city: "",
|
|
23
|
+
value: 0,
|
|
24
|
+
notes: "",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type NovoClienteDrawerProps = {
|
|
28
|
+
open: boolean;
|
|
29
|
+
onOpenChange: (open: boolean) => void;
|
|
30
|
+
/** Disparado ao confirmar — drawer fecha automaticamente após o submit. */
|
|
31
|
+
onSubmit?: (data: NovoClienteFormData) => void;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Drawer "Novo cliente" — replica visual do TblClientFormDrawer
|
|
36
|
+
* (sandbox /design-and-table-v2), recompilado em cima dos componentes do DS:
|
|
37
|
+
* Panel + FormField (Input / Select / Textarea) + ChipGroup + Button.
|
|
38
|
+
*
|
|
39
|
+
* Layout (top → bottom):
|
|
40
|
+
* 1. Nome* — full width
|
|
41
|
+
* 2. Email + WhatsApp — 2 cols
|
|
42
|
+
* 3. Status — ChipGroup com dot colorido
|
|
43
|
+
* 4. Categoria — ChipGroup
|
|
44
|
+
* 5. Cidade + Valor R$ — 2 cols
|
|
45
|
+
* 6. Notas — textarea full width
|
|
46
|
+
*/
|
|
47
|
+
export function NovoClienteDrawer({
|
|
48
|
+
open,
|
|
49
|
+
onOpenChange,
|
|
50
|
+
onSubmit,
|
|
51
|
+
}: NovoClienteDrawerProps) {
|
|
52
|
+
const s = drawerFormStyles();
|
|
53
|
+
const [form, setForm] = useState<NovoClienteFormData>(INITIAL_FORM);
|
|
54
|
+
|
|
55
|
+
// Reseta form sempre que abrir
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (open) setForm(INITIAL_FORM);
|
|
58
|
+
}, [open]);
|
|
59
|
+
|
|
60
|
+
const canSubmit = form.name.trim().length > 0;
|
|
61
|
+
|
|
62
|
+
const handleSubmit = () => {
|
|
63
|
+
if (!canSubmit) return;
|
|
64
|
+
onSubmit?.(form);
|
|
65
|
+
onOpenChange(false);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<Panel
|
|
70
|
+
open={open}
|
|
71
|
+
onOpenChange={onOpenChange}
|
|
72
|
+
title="Novo cliente"
|
|
73
|
+
side="right"
|
|
74
|
+
size="md"
|
|
75
|
+
footer={
|
|
76
|
+
<>
|
|
77
|
+
<Button
|
|
78
|
+
variant="outline"
|
|
79
|
+
color="secondary"
|
|
80
|
+
size="md"
|
|
81
|
+
onClick={() => onOpenChange(false)}
|
|
82
|
+
>
|
|
83
|
+
Cancelar
|
|
84
|
+
</Button>
|
|
85
|
+
<Button
|
|
86
|
+
variant="filled"
|
|
87
|
+
color="primary"
|
|
88
|
+
size="md"
|
|
89
|
+
disabled={!canSubmit}
|
|
90
|
+
onClick={handleSubmit}
|
|
91
|
+
>
|
|
92
|
+
Criar cliente
|
|
93
|
+
</Button>
|
|
94
|
+
</>
|
|
95
|
+
}
|
|
96
|
+
>
|
|
97
|
+
<FormFieldInput
|
|
98
|
+
label="Nome"
|
|
99
|
+
required
|
|
100
|
+
placeholder="Maria Silva"
|
|
101
|
+
value={form.name}
|
|
102
|
+
onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
|
|
103
|
+
/>
|
|
104
|
+
|
|
105
|
+
<div className={s.twoCols()}>
|
|
106
|
+
<FormFieldInput
|
|
107
|
+
label="Email"
|
|
108
|
+
type="email"
|
|
109
|
+
placeholder="cliente@exemplo.com"
|
|
110
|
+
value={form.email}
|
|
111
|
+
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
|
|
112
|
+
/>
|
|
113
|
+
<FormFieldInput
|
|
114
|
+
label="WhatsApp"
|
|
115
|
+
type="tel"
|
|
116
|
+
placeholder="55 11 99999-9999"
|
|
117
|
+
value={form.whatsapp}
|
|
118
|
+
onChange={(e) => setForm((f) => ({ ...f, whatsapp: e.target.value }))}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<FormField label="Status">
|
|
123
|
+
{() => (
|
|
124
|
+
<ChipGroup
|
|
125
|
+
type="single"
|
|
126
|
+
value={form.statusId}
|
|
127
|
+
onValueChange={(v) =>
|
|
128
|
+
v &&
|
|
129
|
+
setForm((f) => ({
|
|
130
|
+
...f,
|
|
131
|
+
statusId: v as keyof typeof STATUSES,
|
|
132
|
+
}))
|
|
133
|
+
}
|
|
134
|
+
size="md"
|
|
135
|
+
shape="pill"
|
|
136
|
+
ariaLabel="Status do cliente"
|
|
137
|
+
>
|
|
138
|
+
{Object.entries(STATUSES).map(([id, st]) => (
|
|
139
|
+
<ChipGroupItem key={id} value={id}>
|
|
140
|
+
<span
|
|
141
|
+
className={s.statusDot()}
|
|
142
|
+
style={{ background: STATUS_DOT[id] ?? st.color }}
|
|
143
|
+
aria-hidden
|
|
144
|
+
/>
|
|
145
|
+
{st.label}
|
|
146
|
+
</ChipGroupItem>
|
|
147
|
+
))}
|
|
148
|
+
</ChipGroup>
|
|
149
|
+
)}
|
|
150
|
+
</FormField>
|
|
151
|
+
|
|
152
|
+
<FormField label="Categoria">
|
|
153
|
+
{() => (
|
|
154
|
+
<ChipGroup
|
|
155
|
+
type="single"
|
|
156
|
+
value={form.categoryId}
|
|
157
|
+
onValueChange={(v) =>
|
|
158
|
+
v &&
|
|
159
|
+
setForm((f) => ({
|
|
160
|
+
...f,
|
|
161
|
+
categoryId: v as keyof typeof CATEGORIES,
|
|
162
|
+
}))
|
|
163
|
+
}
|
|
164
|
+
size="md"
|
|
165
|
+
shape="pill"
|
|
166
|
+
ariaLabel="Categoria do cliente"
|
|
167
|
+
>
|
|
168
|
+
{Object.entries(CATEGORIES).map(([id, cat]) => (
|
|
169
|
+
<ChipGroupItem key={id} value={id}>
|
|
170
|
+
{cat.label}
|
|
171
|
+
</ChipGroupItem>
|
|
172
|
+
))}
|
|
173
|
+
</ChipGroup>
|
|
174
|
+
)}
|
|
175
|
+
</FormField>
|
|
176
|
+
|
|
177
|
+
<div className={s.twoCols()}>
|
|
178
|
+
<FormFieldSelect
|
|
179
|
+
label="Cidade"
|
|
180
|
+
placeholder="Selecionar..."
|
|
181
|
+
value={form.city || undefined}
|
|
182
|
+
onValueChange={(v) => setForm((f) => ({ ...f, city: v }))}
|
|
183
|
+
options={CITIES.map((c) => ({ value: c, label: c }))}
|
|
184
|
+
/>
|
|
185
|
+
<FormFieldInput
|
|
186
|
+
label="Valor (R$)"
|
|
187
|
+
type="number"
|
|
188
|
+
startAddon="R$"
|
|
189
|
+
value={String(form.value)}
|
|
190
|
+
onChange={(e) =>
|
|
191
|
+
setForm((f) => ({ ...f, value: Number(e.target.value) }))
|
|
192
|
+
}
|
|
193
|
+
min={0}
|
|
194
|
+
step={0.01}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<FormFieldTextarea
|
|
199
|
+
label="Notas"
|
|
200
|
+
placeholder="Observações sobre o cliente..."
|
|
201
|
+
rows={4}
|
|
202
|
+
value={form.notes}
|
|
203
|
+
onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
|
|
204
|
+
/>
|
|
205
|
+
</Panel>
|
|
206
|
+
);
|
|
207
|
+
}
|