@burdenoff/microfe-subscriberbot 2026.1031.1 → 2026.1102.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.
- package/dist/stories/pages/NegotiationDetailPage.stories.d.ts +11 -0
- package/dist/stories/pages/NegotiationDetailPage.stories.d.ts.map +1 -0
- package/dist/stories/pages/NegotiationNewPage.stories.d.ts +9 -0
- package/dist/stories/pages/NegotiationNewPage.stories.d.ts.map +1 -0
- package/dist/stories/pages/NegotiationsPage.stories.d.ts +11 -0
- package/dist/stories/pages/NegotiationsPage.stories.d.ts.map +1 -0
- package/dist/stories/support/negotiationFixtures.d.ts +14 -0
- package/dist/stories/support/negotiationFixtures.d.ts.map +1 -0
- package/dist/subscriberbot/SubscriberBotRoutes.d.ts.map +1 -1
- package/dist/subscriberbot/SubscriberBotRoutes.js +18 -6
- package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
- package/dist/subscriberbot/admin/AdminDashboardPage.d.ts.map +1 -1
- package/dist/subscriberbot/admin/AdminDashboardPage.js +61 -51
- package/dist/subscriberbot/admin/AdminDashboardPage.js.map +1 -1
- package/dist/subscriberbot/admin/NegotiationDeskPanel.d.ts +4 -0
- package/dist/subscriberbot/admin/NegotiationDeskPanel.d.ts.map +1 -0
- package/dist/subscriberbot/admin/NegotiationDeskPanel.js +210 -0
- package/dist/subscriberbot/admin/NegotiationDeskPanel.js.map +1 -0
- package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.d.ts +8 -0
- package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.d.ts.map +1 -0
- package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.js +18 -0
- package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.js.map +1 -0
- package/dist/subscriberbot/components/negotiations/NegotiationTimeline.d.ts +8 -0
- package/dist/subscriberbot/components/negotiations/NegotiationTimeline.d.ts.map +1 -0
- package/dist/subscriberbot/components/negotiations/NegotiationTimeline.js +49 -0
- package/dist/subscriberbot/components/negotiations/NegotiationTimeline.js.map +1 -0
- package/dist/subscriberbot/components/negotiations/OutcomeForm.d.ts +13 -0
- package/dist/subscriberbot/components/negotiations/OutcomeForm.d.ts.map +1 -0
- package/dist/subscriberbot/components/negotiations/OutcomeForm.js +112 -0
- package/dist/subscriberbot/components/negotiations/OutcomeForm.js.map +1 -0
- package/dist/subscriberbot/components/negotiations/index.d.ts +5 -0
- package/dist/subscriberbot/components/negotiations/index.d.ts.map +1 -0
- package/dist/subscriberbot/components/negotiations/index.js +4 -0
- package/dist/subscriberbot/components/negotiations/labels.d.ts +16 -0
- package/dist/subscriberbot/components/negotiations/labels.d.ts.map +1 -0
- package/dist/subscriberbot/components/negotiations/labels.js +179 -0
- package/dist/subscriberbot/components/negotiations/labels.js.map +1 -0
- package/dist/subscriberbot/hooks/useNegotiationApi.d.ts +51 -0
- package/dist/subscriberbot/hooks/useNegotiationApi.d.ts.map +1 -0
- package/dist/subscriberbot/hooks/useNegotiationApi.js +106 -0
- package/dist/subscriberbot/hooks/useNegotiationApi.js.map +1 -0
- package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts +1 -0
- package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -1
- package/dist/subscriberbot/hooks/useSubscriberBotApi.js +1 -1
- package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
- package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.d.ts +11 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.d.ts.map +1 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.js +312 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.js.map +1 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.d.ts +11 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.d.ts.map +1 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.js +375 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.js.map +1 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationsPage.d.ts +10 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationsPage.d.ts.map +1 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationsPage.js +155 -0
- package/dist/subscriberbot/pages/negotiations/NegotiationsPage.js.map +1 -0
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +321 -307
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
- package/dist/subscriberbot/types/negotiation.d.ts +101 -0
- package/dist/subscriberbot/types/negotiation.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
|
|
2
|
+
import { PageLayout as t } from "../../components/PageLayout.js";
|
|
3
|
+
import { formatCurrency as n, formatDateTime as r, formatIntervalSuffix as i } from "../../utils/formatters.js";
|
|
4
|
+
import { useTr as a } from "../../hooks/useTr.js";
|
|
5
|
+
import { ErrorView as o, LoadingView as s, Section as c } from "../../components/StateViews.js";
|
|
6
|
+
import "../../components/index.js";
|
|
7
|
+
import { BILL_TYPE_LABEL as l, FEE_STATUS_LABEL as u, OPEN_STATUSES as d, TARGET_LABEL as f } from "../../components/negotiations/labels.js";
|
|
8
|
+
import { NegotiationStatusPill as p } from "../../components/negotiations/NegotiationStatusPill.js";
|
|
9
|
+
import { NegotiationTimeline as m } from "../../components/negotiations/NegotiationTimeline.js";
|
|
10
|
+
import { OutcomeForm as h } from "../../components/negotiations/OutcomeForm.js";
|
|
11
|
+
import "../../components/negotiations/index.js";
|
|
12
|
+
import { useAddNegotiationNote as g, useCancelNegotiation as _, useNegotiation as v, useNegotiationTerms as y, useRecordNegotiationOutcome as b, useSubmitNegotiation as x } from "../../hooks/useNegotiationApi.js";
|
|
13
|
+
import { useState as S } from "react";
|
|
14
|
+
import { ArrowLeft as C, Check as w, Copy as T } from "lucide-react";
|
|
15
|
+
import { useParams as E } from "react-router";
|
|
16
|
+
import { jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
17
|
+
import { GlassCard as k } from "@burdenoff/fe-libs/ui";
|
|
18
|
+
//#region src/subscriberbot/pages/negotiations/NegotiationDetailPage.tsx
|
|
19
|
+
var A = "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]", j = "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50", M = "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50", N = (e) => e ? e instanceof Error ? e.message : String(e) : null;
|
|
20
|
+
function P({ label: e, value: t }) {
|
|
21
|
+
return /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
|
|
22
|
+
className: "text-xs text-text-secondary",
|
|
23
|
+
children: e
|
|
24
|
+
}), /* @__PURE__ */ D("dd", {
|
|
25
|
+
className: "mt-0.5 text-sm font-medium text-text-primary",
|
|
26
|
+
children: t
|
|
27
|
+
})] });
|
|
28
|
+
}
|
|
29
|
+
function F({ playbook: e }) {
|
|
30
|
+
let t = a(), [n, r] = S(!1);
|
|
31
|
+
return /* @__PURE__ */ O(k, {
|
|
32
|
+
treatment: "metric",
|
|
33
|
+
className: "p-5",
|
|
34
|
+
children: [/* @__PURE__ */ D("div", {
|
|
35
|
+
className: "mb-3 flex justify-end",
|
|
36
|
+
children: /* @__PURE__ */ D("button", {
|
|
37
|
+
type: "button",
|
|
38
|
+
onClick: () => {
|
|
39
|
+
navigator.clipboard?.writeText(e).then(() => {
|
|
40
|
+
r(!0), window.setTimeout(() => r(!1), 2e3);
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
className: M,
|
|
44
|
+
children: /* @__PURE__ */ O("span", {
|
|
45
|
+
className: "inline-flex items-center gap-2",
|
|
46
|
+
children: [D(n ? w : T, { className: "h-4 w-4" }), n ? t("negotiations.playbook.copied", "Copied") : t("negotiations.playbook.copy", "Copy playbook")]
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
}), /* @__PURE__ */ D("pre", {
|
|
50
|
+
"data-testid": "negotiation-playbook",
|
|
51
|
+
className: "whitespace-pre-wrap break-words font-sans text-sm leading-relaxed text-text-primary",
|
|
52
|
+
children: e
|
|
53
|
+
})]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function I({ negotiation: e }) {
|
|
57
|
+
let t = a(), n = y(), r = x(), [i, o] = S(!1), s = e.mode === "MANAGED";
|
|
58
|
+
return /* @__PURE__ */ O(k, {
|
|
59
|
+
treatment: "metric",
|
|
60
|
+
className: "space-y-3 p-5",
|
|
61
|
+
"data-testid": "negotiation-submit",
|
|
62
|
+
children: [
|
|
63
|
+
/* @__PURE__ */ D("p", {
|
|
64
|
+
className: "text-sm text-text-primary",
|
|
65
|
+
children: s ? t("negotiations.submit.managedIntro", "Submit this request to the Subscriber Bot negotiation desk. A negotiator contacts the provider for you and keeps you posted here.") : t("negotiations.submit.selfServeIntro", "Ready to make the call? Submit the request to start tracking it, then record what the provider offered.")
|
|
66
|
+
}),
|
|
67
|
+
s && n.data && /* @__PURE__ */ O("div", {
|
|
68
|
+
className: "rounded-lg border border-border-subtle bg-bg-sunken p-3",
|
|
69
|
+
children: [/* @__PURE__ */ D("p", {
|
|
70
|
+
className: "text-xs leading-relaxed text-text-secondary",
|
|
71
|
+
"data-testid": "negotiation-terms",
|
|
72
|
+
children: n.data.authorizationText
|
|
73
|
+
}), /* @__PURE__ */ O("label", {
|
|
74
|
+
className: "mt-3 inline-flex items-start gap-2 text-sm text-text-primary",
|
|
75
|
+
children: [/* @__PURE__ */ D("input", {
|
|
76
|
+
type: "checkbox",
|
|
77
|
+
checked: i,
|
|
78
|
+
onChange: (e) => o(e.target.checked),
|
|
79
|
+
className: "mt-0.5"
|
|
80
|
+
}), t("negotiations.submit.accept", "I authorise the negotiation desk on these terms")]
|
|
81
|
+
})]
|
|
82
|
+
}),
|
|
83
|
+
r.error && /* @__PURE__ */ D("p", {
|
|
84
|
+
role: "alert",
|
|
85
|
+
className: "text-sm text-status-error-text",
|
|
86
|
+
children: N(r.error)
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ D("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
onClick: () => {
|
|
91
|
+
r.mutate({
|
|
92
|
+
id: e.id,
|
|
93
|
+
input: s ? {
|
|
94
|
+
acceptAuthorization: i,
|
|
95
|
+
authorizationVersion: n.data?.authorizationVersion
|
|
96
|
+
} : void 0
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
disabled: r.isPending || s && (!i || !n.data),
|
|
100
|
+
className: j,
|
|
101
|
+
children: s ? t("negotiations.submit.managed", "Submit to the negotiation desk") : t("negotiations.submit.selfServe", "Submit and start")
|
|
102
|
+
})
|
|
103
|
+
]
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function L({ negotiation: e }) {
|
|
107
|
+
let t = a(), n = g(), [r, i] = S(""), o = e.status === "AWAITING_CUSTOMER";
|
|
108
|
+
return /* @__PURE__ */ O("div", {
|
|
109
|
+
className: "space-y-2",
|
|
110
|
+
children: [
|
|
111
|
+
o && /* @__PURE__ */ D("p", {
|
|
112
|
+
className: "rounded-lg bg-status-warning-bg-subtle px-3 py-2 text-sm text-status-warning-text",
|
|
113
|
+
children: t("negotiations.message.awaiting", "The negotiation desk is waiting for your reply. See the latest message below.")
|
|
114
|
+
}),
|
|
115
|
+
/* @__PURE__ */ D("label", {
|
|
116
|
+
htmlFor: "neg-message",
|
|
117
|
+
className: "sr-only",
|
|
118
|
+
children: t("negotiations.message.label", "Message")
|
|
119
|
+
}),
|
|
120
|
+
/* @__PURE__ */ D("textarea", {
|
|
121
|
+
id: "neg-message",
|
|
122
|
+
rows: 2,
|
|
123
|
+
value: r,
|
|
124
|
+
onChange: (e) => i(e.target.value),
|
|
125
|
+
placeholder: e.mode === "MANAGED" ? t("negotiations.message.placeholderDesk", "Write to the negotiation desk…") : t("negotiations.message.placeholderSelf", "Add a note (who you spoke to, offers…)"),
|
|
126
|
+
className: A
|
|
127
|
+
}),
|
|
128
|
+
n.error && /* @__PURE__ */ D("p", {
|
|
129
|
+
role: "alert",
|
|
130
|
+
className: "text-sm text-status-error-text",
|
|
131
|
+
children: N(n.error)
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ D("button", {
|
|
134
|
+
type: "button",
|
|
135
|
+
disabled: n.isPending || !r.trim(),
|
|
136
|
+
onClick: () => n.mutate({
|
|
137
|
+
id: e.id,
|
|
138
|
+
message: r
|
|
139
|
+
}, { onSuccess: () => i("") }),
|
|
140
|
+
className: M,
|
|
141
|
+
children: o ? t("negotiations.message.reply", "Reply to the desk") : t("negotiations.message.send", "Add note")
|
|
142
|
+
})
|
|
143
|
+
]
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function R({ negotiation: e }) {
|
|
147
|
+
let t = a(), r = u[e.feeStatus];
|
|
148
|
+
return /* @__PURE__ */ O(k, {
|
|
149
|
+
treatment: "metric",
|
|
150
|
+
className: "p-5",
|
|
151
|
+
"data-testid": "negotiation-outcome",
|
|
152
|
+
children: [
|
|
153
|
+
/* @__PURE__ */ O("dl", {
|
|
154
|
+
className: "grid grid-cols-2 gap-4 sm:grid-cols-4",
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ D(P, {
|
|
157
|
+
label: t("negotiations.outcome.before", "Before"),
|
|
158
|
+
value: `${n(e.currentAmount, e.currency)}${i(e.interval)}`
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ D(P, {
|
|
161
|
+
label: t("negotiations.outcome.after", "After"),
|
|
162
|
+
value: e.newAmount == null ? "—" : `${n(e.newAmount, e.currency)}${i(e.interval)}`
|
|
163
|
+
}),
|
|
164
|
+
/* @__PURE__ */ D(P, {
|
|
165
|
+
label: t("negotiations.outcome.firstYear", "First-year savings"),
|
|
166
|
+
value: n(e.firstYearSavings, e.currency)
|
|
167
|
+
}),
|
|
168
|
+
/* @__PURE__ */ D(P, {
|
|
169
|
+
label: t("negotiations.outcome.fee", "Success fee"),
|
|
170
|
+
value: e.feeStatus === "NONE" ? t(r.key, r.fallback) : `${n(e.feeAmount, e.currency)} · ${t(r.key, r.fallback)}`
|
|
171
|
+
})
|
|
172
|
+
]
|
|
173
|
+
}),
|
|
174
|
+
e.outcomeSummary && /* @__PURE__ */ D("p", {
|
|
175
|
+
className: "mt-4 text-sm text-text-primary",
|
|
176
|
+
children: e.outcomeSummary
|
|
177
|
+
}),
|
|
178
|
+
e.appliedToRelationship && /* @__PURE__ */ D("p", {
|
|
179
|
+
className: "mt-2 text-xs text-text-secondary",
|
|
180
|
+
children: t("negotiations.outcome.applied", "The tracked subscription now shows the new price.")
|
|
181
|
+
})
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function z() {
|
|
186
|
+
let u = a(), { id: g } = E(), { navigateTo: y } = e(), { data: x, isLoading: S, isError: w, error: T, refetch: A } = v(g), j = _(), z = b(), B = /* @__PURE__ */ O("button", {
|
|
187
|
+
type: "button",
|
|
188
|
+
onClick: () => y("/negotiations"),
|
|
189
|
+
className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
|
|
190
|
+
children: [
|
|
191
|
+
/* @__PURE__ */ D(C, { className: "h-4 w-4" }),
|
|
192
|
+
" ",
|
|
193
|
+
u("negotiations.back", "Back")
|
|
194
|
+
]
|
|
195
|
+
});
|
|
196
|
+
if (S) return /* @__PURE__ */ D(s, { label: u("negotiations.loadingOne", "Loading request…") });
|
|
197
|
+
if (w || !x) return /* @__PURE__ */ D(t, {
|
|
198
|
+
title: u("negotiations.title", "Bill negotiation"),
|
|
199
|
+
actions: B,
|
|
200
|
+
children: /* @__PURE__ */ D(o, {
|
|
201
|
+
title: u("negotiations.notFound", "Negotiation request not found"),
|
|
202
|
+
message: T instanceof Error ? T.message : void 0,
|
|
203
|
+
onRetry: () => void A()
|
|
204
|
+
})
|
|
205
|
+
});
|
|
206
|
+
let V = d.includes(x.status), H = x.status === "SUCCEEDED" || x.status === "NO_SAVINGS";
|
|
207
|
+
return /* @__PURE__ */ O(t, {
|
|
208
|
+
title: x.providerName,
|
|
209
|
+
description: `${u(l[x.billType].key, l[x.billType].fallback)} · ${u(f[x.targetOutcome].key, f[x.targetOutcome].fallback)}`,
|
|
210
|
+
actions: B,
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ O("div", {
|
|
213
|
+
className: "flex flex-wrap items-center gap-3",
|
|
214
|
+
children: [
|
|
215
|
+
/* @__PURE__ */ D(p, { status: x.status }),
|
|
216
|
+
/* @__PURE__ */ D("span", {
|
|
217
|
+
className: "text-sm text-text-secondary",
|
|
218
|
+
children: x.mode === "MANAGED" ? u("negotiations.mode.managedShort", "Negotiation desk") : u("negotiations.mode.selfServeShort", "Do it yourself")
|
|
219
|
+
}),
|
|
220
|
+
x.submittedAt && /* @__PURE__ */ D("span", {
|
|
221
|
+
className: "text-xs text-text-secondary",
|
|
222
|
+
children: u("negotiations.submittedAt", "Submitted {{when}}", { when: r(x.submittedAt) })
|
|
223
|
+
})
|
|
224
|
+
]
|
|
225
|
+
}),
|
|
226
|
+
/* @__PURE__ */ O(k, {
|
|
227
|
+
treatment: "metric",
|
|
228
|
+
className: "mt-4 p-5",
|
|
229
|
+
children: [/* @__PURE__ */ O("dl", {
|
|
230
|
+
className: "grid grid-cols-2 gap-4 sm:grid-cols-4",
|
|
231
|
+
children: [
|
|
232
|
+
/* @__PURE__ */ D(P, {
|
|
233
|
+
label: u("negotiations.fact.current", "Current bill"),
|
|
234
|
+
value: `${n(x.currentAmount, x.currency)}${i(x.interval)}`
|
|
235
|
+
}),
|
|
236
|
+
/* @__PURE__ */ D(P, {
|
|
237
|
+
label: u("negotiations.fact.target", "Target"),
|
|
238
|
+
value: x.targetAmount == null ? "—" : n(x.targetAmount, x.currency)
|
|
239
|
+
}),
|
|
240
|
+
/* @__PURE__ */ D(P, {
|
|
241
|
+
label: u("negotiations.fact.tenure", "Customer for"),
|
|
242
|
+
value: x.tenureMonths == null ? "—" : u("negotiations.fact.months", "{{count}} months", { count: x.tenureMonths })
|
|
243
|
+
}),
|
|
244
|
+
/* @__PURE__ */ D(P, {
|
|
245
|
+
label: u("negotiations.fact.account", "Account"),
|
|
246
|
+
value: x.accountHint ? `${x.accountHolderName ?? ""} ··${x.accountHint}`.trim() : x.accountHolderName ?? "—"
|
|
247
|
+
})
|
|
248
|
+
]
|
|
249
|
+
}), x.competitorOffer && /* @__PURE__ */ D("p", {
|
|
250
|
+
className: "mt-3 text-sm text-text-secondary",
|
|
251
|
+
children: u("negotiations.fact.competitor", "Competing offer: {{offer}}", { offer: x.competitorOffer })
|
|
252
|
+
})]
|
|
253
|
+
}),
|
|
254
|
+
H && /* @__PURE__ */ D(c, {
|
|
255
|
+
title: u("negotiations.section.outcome", "Outcome"),
|
|
256
|
+
children: /* @__PURE__ */ D(R, { negotiation: x })
|
|
257
|
+
}),
|
|
258
|
+
x.status === "DRAFT" && /* @__PURE__ */ D(c, {
|
|
259
|
+
title: u("negotiations.section.submit", "Submit"),
|
|
260
|
+
children: /* @__PURE__ */ D(I, { negotiation: x })
|
|
261
|
+
}),
|
|
262
|
+
x.mode === "SELF_SERVE" && x.status === "SUBMITTED" && /* @__PURE__ */ D(c, {
|
|
263
|
+
title: u("negotiations.section.recordOutcome", "Record what you got"),
|
|
264
|
+
description: u("negotiations.section.recordOutcomeDescription", "Self-serve negotiations are free; this only tracks your savings."),
|
|
265
|
+
children: /* @__PURE__ */ D(k, {
|
|
266
|
+
treatment: "metric",
|
|
267
|
+
className: "p-5",
|
|
268
|
+
children: /* @__PURE__ */ D(h, {
|
|
269
|
+
negotiation: x,
|
|
270
|
+
pending: z.isPending,
|
|
271
|
+
error: N(z.error),
|
|
272
|
+
submitLabel: u("negotiations.outcome.save", "Save outcome"),
|
|
273
|
+
onSubmit: (e) => z.mutate({
|
|
274
|
+
id: x.id,
|
|
275
|
+
input: e
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
})
|
|
279
|
+
}),
|
|
280
|
+
x.playbook && /* @__PURE__ */ D(c, {
|
|
281
|
+
title: u("negotiations.section.playbook", "Negotiation playbook"),
|
|
282
|
+
description: u("negotiations.section.playbookDescription", "Leverage, a call script, what to accept and a written request you can send."),
|
|
283
|
+
children: /* @__PURE__ */ D(F, { playbook: x.playbook })
|
|
284
|
+
}),
|
|
285
|
+
/* @__PURE__ */ O(c, {
|
|
286
|
+
title: u("negotiations.section.timeline", "Timeline"),
|
|
287
|
+
children: [V && x.status !== "DRAFT" && /* @__PURE__ */ D("div", {
|
|
288
|
+
className: "mb-4",
|
|
289
|
+
children: /* @__PURE__ */ D(L, { negotiation: x })
|
|
290
|
+
}), /* @__PURE__ */ D(m, { events: x.events ?? [] })]
|
|
291
|
+
}),
|
|
292
|
+
V && /* @__PURE__ */ O("div", {
|
|
293
|
+
className: "mt-8 border-t border-border-subtle pt-4",
|
|
294
|
+
children: [j.error && /* @__PURE__ */ D("p", {
|
|
295
|
+
role: "alert",
|
|
296
|
+
className: "mb-2 text-sm text-status-error-text",
|
|
297
|
+
children: N(j.error)
|
|
298
|
+
}), /* @__PURE__ */ D("button", {
|
|
299
|
+
type: "button",
|
|
300
|
+
disabled: j.isPending,
|
|
301
|
+
onClick: () => j.mutate({ id: x.id }),
|
|
302
|
+
className: M,
|
|
303
|
+
children: x.mode === "MANAGED" && x.status !== "DRAFT" ? u("negotiations.cancel.managed", "Withdraw request and authorisation") : u("negotiations.cancel.selfServe", "Cancel request")
|
|
304
|
+
})]
|
|
305
|
+
})
|
|
306
|
+
]
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
310
|
+
export { z as NegotiationDetailPage };
|
|
311
|
+
|
|
312
|
+
//# sourceMappingURL=NegotiationDetailPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NegotiationDetailPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/negotiations/NegotiationDetailPage.tsx"],"sourcesContent":["/**\n * Bill negotiation request detail\n * @module subscriberbot/pages/negotiations\n *\n * `/subscriberbot/negotiations/:id` — the playbook, submission (with the\n * negotiation-desk authorisation for managed requests), messages with the\n * desk, the self-serve outcome form, savings and the success fee, and the\n * shared timeline. Every action is a real `Sub*Negotiation*` mutation.\n */\n\nimport { useState } from 'react';\nimport { useParams } from 'react-router';\nimport { ArrowLeft, Check, Copy } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { ErrorView, LoadingView, PageLayout, Section } from '../../components';\nimport {\n BILL_TYPE_LABEL,\n FEE_STATUS_LABEL,\n NegotiationStatusPill,\n NegotiationTimeline,\n OPEN_STATUSES,\n OutcomeForm,\n TARGET_LABEL,\n} from '../../components/negotiations';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport {\n useAddNegotiationNote,\n useCancelNegotiation,\n useNegotiation,\n useNegotiationTerms,\n useRecordNegotiationOutcome,\n useSubmitNegotiation,\n} from '../../hooks/useNegotiationApi';\nimport { useTr } from '../../hooks/useTr';\nimport { formatCurrency, formatDateTime, formatIntervalSuffix } from '../../utils/formatters';\nimport type { SubNegotiation } from '../../types/negotiation';\n\nconst inputCls =\n 'w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\nconst primaryBtn =\n 'rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50';\nconst secondaryBtn =\n 'rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50';\n\nconst errorText = (err: unknown): string | null =>\n err ? (err instanceof Error ? err.message : String(err)) : null;\n\nfunction Fact({ label, value }: { label: string; value: string }) {\n return (\n <div>\n <dt className=\"text-xs text-text-secondary\">{label}</dt>\n <dd className=\"mt-0.5 text-sm font-medium text-text-primary\">{value}</dd>\n </div>\n );\n}\n\nfunction PlaybookCard({ playbook }: { playbook: string }) {\n const tr = useTr();\n const [copied, setCopied] = useState(false);\n const copy = () => {\n void navigator.clipboard?.writeText(playbook).then(() => {\n setCopied(true);\n window.setTimeout(() => setCopied(false), 2000);\n });\n };\n return (\n <GlassCard treatment=\"metric\" className=\"p-5\">\n <div className=\"mb-3 flex justify-end\">\n <button type=\"button\" onClick={copy} className={secondaryBtn}>\n <span className=\"inline-flex items-center gap-2\">\n {copied ? <Check className=\"h-4 w-4\" /> : <Copy className=\"h-4 w-4\" />}\n {copied\n ? tr('negotiations.playbook.copied', 'Copied')\n : tr('negotiations.playbook.copy', 'Copy playbook')}\n </span>\n </button>\n </div>\n <pre\n data-testid=\"negotiation-playbook\"\n className=\"whitespace-pre-wrap break-words font-sans text-sm leading-relaxed text-text-primary\"\n >\n {playbook}\n </pre>\n </GlassCard>\n );\n}\n\nfunction SubmitPanel({ negotiation }: { negotiation: SubNegotiation }) {\n const tr = useTr();\n const terms = useNegotiationTerms();\n const submit = useSubmitNegotiation();\n const [accepted, setAccepted] = useState(false);\n const managed = negotiation.mode === 'MANAGED';\n\n const onSubmit = () => {\n submit.mutate({\n id: negotiation.id,\n input: managed\n ? { acceptAuthorization: accepted, authorizationVersion: terms.data?.authorizationVersion }\n : undefined,\n });\n };\n\n return (\n <GlassCard treatment=\"metric\" className=\"space-y-3 p-5\" data-testid=\"negotiation-submit\">\n <p className=\"text-sm text-text-primary\">\n {managed\n ? tr(\n 'negotiations.submit.managedIntro',\n 'Submit this request to the Subscriber Bot negotiation desk. A negotiator contacts the provider for you and keeps you posted here.'\n )\n : tr(\n 'negotiations.submit.selfServeIntro',\n 'Ready to make the call? Submit the request to start tracking it, then record what the provider offered.'\n )}\n </p>\n {managed && terms.data && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken p-3\">\n <p\n className=\"text-xs leading-relaxed text-text-secondary\"\n data-testid=\"negotiation-terms\"\n >\n {terms.data.authorizationText}\n </p>\n <label className=\"mt-3 inline-flex items-start gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={accepted}\n onChange={(e) => setAccepted(e.target.checked)}\n className=\"mt-0.5\"\n />\n {tr('negotiations.submit.accept', 'I authorise the negotiation desk on these terms')}\n </label>\n </div>\n )}\n {submit.error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {errorText(submit.error)}\n </p>\n )}\n <button\n type=\"button\"\n onClick={onSubmit}\n disabled={submit.isPending || (managed && (!accepted || !terms.data))}\n className={primaryBtn}\n >\n {managed\n ? tr('negotiations.submit.managed', 'Submit to the negotiation desk')\n : tr('negotiations.submit.selfServe', 'Submit and start')}\n </button>\n </GlassCard>\n );\n}\n\nfunction MessagePanel({ negotiation }: { negotiation: SubNegotiation }) {\n const tr = useTr();\n const note = useAddNegotiationNote();\n const [message, setMessage] = useState('');\n const awaiting = negotiation.status === 'AWAITING_CUSTOMER';\n return (\n <div className=\"space-y-2\">\n {awaiting && (\n <p className=\"rounded-lg bg-status-warning-bg-subtle px-3 py-2 text-sm text-status-warning-text\">\n {tr(\n 'negotiations.message.awaiting',\n 'The negotiation desk is waiting for your reply. See the latest message below.'\n )}\n </p>\n )}\n <label htmlFor=\"neg-message\" className=\"sr-only\">\n {tr('negotiations.message.label', 'Message')}\n </label>\n <textarea\n id=\"neg-message\"\n rows={2}\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n placeholder={\n negotiation.mode === 'MANAGED'\n ? tr('negotiations.message.placeholderDesk', 'Write to the negotiation desk…')\n : tr('negotiations.message.placeholderSelf', 'Add a note (who you spoke to, offers…)')\n }\n className={inputCls}\n />\n {note.error && (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {errorText(note.error)}\n </p>\n )}\n <button\n type=\"button\"\n disabled={note.isPending || !message.trim()}\n onClick={() =>\n note.mutate({ id: negotiation.id, message }, { onSuccess: () => setMessage('') })\n }\n className={secondaryBtn}\n >\n {awaiting\n ? tr('negotiations.message.reply', 'Reply to the desk')\n : tr('negotiations.message.send', 'Add note')}\n </button>\n </div>\n );\n}\n\nfunction OutcomeSummary({ negotiation: n }: { negotiation: SubNegotiation }) {\n const tr = useTr();\n const fee = FEE_STATUS_LABEL[n.feeStatus];\n return (\n <GlassCard treatment=\"metric\" className=\"p-5\" data-testid=\"negotiation-outcome\">\n <dl className=\"grid grid-cols-2 gap-4 sm:grid-cols-4\">\n <Fact\n label={tr('negotiations.outcome.before', 'Before')}\n value={`${formatCurrency(n.currentAmount, n.currency)}${formatIntervalSuffix(n.interval)}`}\n />\n <Fact\n label={tr('negotiations.outcome.after', 'After')}\n value={\n n.newAmount != null\n ? `${formatCurrency(n.newAmount, n.currency)}${formatIntervalSuffix(n.interval)}`\n : '—'\n }\n />\n <Fact\n label={tr('negotiations.outcome.firstYear', 'First-year savings')}\n value={formatCurrency(n.firstYearSavings, n.currency)}\n />\n <Fact\n label={tr('negotiations.outcome.fee', 'Success fee')}\n value={\n n.feeStatus === 'NONE'\n ? tr(fee.key, fee.fallback)\n : `${formatCurrency(n.feeAmount, n.currency)} · ${tr(fee.key, fee.fallback)}`\n }\n />\n </dl>\n {n.outcomeSummary && <p className=\"mt-4 text-sm text-text-primary\">{n.outcomeSummary}</p>}\n {n.appliedToRelationship && (\n <p className=\"mt-2 text-xs text-text-secondary\">\n {tr('negotiations.outcome.applied', 'The tracked subscription now shows the new price.')}\n </p>\n )}\n </GlassCard>\n );\n}\n\nexport function NegotiationDetailPage() {\n const tr = useTr();\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useSubscriberBot();\n const { data: n, isLoading, isError, error, refetch } = useNegotiation(id);\n const cancel = useCancelNegotiation();\n const record = useRecordNegotiationOutcome();\n\n const back = (\n <button\n type=\"button\"\n onClick={() => navigateTo('/negotiations')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> {tr('negotiations.back', 'Back')}\n </button>\n );\n\n if (isLoading) return <LoadingView label={tr('negotiations.loadingOne', 'Loading request…')} />;\n if (isError || !n) {\n return (\n <PageLayout title={tr('negotiations.title', 'Bill negotiation')} actions={back}>\n <ErrorView\n title={tr('negotiations.notFound', 'Negotiation request not found')}\n message={error instanceof Error ? error.message : undefined}\n onRetry={() => void refetch()}\n />\n </PageLayout>\n );\n }\n\n const open = OPEN_STATUSES.includes(n.status);\n const finished = n.status === 'SUCCEEDED' || n.status === 'NO_SAVINGS';\n\n return (\n <PageLayout\n title={n.providerName}\n description={`${tr(BILL_TYPE_LABEL[n.billType].key, BILL_TYPE_LABEL[n.billType].fallback)} · ${tr(\n TARGET_LABEL[n.targetOutcome].key,\n TARGET_LABEL[n.targetOutcome].fallback\n )}`}\n actions={back}\n >\n <div className=\"flex flex-wrap items-center gap-3\">\n <NegotiationStatusPill status={n.status} />\n <span className=\"text-sm text-text-secondary\">\n {n.mode === 'MANAGED'\n ? tr('negotiations.mode.managedShort', 'Negotiation desk')\n : tr('negotiations.mode.selfServeShort', 'Do it yourself')}\n </span>\n {n.submittedAt && (\n <span className=\"text-xs text-text-secondary\">\n {tr('negotiations.submittedAt', 'Submitted {{when}}', {\n when: formatDateTime(n.submittedAt),\n })}\n </span>\n )}\n </div>\n\n <GlassCard treatment=\"metric\" className=\"mt-4 p-5\">\n <dl className=\"grid grid-cols-2 gap-4 sm:grid-cols-4\">\n <Fact\n label={tr('negotiations.fact.current', 'Current bill')}\n value={`${formatCurrency(n.currentAmount, n.currency)}${formatIntervalSuffix(n.interval)}`}\n />\n <Fact\n label={tr('negotiations.fact.target', 'Target')}\n value={n.targetAmount != null ? formatCurrency(n.targetAmount, n.currency) : '—'}\n />\n <Fact\n label={tr('negotiations.fact.tenure', 'Customer for')}\n value={\n n.tenureMonths != null\n ? tr('negotiations.fact.months', '{{count}} months', { count: n.tenureMonths })\n : '—'\n }\n />\n <Fact\n label={tr('negotiations.fact.account', 'Account')}\n value={\n n.accountHint\n ? `${n.accountHolderName ?? ''} ··${n.accountHint}`.trim()\n : (n.accountHolderName ?? '—')\n }\n />\n </dl>\n {n.competitorOffer && (\n <p className=\"mt-3 text-sm text-text-secondary\">\n {tr('negotiations.fact.competitor', 'Competing offer: {{offer}}', {\n offer: n.competitorOffer,\n })}\n </p>\n )}\n </GlassCard>\n\n {finished && (\n <Section title={tr('negotiations.section.outcome', 'Outcome')}>\n <OutcomeSummary negotiation={n} />\n </Section>\n )}\n\n {n.status === 'DRAFT' && (\n <Section title={tr('negotiations.section.submit', 'Submit')}>\n <SubmitPanel negotiation={n} />\n </Section>\n )}\n\n {n.mode === 'SELF_SERVE' && n.status === 'SUBMITTED' && (\n <Section\n title={tr('negotiations.section.recordOutcome', 'Record what you got')}\n description={tr(\n 'negotiations.section.recordOutcomeDescription',\n 'Self-serve negotiations are free; this only tracks your savings.'\n )}\n >\n <GlassCard treatment=\"metric\" className=\"p-5\">\n <OutcomeForm\n negotiation={n}\n pending={record.isPending}\n error={errorText(record.error)}\n submitLabel={tr('negotiations.outcome.save', 'Save outcome')}\n onSubmit={(input) => record.mutate({ id: n.id, input })}\n />\n </GlassCard>\n </Section>\n )}\n\n {n.playbook && (\n <Section\n title={tr('negotiations.section.playbook', 'Negotiation playbook')}\n description={tr(\n 'negotiations.section.playbookDescription',\n 'Leverage, a call script, what to accept and a written request you can send.'\n )}\n >\n <PlaybookCard playbook={n.playbook} />\n </Section>\n )}\n\n <Section title={tr('negotiations.section.timeline', 'Timeline')}>\n {open && n.status !== 'DRAFT' && (\n <div className=\"mb-4\">\n <MessagePanel negotiation={n} />\n </div>\n )}\n <NegotiationTimeline events={n.events ?? []} />\n </Section>\n\n {open && (\n <div className=\"mt-8 border-t border-border-subtle pt-4\">\n {cancel.error && (\n <p role=\"alert\" className=\"mb-2 text-sm text-status-error-text\">\n {errorText(cancel.error)}\n </p>\n )}\n <button\n type=\"button\"\n disabled={cancel.isPending}\n onClick={() => cancel.mutate({ id: n.id })}\n className={secondaryBtn}\n >\n {n.mode === 'MANAGED' && n.status !== 'DRAFT'\n ? tr('negotiations.cancel.managed', 'Withdraw request and authorisation')\n : tr('negotiations.cancel.selfServe', 'Cancel request')}\n </button>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New bill negotiation request
|
|
3
|
+
* @module subscriberbot/pages/negotiations
|
|
4
|
+
*
|
|
5
|
+
* `/subscriberbot/negotiations/new[?relationshipId=…]` — describe the bill and
|
|
6
|
+
* pick a service mode. Creates a DRAFT through `subCreateNegotiation`; the
|
|
7
|
+
* playbook is generated server-side and the customer submits from the detail
|
|
8
|
+
* page (where the managed-desk authorisation is accepted).
|
|
9
|
+
*/
|
|
10
|
+
export declare function NegotiationNewPage(): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=NegotiationNewPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NegotiationNewPage.d.ts","sourceRoot":"","sources":["../../../../src/subscriberbot/pages/negotiations/NegotiationNewPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuDH,wBAAgB,kBAAkB,gCAuajC"}
|