@snksergio/design-system 0.1.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/README.md +260 -0
- package/dist-lib/chunks/app-shell-BNTvOETJ.mjs +2681 -0
- package/dist-lib/chunks/app-shell-BNTvOETJ.mjs.map +1 -0
- package/dist-lib/chunks/app-shell-CDy42aNI.mjs +2663 -0
- package/dist-lib/chunks/app-shell-CDy42aNI.mjs.map +1 -0
- package/dist-lib/chunks/app-shell-mocks-kWIVSzLs.mjs +208 -0
- package/dist-lib/chunks/app-shell-mocks-kWIVSzLs.mjs.map +1 -0
- package/dist-lib/chunks/app-shell-mocks-oO_IV3Gw.mjs +207 -0
- package/dist-lib/chunks/app-shell-mocks-oO_IV3Gw.mjs.map +1 -0
- package/dist-lib/chunks/badge-B_2Zt52o.mjs +797 -0
- package/dist-lib/chunks/badge-B_2Zt52o.mjs.map +1 -0
- package/dist-lib/chunks/badge-DKpXURa1.mjs +813 -0
- package/dist-lib/chunks/badge-DKpXURa1.mjs.map +1 -0
- package/dist-lib/chunks/chat-v2-mocks-BV9Wha_Z.mjs +192 -0
- package/dist-lib/chunks/chat-v2-mocks-BV9Wha_Z.mjs.map +1 -0
- package/dist-lib/chunks/chat-v2-mocks-DvZRkhmz.mjs +193 -0
- package/dist-lib/chunks/chat-v2-mocks-DvZRkhmz.mjs.map +1 -0
- package/dist-lib/chunks/chip-group-CsKBBHW2.mjs +796 -0
- package/dist-lib/chunks/chip-group-CsKBBHW2.mjs.map +1 -0
- package/dist-lib/chunks/chip-group-D3D0i72q.mjs +780 -0
- package/dist-lib/chunks/chip-group-D3D0i72q.mjs.map +1 -0
- package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs +185 -0
- package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs.map +1 -0
- package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs +169 -0
- package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs.map +1 -0
- package/dist-lib/chunks/input-374MpdBL.mjs +72 -0
- package/dist-lib/chunks/input-374MpdBL.mjs.map +1 -0
- package/dist-lib/chunks/input-DF4XAWmr.mjs +56 -0
- package/dist-lib/chunks/input-DF4XAWmr.mjs.map +1 -0
- package/dist-lib/chunks/page-header-Dw-3wqAG.mjs +75 -0
- package/dist-lib/chunks/page-header-Dw-3wqAG.mjs.map +1 -0
- package/dist-lib/chunks/page-header-mC1gGtOI.mjs +76 -0
- package/dist-lib/chunks/page-header-mC1gGtOI.mjs.map +1 -0
- package/dist-lib/chunks/panel-Ds15whqp.mjs +9717 -0
- package/dist-lib/chunks/panel-Ds15whqp.mjs.map +1 -0
- package/dist-lib/chunks/panel-bzNmFlEZ.mjs +9737 -0
- package/dist-lib/chunks/panel-bzNmFlEZ.mjs.map +1 -0
- package/dist-lib/chunks/useTheme-BUPLZBMs.mjs +66 -0
- package/dist-lib/chunks/useTheme-BUPLZBMs.mjs.map +1 -0
- package/dist-lib/chunks/useTheme-Dee4mo-A.mjs +65 -0
- package/dist-lib/chunks/useTheme-Dee4mo-A.mjs.map +1 -0
- package/dist-lib/index.cjs +1207 -0
- package/dist-lib/index.cjs.map +1 -0
- package/dist-lib/index.d.ts +2 -0
- package/dist-lib/index.mjs +1209 -0
- package/dist-lib/index.mjs.map +1 -0
- package/dist-lib/preview/chat.cjs +1120 -0
- package/dist-lib/preview/chat.cjs.map +1 -0
- package/dist-lib/preview/chat.d.ts +6 -0
- package/dist-lib/preview/chat.mjs +1120 -0
- package/dist-lib/preview/chat.mjs.map +1 -0
- package/dist-lib/preview/clientes.cjs +897 -0
- package/dist-lib/preview/clientes.cjs.map +1 -0
- package/dist-lib/preview/clientes.d.ts +6 -0
- package/dist-lib/preview/clientes.mjs +897 -0
- package/dist-lib/preview/clientes.mjs.map +1 -0
- package/dist-lib/preview/dashboard.cjs +733 -0
- package/dist-lib/preview/dashboard.cjs.map +1 -0
- package/dist-lib/preview/dashboard.d.ts +4 -0
- package/dist-lib/preview/dashboard.mjs +733 -0
- package/dist-lib/preview/dashboard.mjs.map +1 -0
- package/dist-lib/preview/mocks.cjs +15 -0
- package/dist-lib/preview/mocks.cjs.map +1 -0
- package/dist-lib/preview/mocks.d.ts +2 -0
- package/dist-lib/preview/mocks.mjs +15 -0
- package/dist-lib/preview/mocks.mjs.map +1 -0
- package/dist-lib/theme.css +668 -0
- package/dist-lib/tokens.cjs +915 -0
- package/dist-lib/tokens.cjs.map +1 -0
- package/dist-lib/tokens.d.ts +2 -0
- package/dist-lib/tokens.mjs +915 -0
- package/dist-lib/tokens.mjs.map +1 -0
- package/package.json +142 -0
|
@@ -0,0 +1,1120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const React = require("react");
|
|
5
|
+
const chipGroup = require("../chunks/chip-group-CsKBBHW2.mjs");
|
|
6
|
+
const useTheme = require("../chunks/useTheme-Dee4mo-A.mjs");
|
|
7
|
+
const appShell = require("../chunks/app-shell-BNTvOETJ.mjs");
|
|
8
|
+
const lucideReact = require("lucide-react");
|
|
9
|
+
const appShellMocks = require("../chunks/app-shell-mocks-oO_IV3Gw.mjs");
|
|
10
|
+
const chatV2Mocks = require("../chunks/chat-v2-mocks-BV9Wha_Z.mjs");
|
|
11
|
+
const input = require("../chunks/input-374MpdBL.mjs");
|
|
12
|
+
const chatV2Styles = chipGroup.tv({
|
|
13
|
+
slots: {
|
|
14
|
+
/** Body do AppShell — flex row com gap entre colunas. `relative` pra mobile overlays. */
|
|
15
|
+
root: "flex flex-1 min-h-0 gap-gp-2xl relative",
|
|
16
|
+
/** Wrapper dos filtros (col 1) — escondido em mobile. */
|
|
17
|
+
filtersWrap: "hidden md:contents"
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const mobileOverlay = {
|
|
21
|
+
active: "max-md:absolute max-md:inset-0 max-md:w-full max-md:rounded-radius-none max-md:border-0",
|
|
22
|
+
hidden: "max-md:hidden"
|
|
23
|
+
};
|
|
24
|
+
function useResizable({
|
|
25
|
+
initial,
|
|
26
|
+
min,
|
|
27
|
+
max,
|
|
28
|
+
storageKey
|
|
29
|
+
}) {
|
|
30
|
+
const [width, setWidth] = React.useState(initial);
|
|
31
|
+
const hydrated = React.useRef(false);
|
|
32
|
+
React.useEffect(() => {
|
|
33
|
+
if (typeof window === "undefined") return;
|
|
34
|
+
try {
|
|
35
|
+
const raw = window.localStorage.getItem(storageKey);
|
|
36
|
+
const n = raw ? Number(raw) : NaN;
|
|
37
|
+
if (!Number.isNaN(n) && n >= min && n <= max) setWidth(n);
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
hydrated.current = true;
|
|
41
|
+
}, [min, max, storageKey]);
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
if (!hydrated.current || typeof window === "undefined") return;
|
|
44
|
+
try {
|
|
45
|
+
window.localStorage.setItem(storageKey, String(width));
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
}, [width, storageKey]);
|
|
49
|
+
const onResizeStart = React.useCallback(
|
|
50
|
+
(e) => {
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
const startX = e.clientX;
|
|
53
|
+
const startWidth = width;
|
|
54
|
+
const onMove = (ev) => {
|
|
55
|
+
const delta = startX - ev.clientX;
|
|
56
|
+
const next = Math.max(min, Math.min(max, startWidth + delta));
|
|
57
|
+
setWidth(next);
|
|
58
|
+
};
|
|
59
|
+
const onUp = () => {
|
|
60
|
+
document.removeEventListener("mousemove", onMove);
|
|
61
|
+
document.removeEventListener("mouseup", onUp);
|
|
62
|
+
document.body.style.cursor = "";
|
|
63
|
+
document.body.style.userSelect = "";
|
|
64
|
+
};
|
|
65
|
+
document.addEventListener("mousemove", onMove);
|
|
66
|
+
document.addEventListener("mouseup", onUp);
|
|
67
|
+
document.body.style.cursor = "col-resize";
|
|
68
|
+
document.body.style.userSelect = "none";
|
|
69
|
+
},
|
|
70
|
+
[width, min, max]
|
|
71
|
+
);
|
|
72
|
+
return { width, onResizeStart };
|
|
73
|
+
}
|
|
74
|
+
function ChannelDot({ channel, dotOnly = false }) {
|
|
75
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
76
|
+
"span",
|
|
77
|
+
{
|
|
78
|
+
className: "inline-flex items-center gap-[4px] text-[11px] text-fg-muted",
|
|
79
|
+
title: chatV2Mocks.CHANNEL_LABEL[channel],
|
|
80
|
+
children: [
|
|
81
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
82
|
+
"span",
|
|
83
|
+
{
|
|
84
|
+
className: "size-[8px] rounded-radius-full shrink-0",
|
|
85
|
+
style: { background: chatV2Mocks.CHANNEL_HEX[channel] },
|
|
86
|
+
"aria-hidden": true
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
!dotOnly && chatV2Mocks.CHANNEL_LABEL[channel]
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
function ConversationActionsMenu({
|
|
95
|
+
showResolveInMenu = false,
|
|
96
|
+
onResolve,
|
|
97
|
+
onCall,
|
|
98
|
+
onVideo,
|
|
99
|
+
onAddTag,
|
|
100
|
+
onAssign,
|
|
101
|
+
onArchive
|
|
102
|
+
}) {
|
|
103
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenu, { children: [
|
|
104
|
+
/* @__PURE__ */ jsxRuntime.jsx(appShell.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
105
|
+
chipGroup.Button,
|
|
106
|
+
{
|
|
107
|
+
color: "secondary",
|
|
108
|
+
variant: "outline",
|
|
109
|
+
size: "icon-sm",
|
|
110
|
+
"aria-label": "Mais opções",
|
|
111
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, {})
|
|
112
|
+
}
|
|
113
|
+
) }),
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuContent, { align: "end", sideOffset: 6, className: "min-w-[200px]", children: [
|
|
115
|
+
showResolveInMenu && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
116
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuItem, { onSelect: onResolve, children: [
|
|
117
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, {}),
|
|
118
|
+
" Resolver"
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ jsxRuntime.jsx(appShell.DropdownMenuSeparator, {})
|
|
121
|
+
] }),
|
|
122
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuItem, { onSelect: onCall, children: [
|
|
123
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, {}),
|
|
124
|
+
" Ligar"
|
|
125
|
+
] }),
|
|
126
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuItem, { onSelect: onVideo, children: [
|
|
127
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, {}),
|
|
128
|
+
" Vídeo chamada"
|
|
129
|
+
] }),
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuItem, { onSelect: onAddTag, children: [
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Tag, {}),
|
|
132
|
+
" Adicionar tag"
|
|
133
|
+
] }),
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuItem, { onSelect: onAssign, children: [
|
|
135
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserPlus, {}),
|
|
136
|
+
" Atribuir"
|
|
137
|
+
] }),
|
|
138
|
+
/* @__PURE__ */ jsxRuntime.jsx(appShell.DropdownMenuSeparator, {}),
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsxs(appShell.DropdownMenuItem, { variant: "destructive", onSelect: onArchive, children: [
|
|
140
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Archive, {}),
|
|
141
|
+
" Arquivar"
|
|
142
|
+
] })
|
|
143
|
+
] })
|
|
144
|
+
] });
|
|
145
|
+
}
|
|
146
|
+
function DateSeparator({ label }) {
|
|
147
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center my-pad-md", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-pad-lg py-pad-2xs rounded-radius-full bg-bg-muted text-[11px] text-fg-muted [font-variant-numeric:tabular-nums]", children: label }) });
|
|
148
|
+
}
|
|
149
|
+
const messageBubbleStyles = chipGroup.tv({
|
|
150
|
+
slots: {
|
|
151
|
+
/** Wrapper que controla o alinhamento horizontal (esquerda/direita). */
|
|
152
|
+
row: "flex",
|
|
153
|
+
/** Balão em si — variants definem cor + corner pointer. */
|
|
154
|
+
bubble: "max-w-[70%] px-pad-xl py-pad-md rounded-radius-xl shadow-sh-sm",
|
|
155
|
+
/** Texto da mensagem. */
|
|
156
|
+
text: "text-[13.5px] leading-[1.45] whitespace-pre-wrap break-words",
|
|
157
|
+
/** Footer com horário + status icon. */
|
|
158
|
+
meta: "flex items-center justify-end gap-[4px] mt-[2px] text-[10.5px]",
|
|
159
|
+
/** Span do horário (tabular-nums pra alinhar). */
|
|
160
|
+
time: "[font-variant-numeric:tabular-nums]"
|
|
161
|
+
},
|
|
162
|
+
variants: {
|
|
163
|
+
from: {
|
|
164
|
+
me: {
|
|
165
|
+
row: "justify-end",
|
|
166
|
+
bubble: "bg-bg-brand text-fg-on-brand rounded-br-[4px]",
|
|
167
|
+
meta: "text-fg-on-brand opacity-80"
|
|
168
|
+
},
|
|
169
|
+
them: {
|
|
170
|
+
row: "justify-start",
|
|
171
|
+
bubble: "bg-bg-surface text-fg-default border border-border-subtle rounded-bl-[4px]",
|
|
172
|
+
meta: "text-fg-muted"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
defaultVariants: {
|
|
177
|
+
from: "them"
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
function MessageBubble({ msg }) {
|
|
181
|
+
const from = msg.from === "me" ? "me" : "them";
|
|
182
|
+
const { row, bubble, text, meta, time } = messageBubbleStyles({ from });
|
|
183
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: row(), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: bubble(), children: [
|
|
184
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: text(), children: msg.text }),
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: meta(), children: [
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: time(), children: msg.time }),
|
|
187
|
+
from === "me" && (msg.status === "read" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { size: 12, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 12, strokeWidth: 2 }))
|
|
188
|
+
] })
|
|
189
|
+
] }) });
|
|
190
|
+
}
|
|
191
|
+
const SIZE_CLASSES = {
|
|
192
|
+
sm: "size-[28px] text-[11px]",
|
|
193
|
+
md: "size-[36px] text-[13px]",
|
|
194
|
+
lg: "size-[40px] text-[14px]"
|
|
195
|
+
};
|
|
196
|
+
function PersonAvatar({ initials, hex, size = "md" }) {
|
|
197
|
+
return /* @__PURE__ */ jsxRuntime.jsx(appShell.Avatar, { className: SIZE_CLASSES[size], style: { background: hex }, children: /* @__PURE__ */ jsxRuntime.jsx(appShell.AvatarFallback, { className: "bg-transparent text-white font-bold", children: initials }) });
|
|
198
|
+
}
|
|
199
|
+
const conversationColumnStyles = chipGroup.tv({
|
|
200
|
+
slots: {
|
|
201
|
+
root: "flex flex-col flex-1 min-w-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden",
|
|
202
|
+
header: "flex items-center gap-gp-lg px-pad-2xl py-pad-md border-b border-border-subtle shrink-0",
|
|
203
|
+
headerInfo: "flex-1 min-w-0 flex flex-col gap-[2px]",
|
|
204
|
+
headerTitleRow: "flex items-center gap-gp-sm",
|
|
205
|
+
headerName: "text-title-md text-fg-default whitespace-nowrap overflow-hidden text-ellipsis",
|
|
206
|
+
headerMetaRow: "flex flex-wrap items-center gap-x-gp-sm gap-y-[2px] text-[11.5px] text-fg-muted min-w-0",
|
|
207
|
+
headerActions: "flex items-center gap-gp-sm shrink-0",
|
|
208
|
+
statusInner: "inline-flex items-center gap-[4px]",
|
|
209
|
+
statusDot: "size-[6px] rounded-radius-full shrink-0",
|
|
210
|
+
thread: "flex-1 min-h-0 overflow-y-auto bg-bg-muted dark:bg-bg-canvas px-pad-3xl py-pad-2xl flex flex-col gap-gp-md",
|
|
211
|
+
composer: "flex items-center gap-gp-sm px-pad-2xl py-pad-md border-t border-border-subtle shrink-0 bg-bg-surface"
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
function ConversationColumn({
|
|
215
|
+
conversation,
|
|
216
|
+
detailsOpen,
|
|
217
|
+
onToggleDetails,
|
|
218
|
+
onBackToList,
|
|
219
|
+
className
|
|
220
|
+
}) {
|
|
221
|
+
const s = conversationColumnStyles();
|
|
222
|
+
const [text, setText] = React.useState("");
|
|
223
|
+
const [msgs, setMsgs] = React.useState(chatV2Mocks.SAMPLE_MESSAGES);
|
|
224
|
+
const send = (e) => {
|
|
225
|
+
e?.preventDefault();
|
|
226
|
+
if (!text.trim()) return;
|
|
227
|
+
setMsgs((m) => [
|
|
228
|
+
...m,
|
|
229
|
+
{
|
|
230
|
+
id: Date.now(),
|
|
231
|
+
from: "me",
|
|
232
|
+
text: text.trim(),
|
|
233
|
+
time: (/* @__PURE__ */ new Date()).toLocaleTimeString("pt-BR", {
|
|
234
|
+
hour: "2-digit",
|
|
235
|
+
minute: "2-digit"
|
|
236
|
+
}),
|
|
237
|
+
status: "sent"
|
|
238
|
+
}
|
|
239
|
+
]);
|
|
240
|
+
setText("");
|
|
241
|
+
};
|
|
242
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-label": "Conversa", className: chipGroup.cn(s.root(), className), children: [
|
|
243
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: s.header(), children: [
|
|
244
|
+
onBackToList && /* @__PURE__ */ jsxRuntime.jsx(
|
|
245
|
+
chipGroup.Button,
|
|
246
|
+
{
|
|
247
|
+
color: "secondary",
|
|
248
|
+
variant: "ghost",
|
|
249
|
+
size: "icon-sm",
|
|
250
|
+
"aria-label": "Voltar pra lista",
|
|
251
|
+
onClick: onBackToList,
|
|
252
|
+
className: "md:hidden",
|
|
253
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, {})
|
|
254
|
+
}
|
|
255
|
+
),
|
|
256
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-md:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
257
|
+
PersonAvatar,
|
|
258
|
+
{
|
|
259
|
+
initials: conversation.initials,
|
|
260
|
+
hex: conversation.avatarHex,
|
|
261
|
+
size: "md"
|
|
262
|
+
}
|
|
263
|
+
) }),
|
|
264
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.headerInfo(), children: [
|
|
265
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.headerTitleRow(), children: [
|
|
266
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.headerName(), children: conversation.name }),
|
|
267
|
+
/* @__PURE__ */ jsxRuntime.jsx(chipGroup.Chip, { color: conversation.tagKind, variant: "soft", size: "sm", shape: "pill", children: conversation.tag })
|
|
268
|
+
] }),
|
|
269
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.headerMetaRow(), children: [
|
|
270
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "[font-variant-numeric:tabular-nums]", children: conversation.id }),
|
|
271
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "·" }),
|
|
272
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChannelDot, { channel: conversation.channel }),
|
|
273
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "·" }),
|
|
274
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: s.statusInner(), children: [
|
|
275
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
276
|
+
"span",
|
|
277
|
+
{
|
|
278
|
+
className: s.statusDot(),
|
|
279
|
+
style: { background: chatV2Mocks.STATUS_DOT[conversation.status] },
|
|
280
|
+
"aria-hidden": true
|
|
281
|
+
}
|
|
282
|
+
),
|
|
283
|
+
conversation.statusLabel
|
|
284
|
+
] })
|
|
285
|
+
] })
|
|
286
|
+
] }),
|
|
287
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.headerActions(), children: [
|
|
288
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
289
|
+
chipGroup.Button,
|
|
290
|
+
{
|
|
291
|
+
color: "primary",
|
|
292
|
+
variant: "filled",
|
|
293
|
+
size: "sm",
|
|
294
|
+
iconLeft: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, {}),
|
|
295
|
+
className: "max-md:hidden",
|
|
296
|
+
children: "Resolver"
|
|
297
|
+
}
|
|
298
|
+
),
|
|
299
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
300
|
+
ConversationActionsMenu,
|
|
301
|
+
{
|
|
302
|
+
showResolveInMenu: true,
|
|
303
|
+
onResolve: () => console.log("resolver"),
|
|
304
|
+
onCall: () => console.log("ligar"),
|
|
305
|
+
onVideo: () => console.log("video"),
|
|
306
|
+
onAddTag: () => console.log("tag"),
|
|
307
|
+
onAssign: () => console.log("atribuir"),
|
|
308
|
+
onArchive: () => console.log("arquivar")
|
|
309
|
+
}
|
|
310
|
+
),
|
|
311
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
312
|
+
chipGroup.Button,
|
|
313
|
+
{
|
|
314
|
+
color: "secondary",
|
|
315
|
+
variant: "outline",
|
|
316
|
+
size: "icon-sm",
|
|
317
|
+
"aria-label": detailsOpen ? "Ocultar detalhes" : "Mostrar detalhes",
|
|
318
|
+
"aria-pressed": detailsOpen,
|
|
319
|
+
onClick: onToggleDetails,
|
|
320
|
+
children: detailsOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelRightClose, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelRightOpen, {})
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
] })
|
|
324
|
+
] }),
|
|
325
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.thread(), "aria-live": "polite", children: [
|
|
326
|
+
/* @__PURE__ */ jsxRuntime.jsx(DateSeparator, { label: "Hoje" }),
|
|
327
|
+
msgs.map((m) => /* @__PURE__ */ jsxRuntime.jsx(MessageBubble, { msg: m }, m.id))
|
|
328
|
+
] }),
|
|
329
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: send, className: s.composer(), children: [
|
|
330
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
331
|
+
chipGroup.Button,
|
|
332
|
+
{
|
|
333
|
+
color: "secondary",
|
|
334
|
+
variant: "ghost",
|
|
335
|
+
size: "icon-sm",
|
|
336
|
+
"aria-label": "Anexar",
|
|
337
|
+
type: "button",
|
|
338
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, {})
|
|
339
|
+
}
|
|
340
|
+
),
|
|
341
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
342
|
+
input.Input,
|
|
343
|
+
{
|
|
344
|
+
type: "text",
|
|
345
|
+
value: text,
|
|
346
|
+
onChange: (e) => setText(e.target.value),
|
|
347
|
+
placeholder: "Digite uma mensagem...",
|
|
348
|
+
"aria-label": "Mensagem",
|
|
349
|
+
className: "flex-1"
|
|
350
|
+
}
|
|
351
|
+
),
|
|
352
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
353
|
+
chipGroup.Button,
|
|
354
|
+
{
|
|
355
|
+
color: "secondary",
|
|
356
|
+
variant: "ghost",
|
|
357
|
+
size: "icon-sm",
|
|
358
|
+
"aria-label": "Emoji",
|
|
359
|
+
type: "button",
|
|
360
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Smile, {})
|
|
361
|
+
}
|
|
362
|
+
),
|
|
363
|
+
text.trim() ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
364
|
+
chipGroup.Button,
|
|
365
|
+
{
|
|
366
|
+
color: "primary",
|
|
367
|
+
variant: "filled",
|
|
368
|
+
size: "icon-sm",
|
|
369
|
+
"aria-label": "Enviar",
|
|
370
|
+
type: "submit",
|
|
371
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { strokeWidth: 2.2 })
|
|
372
|
+
}
|
|
373
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
374
|
+
chipGroup.Button,
|
|
375
|
+
{
|
|
376
|
+
color: "primary",
|
|
377
|
+
variant: "filled",
|
|
378
|
+
size: "icon-sm",
|
|
379
|
+
"aria-label": "Gravar áudio",
|
|
380
|
+
type: "button",
|
|
381
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, { strokeWidth: 2.2 })
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
] })
|
|
385
|
+
] });
|
|
386
|
+
}
|
|
387
|
+
function DetailField({ label, value }) {
|
|
388
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-gp-md py-pad-2xs", children: [
|
|
389
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] text-fg-muted shrink-0", children: label }),
|
|
390
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12.5px] text-fg-default text-right break-words min-w-0", children: value || "—" })
|
|
391
|
+
] });
|
|
392
|
+
}
|
|
393
|
+
function DetailSection({
|
|
394
|
+
title,
|
|
395
|
+
open,
|
|
396
|
+
onToggle,
|
|
397
|
+
children
|
|
398
|
+
}) {
|
|
399
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col border-b border-border-subtle pb-pad-xl last:border-b-0 last:pb-0", children: [
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
401
|
+
"button",
|
|
402
|
+
{
|
|
403
|
+
type: "button",
|
|
404
|
+
onClick: onToggle,
|
|
405
|
+
"aria-expanded": open,
|
|
406
|
+
className: "flex items-center justify-between w-full px-pad-sm py-pad-sm -mx-pad-sm rounded-radius-md cursor-pointer text-left transition-colors duration-150 hover:bg-bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring-brand",
|
|
407
|
+
children: [
|
|
408
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[13px] font-semibold text-fg-default", children: title }),
|
|
409
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
410
|
+
lucideReact.ChevronDown,
|
|
411
|
+
{
|
|
412
|
+
size: 14,
|
|
413
|
+
className: [
|
|
414
|
+
"text-fg-muted transition-transform duration-150",
|
|
415
|
+
open ? "" : "-rotate-90"
|
|
416
|
+
].join(" ")
|
|
417
|
+
}
|
|
418
|
+
)
|
|
419
|
+
]
|
|
420
|
+
}
|
|
421
|
+
),
|
|
422
|
+
open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-gp-sm pt-pad-xs", children })
|
|
423
|
+
] });
|
|
424
|
+
}
|
|
425
|
+
const detailsColumnStyles = chipGroup.tv({
|
|
426
|
+
slots: {
|
|
427
|
+
root: "relative flex flex-col shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden",
|
|
428
|
+
/** Resize handle no left edge — 4px. */
|
|
429
|
+
handle: "absolute left-0 top-0 bottom-0 w-[4px] z-[1] bg-transparent cursor-col-resize hover:bg-bg-brand active:bg-bg-brand transition-colors duration-150 focus-visible:outline-none focus-visible:bg-bg-brand",
|
|
430
|
+
header: "flex items-center gap-gp-md px-pad-2xl py-pad-lg border-b border-border-subtle shrink-0",
|
|
431
|
+
title: "m-0 text-title-md text-fg-default flex-1",
|
|
432
|
+
body: "flex-1 min-h-0 overflow-y-auto px-pad-2xl py-pad-md flex flex-col gap-gp-2xl",
|
|
433
|
+
contactHead: "flex flex-col items-center gap-gp-md pb-pad-md",
|
|
434
|
+
contactName: "text-[14px] font-semibold text-fg-default text-center",
|
|
435
|
+
tagsRow: "flex flex-col gap-gp-sm pt-pad-xs",
|
|
436
|
+
tagsLabel: "text-[12px] text-fg-muted",
|
|
437
|
+
tagsChips: "flex items-center gap-gp-xs flex-wrap",
|
|
438
|
+
tagAddBtn: "inline-flex items-center gap-[3px] px-pad-md h-[22px] rounded-radius-full border border-dashed border-border-input text-[11px] font-medium text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors",
|
|
439
|
+
historyEmpty: "text-[12px] text-fg-subtle text-center py-pad-md",
|
|
440
|
+
historyList: "m-0 p-0 list-none flex flex-col gap-gp-sm",
|
|
441
|
+
historyItem: "flex gap-gp-md p-pad-md rounded-radius-md bg-bg-muted border border-border-subtle",
|
|
442
|
+
historyId: "text-[11px] text-fg-muted shrink-0 [font-variant-numeric:tabular-nums] pt-[1px]",
|
|
443
|
+
historyBody: "flex-1 min-w-0 flex flex-col gap-[1px]",
|
|
444
|
+
historySubject: "text-[12.5px] font-medium text-fg-default",
|
|
445
|
+
historyMeta: "text-[11px] text-fg-muted"
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
function DetailsColumn({
|
|
449
|
+
conversation,
|
|
450
|
+
detail,
|
|
451
|
+
openSections,
|
|
452
|
+
onToggleSection,
|
|
453
|
+
onClose,
|
|
454
|
+
width,
|
|
455
|
+
onResizeStart,
|
|
456
|
+
onBackToChat,
|
|
457
|
+
className
|
|
458
|
+
}) {
|
|
459
|
+
const s = detailsColumnStyles();
|
|
460
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
461
|
+
"aside",
|
|
462
|
+
{
|
|
463
|
+
"aria-label": "Detalhes do contato",
|
|
464
|
+
style: { width },
|
|
465
|
+
className: chipGroup.cn(s.root(), className),
|
|
466
|
+
children: [
|
|
467
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
468
|
+
"button",
|
|
469
|
+
{
|
|
470
|
+
type: "button",
|
|
471
|
+
onMouseDown: onResizeStart,
|
|
472
|
+
"aria-label": "Redimensionar painel de detalhes",
|
|
473
|
+
className: s.handle()
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: s.header(), children: [
|
|
477
|
+
onBackToChat && /* @__PURE__ */ jsxRuntime.jsx(
|
|
478
|
+
chipGroup.Button,
|
|
479
|
+
{
|
|
480
|
+
color: "secondary",
|
|
481
|
+
variant: "ghost",
|
|
482
|
+
size: "icon-sm",
|
|
483
|
+
"aria-label": "Voltar pra conversa",
|
|
484
|
+
onClick: onBackToChat,
|
|
485
|
+
className: "md:hidden",
|
|
486
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, {})
|
|
487
|
+
}
|
|
488
|
+
),
|
|
489
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: s.title(), children: "Detalhes" }),
|
|
490
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
491
|
+
chipGroup.Button,
|
|
492
|
+
{
|
|
493
|
+
color: "secondary",
|
|
494
|
+
variant: "ghost",
|
|
495
|
+
size: "icon-sm",
|
|
496
|
+
"aria-label": "Fechar painel",
|
|
497
|
+
onClick: onClose,
|
|
498
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {})
|
|
499
|
+
}
|
|
500
|
+
)
|
|
501
|
+
] }),
|
|
502
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.body(), children: [
|
|
503
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
504
|
+
DetailSection,
|
|
505
|
+
{
|
|
506
|
+
title: "Contato",
|
|
507
|
+
open: openSections.contact,
|
|
508
|
+
onToggle: () => onToggleSection("contact"),
|
|
509
|
+
children: [
|
|
510
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.contactHead(), children: [
|
|
511
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
512
|
+
PersonAvatar,
|
|
513
|
+
{
|
|
514
|
+
initials: conversation.initials,
|
|
515
|
+
hex: conversation.avatarHex,
|
|
516
|
+
size: "lg"
|
|
517
|
+
}
|
|
518
|
+
),
|
|
519
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s.contactName(), children: conversation.name })
|
|
520
|
+
] }),
|
|
521
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Telefone", value: detail.phone }),
|
|
522
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Email", value: detail.email }),
|
|
523
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Primeiro contato", value: detail.firstContact })
|
|
524
|
+
]
|
|
525
|
+
}
|
|
526
|
+
),
|
|
527
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
528
|
+
DetailSection,
|
|
529
|
+
{
|
|
530
|
+
title: "Atendimento",
|
|
531
|
+
open: openSections.ticket,
|
|
532
|
+
onToggle: () => onToggleSection("ticket"),
|
|
533
|
+
children: [
|
|
534
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "ID", value: conversation.id }),
|
|
535
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Status", value: conversation.statusLabel }),
|
|
536
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Atribuído a", value: detail.assignedTo }),
|
|
537
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Canal", value: chatV2Mocks.CHANNEL_LABEL[conversation.channel] }),
|
|
538
|
+
/* @__PURE__ */ jsxRuntime.jsx(DetailField, { label: "Criado em", value: detail.createdAt }),
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.tagsRow(), children: [
|
|
540
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.tagsLabel(), children: "Tags" }),
|
|
541
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.tagsChips(), children: [
|
|
542
|
+
/* @__PURE__ */ jsxRuntime.jsx(chipGroup.Chip, { color: conversation.tagKind, variant: "soft", size: "sm", shape: "pill", children: conversation.tag }),
|
|
543
|
+
detail.extraTags.map((t) => /* @__PURE__ */ jsxRuntime.jsx(chipGroup.Chip, { color: "info", variant: "soft", size: "sm", shape: "pill", children: t }, t)),
|
|
544
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: s.tagAddBtn(), children: [
|
|
545
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 11, strokeWidth: 2.2 }),
|
|
546
|
+
" tag"
|
|
547
|
+
] })
|
|
548
|
+
] })
|
|
549
|
+
] })
|
|
550
|
+
]
|
|
551
|
+
}
|
|
552
|
+
),
|
|
553
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
554
|
+
DetailSection,
|
|
555
|
+
{
|
|
556
|
+
title: "Histórico",
|
|
557
|
+
open: openSections.history,
|
|
558
|
+
onToggle: () => onToggleSection("history"),
|
|
559
|
+
children: detail.history.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: s.historyEmpty(), children: "Nenhum atendimento anterior." }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className: s.historyList(), children: detail.history.map((h) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: s.historyItem(), children: [
|
|
560
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.historyId(), children: h.id }),
|
|
561
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.historyBody(), children: [
|
|
562
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.historySubject(), children: h.subject }),
|
|
563
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: s.historyMeta(), children: [
|
|
564
|
+
h.date,
|
|
565
|
+
" · ",
|
|
566
|
+
h.status
|
|
567
|
+
] })
|
|
568
|
+
] })
|
|
569
|
+
] }, h.id)) })
|
|
570
|
+
}
|
|
571
|
+
)
|
|
572
|
+
] })
|
|
573
|
+
]
|
|
574
|
+
}
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
const filterRowStyles = chipGroup.tv({
|
|
578
|
+
slots: {
|
|
579
|
+
button: [
|
|
580
|
+
"flex items-center gap-gp-md w-full",
|
|
581
|
+
"px-pad-md py-pad-sm rounded-radius-md text-left",
|
|
582
|
+
"transition-colors duration-150 cursor-pointer"
|
|
583
|
+
].join(" "),
|
|
584
|
+
/** Leading slot (icon ou dot fallback). */
|
|
585
|
+
leading: "shrink-0 inline-flex items-center justify-center size-[18px]",
|
|
586
|
+
/** Label do filtro (ellipsis). */
|
|
587
|
+
label: "flex-1 min-w-0 text-[12.5px] font-medium whitespace-nowrap overflow-hidden text-ellipsis",
|
|
588
|
+
/** Dot brand 6px pra "tem novidades". */
|
|
589
|
+
unreadDot: "size-[6px] rounded-radius-full bg-bg-brand shrink-0",
|
|
590
|
+
/** Contador à direita. */
|
|
591
|
+
count: "text-[11px] text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]",
|
|
592
|
+
/** Dot fallback (quando item não tem icon). */
|
|
593
|
+
fallbackDot: "size-[8px] rounded-radius-full"
|
|
594
|
+
},
|
|
595
|
+
variants: {
|
|
596
|
+
isActive: {
|
|
597
|
+
true: {
|
|
598
|
+
button: "bg-bg-muted dark:bg-bg-emphasis text-fg-default font-semibold"
|
|
599
|
+
},
|
|
600
|
+
false: {
|
|
601
|
+
button: "text-fg-muted hover:bg-bg-muted hover:text-fg-default"
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
defaultVariants: {
|
|
606
|
+
isActive: false
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
function FilterRow({ item, isActive, onClick }) {
|
|
610
|
+
const Icon = item.icon;
|
|
611
|
+
const s = filterRowStyles({ isActive });
|
|
612
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
613
|
+
"button",
|
|
614
|
+
{
|
|
615
|
+
type: "button",
|
|
616
|
+
onClick,
|
|
617
|
+
"aria-pressed": isActive,
|
|
618
|
+
className: s.button(),
|
|
619
|
+
children: [
|
|
620
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.leading(), children: Icon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
621
|
+
Icon,
|
|
622
|
+
{
|
|
623
|
+
size: 15,
|
|
624
|
+
strokeWidth: 1.8,
|
|
625
|
+
style: { color: item.color ?? "var(--color-fg-muted)" }
|
|
626
|
+
}
|
|
627
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
628
|
+
"span",
|
|
629
|
+
{
|
|
630
|
+
className: s.fallbackDot(),
|
|
631
|
+
style: { background: item.color ?? "var(--color-fg-muted)" },
|
|
632
|
+
"aria-hidden": true
|
|
633
|
+
}
|
|
634
|
+
) }),
|
|
635
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.label(), children: item.name }),
|
|
636
|
+
item.hasUnread && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s.unreadDot(), "aria-label": "tem novidades" }),
|
|
637
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.count(), children: item.count })
|
|
638
|
+
]
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
const filtersColumnStyles = chipGroup.tv({
|
|
643
|
+
slots: {
|
|
644
|
+
/** Aside raiz da versão expandida (280px). */
|
|
645
|
+
root: "flex flex-col w-[280px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden",
|
|
646
|
+
/** Aside raiz da versão rail (64px). */
|
|
647
|
+
rail: "flex flex-col w-[64px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden",
|
|
648
|
+
/** Container scrollável das seções (expandida). */
|
|
649
|
+
scroll: "flex-1 min-h-0 overflow-y-auto px-pad-md py-pad-md flex flex-col gap-gp-lg",
|
|
650
|
+
/** Container scrollável (rail). */
|
|
651
|
+
railScroll: "flex-1 min-h-0 overflow-y-auto py-pad-md flex flex-col items-center gap-gp-sm",
|
|
652
|
+
/** Section wrapper (expandida). */
|
|
653
|
+
section: "flex flex-col gap-gp-2xs",
|
|
654
|
+
/** Header de section (título all-caps). Usa `subheading-strong-sm` —
|
|
655
|
+
token DS criado especificamente pra este caso (10px/700/+0.06em). */
|
|
656
|
+
sectionTitle: "px-pad-md pt-pad-2xs pb-pad-2xs text-[10px] font-bold tracking-[0.06em] text-fg-subtle uppercase",
|
|
657
|
+
/** Group wrapper (rail) — divider entre grupos. */
|
|
658
|
+
railGroup: "w-full flex flex-col items-center gap-gp-xs px-pad-md",
|
|
659
|
+
/** Modifier de divisor pros grupos não-primeiros (rail). */
|
|
660
|
+
railGroupDivider: "pt-pad-sm border-t border-border-subtle",
|
|
661
|
+
/** Modifier de divisor pras sections não-primeiras (expandida). */
|
|
662
|
+
sectionDivider: "pt-pad-lg border-t border-border-subtle"
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
function FiltersColumn({
|
|
666
|
+
filters,
|
|
667
|
+
onToggleFilter,
|
|
668
|
+
className
|
|
669
|
+
}) {
|
|
670
|
+
const s = filtersColumnStyles();
|
|
671
|
+
return /* @__PURE__ */ jsxRuntime.jsx("aside", { "aria-label": "Filtros", className: chipGroup.cn(s.root(), className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: s.scroll(), children: chatV2Mocks.FILTER_GROUPS.map((sec, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
672
|
+
FilterSection,
|
|
673
|
+
{
|
|
674
|
+
title: sec.title,
|
|
675
|
+
group: sec.group,
|
|
676
|
+
items: sec.items,
|
|
677
|
+
filters,
|
|
678
|
+
onToggle: onToggleFilter,
|
|
679
|
+
isFirst: i === 0
|
|
680
|
+
},
|
|
681
|
+
sec.group
|
|
682
|
+
)) }) });
|
|
683
|
+
}
|
|
684
|
+
function FilterSection({
|
|
685
|
+
title,
|
|
686
|
+
group,
|
|
687
|
+
items,
|
|
688
|
+
filters,
|
|
689
|
+
onToggle,
|
|
690
|
+
isFirst
|
|
691
|
+
}) {
|
|
692
|
+
const s = filtersColumnStyles();
|
|
693
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: chipGroup.cn(s.section(), !isFirst && s.sectionDivider()), children: [
|
|
694
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s.sectionTitle(), children: title }),
|
|
695
|
+
items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
696
|
+
FilterRow,
|
|
697
|
+
{
|
|
698
|
+
item,
|
|
699
|
+
isActive: filters[group].has(item.id),
|
|
700
|
+
onClick: () => onToggle(group, item.id)
|
|
701
|
+
},
|
|
702
|
+
item.id
|
|
703
|
+
))
|
|
704
|
+
] });
|
|
705
|
+
}
|
|
706
|
+
const railItemStyles = chipGroup.tv({
|
|
707
|
+
slots: {
|
|
708
|
+
button: [
|
|
709
|
+
"relative grid place-items-center size-form-md rounded-radius-md cursor-pointer",
|
|
710
|
+
"transition-colors duration-150"
|
|
711
|
+
].join(" "),
|
|
712
|
+
/** Badge dot 6px (top-right) pra "tem novidades". */
|
|
713
|
+
unreadDot: "absolute top-[2px] right-[2px] size-[6px] rounded-radius-full bg-bg-brand",
|
|
714
|
+
/** Fallback dot (quando item não tem icon). */
|
|
715
|
+
fallbackDot: "size-[10px] rounded-radius-full"
|
|
716
|
+
},
|
|
717
|
+
variants: {
|
|
718
|
+
isActive: {
|
|
719
|
+
true: {
|
|
720
|
+
button: "bg-bg-muted dark:bg-bg-emphasis text-fg-default"
|
|
721
|
+
},
|
|
722
|
+
false: {
|
|
723
|
+
button: "text-fg-muted hover:bg-bg-muted hover:text-fg-default"
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
defaultVariants: {
|
|
728
|
+
isActive: false
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
function RailItem({ item, isActive, onClick }) {
|
|
732
|
+
const Icon = item.icon;
|
|
733
|
+
const s = railItemStyles({ isActive });
|
|
734
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
735
|
+
"button",
|
|
736
|
+
{
|
|
737
|
+
type: "button",
|
|
738
|
+
onClick,
|
|
739
|
+
"aria-pressed": isActive,
|
|
740
|
+
title: `${item.name} (${item.count})`,
|
|
741
|
+
className: s.button(),
|
|
742
|
+
children: [
|
|
743
|
+
Icon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
744
|
+
Icon,
|
|
745
|
+
{
|
|
746
|
+
size: 16,
|
|
747
|
+
strokeWidth: 1.8,
|
|
748
|
+
style: { color: item.color ?? "currentColor" }
|
|
749
|
+
}
|
|
750
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
751
|
+
"span",
|
|
752
|
+
{
|
|
753
|
+
className: s.fallbackDot(),
|
|
754
|
+
style: { background: item.color ?? "var(--color-fg-muted)" },
|
|
755
|
+
"aria-hidden": true
|
|
756
|
+
}
|
|
757
|
+
),
|
|
758
|
+
item.hasUnread && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s.unreadDot(), "aria-label": "tem novidades" })
|
|
759
|
+
]
|
|
760
|
+
}
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
function FiltersRail({
|
|
764
|
+
filters,
|
|
765
|
+
onToggleFilter,
|
|
766
|
+
className
|
|
767
|
+
}) {
|
|
768
|
+
const s = filtersColumnStyles();
|
|
769
|
+
return /* @__PURE__ */ jsxRuntime.jsx("aside", { "aria-label": "Filtros (compactos)", className: chipGroup.cn(s.rail(), className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: s.railScroll(), children: chatV2Mocks.FILTER_GROUPS.map(({ group, items }, gi) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
770
|
+
"div",
|
|
771
|
+
{
|
|
772
|
+
className: chipGroup.cn(s.railGroup(), gi > 0 && s.railGroupDivider()),
|
|
773
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
774
|
+
RailItem,
|
|
775
|
+
{
|
|
776
|
+
item,
|
|
777
|
+
isActive: filters[group].has(item.id),
|
|
778
|
+
onClick: () => onToggleFilter(group, item.id)
|
|
779
|
+
},
|
|
780
|
+
item.id
|
|
781
|
+
))
|
|
782
|
+
},
|
|
783
|
+
group
|
|
784
|
+
)) }) });
|
|
785
|
+
}
|
|
786
|
+
const conversationListItemStyles = chipGroup.tv({
|
|
787
|
+
slots: {
|
|
788
|
+
/** Card raiz (button) — flex horizontal com avatar + conteúdo. */
|
|
789
|
+
root: [
|
|
790
|
+
"group/conv text-left relative",
|
|
791
|
+
"flex gap-gp-md p-pad-md rounded-radius-md",
|
|
792
|
+
"cursor-pointer transition-colors duration-150"
|
|
793
|
+
].join(" "),
|
|
794
|
+
/** Coluna direita (3 rows). */
|
|
795
|
+
content: "flex-1 min-w-0 flex flex-col gap-[3px]",
|
|
796
|
+
/** Row 1 — nome + horário. */
|
|
797
|
+
rowTop: "flex items-center gap-gp-sm",
|
|
798
|
+
/** Nome (ellipsis). */
|
|
799
|
+
name: "text-[13px] font-semibold text-fg-default whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0",
|
|
800
|
+
/** Horário. */
|
|
801
|
+
time: "text-[11px] text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]",
|
|
802
|
+
/** Row 2 — preview + badge unread. */
|
|
803
|
+
rowMid: "flex items-center gap-gp-sm",
|
|
804
|
+
/** Preview da última mensagem (ellipsis). */
|
|
805
|
+
preview: "text-[12px] text-fg-muted whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0",
|
|
806
|
+
/** Badge contador de não lidas — usa `subheading-strong-md` (11px/700) como
|
|
807
|
+
base e força `font-bold` + `leading-none` inline pra preservar o weight
|
|
808
|
+
e a centralização vertical do número dentro do círculo (preset DS sozinho
|
|
809
|
+
usa lineHeight 0.875rem, que descentraliza o conteúdo). */
|
|
810
|
+
unread: "inline-flex items-center justify-center min-w-[18px] h-[18px] px-[5px] rounded-radius-full bg-bg-brand text-fg-on-brand text-[10.5px] font-bold leading-none shrink-0 [font-variant-numeric:tabular-nums]",
|
|
811
|
+
/** Row 3 — canal + tag + ID. */
|
|
812
|
+
rowBot: "flex items-center gap-gp-sm",
|
|
813
|
+
/** ID da conversa (canto inferior direito). */
|
|
814
|
+
id: "ml-auto text-[10.5px] text-fg-subtle shrink-0 [font-variant-numeric:tabular-nums]"
|
|
815
|
+
},
|
|
816
|
+
variants: {
|
|
817
|
+
isActive: {
|
|
818
|
+
true: {
|
|
819
|
+
root: [
|
|
820
|
+
"bg-bg-muted dark:bg-bg-emphasis",
|
|
821
|
+
"before:content-[''] before:absolute before:left-0 before:top-[10px] before:bottom-[10px]",
|
|
822
|
+
"before:w-[3px] before:bg-bg-brand before:rounded-r-[2px] before:pointer-events-none"
|
|
823
|
+
].join(" ")
|
|
824
|
+
},
|
|
825
|
+
false: {
|
|
826
|
+
root: "hover:bg-bg-muted"
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
},
|
|
830
|
+
defaultVariants: {
|
|
831
|
+
isActive: false
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
function ConversationListItem({
|
|
835
|
+
conv,
|
|
836
|
+
isActive,
|
|
837
|
+
onSelect
|
|
838
|
+
}) {
|
|
839
|
+
const s = conversationListItemStyles({ isActive });
|
|
840
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
841
|
+
"button",
|
|
842
|
+
{
|
|
843
|
+
type: "button",
|
|
844
|
+
onClick: () => onSelect(conv.id),
|
|
845
|
+
className: s.root(),
|
|
846
|
+
"aria-pressed": isActive,
|
|
847
|
+
children: [
|
|
848
|
+
/* @__PURE__ */ jsxRuntime.jsx(PersonAvatar, { initials: conv.initials, hex: conv.avatarHex, size: "md" }),
|
|
849
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.content(), children: [
|
|
850
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.rowTop(), children: [
|
|
851
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.name(), children: conv.name }),
|
|
852
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.time(), children: conv.time })
|
|
853
|
+
] }),
|
|
854
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.rowMid(), children: [
|
|
855
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.preview(), children: conv.last }),
|
|
856
|
+
conv.unread > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: s.unread(), "aria-label": `${conv.unread} não lidas`, children: conv.unread })
|
|
857
|
+
] }),
|
|
858
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.rowBot(), children: [
|
|
859
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChannelDot, { channel: conv.channel }),
|
|
860
|
+
/* @__PURE__ */ jsxRuntime.jsx(chipGroup.Chip, { color: conv.tagKind, variant: "soft", size: "sm", shape: "pill", children: conv.tag }),
|
|
861
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: s.id(), children: conv.id })
|
|
862
|
+
] })
|
|
863
|
+
] })
|
|
864
|
+
]
|
|
865
|
+
}
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
const queueColumnStyles = chipGroup.tv({
|
|
869
|
+
slots: {
|
|
870
|
+
root: "flex flex-col w-[340px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden",
|
|
871
|
+
header: "flex items-center gap-gp-sm px-pad-md pt-pad-md pb-pad-md",
|
|
872
|
+
title: "m-0 text-title-md text-fg-default flex-1 min-w-0",
|
|
873
|
+
searchWrap: "px-pad-md pb-pad-lg",
|
|
874
|
+
searchInner: "relative",
|
|
875
|
+
searchIcon: "absolute left-pad-lg top-1/2 -translate-y-1/2 text-fg-muted pointer-events-none",
|
|
876
|
+
searchInput: "pl-[34px] pr-[30px]",
|
|
877
|
+
searchClear: "absolute right-pad-md top-1/2 -translate-y-1/2 grid place-items-center size-[20px] rounded-radius-md text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors",
|
|
878
|
+
chipsWrap: "px-pad-md pb-pad-2xl",
|
|
879
|
+
list: "flex-1 min-h-0 overflow-y-auto px-pad-md pb-pad-md flex flex-col gap-gp-xs",
|
|
880
|
+
empty: "py-pad-4xl px-pad-xl text-center text-[12px] text-fg-subtle"
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
function QueueColumn({
|
|
884
|
+
activeId,
|
|
885
|
+
onSelect,
|
|
886
|
+
searchQuery,
|
|
887
|
+
onSearchChange,
|
|
888
|
+
queueFilter,
|
|
889
|
+
onQueueFilterChange,
|
|
890
|
+
filtersCollapsed,
|
|
891
|
+
onToggleFilters,
|
|
892
|
+
className
|
|
893
|
+
}) {
|
|
894
|
+
const s = queueColumnStyles();
|
|
895
|
+
const filtered = React.useMemo(() => {
|
|
896
|
+
const q = searchQuery.trim().toLowerCase();
|
|
897
|
+
const bySearch = q ? chatV2Mocks.CONVERSATIONS.filter(
|
|
898
|
+
(c) => c.name.toLowerCase().includes(q) || c.id.toLowerCase().includes(q) || c.last.toLowerCase().includes(q)
|
|
899
|
+
) : chatV2Mocks.CONVERSATIONS;
|
|
900
|
+
if (queueFilter === "unread") return bySearch.filter((c) => c.unread > 0);
|
|
901
|
+
if (queueFilter === "read") return bySearch.filter((c) => c.unread === 0);
|
|
902
|
+
return bySearch;
|
|
903
|
+
}, [searchQuery, queueFilter]);
|
|
904
|
+
const counts = React.useMemo(() => {
|
|
905
|
+
const q = searchQuery.trim().toLowerCase();
|
|
906
|
+
const bySearch = q ? chatV2Mocks.CONVERSATIONS.filter(
|
|
907
|
+
(c) => c.name.toLowerCase().includes(q) || c.id.toLowerCase().includes(q) || c.last.toLowerCase().includes(q)
|
|
908
|
+
) : chatV2Mocks.CONVERSATIONS;
|
|
909
|
+
return {
|
|
910
|
+
all: bySearch.length,
|
|
911
|
+
unread: bySearch.filter((c) => c.unread > 0).length,
|
|
912
|
+
read: bySearch.filter((c) => c.unread === 0).length
|
|
913
|
+
};
|
|
914
|
+
}, [searchQuery]);
|
|
915
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("aside", { "aria-label": "Fila de conversas", className: chipGroup.cn(s.root(), className), children: [
|
|
916
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: s.header(), children: [
|
|
917
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
918
|
+
chipGroup.Button,
|
|
919
|
+
{
|
|
920
|
+
color: "secondary",
|
|
921
|
+
variant: "ghost",
|
|
922
|
+
size: "icon-sm",
|
|
923
|
+
onClick: onToggleFilters,
|
|
924
|
+
"aria-label": filtersCollapsed ? "Expandir filtros" : "Colapsar filtros",
|
|
925
|
+
"aria-pressed": !filtersCollapsed,
|
|
926
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, {})
|
|
927
|
+
}
|
|
928
|
+
),
|
|
929
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: s.title(), children: "Conversas" }),
|
|
930
|
+
/* @__PURE__ */ jsxRuntime.jsx(chipGroup.Chip, { color: "primary", variant: "soft", size: "sm", shape: "rounded", children: filtered.length })
|
|
931
|
+
] }),
|
|
932
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s.searchWrap(), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.searchInner(), children: [
|
|
933
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { size: 14, strokeWidth: 1.8, className: s.searchIcon() }),
|
|
934
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
935
|
+
input.Input,
|
|
936
|
+
{
|
|
937
|
+
type: "text",
|
|
938
|
+
placeholder: "Buscar conversa, ID ou nome...",
|
|
939
|
+
value: searchQuery,
|
|
940
|
+
onChange: (e) => onSearchChange(e.target.value),
|
|
941
|
+
className: s.searchInput()
|
|
942
|
+
}
|
|
943
|
+
),
|
|
944
|
+
searchQuery && /* @__PURE__ */ jsxRuntime.jsx(
|
|
945
|
+
"button",
|
|
946
|
+
{
|
|
947
|
+
type: "button",
|
|
948
|
+
onClick: () => onSearchChange(""),
|
|
949
|
+
className: s.searchClear(),
|
|
950
|
+
"aria-label": "Limpar busca",
|
|
951
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12 })
|
|
952
|
+
}
|
|
953
|
+
)
|
|
954
|
+
] }) }),
|
|
955
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s.chipsWrap(), children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
956
|
+
chipGroup.ChipGroup,
|
|
957
|
+
{
|
|
958
|
+
type: "single",
|
|
959
|
+
value: queueFilter,
|
|
960
|
+
onValueChange: (v) => onQueueFilterChange(v || "all"),
|
|
961
|
+
size: "md",
|
|
962
|
+
ariaLabel: "Filtrar conversas",
|
|
963
|
+
children: [
|
|
964
|
+
/* @__PURE__ */ jsxRuntime.jsxs(chipGroup.ChipGroupItem, { value: "all", children: [
|
|
965
|
+
"Todas",
|
|
966
|
+
counts.all > 0 && ` (${counts.all})`
|
|
967
|
+
] }),
|
|
968
|
+
/* @__PURE__ */ jsxRuntime.jsxs(chipGroup.ChipGroupItem, { value: "unread", children: [
|
|
969
|
+
"Não lidas",
|
|
970
|
+
counts.unread > 0 && ` (${counts.unread})`
|
|
971
|
+
] }),
|
|
972
|
+
/* @__PURE__ */ jsxRuntime.jsxs(chipGroup.ChipGroupItem, { value: "read", children: [
|
|
973
|
+
"Lidas",
|
|
974
|
+
counts.read > 0 && ` (${counts.read})`
|
|
975
|
+
] })
|
|
976
|
+
]
|
|
977
|
+
}
|
|
978
|
+
) }),
|
|
979
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s.list(), children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: s.empty(), children: "Nenhuma conversa encontrada." }) : filtered.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
980
|
+
ConversationListItem,
|
|
981
|
+
{
|
|
982
|
+
conv: c,
|
|
983
|
+
isActive: c.id === activeId,
|
|
984
|
+
onSelect
|
|
985
|
+
},
|
|
986
|
+
c.id
|
|
987
|
+
)) })
|
|
988
|
+
] });
|
|
989
|
+
}
|
|
990
|
+
function ChatV2() {
|
|
991
|
+
const s = chatV2Styles();
|
|
992
|
+
const [activeId, setActiveId] = React.useState(chatV2Mocks.CONVERSATIONS[0].id);
|
|
993
|
+
const [searchQuery, setSearchQuery] = React.useState("");
|
|
994
|
+
const { theme, setTheme } = useTheme.useTheme();
|
|
995
|
+
const [mobileView, setMobileView] = React.useState("list");
|
|
996
|
+
const handleSelectConversation = (id) => {
|
|
997
|
+
setActiveId(id);
|
|
998
|
+
setMobileView("chat");
|
|
999
|
+
};
|
|
1000
|
+
const handleToggleDetails = () => {
|
|
1001
|
+
const isMobile = typeof window !== "undefined" && window.matchMedia("(max-width: 767px)").matches;
|
|
1002
|
+
if (isMobile) {
|
|
1003
|
+
setDetailsOpen(true);
|
|
1004
|
+
setMobileView((v) => v === "details" ? "chat" : "details");
|
|
1005
|
+
} else {
|
|
1006
|
+
setDetailsOpen((o) => !o);
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
const [filters, setFilters] = React.useState({
|
|
1010
|
+
status: /* @__PURE__ */ new Set(["open"]),
|
|
1011
|
+
channels: /* @__PURE__ */ new Set(),
|
|
1012
|
+
categories: /* @__PURE__ */ new Set(),
|
|
1013
|
+
innerStatus: /* @__PURE__ */ new Set()
|
|
1014
|
+
});
|
|
1015
|
+
const toggleFilter = (group, id) => {
|
|
1016
|
+
setFilters((prev) => {
|
|
1017
|
+
const next = new Set(prev[group]);
|
|
1018
|
+
if (next.has(id)) next.delete(id);
|
|
1019
|
+
else next.add(id);
|
|
1020
|
+
return { ...prev, [group]: next };
|
|
1021
|
+
});
|
|
1022
|
+
};
|
|
1023
|
+
const [filtersCollapsed, setFiltersCollapsed] = React.useState(false);
|
|
1024
|
+
const [queueFilter, setQueueFilter] = React.useState("all");
|
|
1025
|
+
const [detailsOpen, setDetailsOpen] = React.useState(true);
|
|
1026
|
+
const [openSections, setOpenSections] = React.useState({
|
|
1027
|
+
contact: true,
|
|
1028
|
+
ticket: true,
|
|
1029
|
+
history: true
|
|
1030
|
+
});
|
|
1031
|
+
const toggleSection = (id) => setOpenSections((m) => ({ ...m, [id]: !m[id] }));
|
|
1032
|
+
const detailsResize = useResizable({
|
|
1033
|
+
initial: 360,
|
|
1034
|
+
min: 280,
|
|
1035
|
+
max: 520,
|
|
1036
|
+
// Mantém storageKey diferente da ChatShowcase pra não conflitar valores entre as 2 páginas.
|
|
1037
|
+
storageKey: "chat-v2.detailsWidth"
|
|
1038
|
+
});
|
|
1039
|
+
const activeConversation = chatV2Mocks.CONVERSATIONS.find((c) => c.id === activeId) ?? chatV2Mocks.CONVERSATIONS[0];
|
|
1040
|
+
const activeDetail = chatV2Mocks.CONVERSATION_DETAILS[activeConversation.id] ?? chatV2Mocks.DEFAULT_DETAIL;
|
|
1041
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1042
|
+
appShell.AppShell,
|
|
1043
|
+
{
|
|
1044
|
+
contexts: appShellMocks.APP_SHELL_CONTEXTS,
|
|
1045
|
+
defaultActiveContextId: "inbox",
|
|
1046
|
+
defaultActiveItemHref: "#chat-v2",
|
|
1047
|
+
breadcrumb: [{ label: "Atendimentos" }],
|
|
1048
|
+
commandGroups: appShellMocks.APP_SHELL_COMMANDS,
|
|
1049
|
+
notifications: {
|
|
1050
|
+
items: appShellMocks.APP_SHELL_NOTIFICATIONS,
|
|
1051
|
+
onMarkAllRead: () => alert("Marcar todas como lidas"),
|
|
1052
|
+
onMoreActions: () => alert("Mais ações"),
|
|
1053
|
+
onViewAll: () => alert("Ver todas")
|
|
1054
|
+
},
|
|
1055
|
+
messages: {
|
|
1056
|
+
items: appShellMocks.APP_SHELL_MESSAGES,
|
|
1057
|
+
onNewMessage: () => alert("Nova mensagem"),
|
|
1058
|
+
onExpand: () => alert("Expandir"),
|
|
1059
|
+
onViewAll: () => alert("Ver todas")
|
|
1060
|
+
},
|
|
1061
|
+
theme,
|
|
1062
|
+
onThemeChange: (id) => setTheme(id),
|
|
1063
|
+
themeOptions: appShellMocks.APP_SHELL_THEME_OPTIONS,
|
|
1064
|
+
mobileEdgeToEdge: true,
|
|
1065
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.root(), children: [
|
|
1066
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: s.filtersWrap(), children: filtersCollapsed ? /* @__PURE__ */ jsxRuntime.jsx(FiltersRail, { filters, onToggleFilter: toggleFilter }) : /* @__PURE__ */ jsxRuntime.jsx(FiltersColumn, { filters, onToggleFilter: toggleFilter }) }),
|
|
1067
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1068
|
+
QueueColumn,
|
|
1069
|
+
{
|
|
1070
|
+
activeId,
|
|
1071
|
+
onSelect: handleSelectConversation,
|
|
1072
|
+
searchQuery,
|
|
1073
|
+
onSearchChange: setSearchQuery,
|
|
1074
|
+
queueFilter,
|
|
1075
|
+
onQueueFilterChange: setQueueFilter,
|
|
1076
|
+
filtersCollapsed,
|
|
1077
|
+
onToggleFilters: () => setFiltersCollapsed((c) => !c),
|
|
1078
|
+
className: chipGroup.cn(
|
|
1079
|
+
mobileView === "list" ? `${mobileOverlay.active} max-md:z-[1]` : mobileOverlay.hidden
|
|
1080
|
+
)
|
|
1081
|
+
}
|
|
1082
|
+
),
|
|
1083
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1084
|
+
ConversationColumn,
|
|
1085
|
+
{
|
|
1086
|
+
conversation: activeConversation,
|
|
1087
|
+
detailsOpen,
|
|
1088
|
+
onToggleDetails: handleToggleDetails,
|
|
1089
|
+
onBackToList: () => setMobileView("list"),
|
|
1090
|
+
className: chipGroup.cn(
|
|
1091
|
+
mobileView === "chat" ? `${mobileOverlay.active} max-md:z-[2]` : mobileOverlay.hidden
|
|
1092
|
+
)
|
|
1093
|
+
}
|
|
1094
|
+
),
|
|
1095
|
+
detailsOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1096
|
+
DetailsColumn,
|
|
1097
|
+
{
|
|
1098
|
+
conversation: activeConversation,
|
|
1099
|
+
detail: activeDetail,
|
|
1100
|
+
openSections,
|
|
1101
|
+
onToggleSection: toggleSection,
|
|
1102
|
+
onClose: () => {
|
|
1103
|
+
setDetailsOpen(false);
|
|
1104
|
+
setMobileView("chat");
|
|
1105
|
+
},
|
|
1106
|
+
onBackToChat: () => setMobileView("chat"),
|
|
1107
|
+
width: detailsResize.width,
|
|
1108
|
+
onResizeStart: detailsResize.onResizeStart,
|
|
1109
|
+
className: chipGroup.cn(
|
|
1110
|
+
mobileView === "details" ? `${mobileOverlay.active} max-md:!w-full max-md:z-[3]` : mobileOverlay.hidden
|
|
1111
|
+
)
|
|
1112
|
+
}
|
|
1113
|
+
)
|
|
1114
|
+
] })
|
|
1115
|
+
}
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
exports.ChatV2 = ChatV2;
|
|
1119
|
+
exports.default = ChatV2;
|
|
1120
|
+
//# sourceMappingURL=chat.cjs.map
|