@burdenoff/microfe-proserviceworld 2026.703.1 → 2026.706.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/index.js +2 -3
  2. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  3. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  4. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  5. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  6. package/dist/proserviceworld/ProServiceWorldRoot.js +92 -136
  7. package/dist/proserviceworld/ProServiceWorldRoot.js.map +1 -1
  8. package/dist/proserviceworld/ProServiceWorldRoutes.js +18 -26
  9. package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
  10. package/dist/proserviceworld/components/ui.js +273 -0
  11. package/dist/proserviceworld/components/ui.js.map +1 -0
  12. package/dist/proserviceworld/hooks/useFiles.js +45 -0
  13. package/dist/proserviceworld/hooks/useFiles.js.map +1 -0
  14. package/dist/proserviceworld/hooks/useProServiceWorldApi.js +416 -0
  15. package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -0
  16. package/dist/proserviceworld/index.js +0 -1
  17. package/dist/proserviceworld/pages/AnalyticsPage.js +163 -475
  18. package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
  19. package/dist/proserviceworld/pages/ClientDetailPage.js +238 -0
  20. package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -0
  21. package/dist/proserviceworld/pages/ClientsPage.js +295 -0
  22. package/dist/proserviceworld/pages/ClientsPage.js.map +1 -0
  23. package/dist/proserviceworld/pages/CompliancePage.js +307 -0
  24. package/dist/proserviceworld/pages/CompliancePage.js.map +1 -0
  25. package/dist/proserviceworld/pages/ConflictsPage.js +234 -0
  26. package/dist/proserviceworld/pages/ConflictsPage.js.map +1 -0
  27. package/dist/proserviceworld/pages/DashboardPage.js +179 -632
  28. package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
  29. package/dist/proserviceworld/pages/DocumentsPage.js +235 -539
  30. package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
  31. package/dist/proserviceworld/pages/EngagementDetailPage.js +444 -0
  32. package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -0
  33. package/dist/proserviceworld/pages/EngagementsPage.js +256 -0
  34. package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -0
  35. package/dist/proserviceworld/pages/InvoicesPage.js +303 -0
  36. package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -0
  37. package/dist/proserviceworld/pages/MattersPage.js +275 -0
  38. package/dist/proserviceworld/pages/MattersPage.js.map +1 -0
  39. package/dist/proserviceworld/pages/PracticeAreasPage.js +176 -0
  40. package/dist/proserviceworld/pages/PracticeAreasPage.js.map +1 -0
  41. package/dist/proserviceworld/pages/TimePage.js +310 -0
  42. package/dist/proserviceworld/pages/TimePage.js.map +1 -0
  43. package/dist/proserviceworld/utils/cn.js +10 -0
  44. package/dist/proserviceworld/utils/cn.js.map +1 -0
  45. package/dist/proserviceworld/utils/nav.js +11 -0
  46. package/dist/proserviceworld/utils/nav.js.map +1 -0
  47. package/package.json +1 -1
  48. package/dist/proserviceworld/pages/AdminReportsPage.js +0 -579
  49. package/dist/proserviceworld/pages/AdminReportsPage.js.map +0 -1
  50. package/dist/proserviceworld/pages/AdminUsersPage.js +0 -468
  51. package/dist/proserviceworld/pages/AdminUsersPage.js.map +0 -1
  52. package/dist/proserviceworld/pages/BookingsPage.js +0 -446
  53. package/dist/proserviceworld/pages/BookingsPage.js.map +0 -1
  54. package/dist/proserviceworld/pages/MessagesPage.js +0 -238
  55. package/dist/proserviceworld/pages/MessagesPage.js.map +0 -1
  56. package/dist/proserviceworld/pages/PaymentsPage.js +0 -537
  57. package/dist/proserviceworld/pages/PaymentsPage.js.map +0 -1
  58. package/dist/proserviceworld/pages/ProjectsPage.js +0 -627
  59. package/dist/proserviceworld/pages/ProjectsPage.js.map +0 -1
  60. package/dist/proserviceworld/pages/ProviderDetailPage.js +0 -538
  61. package/dist/proserviceworld/pages/ProviderDetailPage.js.map +0 -1
  62. package/dist/proserviceworld/pages/ProvidersPage.js +0 -347
  63. package/dist/proserviceworld/pages/ProvidersPage.js.map +0 -1
  64. package/dist/proserviceworld/pages/ReviewsPage.js +0 -356
  65. package/dist/proserviceworld/pages/ReviewsPage.js.map +0 -1
  66. package/dist/proserviceworld/pages/ServiceDetailsPage.js +0 -631
  67. package/dist/proserviceworld/pages/ServiceDetailsPage.js.map +0 -1
  68. package/dist/proserviceworld/pages/ServicesPage.js +0 -344
  69. package/dist/proserviceworld/pages/ServicesPage.js.map +0 -1
  70. package/dist/proserviceworld/pages/VerificationPage.js +0 -370
  71. package/dist/proserviceworld/pages/VerificationPage.js.map +0 -1
  72. package/dist/proserviceworld/store/proserviceworldStore.js +0 -2490
  73. package/dist/proserviceworld/store/proserviceworldStore.js.map +0 -1
  74. package/dist/proserviceworld/utils/i18n.js +0 -15
  75. package/dist/proserviceworld/utils/i18n.js.map +0 -1
