@burdenoff/microfe-subscriberbot 2026.706.2 → 2026.706.3

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 (36) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.js +14 -6
  2. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  3. package/dist/subscriberbot/components/index.js +7 -0
  4. package/dist/subscriberbot/components/viz.js +196 -0
  5. package/dist/subscriberbot/components/viz.js.map +1 -0
  6. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +38 -30
  7. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  8. package/dist/subscriberbot/pages/AssetVaultPage.js +182 -0
  9. package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -0
  10. package/dist/subscriberbot/pages/DashboardPage.js +272 -199
  11. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  12. package/dist/subscriberbot/pages/InboxPage.js +517 -234
  13. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  14. package/dist/subscriberbot/pages/InsightsPage.js +220 -0
  15. package/dist/subscriberbot/pages/InsightsPage.js.map +1 -0
  16. package/dist/subscriberbot/pages/InvoicesPage.js +325 -237
  17. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  18. package/dist/subscriberbot/pages/WorkflowsPage.js +301 -112
  19. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  20. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +311 -165
  21. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  22. package/dist/subscriberbot/pages/agents/AgentsListPage.js +183 -93
  23. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  24. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +426 -293
  25. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  26. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +217 -153
  27. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
  28. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +215 -112
  29. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  30. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +542 -428
  31. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  32. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +242 -192
  33. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
  34. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +174 -133
  35. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  36. package/package.json +1 -1
@@ -5,13 +5,15 @@ import { formatCurrency as r, formatEnumLabel as i, formatRelativeTime as a } fr
5
5
  import { StatusBadge as o } from "../components/StatusBadge.js";
6
6
  import { EmptyState as s } from "../components/EmptyState.js";
7
7
  import { ErrorView as c, LoadingView as l, Section as u } from "../components/StateViews.js";
8
- import { useInboxMessages as d, useInvoices as f, useRelationships as p, useRenewalEvents as m } from "../hooks/useSubscriberBotApi.js";
9
- import { useMemo as h } from "react";
10
- import { AlertTriangle as g, ArrowRight as _, Bot as v, CalendarClock as y, Inbox as b, Repeat2 as x, Sparkles as S, Wallet as C } from "lucide-react";
11
- import { jsx as w, jsxs as T } from "react/jsx-runtime";
12
- import { PagePurpose as E } from "@burdenoff/fe-libs/ui";
8
+ import { Donut as d, Legend as f, Timeline as p } from "../components/viz.js";
9
+ import "../components/index.js";
10
+ import { useInboxMessages as m, useInvoices as h, useRelationships as g, useRenewalEvents as _ } from "../hooks/useSubscriberBotApi.js";
11
+ import { useMemo as v } from "react";
12
+ import { AlertTriangle as y, ArrowRight as b, ArrowUpRight as x, Bot as S, CalendarClock as C, Inbox as w, Repeat2 as T, ShieldCheck as E, Sparkles as D, Wallet as O } from "lucide-react";
13
+ import { jsx as k, jsxs as A } from "react/jsx-runtime";
14
+ import { GlassCard as j, PagePurpose as M } from "@burdenoff/fe-libs/ui";
13
15
  //#region src/subscriberbot/pages/DashboardPage.tsx
