1import { c as createLucideIcon, r as reactExports, t as trpc, ad as Activity, F as FileText, C as CircleAlert, o as RefreshCw, D as DollarSign, _ as TrendingUp, m as Users, ac as Megaphone, j as jsxRuntimeExports, U as USFlag } from './index-CNT5CkK7.js'; 2import { C as Card, a as CardContent, b as CardHeader, c as CardTitle } from './card-CV3CzesJ.js'; 3import { B as Briefcase } from './briefcase-d8WvXAbR.js'; 4import { F as Filter } from './filter-BxjGUbXo.js'; 5import { U as User } from './user-B4RG8T6t.js'; 6import { C as Clock } from './clock-CjjskDf6.js'; 7import { C as CircleCheck } from './circle-check-CqW-unub.js'; 8 9/** 10 * @license lucide-react v0.453.0 - ISC 11 * 12 * This source code is licensed under the ISC license. 13 * See the LICENSE file in the root directory of this source tree. 14 */ 15 16 17const Workflow = createLucideIcon("Workflow", [ 18 ["rect", { width: "8", height: "8", x: "3", y: "3", rx: "2", key: "by2w9f" }], 19 ["path", { d: "M7 11v4a2 2 0 0 0 2 2h4", key: "xkn7yn" }], 20 ["rect", { width: "8", height: "8", x: "13", y: "13", rx: "2", key: "1cgmvn" }] 21]); 22 23const EPS_GOLD = "#B22234"; 24const EPS_NAVY = "#1B3A6B"; 25const CATEGORIES = [ 26 { key: "all", label: "All Activity", icon: Activity, color: EPS_NAVY }, 27 { key: "policy_change", label: "Policy Changes", icon: FileText, color: "#1e40af" }, 28 { key: "claim", label: "Claims", icon: CircleAlert, color: "#dc2626" }, 29 { key: "renewal", label: "Renewals", icon: RefreshCw, color: "#15803d" }, 30 { key: "payment", label: "Payments", icon: DollarSign, color: "#0891b2" }, 31 { key: "commission", label: "Commissions", icon: TrendingUp, color: "#7c3aed" }, 32 { key: "onboarding", label: "Onboarding", icon: Users, color: "#2563eb" }, 33 { key: "quote", label: "Quotes", icon: Briefcase, color: "#9333ea" }, 34 { key: "marketing", label: "Marketing", icon: Megaphone, color: "#db2777" }, 35 { key: "workflow", label: "Workflows", icon: Workflow, color: "#0d9488" } 36]; 37function getEventStyle(category, eventType) { 38 const styles = { 39 policy_change: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "w-4 h-4" }), bg: "#eff6ff", border: "#bfdbfe" }, 40 claim: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-4 h-4" }), bg: "#fef2f2", border: "#fecaca" }, 41 renewal: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "w-4 h-4" }), bg: "#f0fdf4", border: "#bbf7d0" }, 42 payment: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(DollarSign, { className: "w-4 h-4" }), bg: "#ecfeff", border: "#a5f3fc" }, 43 commission: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TrendingUp, { className: "w-4 h-4" }), bg: "#faf5ff", border: "#e9d5ff" }, 44 onboarding: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { className: "w-4 h-4" }), bg: "#eff6ff", border: "#bfdbfe" }, 45 quote: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Briefcase, { className: "w-4 h-4" }), bg: "#fdf4ff", border: "#f0abfc" }, 46 marketing: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Megaphone, { className: "w-4 h-4" }), bg: "#fdf2f8", border: "#fbcfe8" }, 47 workflow: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Workflow, { className: "w-4 h-4" }), bg: "#f0fdfa", border: "#99f6e4" }, 48 system: { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-4 h-4" }), bg: "#f8fafc", border: "#e2e8f0" } 49 }; 50 if (eventType?.includes("completed") || eventType?.includes("received") || eventType?.includes("paid")) { 51 return { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheck, { className: "w-4 h-4" }), bg: "#f0fdf4", border: "#bbf7d0" }; 52 } 53 return styles[category] ?? styles.system; 54} 55const AGENT_NAMES = { 56 "greg-fay": "Greg Fay", 57 "stacey-hinkle": "Stacey Hinkle", 58 "josh-hinkle": "Josh Hinkle", 59 "charlie-drain": "Charlie Drain", 60 "michael-jividen": "Michael Jividen", 61 "jon-bucher": "Jon Bucher", 62 "zach-hinkle": "Zach Hinkle", 63 "angie-hinkle": "Angie Hinkle", 64 "adam-kaufman": "Adam Kaufman", 65 "lesley-wiegand": "Lesley Wiegand", 66 system: "System" 67}; 68const AGENT_KEYS = Object.keys(AGENT_NAMES).filter((k) => k !== "system"); 69function timeAgo(date) { 70 const d = new Date(date); 71 const now = /* @__PURE__ */ new Date(); 72 const diff = Math.floor((now.getTime() - d.getTime()) / 1e3); 73 if (diff < 60) return `${diff}s ago`; 74 if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; 75 if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; 76 if (diff < 86400 * 7) return `${Math.floor(diff / 86400)}d ago`; 77 return d.toLocaleDateString(); 78} 79function formatDate(date) {
80 return new Date(date).toLocaleString("en-US", { 81 month: "short", 82 day: "numeric", 83 hour: "numeric", 84 minute: "2-digit", 85 hour12: true 86 }); 87} 88function MessagesPanel() { 89 const [category, setCategory] = reactExports.useState("all"); 90 const [agentFilter, setAgentFilter] = reactExports.useState(""); 91 const [search, setSearch] = reactExports.useState(""); 92 const { data, isLoading, refetch, isFetching } = trpc.messages.activityFeed.useQuery( 93 { limit: 200, category, agentKey: agentFilter || void 0 }, 94 { refetchInterval: 2e4 } 95 ); 96 const events = data?.events ?? []; 97 const filtered = search.trim() ? events.filter( 98 (e) => e.description.toLowerCase().includes(search.toLowerCase()) || (e.clientName ?? "").toLowerCase().includes(search.toLowerCase()) || (e.agentKey ? AGENT_NAMES[e.agentKey] ?? e.agentKey : "").toLowerCase().includes(search.toLowerCase()) 99 ) : events; 100 const stats = CATEGORIES.filter((c) => c.key !== "all").map((c) => ({ 101 ...c, 102 count: events.filter((e) => e.category === c.key).length 103 })).filter((s) => s.count > 0); 104 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [ 105 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between flex-wrap gap-3", children: [
106 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 107 /* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "text-2xl font-bold", style: { fontFamily: "'Playfair Display', serif" }, children: [ 108 /* @__PURE__ */ jsxRuntimeExports.jsx(USFlag, { size: 18 }), 109 " Activity Feed" 110 ] }), 111 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground text-sm mt-1", children: "Live audit trail across all agency workflows â policy changes, claims, renewals, payments, and more" }) 112 ] }), 113 /* @__PURE__ */ jsxRuntimeExports.jsxs( 114 "button", 115 { 116 onClick: () => refetch(), 117 disabled: isFetching, 118 className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg border text-xs font-medium hover:bg-muted/40 transition-colors disabled:opacity-50", 119 children: [ 120 /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: `w-3.5 h-3.5 ${isFetching ? "animate-spin" : ""}` }), 121 "Refresh" 122 ] 123 } 124 ) 125 ] }), 126 stats.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3", children: stats.slice(0, 5).map((s) => { 127 const Icon = s.icon; 128 return /* @__PURE__ */ jsxRuntimeExports.jsx( 129 Card, 130 { 131 className: "border cursor-pointer hover:shadow-sm transition-shadow", 132 onClick: () => setCategory(s.key), 133 style: { borderColor: category === s.key ? s.color : void 0 }, 134 children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "pt-3 pb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
135 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 136 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground truncate", children: s.label }), 137 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xl font-bold", style: { color: s.color }, children: s.count }) 138 ] }), 139 /* @__PURE__ */ jsxRuntimeExports.jsx( 140 "div", 141 { 142 className: "w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0", 143 style: { background: `${s.color}18`, color: s.color }, 144 children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "w-4 h-4" }) 145 } 146 ) 147 ] }) }) 148 }, 149 s.key 150 ); 151 }) }), 152 /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { className: "border", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "pt-4 pb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-3 items-center", children: [
153 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 flex-wrap", children: [ 154 /* @__PURE__ */ jsxRuntimeExports.jsx(Filter, { className: "w-3.5 h-3.5 text-muted-foreground flex-shrink-0" }), 155 CATEGORIES.map((c) => { 156 const Icon = c.icon; 157 const active = category === c.key; 158 return /* @__PURE__ */ jsxRuntimeExports.jsxs( 159 "button", 160 { 161 onClick: () => setCategory(c.key), 162 className: `flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium transition-colors ${active ? "text-white" : "border hover:bg-muted/40"}`, 163 style: active ? { background: c.color, borderColor: c.color } : { borderColor: "var(--border)" }, 164 children: [ 165 /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "w-3 h-3" }), 166 c.label 167 ] 168 }, 169 c.key 170 ); 171 }) 172 ] }), 173 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 ml-auto", children: [
174 /* @__PURE__ */ jsxRuntimeExports.jsx(User, { className: "w-3.5 h-3.5 text-muted-foreground" }), 175 /* @__PURE__ */ jsxRuntimeExports.jsxs( 176 "select", 177 { 178 value: agentFilter, 179 onChange: (e) => setAgentFilter(e.target.value), 180 className: "text-xs border rounded-md px-2 py-1 focus:outline-none focus:ring-1 bg-background", 181 style: { borderColor: "var(--border)" }, 182 children: [ 183 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "All Agents" }), 184 AGENT_KEYS.map((k) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: k, children: AGENT_NAMES[k] }, k)) 185 ] 186 } 187 ) 188 ] }), 189 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 190 "input", 191 { 192 type: "text", 193 placeholder: "Search eventsâ¦", 194 value: search, 195 onChange: (e) => setSearch(e.target.value), 196 className: "text-xs border rounded-md pl-3 pr-3 py-1 focus:outline-none focus:ring-1 w-44 bg-background", 197 style: { borderColor: "var(--border)" } 198 } 199 ) }) 200 ] }) }) }), 201 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: "border", children: [
202 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-2 pt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "text-sm flex items-center gap-2", children: [ 203 /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-4 h-4", style: { color: EPS_GOLD } }), 204 filtered.length, 205 " event", 206 filtered.length !== 1 ? "s" : "", 207 category !== "all" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground font-normal", children: [ 208 "in ", 209 CATEGORIES.find((c) => c.key === category)?.label 210 ] }), 211 agentFilter && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground font-normal", children: [ 212 "for ", 213 AGENT_NAMES[agentFilter] ?? agentFilter 214 ] }) 215 ] }) }), 216 /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "pb-4", children: isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-12 text-center", children: [
217 /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-8 h-8 mx-auto mb-3 text-muted-foreground opacity-40 animate-pulse" }), 218 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: "Loading activity feedâ¦" }) 219 ] }) : filtered.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-12 text-center", children: [ 220 /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { className: "w-10 h-10 mx-auto mb-3 text-muted-foreground opacity-40" }), 221 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: "No events found." }), 222 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: search ? "Try a different search term." : "Activity will appear here as agents process tasks." }) 223 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1.5", children: filtered.map((event) => { 224 const style = getEventStyle(event.category, event.eventType); 225 const agentName = event.agentKey ? AGENT_NAMES[event.agentKey] ?? event.agentKey : event.agentName ?? null; 226 const catConfig = CATEGORIES.find((c) => c.key === event.category); 227 return /* @__PURE__ */ jsxRuntimeExports.jsxs( 228 "div", 229 { 230 className: "flex items-start gap-3 p-3 rounded-lg border transition-colors hover:bg-muted/10", 231 style: { borderColor: style.border, background: style.bg }, 232 children: [
233 /* @__PURE__ */ jsxRuntimeExports.jsx( 234 "div", 235 { 236 className: "w-7 h-7 rounded-md flex items-center justify-center flex-shrink-0 mt-0.5", 237 style: { background: catConfig ? `${catConfig.color}20` : "#f1f5f9", color: catConfig?.color ?? EPS_NAVY }, 238 children: style.icon 239 } 240 ), 241 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [ 242 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-wrap mb-0.5", children: [ 243 catConfig && /* @__PURE__ */ jsxRuntimeExports.jsx( 244 "span", 245 { 246 className: "px-1.5 py-0.5 rounded text-xs font-semibold", 247 style: { background: `${catConfig.color}18`, color: catConfig.color }, 248 children: catConfig.label 249 } 250 ), 251 agentName && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
252 /* @__PURE__ */ jsxRuntimeExports.jsx(User, { className: "w-3 h-3" }), 253 agentName 254 ] }), 255 event.clientName && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-medium text-foreground truncate max-w-[180px]", children: event.clientName }) 256 ] }), 257 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-foreground leading-snug", children: event.description }) 258 ] }), 259 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-end gap-0.5 flex-shrink-0 text-right", children: [ 260 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [ 261 /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "w-3 h-3" }), 262 timeAgo(event.createdAt) 263 ] }), 264 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground/60", children: formatDate(event.createdAt) }) 265 ] }) 266 ] 267 }, 268 event.id 269 ); 270 }) }) }) 271 ] }) 272 ] }); 273} 274 275export { MessagesPanel as default };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.