@burdenoff/microfe-billing 2026.530.2 → 2026.530.4
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/billing/BillingAdminRoutes.js +110 -71
- package/dist/billing/BillingAdminRoutes.js.map +1 -1
- package/dist/billing/BillingRoot.js +81 -73
- package/dist/billing/BillingRoot.js.map +1 -1
- package/dist/billing/BillingUserRoutes.js +103 -90
- package/dist/billing/BillingUserRoutes.js.map +1 -1
- package/dist/billing/modules/billing/index.js +2 -1
- package/dist/billing/modules/billing/pages/InvoicesListPage.js +135 -126
- package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/UserRefundsPage.js +417 -0
- package/dist/billing/modules/billing/pages/UserRefundsPage.js.map +1 -0
- package/dist/billing/modules/billing/pages/index.js +1 -0
- package/dist/billing/modules/checkout/hooks/useCheckout.js +163 -161
- package/dist/billing/modules/checkout/hooks/useCheckout.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js +344 -167
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
- package/dist/billing/modules/plans/constants/featuredQuotas.js +37 -0
- package/dist/billing/modules/plans/constants/featuredQuotas.js.map +1 -0
- package/dist/billing/modules/plans/index.js +2 -1
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +205 -0
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -0
- package/dist/billing/modules/plans/pages/PlanCreatePage.js +51 -33
- package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanEditPage.js +78 -60
- package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js +246 -126
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/index.js +1 -0
- package/dist/billing/modules/promotions/index.js +4 -0
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +289 -0
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -0
- package/dist/billing/modules/promotions/pages/PromotionsListPage.js +168 -0
- package/dist/billing/modules/promotions/pages/PromotionsListPage.js.map +1 -0
- package/dist/billing/modules/promotions/pages/index.js +2 -0
- package/dist/billing/shared/types/graphql.js.map +1 -1
- package/dist/generated/global-operations.js +422 -290
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.js +3 -1
- package/dist/generated/global-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,16 +4,92 @@ import "../../../shared/components/index.js";
|
|
|
4
4
|
import { useBillingPermissions as n } from "../../../hooks/useBillingPermissions.js";
|
|
5
5
|
import { useCreateCouponMutation as r } from "../../../../generated/global-operations.js";
|
|
6
6
|
import { useBillingNavigate as i } from "../../../hooks/useBillingNavigate.js";
|
|
7
|
-
import {
|
|
8
|
-
import { ArrowLeft as
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { useI18n as
|
|
7
|
+
import { useRef as a, useState as o } from "react";
|
|
8
|
+
import { ArrowLeft as s, Package as c, Percent as l, Save as u, Tag as d, Users as f, X as p } from "lucide-react";
|
|
9
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
10
|
+
import { useI18n as _ } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
11
|
//#region src/billing/modules/coupons/pages/CreateCouponPage.tsx
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
var v = [
|
|
13
|
+
{
|
|
14
|
+
code: "USD",
|
|
15
|
+
symbol: "$",
|
|
16
|
+
name: "US Dollar"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
code: "EUR",
|
|
20
|
+
symbol: "€",
|
|
21
|
+
name: "Euro"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
code: "GBP",
|
|
25
|
+
symbol: "£",
|
|
26
|
+
name: "British Pound"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
code: "INR",
|
|
30
|
+
symbol: "₹",
|
|
31
|
+
name: "Indian Rupee"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
code: "AUD",
|
|
35
|
+
symbol: "A$",
|
|
36
|
+
name: "Australian Dollar"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
code: "CAD",
|
|
40
|
+
symbol: "C$",
|
|
41
|
+
name: "Canadian Dollar"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
code: "SGD",
|
|
45
|
+
symbol: "S$",
|
|
46
|
+
name: "Singapore Dollar"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
code: "JPY",
|
|
50
|
+
symbol: "¥",
|
|
51
|
+
name: "Japanese Yen"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
code: "MXN",
|
|
55
|
+
symbol: "MX$",
|
|
56
|
+
name: "Mexican Peso"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
code: "BRL",
|
|
60
|
+
symbol: "R$",
|
|
61
|
+
name: "Brazilian Real"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
code: "CHF",
|
|
65
|
+
symbol: "Fr",
|
|
66
|
+
name: "Swiss Franc"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
code: "HKD",
|
|
70
|
+
symbol: "HK$",
|
|
71
|
+
name: "Hong Kong Dollar"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
code: "NZD",
|
|
75
|
+
symbol: "NZ$",
|
|
76
|
+
name: "New Zealand Dollar"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
code: "SEK",
|
|
80
|
+
symbol: "kr",
|
|
81
|
+
name: "Swedish Krona"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
code: "KRW",
|
|
85
|
+
symbol: "₩",
|
|
86
|
+
name: "South Korean Won"
|
|
87
|
+
}
|
|
88
|
+
], y = () => {
|
|
89
|
+
let { t: y } = _(), b = (e, t) => {
|
|
90
|
+
let n = y(e);
|
|
15
91
|
return n === e ? t : n;
|
|
16
|
-
},
|
|
92
|
+
}, x = i(), S = n(), [C, w] = o(""), T = a(null), [E, D] = o({
|
|
17
93
|
code: "",
|
|
18
94
|
name: "",
|
|
19
95
|
description: "",
|
|
@@ -31,138 +107,168 @@ var g = () => {
|
|
|
31
107
|
applicableProducts: [],
|
|
32
108
|
applicableServices: [],
|
|
33
109
|
campaignName: ""
|
|
34
|
-
}), [
|
|
35
|
-
if (!
|
|
36
|
-
let
|
|
37
|
-
|
|
110
|
+
}), [O, k] = o({}), [A, j] = o(!1), M = v.find((e) => e.code === E.currency)?.symbol ?? E.currency, [N] = r();
|
|
111
|
+
if (!S.canManageDiscounts) return /* @__PURE__ */ h(e, { message: "You don't have permission to create coupons." });
|
|
112
|
+
let P = (e, t) => {
|
|
113
|
+
D((n) => ({
|
|
38
114
|
...n,
|
|
39
115
|
[e]: t
|
|
40
|
-
})),
|
|
116
|
+
})), O[e] && k((t) => {
|
|
41
117
|
let n = { ...t };
|
|
42
118
|
return delete n[e], n;
|
|
43
119
|
});
|
|
44
|
-
},
|
|
120
|
+
}, F = () => {
|
|
45
121
|
let e = {};
|
|
46
|
-
return
|
|
122
|
+
return E.code.trim() ? /^[A-Z0-9-_]+$/.test(E.code) ? E.code.length < 3 ? e.code = "Code must be at least 3 characters" : E.code.length > 50 && (e.code = "Code must be at most 50 characters") : e.code = "Code must contain only uppercase letters, numbers, hyphens, and underscores" : e.code = "Coupon code is required", E.name.trim() || (e.name = "Coupon name is required"), E.value <= 0 && (e.value = "Value must be greater than 0"), E.type === "PERCENTAGE" && E.value > 100 && (e.value = "Percentage cannot exceed 100%"), E.scope === "USER_SPECIFIC" && E.restrictedToUserIds.length === 0 && (e.restrictedToUserIds = "Add at least one user email or ID"), E.validFrom || (e.validFrom = "Start date is required"), E.validUntil && E.validUntil < E.validFrom && (e.validUntil = "End date must be after start date"), k(e), Object.keys(e).length === 0;
|
|
123
|
+
}, I = (e) => {
|
|
124
|
+
let t = e.trim();
|
|
125
|
+
t && (E.restrictedToUserIds.includes(t) || P("restrictedToUserIds", [...E.restrictedToUserIds, t]), w(""));
|
|
126
|
+
}, L = (e) => {
|
|
127
|
+
P("restrictedToUserIds", E.restrictedToUserIds.filter((t) => t !== e));
|
|
47
128
|
};
|
|
48
|
-
return /* @__PURE__ */
|
|
129
|
+
return /* @__PURE__ */ g("div", {
|
|
49
130
|
className: "max-w-4xl mx-auto p-4 sm:p-6 space-y-6",
|
|
50
|
-
children: [/* @__PURE__ */
|
|
131
|
+
children: [/* @__PURE__ */ g("div", {
|
|
51
132
|
className: "flex items-center gap-4",
|
|
52
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ h("button", {
|
|
53
134
|
type: "button",
|
|
54
|
-
onClick: () =>
|
|
135
|
+
onClick: () => x("/coupons"),
|
|
55
136
|
className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground",
|
|
56
|
-
children: /* @__PURE__ */
|
|
57
|
-
}), /* @__PURE__ */
|
|
58
|
-
title:
|
|
137
|
+
children: /* @__PURE__ */ h(s, { className: "size-5" })
|
|
138
|
+
}), /* @__PURE__ */ h(t, {
|
|
139
|
+
title: b("billing.coupons.createTitle", "Create Coupon"),
|
|
59
140
|
description: "Create a new discount code or promotional offer",
|
|
60
|
-
icon: /* @__PURE__ */
|
|
141
|
+
icon: /* @__PURE__ */ h(d, { className: "size-6" })
|
|
61
142
|
})]
|
|
62
|
-
}), /* @__PURE__ */
|
|
143
|
+
}), /* @__PURE__ */ g("form", {
|
|
63
144
|
onSubmit: async (e) => {
|
|
64
|
-
if (e.preventDefault(),
|
|
65
|
-
|
|
145
|
+
if (e.preventDefault(), F()) {
|
|
146
|
+
j(!0);
|
|
66
147
|
try {
|
|
67
|
-
if ((await
|
|
68
|
-
code:
|
|
69
|
-
name:
|
|
70
|
-
description:
|
|
71
|
-
scope:
|
|
72
|
-
type:
|
|
73
|
-
value:
|
|
74
|
-
currency:
|
|
75
|
-
minPurchaseAmount:
|
|
76
|
-
maxDiscountAmount:
|
|
77
|
-
maxTotalUses:
|
|
78
|
-
maxUsesPerUser:
|
|
79
|
-
validFrom: new Date(
|
|
80
|
-
validUntil:
|
|
81
|
-
restrictedToUserIds:
|
|
82
|
-
applicableProducts:
|
|
83
|
-
applicableServices:
|
|
148
|
+
if ((await N({ variables: { input: {
|
|
149
|
+
code: E.code,
|
|
150
|
+
name: E.name,
|
|
151
|
+
description: E.description,
|
|
152
|
+
scope: E.scope,
|
|
153
|
+
type: E.type,
|
|
154
|
+
value: E.value,
|
|
155
|
+
currency: E.currency,
|
|
156
|
+
minPurchaseAmount: E.minPurchaseAmount,
|
|
157
|
+
maxDiscountAmount: E.maxDiscountAmount,
|
|
158
|
+
maxTotalUses: E.maxTotalUses,
|
|
159
|
+
maxUsesPerUser: E.maxUsesPerUser,
|
|
160
|
+
validFrom: new Date(E.validFrom).toISOString(),
|
|
161
|
+
validUntil: E.validUntil ? new Date(E.validUntil).toISOString() : void 0,
|
|
162
|
+
restrictedToUserIds: E.restrictedToUserIds,
|
|
163
|
+
applicableProducts: E.applicableProducts,
|
|
164
|
+
applicableServices: E.applicableServices,
|
|
84
165
|
excludedProducts: [],
|
|
85
166
|
excludedServices: [],
|
|
86
|
-
campaignName:
|
|
87
|
-
} } })).data?.createCoupon)
|
|
167
|
+
campaignName: E.campaignName || void 0
|
|
168
|
+
} } })).data?.createCoupon) x("/coupons");
|
|
88
169
|
else throw Error("Failed to create coupon");
|
|
89
170
|
} catch (e) {
|
|
90
|
-
console.error("Error creating coupon:", e),
|
|
171
|
+
console.error("Error creating coupon:", e), k({ code: e instanceof Error ? e.message : "Failed to create coupon. Please try again." });
|
|
91
172
|
} finally {
|
|
92
|
-
|
|
173
|
+
j(!1);
|
|
93
174
|
}
|
|
94
175
|
}
|
|
95
176
|
},
|
|
96
177
|
className: "space-y-6",
|
|
97
178
|
children: [
|
|
98
|
-
/* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ g("div", {
|
|
99
180
|
className: "bg-card border border-border rounded-lg p-6 space-y-4",
|
|
100
181
|
children: [
|
|
101
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ h("h3", {
|
|
102
183
|
className: "text-lg font-semibold text-foreground",
|
|
103
184
|
children: "Basic Information"
|
|
104
185
|
}),
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
-
/* @__PURE__ */
|
|
186
|
+
/* @__PURE__ */ g("div", { children: [
|
|
187
|
+
/* @__PURE__ */ h("label", {
|
|
107
188
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
108
189
|
children: "Coupon Code *"
|
|
109
190
|
}),
|
|
110
|
-
/* @__PURE__ */
|
|
191
|
+
/* @__PURE__ */ h("input", {
|
|
111
192
|
type: "text",
|
|
112
|
-
value:
|
|
113
|
-
onChange: (e) =>
|
|
193
|
+
value: E.code,
|
|
194
|
+
onChange: (e) => P("code", e.target.value.toUpperCase()),
|
|
114
195
|
placeholder: "e.g., WELCOME20",
|
|
115
|
-
className: `w-full px-4 py-2 rounded-lg border ${
|
|
196
|
+
className: `w-full px-4 py-2 rounded-lg border ${O.code ? "border-destructive" : "border-border"} bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20`
|
|
116
197
|
}),
|
|
117
|
-
|
|
198
|
+
O.code && /* @__PURE__ */ h("p", {
|
|
118
199
|
className: "text-sm text-destructive mt-1",
|
|
119
|
-
children:
|
|
200
|
+
children: O.code
|
|
120
201
|
}),
|
|
121
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ h("p", {
|
|
122
203
|
className: "text-xs text-muted-foreground mt-1",
|
|
123
204
|
children: "Use uppercase letters, numbers, hyphens, and underscores"
|
|
124
205
|
})
|
|
125
206
|
] }),
|
|
126
|
-
/* @__PURE__ */
|
|
127
|
-
/* @__PURE__ */
|
|
207
|
+
/* @__PURE__ */ g("div", { children: [
|
|
208
|
+
/* @__PURE__ */ h("label", {
|
|
128
209
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
129
210
|
children: "Display Name *"
|
|
130
211
|
}),
|
|
131
|
-
/* @__PURE__ */
|
|
212
|
+
/* @__PURE__ */ h("input", {
|
|
132
213
|
type: "text",
|
|
133
|
-
value:
|
|
134
|
-
onChange: (e) =>
|
|
214
|
+
value: E.name,
|
|
215
|
+
onChange: (e) => P("name", e.target.value),
|
|
135
216
|
placeholder: "e.g., Welcome 20% Off",
|
|
136
|
-
className: `w-full px-4 py-2 rounded-lg border ${
|
|
217
|
+
className: `w-full px-4 py-2 rounded-lg border ${O.name ? "border-destructive" : "border-border"} bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20`
|
|
137
218
|
}),
|
|
138
|
-
|
|
219
|
+
O.name && /* @__PURE__ */ h("p", {
|
|
139
220
|
className: "text-sm text-destructive mt-1",
|
|
140
|
-
children:
|
|
221
|
+
children: O.name
|
|
141
222
|
})
|
|
142
223
|
] }),
|
|
143
|
-
/* @__PURE__ */
|
|
224
|
+
/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
144
225
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
145
226
|
children: "Description"
|
|
146
|
-
}), /* @__PURE__ */
|
|
147
|
-
value:
|
|
148
|
-
onChange: (e) =>
|
|
227
|
+
}), /* @__PURE__ */ h("textarea", {
|
|
228
|
+
value: E.description,
|
|
229
|
+
onChange: (e) => P("description", e.target.value),
|
|
149
230
|
placeholder: "Optional description for internal use",
|
|
150
231
|
rows: 3,
|
|
151
232
|
className: "w-full px-4 py-2 rounded-lg border border-border bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
|
|
152
233
|
})] })
|
|
153
234
|
]
|
|
154
235
|
}),
|
|
155
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ g("div", {
|
|
156
237
|
className: "bg-card border border-border rounded-lg p-6 space-y-4",
|
|
157
238
|
children: [
|
|
158
|
-
/* @__PURE__ */
|
|
239
|
+
/* @__PURE__ */ h("h3", {
|
|
159
240
|
className: "text-lg font-semibold text-foreground",
|
|
160
241
|
children: "Discount Configuration"
|
|
161
242
|
}),
|
|
162
|
-
/* @__PURE__ */
|
|
243
|
+
/* @__PURE__ */ g("div", { children: [
|
|
244
|
+
/* @__PURE__ */ h("label", {
|
|
245
|
+
className: "block text-sm font-medium text-foreground mb-1",
|
|
246
|
+
children: "Coupon Currency *"
|
|
247
|
+
}),
|
|
248
|
+
/* @__PURE__ */ h("select", {
|
|
249
|
+
value: E.currency,
|
|
250
|
+
onChange: (e) => P("currency", e.target.value),
|
|
251
|
+
className: "w-full px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20",
|
|
252
|
+
children: v.map(({ code: e, symbol: t, name: n }) => /* @__PURE__ */ g("option", {
|
|
253
|
+
value: e,
|
|
254
|
+
children: [
|
|
255
|
+
t,
|
|
256
|
+
" ",
|
|
257
|
+
e,
|
|
258
|
+
" — ",
|
|
259
|
+
n
|
|
260
|
+
]
|
|
261
|
+
}, e))
|
|
262
|
+
}),
|
|
263
|
+
/* @__PURE__ */ h("p", {
|
|
264
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
265
|
+
children: "Amounts below are in this currency. Users paying in a different currency (e.g. INR) will have the amounts automatically converted using live exchange rates at validation time."
|
|
266
|
+
})
|
|
267
|
+
] }),
|
|
268
|
+
/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
163
269
|
className: "block text-sm font-medium text-foreground mb-2",
|
|
164
270
|
children: "Discount Type *"
|
|
165
|
-
}), /* @__PURE__ */
|
|
271
|
+
}), /* @__PURE__ */ h("div", {
|
|
166
272
|
className: "grid grid-cols-3 gap-3",
|
|
167
273
|
children: [
|
|
168
274
|
{
|
|
@@ -172,244 +278,315 @@ var g = () => {
|
|
|
172
278
|
},
|
|
173
279
|
{
|
|
174
280
|
value: "FIXED_AMOUNT",
|
|
175
|
-
label:
|
|
176
|
-
icon:
|
|
281
|
+
label: `Fixed (${M})`,
|
|
282
|
+
icon: null
|
|
177
283
|
},
|
|
178
284
|
{
|
|
179
285
|
value: "FREE_SHIPPING",
|
|
180
286
|
label: "Free Shipping",
|
|
181
287
|
icon: c
|
|
182
288
|
}
|
|
183
|
-
].map(({ value: e, label: t, icon: n }) => /* @__PURE__ */
|
|
289
|
+
].map(({ value: e, label: t, icon: n }) => /* @__PURE__ */ g("button", {
|
|
184
290
|
type: "button",
|
|
185
|
-
onClick: () =>
|
|
186
|
-
className: `p-4 rounded-lg border-2 transition-colors ${
|
|
187
|
-
children: [/* @__PURE__ */
|
|
291
|
+
onClick: () => P("type", e),
|
|
292
|
+
className: `p-4 rounded-lg border-2 transition-colors ${E.type === e ? "border-primary bg-primary/10" : "border-border hover:border-primary/50"}`,
|
|
293
|
+
children: [n ? /* @__PURE__ */ h(n, { className: "size-5 mx-auto mb-2" }) : /* @__PURE__ */ h("span", {
|
|
294
|
+
className: "block text-lg font-bold mb-2",
|
|
295
|
+
children: M
|
|
296
|
+
}), /* @__PURE__ */ h("p", {
|
|
188
297
|
className: "text-sm font-medium",
|
|
189
298
|
children: t
|
|
190
299
|
})]
|
|
191
300
|
}, e))
|
|
192
301
|
})] }),
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
-
/* @__PURE__ */
|
|
302
|
+
/* @__PURE__ */ g("div", { children: [
|
|
303
|
+
/* @__PURE__ */ h("label", {
|
|
195
304
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
196
305
|
children: "Discount Value *"
|
|
197
306
|
}),
|
|
198
|
-
/* @__PURE__ */
|
|
307
|
+
/* @__PURE__ */ h("div", {
|
|
199
308
|
className: "relative",
|
|
200
|
-
children:
|
|
309
|
+
children: E.type === "PERCENTAGE" ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(l, { className: "absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" }), /* @__PURE__ */ h("input", {
|
|
201
310
|
type: "number",
|
|
202
|
-
value:
|
|
203
|
-
onChange: (e) =>
|
|
311
|
+
value: E.value,
|
|
312
|
+
onChange: (e) => P("value", parseFloat(e.target.value)),
|
|
204
313
|
min: "0",
|
|
205
314
|
max: "100",
|
|
206
315
|
step: "0.01",
|
|
207
|
-
className: `w-full pl-10 pr-4 py-2 rounded-lg border ${
|
|
208
|
-
})] }) : /* @__PURE__ */ m
|
|
316
|
+
className: `w-full pl-10 pr-4 py-2 rounded-lg border ${O.value ? "border-destructive" : "border-border"} bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20`
|
|
317
|
+
})] }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("span", {
|
|
318
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground font-medium",
|
|
319
|
+
children: M
|
|
320
|
+
}), /* @__PURE__ */ h("input", {
|
|
209
321
|
type: "number",
|
|
210
|
-
value:
|
|
211
|
-
onChange: (e) =>
|
|
322
|
+
value: E.value,
|
|
323
|
+
onChange: (e) => P("value", parseFloat(e.target.value)),
|
|
212
324
|
min: "0",
|
|
213
325
|
step: "0.01",
|
|
214
|
-
className: `w-full pl-10 pr-4 py-2 rounded-lg border ${
|
|
326
|
+
className: `w-full pl-10 pr-4 py-2 rounded-lg border ${O.value ? "border-destructive" : "border-border"} bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20`
|
|
215
327
|
})] })
|
|
216
328
|
}),
|
|
217
|
-
|
|
329
|
+
O.value && /* @__PURE__ */ h("p", {
|
|
218
330
|
className: "text-sm text-destructive mt-1",
|
|
219
|
-
children:
|
|
331
|
+
children: O.value
|
|
220
332
|
})
|
|
221
333
|
] }),
|
|
222
|
-
/* @__PURE__ */
|
|
223
|
-
/* @__PURE__ */
|
|
334
|
+
/* @__PURE__ */ g("div", { children: [
|
|
335
|
+
/* @__PURE__ */ g("label", {
|
|
224
336
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
225
|
-
children:
|
|
337
|
+
children: [
|
|
338
|
+
"Minimum Purchase Amount (",
|
|
339
|
+
E.currency,
|
|
340
|
+
")"
|
|
341
|
+
]
|
|
226
342
|
}),
|
|
227
|
-
/* @__PURE__ */
|
|
343
|
+
/* @__PURE__ */ g("div", {
|
|
228
344
|
className: "relative",
|
|
229
|
-
children: [/* @__PURE__ */
|
|
345
|
+
children: [/* @__PURE__ */ h("span", {
|
|
346
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground font-medium",
|
|
347
|
+
children: M
|
|
348
|
+
}), /* @__PURE__ */ h("input", {
|
|
230
349
|
type: "number",
|
|
231
|
-
value:
|
|
232
|
-
onChange: (e) =>
|
|
350
|
+
value: E.minPurchaseAmount || "",
|
|
351
|
+
onChange: (e) => P("minPurchaseAmount", e.target.value ? parseFloat(e.target.value) : null),
|
|
233
352
|
min: "0",
|
|
234
353
|
step: "0.01",
|
|
235
354
|
placeholder: "No minimum",
|
|
236
355
|
className: "w-full pl-10 pr-4 py-2 rounded-lg border border-border bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
|
|
237
356
|
})]
|
|
238
357
|
}),
|
|
239
|
-
/* @__PURE__ */
|
|
358
|
+
/* @__PURE__ */ g("p", {
|
|
240
359
|
className: "text-xs text-muted-foreground mt-1",
|
|
241
|
-
children:
|
|
360
|
+
children: [
|
|
361
|
+
"Order must be at least this amount in ",
|
|
362
|
+
E.currency,
|
|
363
|
+
" (auto-converted for other currencies)"
|
|
364
|
+
]
|
|
242
365
|
})
|
|
243
366
|
] }),
|
|
244
|
-
|
|
245
|
-
/* @__PURE__ */
|
|
367
|
+
E.type === "PERCENTAGE" && /* @__PURE__ */ g("div", { children: [
|
|
368
|
+
/* @__PURE__ */ g("label", {
|
|
246
369
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
247
|
-
children:
|
|
370
|
+
children: [
|
|
371
|
+
"Maximum Discount Amount (",
|
|
372
|
+
E.currency,
|
|
373
|
+
")"
|
|
374
|
+
]
|
|
248
375
|
}),
|
|
249
|
-
/* @__PURE__ */
|
|
376
|
+
/* @__PURE__ */ g("div", {
|
|
250
377
|
className: "relative",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
378
|
+
children: [/* @__PURE__ */ h("span", {
|
|
379
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground font-medium",
|
|
380
|
+
children: M
|
|
381
|
+
}), /* @__PURE__ */ h("input", {
|
|
252
382
|
type: "number",
|
|
253
|
-
value:
|
|
254
|
-
onChange: (e) =>
|
|
383
|
+
value: E.maxDiscountAmount || "",
|
|
384
|
+
onChange: (e) => P("maxDiscountAmount", e.target.value ? parseFloat(e.target.value) : null),
|
|
255
385
|
min: "0",
|
|
256
386
|
step: "0.01",
|
|
257
387
|
placeholder: "No maximum",
|
|
258
388
|
className: "w-full pl-10 pr-4 py-2 rounded-lg border border-border bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
|
|
259
389
|
})]
|
|
260
390
|
}),
|
|
261
|
-
/* @__PURE__ */
|
|
391
|
+
/* @__PURE__ */ g("p", {
|
|
262
392
|
className: "text-xs text-muted-foreground mt-1",
|
|
263
|
-
children:
|
|
393
|
+
children: [
|
|
394
|
+
"Cap the discount in ",
|
|
395
|
+
E.currency,
|
|
396
|
+
" — auto-converted to the user's payment currency"
|
|
397
|
+
]
|
|
264
398
|
})
|
|
265
399
|
] })
|
|
266
400
|
]
|
|
267
401
|
}),
|
|
268
|
-
/* @__PURE__ */
|
|
402
|
+
/* @__PURE__ */ g("div", {
|
|
269
403
|
className: "bg-card border border-border rounded-lg p-6 space-y-4",
|
|
270
404
|
children: [
|
|
271
|
-
/* @__PURE__ */
|
|
405
|
+
/* @__PURE__ */ h("h3", {
|
|
272
406
|
className: "text-lg font-semibold text-foreground",
|
|
273
407
|
children: "Usage Limits"
|
|
274
408
|
}),
|
|
275
|
-
/* @__PURE__ */
|
|
276
|
-
/* @__PURE__ */
|
|
409
|
+
/* @__PURE__ */ g("div", { children: [
|
|
410
|
+
/* @__PURE__ */ h("label", {
|
|
277
411
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
278
412
|
children: "Total Usage Limit"
|
|
279
413
|
}),
|
|
280
|
-
/* @__PURE__ */
|
|
414
|
+
/* @__PURE__ */ h("input", {
|
|
281
415
|
type: "number",
|
|
282
|
-
value:
|
|
283
|
-
onChange: (e) =>
|
|
416
|
+
value: E.maxTotalUses || "",
|
|
417
|
+
onChange: (e) => P("maxTotalUses", e.target.value ? parseInt(e.target.value) : null),
|
|
284
418
|
min: "1",
|
|
285
419
|
placeholder: "Unlimited",
|
|
286
420
|
className: "w-full px-4 py-2 rounded-lg border border-border bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
|
|
287
421
|
}),
|
|
288
|
-
/* @__PURE__ */
|
|
422
|
+
/* @__PURE__ */ h("p", {
|
|
289
423
|
className: "text-xs text-muted-foreground mt-1",
|
|
290
424
|
children: "Maximum number of times this coupon can be used across all users"
|
|
291
425
|
})
|
|
292
426
|
] }),
|
|
293
|
-
/* @__PURE__ */
|
|
294
|
-
/* @__PURE__ */
|
|
427
|
+
/* @__PURE__ */ g("div", { children: [
|
|
428
|
+
/* @__PURE__ */ h("label", {
|
|
295
429
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
296
430
|
children: "Per-User Limit *"
|
|
297
431
|
}),
|
|
298
|
-
/* @__PURE__ */
|
|
432
|
+
/* @__PURE__ */ h("input", {
|
|
299
433
|
type: "number",
|
|
300
|
-
value:
|
|
301
|
-
onChange: (e) =>
|
|
434
|
+
value: E.maxUsesPerUser,
|
|
435
|
+
onChange: (e) => P("maxUsesPerUser", parseInt(e.target.value)),
|
|
302
436
|
min: "1",
|
|
303
437
|
className: "w-full px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
|
|
304
438
|
}),
|
|
305
|
-
/* @__PURE__ */
|
|
439
|
+
/* @__PURE__ */ h("p", {
|
|
306
440
|
className: "text-xs text-muted-foreground mt-1",
|
|
307
441
|
children: "Maximum times a single user can use this coupon"
|
|
308
442
|
})
|
|
309
443
|
] })
|
|
310
444
|
]
|
|
311
445
|
}),
|
|
312
|
-
/* @__PURE__ */
|
|
446
|
+
/* @__PURE__ */ g("div", {
|
|
313
447
|
className: "bg-card border border-border rounded-lg p-6 space-y-4",
|
|
314
|
-
children: [/* @__PURE__ */
|
|
448
|
+
children: [/* @__PURE__ */ h("h3", {
|
|
315
449
|
className: "text-lg font-semibold text-foreground",
|
|
316
450
|
children: "Validity Period"
|
|
317
|
-
}), /* @__PURE__ */
|
|
451
|
+
}), /* @__PURE__ */ g("div", {
|
|
318
452
|
className: "grid grid-cols-1 md:grid-cols-2 gap-4",
|
|
319
|
-
children: [/* @__PURE__ */
|
|
320
|
-
/* @__PURE__ */
|
|
453
|
+
children: [/* @__PURE__ */ g("div", { children: [
|
|
454
|
+
/* @__PURE__ */ h("label", {
|
|
321
455
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
322
456
|
children: "Start Date *"
|
|
323
457
|
}),
|
|
324
|
-
/* @__PURE__ */
|
|
458
|
+
/* @__PURE__ */ h("input", {
|
|
325
459
|
type: "date",
|
|
326
|
-
value:
|
|
327
|
-
onChange: (e) =>
|
|
328
|
-
className: `w-full px-4 py-2 rounded-lg border ${
|
|
460
|
+
value: E.validFrom,
|
|
461
|
+
onChange: (e) => P("validFrom", e.target.value),
|
|
462
|
+
className: `w-full px-4 py-2 rounded-lg border ${O.validFrom ? "border-destructive" : "border-border"} bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20`
|
|
329
463
|
}),
|
|
330
|
-
|
|
464
|
+
O.validFrom && /* @__PURE__ */ h("p", {
|
|
331
465
|
className: "text-sm text-destructive mt-1",
|
|
332
|
-
children:
|
|
466
|
+
children: O.validFrom
|
|
333
467
|
})
|
|
334
|
-
] }), /* @__PURE__ */
|
|
335
|
-
/* @__PURE__ */
|
|
468
|
+
] }), /* @__PURE__ */ g("div", { children: [
|
|
469
|
+
/* @__PURE__ */ h("label", {
|
|
336
470
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
337
471
|
children: "End Date"
|
|
338
472
|
}),
|
|
339
|
-
/* @__PURE__ */
|
|
473
|
+
/* @__PURE__ */ h("input", {
|
|
340
474
|
type: "date",
|
|
341
|
-
value:
|
|
342
|
-
onChange: (e) =>
|
|
343
|
-
className: `w-full px-4 py-2 rounded-lg border ${
|
|
475
|
+
value: E.validUntil,
|
|
476
|
+
onChange: (e) => P("validUntil", e.target.value),
|
|
477
|
+
className: `w-full px-4 py-2 rounded-lg border ${O.validUntil ? "border-destructive" : "border-border"} bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20`
|
|
344
478
|
}),
|
|
345
|
-
|
|
479
|
+
O.validUntil && /* @__PURE__ */ h("p", {
|
|
346
480
|
className: "text-sm text-destructive mt-1",
|
|
347
|
-
children:
|
|
481
|
+
children: O.validUntil
|
|
348
482
|
}),
|
|
349
|
-
/* @__PURE__ */
|
|
483
|
+
/* @__PURE__ */ h("p", {
|
|
350
484
|
className: "text-xs text-muted-foreground mt-1",
|
|
351
485
|
children: "Leave empty for no expiry"
|
|
352
486
|
})
|
|
353
487
|
] })]
|
|
354
488
|
})]
|
|
355
489
|
}),
|
|
356
|
-
/* @__PURE__ */
|
|
490
|
+
/* @__PURE__ */ g("div", {
|
|
357
491
|
className: "bg-card border border-border rounded-lg p-6 space-y-4",
|
|
358
492
|
children: [
|
|
359
|
-
/* @__PURE__ */
|
|
493
|
+
/* @__PURE__ */ h("h3", {
|
|
360
494
|
className: "text-lg font-semibold text-foreground",
|
|
361
495
|
children: "Coupon Scope"
|
|
362
496
|
}),
|
|
363
|
-
/* @__PURE__ */
|
|
497
|
+
/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
364
498
|
className: "block text-sm font-medium text-foreground mb-2",
|
|
365
499
|
children: "Who can use this coupon? *"
|
|
366
|
-
}), /* @__PURE__ */
|
|
367
|
-
value:
|
|
368
|
-
onChange: (e) =>
|
|
500
|
+
}), /* @__PURE__ */ g("select", {
|
|
501
|
+
value: E.scope,
|
|
502
|
+
onChange: (e) => P("scope", e.target.value),
|
|
369
503
|
className: "w-full px-4 py-2 rounded-lg border border-border bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20",
|
|
370
504
|
children: [
|
|
371
|
-
/* @__PURE__ */
|
|
505
|
+
/* @__PURE__ */ h("option", {
|
|
372
506
|
value: "GENERIC",
|
|
373
507
|
children: "Anyone (Public)"
|
|
374
508
|
}),
|
|
375
|
-
/* @__PURE__ */
|
|
509
|
+
/* @__PURE__ */ h("option", {
|
|
376
510
|
value: "USER_SPECIFIC",
|
|
377
511
|
children: "Specific Users Only"
|
|
378
512
|
}),
|
|
379
|
-
/* @__PURE__ */
|
|
513
|
+
/* @__PURE__ */ h("option", {
|
|
380
514
|
value: "REFERRAL",
|
|
381
515
|
children: "Referral Code"
|
|
382
516
|
}),
|
|
383
|
-
/* @__PURE__ */
|
|
517
|
+
/* @__PURE__ */ h("option", {
|
|
384
518
|
value: "CAMPAIGN",
|
|
385
519
|
children: "Campaign-Specific"
|
|
386
520
|
})
|
|
387
521
|
]
|
|
388
522
|
})] }),
|
|
389
|
-
|
|
523
|
+
E.scope === "CAMPAIGN" && /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
390
524
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
391
525
|
children: "Campaign Name"
|
|
392
|
-
}), /* @__PURE__ */
|
|
526
|
+
}), /* @__PURE__ */ h("input", {
|
|
393
527
|
type: "text",
|
|
394
|
-
value:
|
|
395
|
-
onChange: (e) =>
|
|
528
|
+
value: E.campaignName,
|
|
529
|
+
onChange: (e) => P("campaignName", e.target.value),
|
|
396
530
|
placeholder: "e.g., Summer Sale 2024",
|
|
397
531
|
className: "w-full px-4 py-2 rounded-lg border border-border bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20"
|
|
398
|
-
})] })
|
|
532
|
+
})] }),
|
|
533
|
+
E.scope === "USER_SPECIFIC" && /* @__PURE__ */ g("div", { children: [
|
|
534
|
+
/* @__PURE__ */ h("label", {
|
|
535
|
+
className: "block text-sm font-medium text-foreground mb-1",
|
|
536
|
+
children: /* @__PURE__ */ g("span", {
|
|
537
|
+
className: "flex items-center gap-1.5",
|
|
538
|
+
children: [/* @__PURE__ */ h(f, { className: "size-4" }), "Restricted Users *"]
|
|
539
|
+
})
|
|
540
|
+
}),
|
|
541
|
+
/* @__PURE__ */ g("div", {
|
|
542
|
+
className: `min-h-[42px] flex flex-wrap gap-2 px-3 py-2 rounded-lg border ${O.restrictedToUserIds ? "border-destructive" : "border-border"} bg-background cursor-text`,
|
|
543
|
+
onClick: () => T.current?.focus(),
|
|
544
|
+
children: [E.restrictedToUserIds.map((e) => /* @__PURE__ */ g("span", {
|
|
545
|
+
className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-primary/10 text-primary text-sm font-medium",
|
|
546
|
+
children: [e, /* @__PURE__ */ h("button", {
|
|
547
|
+
type: "button",
|
|
548
|
+
onClick: (t) => {
|
|
549
|
+
t.stopPropagation(), L(e);
|
|
550
|
+
},
|
|
551
|
+
className: "hover:text-destructive",
|
|
552
|
+
children: /* @__PURE__ */ h(p, { className: "size-3" })
|
|
553
|
+
})]
|
|
554
|
+
}, e)), /* @__PURE__ */ h("input", {
|
|
555
|
+
ref: T,
|
|
556
|
+
type: "text",
|
|
557
|
+
value: C,
|
|
558
|
+
onChange: (e) => w(e.target.value),
|
|
559
|
+
onKeyDown: (e) => {
|
|
560
|
+
e.key === "Enter" || e.key === "," ? (e.preventDefault(), I(C)) : e.key === "Backspace" && !C && E.restrictedToUserIds.length > 0 && L(E.restrictedToUserIds[E.restrictedToUserIds.length - 1]);
|
|
561
|
+
},
|
|
562
|
+
onBlur: () => I(C),
|
|
563
|
+
placeholder: E.restrictedToUserIds.length === 0 ? "Enter user email or ID, press Enter to add" : "Add another…",
|
|
564
|
+
className: "flex-1 min-w-[200px] bg-transparent text-foreground placeholder:text-muted-foreground text-sm focus:outline-none"
|
|
565
|
+
})]
|
|
566
|
+
}),
|
|
567
|
+
O.restrictedToUserIds && /* @__PURE__ */ h("p", {
|
|
568
|
+
className: "text-sm text-destructive mt-1",
|
|
569
|
+
children: O.restrictedToUserIds
|
|
570
|
+
}),
|
|
571
|
+
/* @__PURE__ */ h("p", {
|
|
572
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
573
|
+
children: "Type an email or user ID and press Enter or comma to add. Only these users can redeem this coupon."
|
|
574
|
+
})
|
|
575
|
+
] })
|
|
399
576
|
]
|
|
400
577
|
}),
|
|
401
|
-
/* @__PURE__ */
|
|
578
|
+
/* @__PURE__ */ g("div", {
|
|
402
579
|
className: "flex items-center justify-end gap-3",
|
|
403
|
-
children: [/* @__PURE__ */
|
|
580
|
+
children: [/* @__PURE__ */ h("button", {
|
|
404
581
|
type: "button",
|
|
405
|
-
onClick: () =>
|
|
582
|
+
onClick: () => x("/coupons"),
|
|
406
583
|
className: "px-6 py-3 rounded-lg border border-border text-foreground hover:bg-muted",
|
|
407
584
|
children: "Cancel"
|
|
408
|
-
}), /* @__PURE__ */
|
|
585
|
+
}), /* @__PURE__ */ h("button", {
|
|
409
586
|
type: "submit",
|
|
410
|
-
disabled:
|
|
587
|
+
disabled: A,
|
|
411
588
|
className: "px-6 py-3 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
412
|
-
children:
|
|
589
|
+
children: A ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("div", { className: "size-4 border-2 border-primary-foreground border-t-transparent rounded-full animate-spin" }), "Creating…"] }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(u, { className: "size-4" }), "Create Coupon"] })
|
|
413
590
|
})]
|
|
414
591
|
})
|
|
415
592
|
]
|
|
@@ -417,6 +594,6 @@ var g = () => {
|
|
|
417
594
|
});
|
|
418
595
|
};
|
|
419
596
|
//#endregion
|
|
420
|
-
export {
|
|
597
|
+
export { y as CreateCouponPage };
|
|
421
598
|
|
|
422
599
|
//# sourceMappingURL=CreateCouponPage.js.map
|