payment-kit 1.18.55 → 1.19.0
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/.eslintrc.js +6 -0
- package/api/src/libs/queue/index.ts +1 -3
- package/blocklet.yml +1 -1
- package/package.json +57 -58
- package/src/components/actions.tsx +22 -9
- package/src/components/balance-list.tsx +40 -12
- package/src/components/collapse.tsx +22 -14
- package/src/components/copyable.tsx +8 -7
- package/src/components/currency.tsx +15 -7
- package/src/components/customer/actions.tsx +1 -5
- package/src/components/customer/form.tsx +3 -1
- package/src/components/customer/link.tsx +4 -12
- package/src/components/customer/notification-preference.tsx +18 -9
- package/src/components/customer/overdraft-protection.tsx +112 -41
- package/src/components/drawer-form.tsx +42 -18
- package/src/components/error.tsx +1 -5
- package/src/components/event/list.tsx +9 -10
- package/src/components/filter-toolbar.tsx +20 -19
- package/src/components/info-card.tsx +32 -18
- package/src/components/info-metric.tsx +16 -6
- package/src/components/info-row-group.tsx +1 -7
- package/src/components/info-row.tsx +30 -24
- package/src/components/invoice/action.tsx +1 -7
- package/src/components/invoice/list.tsx +15 -25
- package/src/components/invoice/recharge.tsx +5 -7
- package/src/components/invoice/table.tsx +17 -12
- package/src/components/layout/user.tsx +1 -1
- package/src/components/metadata/form.tsx +13 -13
- package/src/components/metadata/list.tsx +11 -3
- package/src/components/passport/actions.tsx +9 -4
- package/src/components/payment-currency/add.tsx +16 -3
- package/src/components/payment-currency/form.tsx +12 -6
- package/src/components/payment-intent/actions.tsx +24 -16
- package/src/components/payment-intent/list.tsx +11 -8
- package/src/components/payment-link/actions.tsx +1 -5
- package/src/components/payment-link/after-pay.tsx +4 -2
- package/src/components/payment-link/before-pay.tsx +14 -4
- package/src/components/payment-link/item.tsx +27 -6
- package/src/components/payment-link/preview.tsx +9 -9
- package/src/components/payment-link/product-select.tsx +17 -3
- package/src/components/payment-method/arcblock.tsx +6 -1
- package/src/components/payment-method/base.tsx +6 -1
- package/src/components/payment-method/bitcoin.tsx +6 -1
- package/src/components/payment-method/ethereum.tsx +6 -1
- package/src/components/payment-method/evm-rpc-input.tsx +11 -7
- package/src/components/payment-method/form.tsx +2 -7
- package/src/components/payouts/actions.tsx +1 -5
- package/src/components/payouts/list.tsx +11 -9
- package/src/components/payouts/portal/list.tsx +11 -9
- package/src/components/price/currency-select.tsx +28 -17
- package/src/components/price/form.tsx +135 -84
- package/src/components/price/upsell-select.tsx +10 -2
- package/src/components/price/upsell.tsx +7 -2
- package/src/components/pricing-table/actions.tsx +1 -5
- package/src/components/pricing-table/customer-settings.tsx +5 -1
- package/src/components/pricing-table/payment-settings.tsx +14 -4
- package/src/components/pricing-table/preview.tsx +9 -9
- package/src/components/pricing-table/price-item.tsx +6 -1
- package/src/components/pricing-table/product-item.tsx +6 -1
- package/src/components/pricing-table/product-settings.tsx +17 -4
- package/src/components/product/actions.tsx +1 -5
- package/src/components/product/create.tsx +1 -5
- package/src/components/product/cross-sell-select.tsx +5 -1
- package/src/components/product/cross-sell.tsx +7 -2
- package/src/components/product/features.tsx +13 -3
- package/src/components/product/form.tsx +38 -10
- package/src/components/progress-bar.tsx +1 -1
- package/src/components/refund/actions.tsx +1 -7
- package/src/components/refund/list.tsx +12 -17
- package/src/components/section/header.tsx +23 -12
- package/src/components/subscription/actions/cancel.tsx +22 -5
- package/src/components/subscription/actions/index.tsx +9 -10
- package/src/components/subscription/actions/pause.tsx +32 -6
- package/src/components/subscription/actions/slash-stake.tsx +5 -3
- package/src/components/subscription/description.tsx +12 -8
- package/src/components/subscription/items/index.tsx +30 -15
- package/src/components/subscription/items/usage-records.tsx +19 -5
- package/src/components/subscription/list.tsx +5 -7
- package/src/components/subscription/metrics.tsx +27 -12
- package/src/components/subscription/portal/actions.tsx +76 -70
- package/src/components/subscription/portal/cancel.tsx +10 -3
- package/src/components/subscription/portal/list.tsx +48 -26
- package/src/components/uploader.tsx +5 -13
- package/src/components/webhook/attempts.tsx +51 -16
- package/src/components/webhook/request-info.tsx +8 -6
- package/src/contexts/products.tsx +1 -1
- package/src/pages/admin/billing/invoices/detail.tsx +48 -12
- package/src/pages/admin/billing/subscriptions/detail.tsx +43 -11
- package/src/pages/admin/customers/customers/detail.tsx +53 -12
- package/src/pages/admin/customers/customers/index.tsx +6 -1
- package/src/pages/admin/developers/events/detail.tsx +36 -10
- package/src/pages/admin/developers/webhooks/detail.tsx +41 -11
- package/src/pages/admin/index.tsx +15 -2
- package/src/pages/admin/overview.tsx +107 -19
- package/src/pages/admin/payments/intents/detail.tsx +57 -13
- package/src/pages/admin/payments/payouts/detail.tsx +62 -14
- package/src/pages/admin/payments/refunds/detail.tsx +57 -13
- package/src/pages/admin/products/index.tsx +8 -2
- package/src/pages/admin/products/links/create.tsx +22 -4
- package/src/pages/admin/products/links/detail.tsx +42 -13
- package/src/pages/admin/products/passports/index.tsx +23 -4
- package/src/pages/admin/products/prices/actions.tsx +1 -6
- package/src/pages/admin/products/prices/detail.tsx +43 -11
- package/src/pages/admin/products/prices/list.tsx +7 -2
- package/src/pages/admin/products/pricing-tables/create.tsx +45 -12
- package/src/pages/admin/products/pricing-tables/detail.tsx +44 -13
- package/src/pages/admin/products/products/create.tsx +4 -1
- package/src/pages/admin/products/products/detail.tsx +72 -17
- package/src/pages/admin/settings/index.tsx +8 -1
- package/src/pages/admin/settings/payment-methods/index.tsx +84 -19
- package/src/pages/admin/settings/vault-config/edit-form.tsx +42 -28
- package/src/pages/admin/settings/vault-config/index.tsx +57 -10
- package/src/pages/customer/index.tsx +41 -15
- package/src/pages/customer/invoice/detail.tsx +63 -14
- package/src/pages/customer/invoice/past-due.tsx +11 -3
- package/src/pages/customer/payout/detail.tsx +56 -13
- package/src/pages/customer/recharge/account.tsx +80 -20
- package/src/pages/customer/recharge/subscription.tsx +86 -25
- package/src/pages/customer/refund/list.tsx +60 -24
- package/src/pages/customer/subscription/change-payment.tsx +13 -4
- package/src/pages/customer/subscription/change-plan.tsx +34 -7
- package/src/pages/customer/subscription/detail.tsx +86 -20
- package/src/pages/customer/subscription/embed.tsx +24 -4
- package/src/pages/home.tsx +26 -4
- package/src/pages/integrations/donations/edit-form.tsx +25 -9
- package/src/pages/integrations/donations/index.tsx +26 -9
- package/src/pages/integrations/donations/preview.tsx +59 -15
- package/src/pages/integrations/index.tsx +10 -1
- package/src/pages/integrations/overview.tsx +78 -17
- package/vite.config.ts +60 -30
|
@@ -75,11 +75,6 @@ type PriceFormProps = {
|
|
|
75
75
|
simple?: boolean;
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
PriceForm.defaultProps = {
|
|
79
|
-
prefix: '',
|
|
80
|
-
simple: false,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
78
|
const INPUT_WIDTH = 260;
|
|
84
79
|
|
|
85
80
|
const hasMoreCurrency = (methods: TPaymentMethodExpanded[] = []) => {
|
|
@@ -96,7 +91,7 @@ function stripeCurrencyValidate(v: number, currency: TPaymentCurrencyExpanded |
|
|
|
96
91
|
return true;
|
|
97
92
|
}
|
|
98
93
|
|
|
99
|
-
export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
94
|
+
export default function PriceForm({ prefix = '', simple = false }: PriceFormProps) {
|
|
100
95
|
const getFieldName = (name: string) => (prefix ? `${prefix}.${name}` : name);
|
|
101
96
|
|
|
102
97
|
const { t, locale } = useLocaleContext();
|
|
@@ -200,8 +195,17 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
200
195
|
render={({ field }) => (
|
|
201
196
|
<Box>
|
|
202
197
|
<FormLabel sx={{ color: 'text.primary' }}>
|
|
203
|
-
<Stack
|
|
204
|
-
|
|
198
|
+
<Stack
|
|
199
|
+
direction="row"
|
|
200
|
+
spacing={0.5}
|
|
201
|
+
sx={{
|
|
202
|
+
alignItems: 'center',
|
|
203
|
+
}}>
|
|
204
|
+
<Typography
|
|
205
|
+
component="span"
|
|
206
|
+
sx={{
|
|
207
|
+
color: 'text.primary',
|
|
208
|
+
}}>
|
|
205
209
|
{t('admin.price.amount')}
|
|
206
210
|
</Typography>
|
|
207
211
|
<Tooltip title={t('admin.price.amountTip')} placement="top" arrow>
|
|
@@ -216,33 +220,6 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
216
220
|
sx={{ width: INPUT_WIDTH }}
|
|
217
221
|
error={!!getFieldError(getFieldName('unit_amount'))}
|
|
218
222
|
helperText={getFieldError(getFieldName('unit_amount'))?.message}
|
|
219
|
-
InputProps={{
|
|
220
|
-
endAdornment: (
|
|
221
|
-
<InputAdornment position="end">
|
|
222
|
-
<CurrencySelect
|
|
223
|
-
mode="selected"
|
|
224
|
-
hasSelected={(currency) =>
|
|
225
|
-
currencies.fields.some((x: any) => x.currency_id === currency.id) ||
|
|
226
|
-
currency.id === defaultCurrencyId
|
|
227
|
-
}
|
|
228
|
-
onSelect={(currencyId) => {
|
|
229
|
-
const index = currencies.fields.findIndex((x: any) => x.currency_id === defaultCurrencyId);
|
|
230
|
-
if (index > -1) {
|
|
231
|
-
// @ts-ignore
|
|
232
|
-
handleCurrencyChange(index, currencyId);
|
|
233
|
-
}
|
|
234
|
-
setValue(getFieldName('currency'), findCurrency(settings.paymentMethods, currencyId), {
|
|
235
|
-
shouldValidate: true,
|
|
236
|
-
});
|
|
237
|
-
setValue(getFieldName('currency_id'), currencyId, { shouldValidate: true });
|
|
238
|
-
}}
|
|
239
|
-
value={defaultCurrencyId}
|
|
240
|
-
disabled={isLocked}
|
|
241
|
-
selectSX={{ '.MuiOutlinedInput-notchedOutline': { border: 'none' } }}
|
|
242
|
-
/>
|
|
243
|
-
</InputAdornment>
|
|
244
|
-
),
|
|
245
|
-
}}
|
|
246
223
|
onChange={(e) => {
|
|
247
224
|
const { value } = e.target;
|
|
248
225
|
field.onChange(value);
|
|
@@ -252,6 +229,35 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
252
229
|
}
|
|
253
230
|
setValue(getFieldName(`currency_options.${index}.unit_amount`), value, { shouldValidate: true });
|
|
254
231
|
}}
|
|
232
|
+
slotProps={{
|
|
233
|
+
input: {
|
|
234
|
+
endAdornment: (
|
|
235
|
+
<InputAdornment position="end">
|
|
236
|
+
<CurrencySelect
|
|
237
|
+
mode="selected"
|
|
238
|
+
hasSelected={(currency) =>
|
|
239
|
+
currencies.fields.some((x: any) => x.currency_id === currency.id) ||
|
|
240
|
+
currency.id === defaultCurrencyId
|
|
241
|
+
}
|
|
242
|
+
onSelect={(currencyId) => {
|
|
243
|
+
const index = currencies.fields.findIndex((x: any) => x.currency_id === defaultCurrencyId);
|
|
244
|
+
if (index > -1) {
|
|
245
|
+
// @ts-ignore
|
|
246
|
+
handleCurrencyChange(index, currencyId);
|
|
247
|
+
}
|
|
248
|
+
setValue(getFieldName('currency'), findCurrency(settings.paymentMethods, currencyId), {
|
|
249
|
+
shouldValidate: true,
|
|
250
|
+
});
|
|
251
|
+
setValue(getFieldName('currency_id'), currencyId, { shouldValidate: true });
|
|
252
|
+
}}
|
|
253
|
+
value={defaultCurrencyId}
|
|
254
|
+
disabled={isLocked}
|
|
255
|
+
selectSX={{ '.MuiOutlinedInput-notchedOutline': { border: 'none' } }}
|
|
256
|
+
/>
|
|
257
|
+
</InputAdornment>
|
|
258
|
+
),
|
|
259
|
+
},
|
|
260
|
+
}}
|
|
255
261
|
/>
|
|
256
262
|
</Box>
|
|
257
263
|
)}
|
|
@@ -262,16 +268,21 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
262
268
|
control={control}
|
|
263
269
|
disabled={isLocked}
|
|
264
270
|
render={({ field }) => (
|
|
265
|
-
<Box
|
|
271
|
+
<Box
|
|
272
|
+
sx={{
|
|
273
|
+
ml: 2,
|
|
274
|
+
}}>
|
|
266
275
|
<FormLabel> </FormLabel>
|
|
267
276
|
<TextField
|
|
268
277
|
{...field}
|
|
269
278
|
type="number"
|
|
270
279
|
size="small"
|
|
271
280
|
sx={{ width: INPUT_WIDTH }}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
slotProps={{
|
|
282
|
+
input: {
|
|
283
|
+
startAdornment: <InputAdornment position="start">{t('common.per')}</InputAdornment>,
|
|
284
|
+
endAdornment: <InputAdornment position="end">{t('common.unit')}</InputAdornment>,
|
|
285
|
+
},
|
|
275
286
|
}}
|
|
276
287
|
/>
|
|
277
288
|
</Box>
|
|
@@ -288,7 +299,13 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
288
299
|
const fieldName = getFieldName(`currency_options.${index}.unit_amount`);
|
|
289
300
|
const currency = findCurrency(settings.paymentMethods, item.currency_id);
|
|
290
301
|
return (
|
|
291
|
-
<Stack
|
|
302
|
+
<Stack
|
|
303
|
+
key={item.currency_id}
|
|
304
|
+
direction="row"
|
|
305
|
+
spacing={1}
|
|
306
|
+
sx={{
|
|
307
|
+
alignItems: 'start',
|
|
308
|
+
}}>
|
|
292
309
|
<Controller
|
|
293
310
|
name={fieldName}
|
|
294
311
|
control={control}
|
|
@@ -312,30 +329,32 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
312
329
|
sx={{ width: INPUT_WIDTH }}
|
|
313
330
|
error={!!getFieldError(fieldName)}
|
|
314
331
|
helperText={getFieldError(fieldName)?.message as string}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
<
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
onSelect={(currencyId) => {
|
|
325
|
-
const cIndex = currencies.fields.findIndex(
|
|
326
|
-
(x: any) => x.currency_id === currency?.id
|
|
327
|
-
);
|
|
328
|
-
if (cIndex > -1) {
|
|
329
|
-
// @ts-ignore
|
|
330
|
-
handleCurrencyChange(cIndex, currencyId);
|
|
332
|
+
slotProps={{
|
|
333
|
+
input: {
|
|
334
|
+
endAdornment: (
|
|
335
|
+
<InputAdornment position="end">
|
|
336
|
+
<CurrencySelect
|
|
337
|
+
mode="selected"
|
|
338
|
+
hasSelected={(c) =>
|
|
339
|
+
currencies.fields.some((x: any) => x.currency_id === c.id) ||
|
|
340
|
+
c.id === defaultCurrencyId
|
|
331
341
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
342
|
+
onSelect={(currencyId) => {
|
|
343
|
+
const cIndex = currencies.fields.findIndex(
|
|
344
|
+
(x: any) => x.currency_id === currency?.id
|
|
345
|
+
);
|
|
346
|
+
if (cIndex > -1) {
|
|
347
|
+
// @ts-ignore
|
|
348
|
+
handleCurrencyChange(cIndex, currencyId);
|
|
349
|
+
}
|
|
350
|
+
}}
|
|
351
|
+
value={currency?.id!}
|
|
352
|
+
disabled={isLocked}
|
|
353
|
+
selectSX={{ '.MuiOutlinedInput-notchedOutline': { border: 'none' } }}
|
|
354
|
+
/>
|
|
355
|
+
</InputAdornment>
|
|
356
|
+
),
|
|
357
|
+
},
|
|
339
358
|
}}
|
|
340
359
|
/>
|
|
341
360
|
);
|
|
@@ -447,7 +466,10 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
447
466
|
},
|
|
448
467
|
}}
|
|
449
468
|
render={({ field }) => (
|
|
450
|
-
<Box
|
|
469
|
+
<Box
|
|
470
|
+
sx={{
|
|
471
|
+
ml: 2,
|
|
472
|
+
}}>
|
|
451
473
|
<FormLabel> </FormLabel>
|
|
452
474
|
<TextField
|
|
453
475
|
{...field}
|
|
@@ -456,21 +478,23 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
456
478
|
sx={{ width: INPUT_WIDTH }}
|
|
457
479
|
error={!!get(errors, getFieldName('recurring.interval_count'))}
|
|
458
480
|
helperText={get(errors, getFieldName('recurring.interval_count'))?.message as string}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
<
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
481
|
+
slotProps={{
|
|
482
|
+
input: {
|
|
483
|
+
startAdornment: <InputAdornment position="start">{t('common.every')}</InputAdornment>,
|
|
484
|
+
endAdornment: (
|
|
485
|
+
<InputAdornment position="end">
|
|
486
|
+
<select
|
|
487
|
+
onChange={(e) => setValue(getFieldName('recurring.interval'), e.target.value)}
|
|
488
|
+
value={intervalSelectValue}
|
|
489
|
+
style={{ background: 'none', outline: 'none' }}>
|
|
490
|
+
<option value="day">{t('common.days')}</option>
|
|
491
|
+
<option value="week">{t('common.weeks')}</option>
|
|
492
|
+
<option value="month">{t('common.months')}</option>
|
|
493
|
+
<option value="year">{t('common.years')}</option>
|
|
494
|
+
</select>
|
|
495
|
+
</InputAdornment>
|
|
496
|
+
),
|
|
497
|
+
},
|
|
474
498
|
}}
|
|
475
499
|
/>
|
|
476
500
|
</Box>
|
|
@@ -496,8 +520,17 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
496
520
|
}
|
|
497
521
|
label={
|
|
498
522
|
<Stack>
|
|
499
|
-
<Typography
|
|
500
|
-
|
|
523
|
+
<Typography
|
|
524
|
+
sx={{
|
|
525
|
+
color: 'text.primary',
|
|
526
|
+
}}>
|
|
527
|
+
{t('admin.price.recurring.metered')}
|
|
528
|
+
</Typography>
|
|
529
|
+
<Typography
|
|
530
|
+
sx={{
|
|
531
|
+
color: 'text.secondary',
|
|
532
|
+
maxWidth: '80%',
|
|
533
|
+
}}>
|
|
501
534
|
{t('admin.price.recurring.meteredTip')}
|
|
502
535
|
</Typography>
|
|
503
536
|
</Stack>
|
|
@@ -526,7 +559,11 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
526
559
|
)}
|
|
527
560
|
{!simple && (
|
|
528
561
|
<Collapse trigger={t('admin.price.additional')} expanded={isLocked}>
|
|
529
|
-
<Stack
|
|
562
|
+
<Stack
|
|
563
|
+
spacing={2}
|
|
564
|
+
sx={{
|
|
565
|
+
alignItems: 'flex-start',
|
|
566
|
+
}}>
|
|
530
567
|
<Controller
|
|
531
568
|
name={getFieldName('quantity_available')}
|
|
532
569
|
control={control}
|
|
@@ -577,7 +614,14 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
577
614
|
render={({ field }) => (
|
|
578
615
|
<Box>
|
|
579
616
|
<FormLabel sx={{ color: 'text.primary' }}>{t('admin.price.nickname.label')}</FormLabel>
|
|
580
|
-
<TextField
|
|
617
|
+
<TextField
|
|
618
|
+
{...field}
|
|
619
|
+
size="small"
|
|
620
|
+
sx={{ width: INPUT_WIDTH }}
|
|
621
|
+
slotProps={{
|
|
622
|
+
htmlInput: { maxLength: 64 },
|
|
623
|
+
}}
|
|
624
|
+
/>
|
|
581
625
|
</Box>
|
|
582
626
|
)}
|
|
583
627
|
/>
|
|
@@ -593,7 +637,14 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
|
|
|
593
637
|
render={({ field }) => (
|
|
594
638
|
<Box>
|
|
595
639
|
<FormLabel sx={{ color: 'text.primary' }}>{t('admin.price.lookup_key.label')}</FormLabel>
|
|
596
|
-
<TextField
|
|
640
|
+
<TextField
|
|
641
|
+
{...field}
|
|
642
|
+
size="small"
|
|
643
|
+
sx={{ width: INPUT_WIDTH }}
|
|
644
|
+
slotProps={{
|
|
645
|
+
htmlInput: { maxLength: 64 },
|
|
646
|
+
}}
|
|
647
|
+
/>
|
|
597
648
|
</Box>
|
|
598
649
|
)}
|
|
599
650
|
/>
|
|
@@ -81,12 +81,20 @@ export default function UpsellSelect({ price, onSelect, onAdd }: Props) {
|
|
|
81
81
|
onChange={onSelectPrice}
|
|
82
82
|
MenuProps={{ style: { maxHeight: 480 } }}>
|
|
83
83
|
<MenuItem value="empty">
|
|
84
|
-
<Stack
|
|
84
|
+
<Stack
|
|
85
|
+
direction="row"
|
|
86
|
+
sx={{
|
|
87
|
+
alignItems: 'center',
|
|
88
|
+
}}>
|
|
85
89
|
<Typography>{t('admin.price.find')}</Typography>
|
|
86
90
|
</Stack>
|
|
87
91
|
</MenuItem>
|
|
88
92
|
<MenuItem value="add">
|
|
89
|
-
<Stack
|
|
93
|
+
<Stack
|
|
94
|
+
direction="row"
|
|
95
|
+
sx={{
|
|
96
|
+
alignItems: 'center',
|
|
97
|
+
}}>
|
|
90
98
|
<AddOutlined />
|
|
91
99
|
<Typography>{t('admin.price.add')}</Typography>
|
|
92
100
|
</Stack>
|
|
@@ -48,7 +48,12 @@ export function UpsellForm({ data, onChange }: { data: TPriceExpanded; onChange:
|
|
|
48
48
|
|
|
49
49
|
if (data.upsell?.upsells_to_id) {
|
|
50
50
|
return (
|
|
51
|
-
<Stack
|
|
51
|
+
<Stack
|
|
52
|
+
spacing={1}
|
|
53
|
+
direction="row"
|
|
54
|
+
sx={{
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
}}>
|
|
52
57
|
<Typography>{formatPrice(data.upsell.upsells_to, defaultCurrency)}</Typography>
|
|
53
58
|
<IconButton size="small" sx={{ ml: 1 }} onClick={onRemoveUpsell}>
|
|
54
59
|
<DeleteOutlineOutlined color="error" sx={{ opacity: 0.75 }} />
|
|
@@ -63,7 +68,7 @@ export function UpsellForm({ data, onChange }: { data: TPriceExpanded; onChange:
|
|
|
63
68
|
export default function PriceUpsell({ data, onChange }: { data: TPriceExpanded; onChange: Function }) {
|
|
64
69
|
return (
|
|
65
70
|
<Grid container>
|
|
66
|
-
<Grid
|
|
71
|
+
<Grid size={{ xs: 12, md: 12 }}>
|
|
67
72
|
<InfoRow label="" value={<UpsellForm data={data} onChange={onChange} />} showLabel={false} />
|
|
68
73
|
</Grid>
|
|
69
74
|
</Grid>
|
|
@@ -18,11 +18,7 @@ type Props = {
|
|
|
18
18
|
variant?: LiteralUnion<'compact' | 'normal', string>;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
PricingTableActions
|
|
22
|
-
variant: 'compact',
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export default function PricingTableActions({ data, variant, onChange }: Props) {
|
|
21
|
+
export default function PricingTableActions({ data, variant = 'compact', onChange }: Props) {
|
|
26
22
|
const { t } = useLocaleContext();
|
|
27
23
|
const [state, setState] = useSetState({
|
|
28
24
|
action: '',
|
|
@@ -5,7 +5,11 @@ export default function PricingTableCustomerSettings() {
|
|
|
5
5
|
const { t } = useLocaleContext();
|
|
6
6
|
|
|
7
7
|
return (
|
|
8
|
-
<Stack
|
|
8
|
+
<Stack
|
|
9
|
+
spacing={2}
|
|
10
|
+
sx={{
|
|
11
|
+
alignItems: 'flex-start',
|
|
12
|
+
}}>
|
|
9
13
|
<Typography variant="h6" sx={{ mb: 2, fontWeight: 600 }}>
|
|
10
14
|
{t('admin.pricingTable.customer')}
|
|
11
15
|
</Typography>
|
|
@@ -27,7 +27,11 @@ export function PricePaymentSettings({ index }: { index: number }) {
|
|
|
27
27
|
const values = getValues();
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
|
-
<Stack
|
|
30
|
+
<Stack
|
|
31
|
+
spacing={2}
|
|
32
|
+
sx={{
|
|
33
|
+
mb: 2,
|
|
34
|
+
}}>
|
|
31
35
|
<Controller
|
|
32
36
|
name={getFieldName('billing_address_collection')}
|
|
33
37
|
control={control}
|
|
@@ -126,8 +130,10 @@ export function PricePaymentSettings({ index }: { index: number }) {
|
|
|
126
130
|
size="small"
|
|
127
131
|
error={!!get(errors, field.name)}
|
|
128
132
|
helperText={(get(errors, field.name)?.message as string) || t('admin.paymentLink.customMessageTip')}
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
slotProps={{
|
|
134
|
+
htmlInput: {
|
|
135
|
+
maxLength: 200,
|
|
136
|
+
},
|
|
131
137
|
}}
|
|
132
138
|
/>
|
|
133
139
|
)}
|
|
@@ -259,7 +265,11 @@ export default function PricingTablePaymentSettings() {
|
|
|
259
265
|
const grouped = groupPricingTableItems(items.fields);
|
|
260
266
|
|
|
261
267
|
return (
|
|
262
|
-
<Stack
|
|
268
|
+
<Stack
|
|
269
|
+
spacing={2}
|
|
270
|
+
sx={{
|
|
271
|
+
alignItems: 'flex-start',
|
|
272
|
+
}}>
|
|
263
273
|
<Typography variant="h6" sx={{ mb: 2, fontWeight: 600 }}>
|
|
264
274
|
{t('admin.paymentLink.products')}
|
|
265
275
|
</Typography>
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
2
2
|
import { useFullscreen, useSize } from 'ahooks';
|
|
3
3
|
import IframeResizer from 'iframe-resizer-react';
|
|
4
4
|
import { useTheme } from '@mui/material';
|
|
5
5
|
import Chrome from '../payment-link/chrome';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export default function PricingTablePreview({
|
|
8
|
+
ref = undefined,
|
|
9
|
+
id,
|
|
10
|
+
version = 1,
|
|
11
|
+
}: { id: string; version?: number } & {
|
|
12
|
+
ref?: React.RefObject<unknown>;
|
|
13
|
+
}) {
|
|
8
14
|
const innerRef = useRef(null);
|
|
9
15
|
const size = useSize(innerRef);
|
|
10
16
|
const theme = useTheme();
|
|
@@ -50,10 +56,4 @@ const PricingTablePreview = forwardRef(({ id, version = 1 }: { id: string; versi
|
|
|
50
56
|
)}
|
|
51
57
|
</div>
|
|
52
58
|
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
PricingTablePreview.defaultProps = {
|
|
56
|
-
version: 1,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default PricingTablePreview;
|
|
59
|
+
}
|
|
@@ -26,7 +26,12 @@ export default function PriceItem({ prefix, price, onRemove }: Props) {
|
|
|
26
26
|
const currency = findCurrency(settings.paymentMethods, price?.currency_id ?? '') || settings.baseCurrency;
|
|
27
27
|
return (
|
|
28
28
|
<Box sx={{ width: '100%' }}>
|
|
29
|
-
<Stack
|
|
29
|
+
<Stack
|
|
30
|
+
direction="row"
|
|
31
|
+
sx={{
|
|
32
|
+
alignItems: 'center',
|
|
33
|
+
justifyContent: 'space-between',
|
|
34
|
+
}}>
|
|
30
35
|
<Typography>{formatPrice(price, currency!)}</Typography>
|
|
31
36
|
<IconButton size="small" onClick={onRemove}>
|
|
32
37
|
<DeleteOutlineOutlined color="inherit" sx={{ opacity: 0.75 }} />
|
|
@@ -63,7 +63,12 @@ export default function ProductItem({ product, prices, valid, onUpdate, onRemove
|
|
|
63
63
|
/>
|
|
64
64
|
</ClickBoundary>
|
|
65
65
|
<InfoCard logo={product.images[0]} name={product.name} description={product.description} />
|
|
66
|
-
<Stack
|
|
66
|
+
<Stack
|
|
67
|
+
direction="column"
|
|
68
|
+
spacing={2}
|
|
69
|
+
sx={{
|
|
70
|
+
alignItems: 'flex-start',
|
|
71
|
+
}}>
|
|
67
72
|
{prices.map((x: any) => (
|
|
68
73
|
<PriceItem
|
|
69
74
|
key={x.index}
|
|
@@ -14,7 +14,7 @@ import ProductItem from './product-item';
|
|
|
14
14
|
export default function PricingTableProductSettings({
|
|
15
15
|
triggerError = () => {},
|
|
16
16
|
}: {
|
|
17
|
-
triggerError
|
|
17
|
+
triggerError?: (keys: { [key: string]: boolean }) => void;
|
|
18
18
|
}) {
|
|
19
19
|
const { t } = useLocaleContext();
|
|
20
20
|
const [params, setParams] = useSearchParams();
|
|
@@ -121,7 +121,11 @@ export default function PricingTableProductSettings({
|
|
|
121
121
|
}, [items.fields, products]);
|
|
122
122
|
|
|
123
123
|
return (
|
|
124
|
-
<Stack
|
|
124
|
+
<Stack
|
|
125
|
+
spacing={2}
|
|
126
|
+
sx={{
|
|
127
|
+
alignItems: 'flex-start',
|
|
128
|
+
}}>
|
|
125
129
|
<Typography variant="h6" sx={{ mb: 2, fontWeight: 600 }}>
|
|
126
130
|
{t('admin.paymentLink.products')}
|
|
127
131
|
</Typography>
|
|
@@ -148,7 +152,11 @@ export default function PricingTableProductSettings({
|
|
|
148
152
|
);
|
|
149
153
|
})}
|
|
150
154
|
{items.fields.some((_, index) => !isPriceCurrencyAligned(items.fields as any[], products, index)) && (
|
|
151
|
-
<Typography
|
|
155
|
+
<Typography
|
|
156
|
+
color="error"
|
|
157
|
+
sx={{
|
|
158
|
+
fontSize: 'small',
|
|
159
|
+
}}>
|
|
152
160
|
{t('admin.paymentLink.currencyNotAligned')}
|
|
153
161
|
</Typography>
|
|
154
162
|
)}
|
|
@@ -188,7 +196,12 @@ export default function PricingTableProductSettings({
|
|
|
188
196
|
)}
|
|
189
197
|
/>
|
|
190
198
|
{highlight && (
|
|
191
|
-
<Stack
|
|
199
|
+
<Stack
|
|
200
|
+
direction="row"
|
|
201
|
+
spacing={0.5}
|
|
202
|
+
sx={{
|
|
203
|
+
alignItems: 'center',
|
|
204
|
+
}}>
|
|
192
205
|
<Controller
|
|
193
206
|
name="highlight_product_id"
|
|
194
207
|
control={control}
|
|
@@ -17,11 +17,7 @@ type ProductActionProps = {
|
|
|
17
17
|
variant?: LiteralUnion<'compact' | 'normal', string>;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
ProductActions
|
|
21
|
-
variant: 'compact',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default function ProductActions({ data, variant, onChange }: ProductActionProps) {
|
|
20
|
+
export default function ProductActions({ data, variant = 'compact', onChange }: ProductActionProps) {
|
|
25
21
|
const isLocked = data.locked || (!isEmpty(data.prices) && data.prices.some((x) => x.locked));
|
|
26
22
|
const { t } = useLocaleContext();
|
|
27
23
|
const [state, setState] = useSetState({
|
|
@@ -11,7 +11,7 @@ import PriceForm, { DEFAULT_PRICE } from '../price/form';
|
|
|
11
11
|
import ProductForm, { Product } from './form';
|
|
12
12
|
|
|
13
13
|
export default function CreateProduct({
|
|
14
|
-
simple,
|
|
14
|
+
simple = true,
|
|
15
15
|
onSave,
|
|
16
16
|
onCancel,
|
|
17
17
|
}: {
|
|
@@ -100,7 +100,3 @@ export default function CreateProduct({
|
|
|
100
100
|
</Dialog>
|
|
101
101
|
);
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
CreateProduct.defaultProps = {
|
|
105
|
-
simple: true,
|
|
106
|
-
};
|
|
@@ -39,7 +39,11 @@ export default function CrossSellSelect({ data, onSelect, valid }: Props) {
|
|
|
39
39
|
onChange={onSelectPrice}
|
|
40
40
|
MenuProps={{ style: { maxHeight: 480 } }}>
|
|
41
41
|
<MenuItem value="empty">
|
|
42
|
-
<Stack
|
|
42
|
+
<Stack
|
|
43
|
+
direction="row"
|
|
44
|
+
sx={{
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
}}>
|
|
43
47
|
<Typography>{t('admin.product.find')}</Typography>
|
|
44
48
|
</Stack>
|
|
45
49
|
</MenuItem>
|
|
@@ -64,7 +64,12 @@ export function CrossSellForm({ data, onChange }: { data: TProductExpanded; onCh
|
|
|
64
64
|
if (data.cross_sell?.cross_sells_to_id) {
|
|
65
65
|
const to = data.cross_sell.cross_sells_to;
|
|
66
66
|
return (
|
|
67
|
-
<Stack
|
|
67
|
+
<Stack
|
|
68
|
+
spacing={1}
|
|
69
|
+
direction="row"
|
|
70
|
+
sx={{
|
|
71
|
+
alignItems: 'center',
|
|
72
|
+
}}>
|
|
68
73
|
<InfoCard
|
|
69
74
|
name={to.name}
|
|
70
75
|
description={formatProductPrice(to as any, defaultCurrency, locale)}
|
|
@@ -91,7 +96,7 @@ export default function ProductCrossSell({ data, onChange }: { data: TProductExp
|
|
|
91
96
|
return (
|
|
92
97
|
<ProductsProvider>
|
|
93
98
|
<Grid container>
|
|
94
|
-
<Grid
|
|
99
|
+
<Grid size={{ xs: 12 }}>
|
|
95
100
|
<CrossSellForm data={data} onChange={onChange} />
|
|
96
101
|
</Grid>
|
|
97
102
|
</Grid>
|
|
@@ -15,16 +15,23 @@ export default function MetadataForm() {
|
|
|
15
15
|
<Box sx={{ width: 1 }}>
|
|
16
16
|
<Typography>{t('admin.product.features.label')}</Typography>
|
|
17
17
|
{features.fields.map((feature, index) => (
|
|
18
|
-
<Box
|
|
18
|
+
<Box
|
|
19
|
+
key={feature.id}
|
|
20
|
+
sx={{
|
|
21
|
+
mt: 2,
|
|
22
|
+
width: 1,
|
|
23
|
+
}}>
|
|
19
24
|
<Controller
|
|
20
25
|
render={({ field }) => (
|
|
21
26
|
<TextField
|
|
22
27
|
{...field}
|
|
23
28
|
sx={{ width: '80%' }}
|
|
24
29
|
size="small"
|
|
25
|
-
inputProps={{ maxLength: 64 }}
|
|
26
30
|
error={!!get(errors, field.name)}
|
|
27
31
|
helperText={get(errors, field.name)?.message as string}
|
|
32
|
+
slotProps={{
|
|
33
|
+
htmlInput: { maxLength: 64 },
|
|
34
|
+
}}
|
|
28
35
|
/>
|
|
29
36
|
)}
|
|
30
37
|
rules={{ maxLength: { value: 64, message: t('common.maxLength', { len: 64 }) } }}
|
|
@@ -36,7 +43,10 @@ export default function MetadataForm() {
|
|
|
36
43
|
</IconButton>
|
|
37
44
|
</Box>
|
|
38
45
|
))}
|
|
39
|
-
<Box
|
|
46
|
+
<Box
|
|
47
|
+
sx={{
|
|
48
|
+
mt: features.fields.length ? 2 : 1,
|
|
49
|
+
}}>
|
|
40
50
|
<Button size="small" variant="outlined" color="inherit" onClick={() => features.append({ name: '' })}>
|
|
41
51
|
<AddOutlined fontSize="small" /> {t('admin.product.features.add')}
|
|
42
52
|
</Button>
|