@@ -1,238 +0,0 @@
1
- import { useProServiceWorldStore as e } from "../store/proserviceworldStore.js";
2
- import { tWithFallback as t } from "../utils/i18n.js";
3
- import { useMemo as n, useState as r } from "react";
4
- import { Check as i, CheckCheck as a, Circle as o, MessageSquare as s, MoreHorizontal as c, Paperclip as l, Phone as u, Search as d, Send as f, Smile as p, Video as m } from "lucide-react";
5
- import { useI18n as h } from "@burdenoff/fe-libs/shared/providers/shell";
6
- import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
7
- import { AuroraBackground as y, Badge as b, Button as x, GradientText as S, IllustratedEmptyState as C, Input as w, PagePurpose as T } from "@burdenoff/fe-libs/ui";
8
- //#region src/proserviceworld/pages/MessagesPage.tsx
9
- function E() {
10
- let { t: E } = h(), D = (e, n, r) => t(E, e, n, r), { conversations: O } = e(), [k, A] = r(""), [j, M] = r(O[0]?.id ?? ""), [N, P] = r(""), F = n(() => {
11
- if (!k.trim()) return O;
12
- let e = k.toLowerCase();
13
- return O.filter((t) => t.participantName.toLowerCase().includes(e) || t.lastMessage.toLowerCase().includes(e));
14
- }, [O, k]), I = O.find((e) => e.id === j), L = O.reduce((e, t) => e + t.unreadCount, 0), R = L > 0 ? D("proserviceworld.messages.subtitle.unread", "{{count}} unread messages", { count: L }) : D("proserviceworld.messages.subtitle.caughtUp", "All caught up"), z = (e) => {
15
- let t = new Date(e), n = Math.floor(((/* @__PURE__ */ new Date()).getTime() - t.getTime()) / (1e3 * 60 * 60 * 24));
16
- return n === 0 ? t.toLocaleTimeString([], {
17
- hour: "2-digit",
18
- minute: "2-digit"
19
- }) : n === 1 ? D("proserviceworld.messages.time.yesterday", "Yesterday") : n < 7 ? t.toLocaleDateString([], { weekday: "short" }) : t.toLocaleDateString([], {
20
- month: "short",
21
- day: "numeric"
22
- });
23
- };
24
- return /* @__PURE__ */ v("div", {
25
- className: "p-6 bg-bg-canvas min-h-screen",
26
- children: [
27
- /* @__PURE__ */ v("div", {
28
- className: "relative overflow-hidden rounded-card -mx-2 px-2 pt-1 mb-6 flex items-center justify-between gap-4",
29
- children: [
30
- /* @__PURE__ */ _(y, { intensity: "subtle" }),
31
- /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h1", {
32
- className: "text-2xl font-semibold tracking-tight",
33
- children: /* @__PURE__ */ _(S, { children: D("proserviceworld.messages.title", "Messages") })
34
- }), /* @__PURE__ */ _("p", {
35
- className: "text-sm text-text-secondary",
36
- children: R
37
- })] }),
38
- /* @__PURE__ */ v(x, {
39
- size: "sm",
40
- children: [/* @__PURE__ */ _(s, { className: "mr-2 h-4 w-4" }), D("proserviceworld.messages.actions.newMessage", "New Message")]
41
- })
42
- ]
43
- }),
44
- /* @__PURE__ */ _("div", {
45
- className: "mb-6",
46
- children: /* @__PURE__ */ _(T, {
47
- icon: /* @__PURE__ */ _(s, { className: "h-4 w-4" }),
48
- children: D("proserviceworld.messages.purpose", "Keep every client and provider conversation in one place. Discuss scope, share updates, and coordinate bookings in real time — pick a conversation on the left to read the full thread and reply.")
49
- })
50
- }),
51
- /* @__PURE__ */ v("div", {
52
- className: "grid gap-0 overflow-hidden rounded-card border border-border-seam bg-bg-surface shadow-pop lg:grid-cols-3",
53
- style: {
54
- height: "calc(100vh - 220px)",
55
- minHeight: "500px"
56
- },
57
- children: [/* @__PURE__ */ v("div", {
58
- className: "flex flex-col border-r border-border-seam lg:col-span-1",
59
- children: [/* @__PURE__ */ _("div", {
60
- className: "border-b border-border-seam p-3",
61
- children: /* @__PURE__ */ v("div", {
62
- className: "relative",
63
- children: [/* @__PURE__ */ _(d, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ _(w, {
64
- placeholder: D("proserviceworld.messages.search.placeholder", "Search conversations..."),
65
- value: k,
66
- onChange: (e) => A(e.target.value),
67
- className: "pl-10"
68
- })]
69
- })
70
- }), /* @__PURE__ */ _("div", {
71
- className: "flex-1 overflow-y-auto",
72
- children: F.length === 0 ? /* @__PURE__ */ _("div", {
73
- className: "p-4",
74
- children: /* @__PURE__ */ _(C, {
75
- illustration: k ? "empty-search" : "empty-people",
76
- title: D("proserviceworld.messages.empty.list", "No conversations found"),
77
- description: k ? D("proserviceworld.messages.empty.listSearch", "No conversations match your search.") : D("proserviceworld.messages.empty.listDescription", "Conversations with clients and providers will appear here.")
78
- })
79
- }) : F.map((e) => /* @__PURE__ */ _("button", {
80
- onClick: () => M(e.id),
81
- className: `w-full border-b border-border-seam p-3 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus ${j === e.id ? "bg-accent-soft" : "hover:bg-bg-sunken/50"}`,
82
- children: /* @__PURE__ */ v("div", {
83
- className: "flex items-start gap-3",
84
- children: [/* @__PURE__ */ v("div", {
85
- className: "relative shrink-0",
86
- children: [/* @__PURE__ */ _("div", {
87
- className: "flex h-10 w-10 items-center justify-center rounded-full bg-accent-soft font-semibold text-text-primary",
88
- children: e.participantName.charAt(0)
89
- }), e.online && /* @__PURE__ */ _(o, { className: "absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 fill-status-success-text text-status-success-text stroke-bg-surface motion-safe:animate-vc-glow-pulse" })]
90
- }), /* @__PURE__ */ v("div", {
91
- className: "min-w-0 flex-1",
92
- children: [
93
- /* @__PURE__ */ v("div", {
94
- className: "flex items-center justify-between",
95
- children: [/* @__PURE__ */ _("h3", {
96
- className: `truncate text-sm ${e.unreadCount > 0 ? "font-bold" : "font-medium"}`,
97
- children: e.participantName
98
- }), /* @__PURE__ */ _("span", {
99
- className: "shrink-0 text-xs text-text-secondary",
100
- children: z(e.lastMessageTime)
101
- })]
102
- }),
103
- /* @__PURE__ */ _("p", {
104
- className: "text-xs text-text-secondary",
105
- children: e.participantRole
106
- }),
107
- /* @__PURE__ */ v("div", {
108
- className: "mt-1 flex items-center justify-between",
109
- children: [/* @__PURE__ */ _("p", {
110
- className: `truncate text-xs ${e.unreadCount > 0 ? "font-medium text-text-primary" : "text-text-secondary"}`,
111
- children: e.lastMessage
112
- }), e.unreadCount > 0 && /* @__PURE__ */ _(b, {
113
- className: "ml-2 h-5 w-5 shrink-0 rounded-full p-0 text-xs flex items-center justify-center",
114
- children: e.unreadCount
115
- })]
116
- })
117
- ]
118
- })]
119
- })
120
- }, e.id))
121
- })]
122
- }), /* @__PURE__ */ _("div", {
123
- className: "flex flex-col lg:col-span-2",
124
- children: I ? /* @__PURE__ */ v(g, { children: [
125
- /* @__PURE__ */ v("div", {
126
- className: "flex items-center justify-between border-b border-border-seam p-3",
127
- children: [/* @__PURE__ */ v("div", {
128
- className: "flex items-center gap-3",
129
- children: [/* @__PURE__ */ v("div", {
130
- className: "relative",
131
- children: [/* @__PURE__ */ _("div", {
132
- className: "flex h-10 w-10 items-center justify-center rounded-full bg-accent-soft font-semibold text-text-primary",
133
- children: I.participantName.charAt(0)
134
- }), I.online && /* @__PURE__ */ _(o, { className: "absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 fill-status-success-text text-status-success-text stroke-bg-surface motion-safe:animate-vc-glow-pulse" })]
135
- }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h3", {
136
- className: "font-medium",
137
- children: I.participantName
138
- }), /* @__PURE__ */ v("p", {
139
- className: "text-xs text-text-secondary",
140
- children: [
141
- I.online ? D("proserviceworld.messages.presence.online", "Online") : D("proserviceworld.messages.presence.offline", "Offline"),
142
- " ",
143
- "- ",
144
- I.participantRole
145
- ]
146
- })] })]
147
- }), /* @__PURE__ */ v("div", {
148
- className: "flex gap-1",
149
- children: [
150
- /* @__PURE__ */ _(x, {
151
- variant: "outline",
152
- size: "sm",
153
- children: /* @__PURE__ */ _(u, { className: "h-4 w-4" })
154
- }),
155
- /* @__PURE__ */ _(x, {
156
- variant: "outline",
157
- size: "sm",
158
- children: /* @__PURE__ */ _(m, { className: "h-4 w-4" })
159
- }),
160
- /* @__PURE__ */ _(x, {
161
- variant: "outline",
162
- size: "sm",
163
- children: /* @__PURE__ */ _(c, { className: "h-4 w-4" })
164
- })
165
- ]
166
- })]
167
- }),
168
- /* @__PURE__ */ _("div", {
169
- className: "flex-1 overflow-y-auto p-4 space-y-4",
170
- children: I.messages.map((e) => /* @__PURE__ */ _("div", {
171
- className: `flex ${e.isOwn ? "justify-end" : "justify-start"}`,
172
- children: /* @__PURE__ */ v("div", {
173
- className: `flex max-w-[75%] items-end gap-2 ${e.isOwn ? "flex-row-reverse" : ""}`,
174
- children: [!e.isOwn && /* @__PURE__ */ _("div", {
175
- className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent-soft text-xs font-semibold text-text-primary",
176
- children: e.senderName.charAt(0)
177
- }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("div", {
178
- className: `rounded-2xl px-4 py-2 ${e.isOwn ? "bg-action-primary-bg text-action-primary-text rounded-br-md" : "bg-bg-sunken rounded-bl-md"}`,
179
- children: /* @__PURE__ */ _("p", {
180
- className: "text-sm",
181
- children: e.content
182
- })
183
- }), /* @__PURE__ */ v("div", {
184
- className: `mt-1 flex items-center gap-1 text-xs text-text-secondary ${e.isOwn ? "justify-end" : ""}`,
185
- children: [/* @__PURE__ */ _("span", { children: z(e.timestamp) }), e.isOwn && (e.read ? /* @__PURE__ */ _(a, { className: "h-3 w-3 text-accent-blue" }) : /* @__PURE__ */ _(i, { className: "h-3 w-3" }))]
186
- })] })]
187
- })
188
- }, e.id))
189
- }),
190
- /* @__PURE__ */ _("div", {
191
- className: "border-t border-border-seam p-3",
192
- children: /* @__PURE__ */ v("div", {
193
- className: "flex items-center gap-2",
194
- children: [
195
- /* @__PURE__ */ _(x, {
196
- variant: "outline",
197
- size: "sm",
198
- children: /* @__PURE__ */ _(l, { className: "h-4 w-4" })
199
- }),
200
- /* @__PURE__ */ _(w, {
201
- placeholder: D("proserviceworld.messages.input.placeholder", "Type a message..."),
202
- value: N,
203
- onChange: (e) => P(e.target.value),
204
- onKeyDown: (e) => {
205
- e.key === "Enter" && N.trim() && P("");
206
- },
207
- className: "flex-1"
208
- }),
209
- /* @__PURE__ */ _(x, {
210
- variant: "outline",
211
- size: "sm",
212
- children: /* @__PURE__ */ _(p, { className: "h-4 w-4" })
213
- }),
214
- /* @__PURE__ */ _(x, {
215
- size: "sm",
216
- disabled: !N.trim(),
217
- children: /* @__PURE__ */ _(f, { className: "h-4 w-4" })
218
- })
219
- ]
220
- })
221
- })
222
- ] }) : /* @__PURE__ */ _("div", {
223
- className: "flex flex-1 items-center justify-center",
224
- children: /* @__PURE__ */ _(C, {
225
- illustration: "empty-notifications",
226
- title: D("proserviceworld.messages.emptyConversation.title", "Select a conversation"),
227
- description: D("proserviceworld.messages.emptyConversation.description", "Choose a conversation to start messaging.")
228
- })
229
- })
230
- })]
231
- })
232
- ]
233
- });
234
- }
235
- //#endregion
236
- export { E as MessagesPage };
237
-
238
- //# sourceMappingURL=MessagesPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MessagesPage.js","names":[],"sources":["../../../src/proserviceworld/pages/MessagesPage.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n Badge,\n Button,\n Input,\n AuroraBackground,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Search,\n Send,\n Circle,\n CheckCheck,\n Check,\n MessageSquare,\n Phone,\n Video,\n MoreHorizontal,\n Paperclip,\n Smile,\n} from 'lucide-react';\nimport { useProServiceWorldStore } from '../store/proserviceworldStore';\nimport { tWithFallback } from '../utils/i18n';\n\nexport function MessagesPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>): string =>\n tWithFallback(t, key, fallback, params);\n const { conversations } = useProServiceWorldStore();\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedConversationId, setSelectedConversationId] = useState<string>(\n conversations[0]?.id ?? ''\n );\n const [messageInput, setMessageInput] = useState('');\n\n const filteredConversations = useMemo(() => {\n if (!searchQuery.trim()) return conversations;\n const q = searchQuery.toLowerCase();\n return conversations.filter(\n (c) => c.participantName.toLowerCase().includes(q) || c.lastMessage.toLowerCase().includes(q)\n );\n }, [conversations, searchQuery]);\n\n const selectedConversation = conversations.find((c) => c.id === selectedConversationId);\n const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n const unreadSummary =\n totalUnread > 0\n ? tr('proserviceworld.messages.subtitle.unread', '{{count}} unread messages', {\n count: totalUnread,\n })\n : tr('proserviceworld.messages.subtitle.caughtUp', 'All caught up');\n\n const formatTime = (timestamp: string) => {\n const date = new Date(timestamp);\n const now = new Date();\n const diffDays = Math.floor((now.getTime() - date.getTime()) / (1000 * 60 * 60 * 24));\n if (diffDays === 0) {\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n }\n if (diffDays === 1) return tr('proserviceworld.messages.time.yesterday', 'Yesterday');\n if (diffDays < 7) return date.toLocaleDateString([], { weekday: 'short' });\n return date.toLocaleDateString([], { month: 'short', day: 'numeric' });\n };\n\n return (\n <div className=\"p-6 bg-bg-canvas min-h-screen\">\n <div className=\"relative overflow-hidden rounded-card -mx-2 px-2 pt-1 mb-6 flex items-center justify-between gap-4\">\n <AuroraBackground intensity=\"subtle\" />\n <div>\n <h1 className=\"text-2xl font-semibold tracking-tight\">\n <GradientText>{tr('proserviceworld.messages.title', 'Messages')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{unreadSummary}</p>\n </div>\n <Button size=\"sm\">\n <MessageSquare className=\"mr-2 h-4 w-4\" />\n {tr('proserviceworld.messages.actions.newMessage', 'New Message')}\n </Button>\n </div>\n\n <div className=\"mb-6\">\n <PagePurpose icon={<MessageSquare className=\"h-4 w-4\" />}>\n {tr(\n 'proserviceworld.messages.purpose',\n 'Keep every client and provider conversation in one place. Discuss scope, share updates, and coordinate bookings in real time — pick a conversation on the left to read the full thread and reply.'\n )}\n </PagePurpose>\n </div>\n\n <div\n className=\"grid gap-0 overflow-hidden rounded-card border border-border-seam bg-bg-surface shadow-pop lg:grid-cols-3\"\n style={{ height: 'calc(100vh - 220px)', minHeight: '500px' }}\n >\n {/* Conversation sidebar */}\n <div className=\"flex flex-col border-r border-border-seam lg:col-span-1\">\n {/* Search */}\n <div className=\"border-b border-border-seam p-3\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder={tr(\n 'proserviceworld.messages.search.placeholder',\n 'Search conversations...'\n )}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"pl-10\"\n />\n </div>\n </div>\n\n {/* Conversation list */}\n <div className=\"flex-1 overflow-y-auto\">\n {filteredConversations.length === 0 ? (\n <div className=\"p-4\">\n <IllustratedEmptyState\n illustration={searchQuery ? 'empty-search' : 'empty-people'}\n title={tr('proserviceworld.messages.empty.list', 'No conversations found')}\n description={\n searchQuery\n ? tr(\n 'proserviceworld.messages.empty.listSearch',\n 'No conversations match your search.'\n )\n : tr(\n 'proserviceworld.messages.empty.listDescription',\n 'Conversations with clients and providers will appear here.'\n )\n }\n />\n </div>\n ) : (\n filteredConversations.map((conversation) => (\n <button\n key={conversation.id}\n onClick={() => setSelectedConversationId(conversation.id)}\n className={`w-full border-b border-border-seam p-3 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-focus ${\n selectedConversationId === conversation.id\n ? 'bg-accent-soft'\n : 'hover:bg-bg-sunken/50'\n }`}\n >\n <div className=\"flex items-start gap-3\">\n {/* Avatar */}\n <div className=\"relative shrink-0\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-accent-soft font-semibold text-text-primary\">\n {conversation.participantName.charAt(0)}\n </div>\n {conversation.online && (\n <Circle className=\"absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 fill-status-success-text text-status-success-text stroke-bg-surface motion-safe:animate-vc-glow-pulse\" />\n )}\n </div>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between\">\n <h3\n className={`truncate text-sm ${conversation.unreadCount > 0 ? 'font-bold' : 'font-medium'}`}\n >\n {conversation.participantName}\n </h3>\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {formatTime(conversation.lastMessageTime)}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n {conversation.participantRole}\n </p>\n <div className=\"mt-1 flex items-center justify-between\">\n <p\n className={`truncate text-xs ${conversation.unreadCount > 0 ? 'font-medium text-text-primary' : 'text-text-secondary'}`}\n >\n {conversation.lastMessage}\n </p>\n {conversation.unreadCount > 0 && (\n <Badge className=\"ml-2 h-5 w-5 shrink-0 rounded-full p-0 text-xs flex items-center justify-center\">\n {conversation.unreadCount}\n </Badge>\n )}\n </div>\n </div>\n </div>\n </button>\n ))\n )}\n </div>\n </div>\n\n {/* Chat area */}\n <div className=\"flex flex-col lg:col-span-2\">\n {selectedConversation ? (\n <>\n {/* Chat header */}\n <div className=\"flex items-center justify-between border-b border-border-seam p-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"relative\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-accent-soft font-semibold text-text-primary\">\n {selectedConversation.participantName.charAt(0)}\n </div>\n {selectedConversation.online && (\n <Circle className=\"absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 fill-status-success-text text-status-success-text stroke-bg-surface motion-safe:animate-vc-glow-pulse\" />\n )}\n </div>\n <div>\n <h3 className=\"font-medium\">{selectedConversation.participantName}</h3>\n <p className=\"text-xs text-text-secondary\">\n {selectedConversation.online\n ? tr('proserviceworld.messages.presence.online', 'Online')\n : tr('proserviceworld.messages.presence.offline', 'Offline')}{' '}\n - {selectedConversation.participantRole}\n </p>\n </div>\n </div>\n <div className=\"flex gap-1\">\n <Button variant=\"outline\" size=\"sm\">\n <Phone className=\"h-4 w-4\" />\n </Button>\n <Button variant=\"outline\" size=\"sm\">\n <Video className=\"h-4 w-4\" />\n </Button>\n <Button variant=\"outline\" size=\"sm\">\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n\n {/* Messages area */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {selectedConversation.messages.map((message) => (\n <div\n key={message.id}\n className={`flex ${message.isOwn ? 'justify-end' : 'justify-start'}`}\n >\n <div\n className={`flex max-w-[75%] items-end gap-2 ${message.isOwn ? 'flex-row-reverse' : ''}`}\n >\n {!message.isOwn && (\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-accent-soft text-xs font-semibold text-text-primary\">\n {message.senderName.charAt(0)}\n </div>\n )}\n <div>\n <div\n className={`rounded-2xl px-4 py-2 ${\n message.isOwn\n ? 'bg-action-primary-bg text-action-primary-text rounded-br-md'\n : 'bg-bg-sunken rounded-bl-md'\n }`}\n >\n <p className=\"text-sm\">{message.content}</p>\n </div>\n <div\n className={`mt-1 flex items-center gap-1 text-xs text-text-secondary ${message.isOwn ? 'justify-end' : ''}`}\n >\n <span>{formatTime(message.timestamp)}</span>\n {message.isOwn &&\n (message.read ? (\n <CheckCheck className=\"h-3 w-3 text-accent-blue\" />\n ) : (\n <Check className=\"h-3 w-3\" />\n ))}\n </div>\n </div>\n </div>\n </div>\n ))}\n </div>\n\n {/* Message input */}\n <div className=\"border-t border-border-seam p-3\">\n <div className=\"flex items-center gap-2\">\n <Button variant=\"outline\" size=\"sm\">\n <Paperclip className=\"h-4 w-4\" />\n </Button>\n <Input\n placeholder={tr(\n 'proserviceworld.messages.input.placeholder',\n 'Type a message...'\n )}\n value={messageInput}\n onChange={(e) => setMessageInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && messageInput.trim()) {\n setMessageInput('');\n }\n }}\n className=\"flex-1\"\n />\n <Button variant=\"outline\" size=\"sm\">\n <Smile className=\"h-4 w-4\" />\n </Button>\n <Button size=\"sm\" disabled={!messageInput.trim()}>\n <Send className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n </>\n ) : (\n <div className=\"flex flex-1 items-center justify-center\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title={tr('proserviceworld.messages.emptyConversation.title', 'Select a conversation')}\n description={tr(\n 'proserviceworld.messages.emptyConversation.description',\n 'Choose a conversation to start messaging.'\n )}\n />\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}