14
- var D = {
16
+ var N = {
15
17
  DAILY: 30,
16
18
  WEEKLY: 4.345,
17
19
  MONTHLY: 1,
@@ -20,250 +22,321 @@ var D = {
20
22
  LIFETIME: 0,
21
23
  FREE: 0,
22
24
  USAGE_BASED: 1
23
- };
24
- function O() {
25
- let { navigateTo: O, currentUser: k } = e(), A = p({ pagination: {
25
+ }, P = 1e3 * 60 * 60 * 24;
26
+ function F() {
27
+ let { navigateTo: F, currentUser: I } = e(), L = g({ pagination: {
26
28
  limit: 100,
27
29
  offset: 0
28
- } }), j = f({ pagination: {
30
+ } }), R = h({ pagination: {
29
31
  limit: 50,
30
32
  offset: 0
31
- } }), M = d({ pagination: {
33
+ } }), z = m({ pagination: {
32
34
  limit: 50,
33
35
  offset: 0
34
- } }), N = m({ upcomingOnly: !0 }), P = h(() => A.data?.items ?? [], [A.data]), F = h(() => j.data?.items ?? [], [j.data]), I = h(() => M.data?.items ?? [], [M.data]), L = N.data ?? [], R = h(() => {
35
- let e = P.filter((e) => e.status === "ACTIVE" || e.status === "TRIAL"), t = e.reduce((e, t) => e + t.amount * (D[t.interval] ?? 1), 0), n = P.filter((e) => e.status === "TRIAL").length, r = P.filter((e) => e.status === "PAST_DUE").length, i = e[0]?.currency ?? "USD", a = I.filter((e) => e.actionRequired && !e.isRead).length, o = F.filter((e) => e.status === "ISSUED" || e.status === "OVERDUE" || e.status === "FAILED"), s = o.reduce((e, t) => e + t.total, 0);
36
+ } }), B = _({ upcomingOnly: !0 }), V = v(() => L.data?.items ?? [], [L.data]), H = v(() => R.data?.items ?? [], [R.data]), U = v(() => z.data?.items ?? [], [z.data]), W = v(() => B.data ?? [], [B.data]), G = v(() => {
37
+ let e = /* @__PURE__ */ new Map();
38
+ return V.forEach((t) => e.set(t.id, t)), e;
39
+ }, [V]), K = v(() => {
40
+ let e = V.filter((e) => e.status === "ACTIVE" || e.status === "TRIAL"), t = e.reduce((e, t) => e + t.amount * (N[t.interval] ?? 1), 0), n = e[0]?.currency ?? V[0]?.currency ?? "USD", r = U.filter((e) => e.actionRequired && !e.isRead).length, i = H.filter((e) => e.status === "ISSUED" || e.status === "OVERDUE" || e.status === "FAILED"), a = i.reduce((e, t) => e + t.total, 0), o = V.filter((e) => e.status === "PAST_DUE" || e.status === "LAPSED").length;
36
41
  return {
37
42
  activeCount: e.length,
43
+ totalCount: V.length,
38
44
  monthlySpend: t,
39
- primaryCurrency: i,
40
- trials: n,
41
- pastDue: r,
42
- unreadActionRequired: a,
43
- openInvoiceCount: o.length,
44
- openInvoiceTotal: s
45
+ primaryCurrency: n,
46
+ unreadActionRequired: r,
47
+ openInvoiceCount: i.length,
48
+ openInvoiceTotal: a,
49
+ atRisk: o
45
50
  };
46
51
  }, [
47
- P,
48
- I,
49
- F
50
- ]), z = h(() => {
52
+ V,
53
+ U,
54
+ H
55
+ ]), q = v(() => {
51
56
  let e = /* @__PURE__ */ new Map();
52
- return P.forEach((t) => e.set(t.status, (e.get(t.status) ?? 0) + 1)), Array.from(e.entries()).sort((e, t) => t[1] - e[1]);
53
- }, [P]), B = A.isLoading || j.isLoading || M.isLoading || N.isLoading, V = A.isError && j.isError && M.isError && N.isError;
54
- if (B) return /* @__PURE__ */ w(t, {
57
+ return V.forEach((t) => e.set(t.status, (e.get(t.status) ?? 0) + 1)), Array.from(e.entries()).sort((e, t) => t[1] - e[1]).map(([e, t]) => ({
58
+ label: i(e),
59
+ value: t
60
+ }));
61
+ }, [V]), J = v(() => {
62
+ let e = Date.now(), t = W.map((t) => {
63
+ let n = G.get(t.relationshipId), r = new Date(t.occursAt).getTime();
64
+ return {
65
+ id: t.id,
66
+ relationshipId: t.relationshipId,
67
+ title: n?.label ?? i(t.eventType),
68
+ when: t.occursAt,
69
+ amount: t.amount ?? n?.amount ?? null,
70
+ currency: t.currency ?? n?.currency ?? null,
71
+ soon: !Number.isNaN(r) && r - e <= 7 * P
72
+ };
73
+ });
74
+ return t.length > 0 ? t.filter((e) => !Number.isNaN(new Date(e.when).getTime())).sort((e, t) => new Date(e.when).getTime() - new Date(t.when).getTime()) : V.filter((t) => {
75
+ if (!t.renewsAt) return !1;
76
+ let n = new Date(t.renewsAt).getTime();
77
+ return !Number.isNaN(n) && n >= e;
78
+ }).map((t) => {
79
+ let n = new Date(t.renewsAt).getTime();
80
+ return {
81
+ id: t.id,
82
+ relationshipId: t.id,
83
+ title: t.label,
84
+ when: t.renewsAt,
85
+ amount: t.amount,
86
+ currency: t.currency,
87
+ soon: n - e <= 7 * P
88
+ };
89
+ }).sort((e, t) => new Date(e.when).getTime() - new Date(t.when).getTime());
90
+ }, [
91
+ W,
92
+ V,
93
+ G
94
+ ]), Y = v(() => J.slice(0, 6).map((e) => ({
95
+ title: e.title,
96
+ sub: a(e.when),
97
+ tone: e.soon ? "warning" : "default",
98
+ meta: e.amount == null ? void 0 : r(e.amount, e.currency ?? K.primaryCurrency, { maximumFractionDigits: 0 })
99
+ })), [J, K.primaryCurrency]), X = v(() => U.filter((e) => e.actionRequired), [U]), Z = L.isLoading || R.isLoading || z.isLoading || B.isLoading, Q = L.isError && R.isError && z.isError && B.isError;
100
+ if (Z) return /* @__PURE__ */ k(t, {
55
101
  title: "Overview",
56
102
  description: "Your recurring digital relationships at a glance",
57
- children: /* @__PURE__ */ w(l, { label: "Loading your subscription portfolio…" })
103
+ children: /* @__PURE__ */ k(l, { label: "Loading your subscription portfolio…" })
58
104
  });
59
- if (V) return /* @__PURE__ */ w(t, {
105
+ if (Q) return /* @__PURE__ */ k(t, {
60
106
  title: "Overview",
61
107
  description: "Your recurring digital relationships at a glance",
62
- children: /* @__PURE__ */ w(c, {
108
+ children: /* @__PURE__ */ k(c, {
63
109
  message: "We couldn't reach the Subscriber Bot service. Please try again.",
64
110
  onRetry: () => {
65
- A.refetch(), j.refetch(), M.refetch(), N.refetch();
111
+ L.refetch(), R.refetch(), z.refetch(), B.refetch();
66
112
  }
67
113
  })
68
114
  });
69
- let H = k?.firstName || k?.name?.split(" ")[0];
70
- return /* @__PURE__ */ T(t, {
71
- title: H ? `Welcome back, ${H}` : "Overview",
115
+ let $ = I?.firstName || I?.name?.split(" ")[0], ee = [
116
+ {
117
+ label: "Add a relationship",
118
+ description: "Track a new subscription",
119
+ icon: /* @__PURE__ */ k(T, { className: "h-5 w-5" }),
120
+ path: "/relationships/new"
121
+ },
122
+ {
123
+ label: "Discover providers",
124
+ description: "Browse the registry",
125
+ icon: /* @__PURE__ */ k(D, { className: "h-5 w-5" }),
126
+ path: "/providers"
127
+ },
128
+ {
129
+ label: "Open inbox",
130
+ description: "Merged communications",
131
+ icon: /* @__PURE__ */ k(w, { className: "h-5 w-5" }),
132
+ path: "/inbox"
133
+ },
134
+ {
135
+ label: "Configure agents",
136
+ description: "Automate your portfolio",
137
+ icon: /* @__PURE__ */ k(S, { className: "h-5 w-5" }),
138
+ path: "/agents"
139
+ }
140
+ ];
141
+ return /* @__PURE__ */ A(t, {
142
+ title: $ ? `Welcome back, ${$}` : "Overview",
72
143
  description: "Everything you pay for on repeat — in one intelligent console.",
73
144
  children: [
74
- /* @__PURE__ */ w(E, {
145
+ /* @__PURE__ */ k(M, {
75
146
  className: "mb-6",
76
147
  children: "Subscriber Bot is your system of record for every recurring digital relationship. See total recurring spend, what renews next, what needs action, and what to optimize — all from real data across your providers."
77
148
  }),
78
- /* @__PURE__ */ T("div", {
149
+ /* @__PURE__ */ A("div", {
79
150
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
80
151
  children: [
81
- /* @__PURE__ */ w(n, {
152
+ /* @__PURE__ */ k(n, {
82
153
  featured: !0,
83
- icon: /* @__PURE__ */ w(C, {}),
84
- value: r(R.monthlySpend, R.primaryCurrency, { maximumFractionDigits: 0 }),
154
+ icon: /* @__PURE__ */ k(O, {}),
155
+ value: r(K.monthlySpend, K.primaryCurrency, { maximumFractionDigits: 0 }),
85
156
  label: "Recurring spend / month"
86
157
  }),
87
- /* @__PURE__ */ w(n, {
88
- icon: /* @__PURE__ */ w(x, {}),
89
- value: R.activeCount,
158
+ /* @__PURE__ */ k(n, {
159
+ icon: /* @__PURE__ */ k(T, {}),
160
+ value: K.activeCount,
90
161
  label: "Active relationships"
91
162
  }),
92
- /* @__PURE__ */ w(n, {
93
- icon: /* @__PURE__ */ w(y, {}),
94
- value: L.length,
163
+ /* @__PURE__ */ k(n, {
164
+ icon: /* @__PURE__ */ k(C, {}),
165
+ value: J.length,
95
166
  label: "Upcoming renewals"
96
167
  }),
97
- /* @__PURE__ */ w(n, {
98
- icon: /* @__PURE__ */ w(g, {}),
99
- value: R.unreadActionRequired,
100
- label: "Need your action"
168
+ /* @__PURE__ */ k(n, {
169
+ icon: /* @__PURE__ */ k(y, {}),
170
+ value: K.unreadActionRequired,
171
+ label: "Need your action",
172
+ trend: K.unreadActionRequired > 0 ? "down" : void 0
101
173
  })
102
174
  ]
103
175
  }),
104
- /* @__PURE__ */ w("div", {
105
- className: "mt-6 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4",
106
- children: [
107
- {
108
- label: "Add a relationship",
109
- description: "Track a new subscription",
110
- icon: /* @__PURE__ */ w(x, { className: "h-5 w-5" }),
111
- path: "/relationships/new"
112
- },
113
- {
114
- label: "Discover providers",
115
- description: "Browse the registry",
116
- icon: /* @__PURE__ */ w(S, { className: "h-5 w-5" }),
117
- path: "/providers"
118
- },
119
- {
120
- label: "Open inbox",
121
- description: "Merged communications",
122
- icon: /* @__PURE__ */ w(b, { className: "h-5 w-5" }),
123
- path: "/inbox"
124
- },
125
- {
126
- label: "Configure agents",
127
- description: "Automate your portfolio",
128
- icon: /* @__PURE__ */ w(v, { className: "h-5 w-5" }),
129
- path: "/agents"
130
- }
131
- ].map((e) => /* @__PURE__ */ T("button", {
132
- type: "button",
133
- onClick: () => O(e.path),
134
- className: "flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4 text-left transition-shadow hover:shadow-md",
135
- children: [
136
- /* @__PURE__ */ w("span", {
137
- className: "flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
138
- children: e.icon
139
- }),
140
- /* @__PURE__ */ T("span", {
141
- className: "min-w-0 flex-1",
142
- children: [/* @__PURE__ */ w("span", {
143
- className: "block text-sm font-medium text-text-primary",
144
- children: e.label
145
- }), /* @__PURE__ */ w("span", {
146
- className: "block text-xs text-text-secondary",
147
- children: e.description
148
- })]
149
- }),
150
- /* @__PURE__ */ w(_, { className: "h-4 w-4 shrink-0 text-text-secondary" })
151
- ]
152
- }, e.path))
153
- }),
154
- /* @__PURE__ */ T("div", {
155
- className: "grid grid-cols-1 gap-8 lg:grid-cols-2",
156
- children: [/* @__PURE__ */ w(u, {
157
- title: "Upcoming renewals",
158
- description: "What's charging next",
159
- action: /* @__PURE__ */ w("button", {
160
- type: "button",
161
- onClick: () => O("/relationships"),
162
- className: "text-sm font-medium text-text-link hover:underline",
163
- children: "View all"
164
- }),
165
- children: L.length === 0 ? /* @__PURE__ */ w(s, {
166
- illustration: "empty-calendar",
167
- title: "No upcoming renewals",
168
- description: "Renewals you track will appear here ahead of time."
169
- }) : /* @__PURE__ */ w("div", {
170
- className: "divide-y divide-border-subtle rounded-lg border border-border-subtle bg-bg-surface",
171
- children: L.slice(0, 6).map((e) => /* @__PURE__ */ T("button", {
176
+ /* @__PURE__ */ A("div", {
177
+ className: "mt-8 grid grid-cols-1 gap-6 lg:grid-cols-3",
178
+ children: [/* @__PURE__ */ k("div", {
179
+ className: "lg:col-span-2",
180
+ children: /* @__PURE__ */ k(u, {
181
+ title: "Upcoming renewals",
182
+ description: "What's charging next across your portfolio",
183
+ className: "mt-0",
184
+ action: /* @__PURE__ */ A("button", {
172
185
  type: "button",
173
- onClick: () => O(`/relationships/${e.relationshipId}`),
174
- className: "flex w-full items-center justify-between gap-3 p-3 text-left hover:bg-bg-sunken",
175
- children: [/* @__PURE__ */ T("div", {
176
- className: "min-w-0",
177
- children: [/* @__PURE__ */ w("p", {
178
- className: "truncate text-sm font-medium text-text-primary",
179
- children: i(e.eventType)
180
- }), /* @__PURE__ */ T("p", {
181
- className: "text-xs text-text-secondary",
182
- children: [a(e.occursAt), e.detail ? ` · ${e.detail}` : ""]
183
- })]
184
- }), e.amount != null && /* @__PURE__ */ w("span", {
185
- className: "shrink-0 text-sm font-semibold tabular-nums text-text-primary",
186
- children: r(e.amount, e.currency ?? R.primaryCurrency)
187
- })]
188
- }, e.id))
186
+ onClick: () => F("/relationships"),
187
+ className: "inline-flex items-center gap-1 text-sm font-medium text-text-link hover:underline",
188
+ children: ["View all ", /* @__PURE__ */ k(x, { className: "h-3.5 w-3.5" })]
189
+ }),
190
+ children: /* @__PURE__ */ k(j, {
191
+ treatment: "plain",
192
+ className: "p-5",
193
+ children: Y.length === 0 ? /* @__PURE__ */ k(s, {
194
+ illustration: "empty-calendar",
195
+ title: "No upcoming renewals",
196
+ description: "Renewals you track will appear here ahead of time."
197
+ }) : /* @__PURE__ */ k(p, { items: Y })
198
+ })
189
199
  })
190
- }), /* @__PURE__ */ w(u, {
191
- title: "Needs your attention",
192
- description: "Required actions from the Universal Inbox",
193
- action: /* @__PURE__ */ w("button", {
194
- type: "button",
195
- onClick: () => O("/inbox"),
196
- className: "text-sm font-medium text-text-link hover:underline",
197
- children: "Open inbox"
198
- }),
199
- children: I.filter((e) => e.actionRequired).length === 0 ? /* @__PURE__ */ w(s, {
200
- illustration: "empty-inbox",
201
- title: "You're all caught up",
202
- description: "Required actions across all your channels will surface here."
203
- }) : /* @__PURE__ */ w("div", {
204
- className: "divide-y divide-border-subtle rounded-lg border border-border-subtle bg-bg-surface",
205
- children: I.filter((e) => e.actionRequired).slice(0, 6).map((e) => /* @__PURE__ */ T("button", {
200
+ }), /* @__PURE__ */ A("div", {
201
+ className: "flex flex-col gap-6",
202
+ children: [/* @__PURE__ */ k(u, {
203
+ title: "Portfolio by status",
204
+ description: "Where your relationships stand",
205
+ className: "mt-0",
206
+ children: /* @__PURE__ */ k(j, {
207
+ treatment: "glass",
208
+ className: "p-5",
209
+ children: q.length === 0 ? /* @__PURE__ */ k(s, {
210
+ illustration: "empty-data",
211
+ title: "No relationships yet",
212
+ description: "Add your first subscription to see the breakdown.",
213
+ action: /* @__PURE__ */ k("button", {
214
+ type: "button",
215
+ onClick: () => F("/relationships/new"),
216
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
217
+ children: "Add relationship"
218
+ })
219
+ }) : /* @__PURE__ */ A("div", {
220
+ className: "flex flex-col items-center gap-5 sm:flex-row sm:items-center lg:flex-col xl:flex-row",
221
+ children: [/* @__PURE__ */ k(d, {
222
+ data: q,
223
+ size: 148,
224
+ thickness: 20,
225
+ centerLabel: String(K.totalCount),
226
+ centerSub: K.totalCount === 1 ? "relationship" : "relationships",
227
+ className: "shrink-0"
228
+ }), /* @__PURE__ */ k(f, {
229
+ data: q,
230
+ className: "w-full min-w-0 flex-1"
231
+ })]
232
+ })
233
+ })
234
+ }), /* @__PURE__ */ k(u, {
235
+ title: "Needs attention",
236
+ description: "Required actions from the Universal Inbox",
237
+ className: "mt-0",
238
+ action: /* @__PURE__ */ k("button", {
206
239
  type: "button",
207
- onClick: () => O("/inbox"),
208
- className: "flex w-full items-start justify-between gap-3 p-3 text-left hover:bg-bg-sunken",
209
- children: [/* @__PURE__ */ T("div", {
210
- className: "min-w-0",
211
- children: [/* @__PURE__ */ w("p", {
212
- className: "truncate text-sm font-medium text-text-primary",
213
- children: e.subject || "(no subject)"
214
- }), e.preview && /* @__PURE__ */ w("p", {
215
- className: "truncate text-xs text-text-secondary",
216
- children: e.preview
240
+ onClick: () => F("/inbox"),
241
+ className: "text-sm font-medium text-text-link hover:underline",
242
+ children: "Open inbox"
243
+ }),
244
+ children: /* @__PURE__ */ k(j, {
245
+ treatment: "plain",
246
+ className: "p-3",
247
+ children: X.length === 0 ? /* @__PURE__ */ A("div", {
248
+ className: "flex items-center gap-3 px-2 py-4",
249
+ children: [/* @__PURE__ */ k("span", {
250
+ className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-status-success-bg-subtle text-status-success-text",
251
+ children: /* @__PURE__ */ k(E, { className: "h-5 w-5" })
252
+ }), /* @__PURE__ */ A("div", {
253
+ className: "min-w-0",
254
+ children: [/* @__PURE__ */ k("p", {
255
+ className: "text-sm font-medium text-text-primary",
256
+ children: "You're all caught up"
257
+ }), /* @__PURE__ */ k("p", {
258
+ className: "text-xs text-text-secondary",
259
+ children: "Required actions across your channels will surface here."
260
+ })]
217
261
  })]
218
- }), /* @__PURE__ */ w(o, {
219
- status: e.category,
220
- className: "shrink-0"
221
- })]
222
- }, e.id))
223
- })
262
+ }) : /* @__PURE__ */ k("ul", {
263
+ className: "space-y-1",
264
+ children: X.slice(0, 5).map((e) => /* @__PURE__ */ k("li", { children: /* @__PURE__ */ A("button", {
265
+ type: "button",
266
+ onClick: () => F("/inbox"),
267
+ className: "flex w-full items-center gap-3 rounded-lg border-l-2 border-status-warning-text/60 bg-status-warning-bg-subtle/50 p-3 text-left transition-colors hover:bg-status-warning-bg-subtle",
268
+ children: [/* @__PURE__ */ A("div", {
269
+ className: "min-w-0 flex-1",
270
+ children: [/* @__PURE__ */ k("p", {
271
+ className: "truncate text-sm font-medium text-text-primary",
272
+ children: e.subject || "(no subject)"
273
+ }), e.preview && /* @__PURE__ */ k("p", {
274
+ className: "truncate text-xs text-text-secondary",
275
+ children: e.preview
276
+ })]
277
+ }), /* @__PURE__ */ k(o, {
278
+ status: e.category,
279
+ className: "shrink-0"
280
+ })]
281
+ }) }, e.id))
282
+ })
283
+ })
284
+ })]
224
285
  })]
225
286
  }),
226
- /* @__PURE__ */ w(u, {
227
- title: "Portfolio by lifecycle",
228
- description: "Where your relationships stand",
229
- children: z.length === 0 ? /* @__PURE__ */ w(s, {
230
- illustration: "empty-data",
231
- title: "No relationships yet",
232
- description: "Add your first subscription to see your portfolio breakdown.",
233
- action: /* @__PURE__ */ w("button", {
234
- type: "button",
235
- onClick: () => O("/relationships/new"),
236
- className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
237
- children: "Add relationship"
238
- })
239
- }) : /* @__PURE__ */ T("div", {
240
- className: "flex flex-wrap gap-3",
241
- children: [z.map(([e, t]) => /* @__PURE__ */ T("div", {
242
- className: "flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-4 py-3",
243
- children: [/* @__PURE__ */ w(o, { status: e }), /* @__PURE__ */ w("span", {
244
- className: "text-lg font-semibold tabular-nums text-text-primary",
245
- children: t
246
- })]
247
- }, e)), R.openInvoiceCount > 0 && /* @__PURE__ */ w("div", {
248
- className: "flex items-center gap-2 rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle px-4 py-3",
249
- children: /* @__PURE__ */ T("span", {
250
- className: "text-sm font-medium text-status-warning-text",
251
- children: [
252
- R.openInvoiceCount,
253
- " open invoice",
254
- R.openInvoiceCount === 1 ? "" : "s",
255
- " ·",
256
- " ",
257
- r(R.openInvoiceTotal, R.primaryCurrency)
258
- ]
259
- })
287
+ K.openInvoiceCount > 0 && /* @__PURE__ */ A("button", {
288
+ type: "button",
289
+ onClick: () => F("/invoices"),
290
+ className: "mt-6 flex w-full items-center justify-between gap-3 rounded-xl border border-status-warning-text/30 bg-status-warning-bg-subtle px-5 py-4 text-left transition-shadow hover:shadow-md",
291
+ children: [/* @__PURE__ */ A("div", {
292
+ className: "flex items-center gap-3",
293
+ children: [/* @__PURE__ */ k(y, { className: "h-5 w-5 shrink-0 text-status-warning-text" }), /* @__PURE__ */ A("span", {
294
+ className: "text-sm font-medium text-status-warning-text",
295
+ children: [
296
+ K.openInvoiceCount,
297
+ " open invoice",
298
+ K.openInvoiceCount === 1 ? "" : "s",
299
+ " ·",
300
+ " ",
301
+ r(K.openInvoiceTotal, K.primaryCurrency),
302
+ " outstanding"
303
+ ]
260
304
  })]
305
+ }), /* @__PURE__ */ k(b, { className: "h-4 w-4 shrink-0 text-status-warning-text" })]
306
+ }),
307
+ /* @__PURE__ */ k(u, {
308
+ title: "Quick actions",
309
+ description: "Jump straight into your workflow",
310
+ children: /* @__PURE__ */ k("div", {
311
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4",
312
+ children: ee.map((e) => /* @__PURE__ */ A("button", {
313
+ type: "button",
314
+ onClick: () => F(e.path),
315
+ className: "group flex items-center gap-3 rounded-xl border border-border-subtle bg-bg-surface p-4 text-left transition-all hover:-translate-y-0.5 hover:border-border-seam hover:shadow-md",
316
+ children: [
317
+ /* @__PURE__ */ k("span", {
318
+ className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
319
+ children: e.icon
320
+ }),
321
+ /* @__PURE__ */ A("span", {
322
+ className: "min-w-0 flex-1",
323
+ children: [/* @__PURE__ */ k("span", {
324
+ className: "block text-sm font-medium text-text-primary",
325
+ children: e.label
326
+ }), /* @__PURE__ */ k("span", {
327
+ className: "block text-xs text-text-secondary",
328
+ children: e.description
329
+ })]
330
+ }),
331
+ /* @__PURE__ */ k(b, { className: "h-4 w-4 shrink-0 text-text-secondary transition-transform group-hover:translate-x-0.5" })
332
+ ]
333
+ }, e.path))
261
334
  })
262
335
  })
263
336
  ]
264
337
  });
265
338
  }
266
339
  //#endregion
267
- export { O as DashboardPage };
340
+ export { F as DashboardPage };
268
341
 
269
342
  //# sourceMappingURL=DashboardPage.js.map