@lmnto/h-mall-shared 1.0.5 → 1.0.7
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/package.json +1 -1
- package/shared/components/payments/NowpaymentsDepositNoticeDialog.tsx +128 -0
- package/shared/components/payments/RequestProcessingWithCancelConfirm.tsx +225 -0
- package/shared/constants/app.ts +1 -0
- package/shared/i18n/locales/en.ts +21 -0
- package/shared/i18n/locales/it.ts +21 -0
package/package.json
CHANGED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Checkbox,
|
|
3
|
+
Dialog,
|
|
4
|
+
DialogBody,
|
|
5
|
+
DialogFooter,
|
|
6
|
+
DialogHeader,
|
|
7
|
+
IconButton,
|
|
8
|
+
Typography,
|
|
9
|
+
} from "@material-tailwind/react";
|
|
10
|
+
import React, { useEffect, useState } from "react";
|
|
11
|
+
|
|
12
|
+
import ButtonCustom from "../../components/Button";
|
|
13
|
+
import CustomNextLink from "../../components/CustomNextLink";
|
|
14
|
+
import { ROUTES } from "../../constants/routes";
|
|
15
|
+
import { _useScopedI18n } from "../../i18n/client";
|
|
16
|
+
|
|
17
|
+
export type NowpaymentsDepositNoticeDialogProps = {
|
|
18
|
+
open: boolean;
|
|
19
|
+
setOpen: (value: boolean) => void;
|
|
20
|
+
actionLoading: boolean;
|
|
21
|
+
onConfirm: () => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function NowpaymentsDepositNoticeDialog({
|
|
25
|
+
open,
|
|
26
|
+
setOpen,
|
|
27
|
+
actionLoading,
|
|
28
|
+
onConfirm,
|
|
29
|
+
}: NowpaymentsDepositNoticeDialogProps) {
|
|
30
|
+
const scopeT = _useScopedI18n("payment.nowpaymentsDepositNoticeDialog");
|
|
31
|
+
const [confirmed, setConfirmed] = useState(false);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (open) {
|
|
35
|
+
setConfirmed(false);
|
|
36
|
+
}
|
|
37
|
+
}, [open]);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Dialog
|
|
41
|
+
open={open}
|
|
42
|
+
size="lg"
|
|
43
|
+
handler={() => {
|
|
44
|
+
if (!actionLoading) setOpen(false);
|
|
45
|
+
}}
|
|
46
|
+
className="p-2 md:p-5 overflow-y-auto max-h-[92vh] nowpayments-deposit-notice-dialog"
|
|
47
|
+
>
|
|
48
|
+
<DialogHeader className="flex flex-col gap-2 p-0 pb-2 shrink-0">
|
|
49
|
+
<div className="text-right size-full">
|
|
50
|
+
<IconButton
|
|
51
|
+
color="blue-gray"
|
|
52
|
+
size="sm"
|
|
53
|
+
variant="text"
|
|
54
|
+
disabled={actionLoading}
|
|
55
|
+
onClick={() => setOpen(false)}
|
|
56
|
+
>
|
|
57
|
+
<svg
|
|
58
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
59
|
+
fill="none"
|
|
60
|
+
viewBox="0 0 24 24"
|
|
61
|
+
stroke="currentColor"
|
|
62
|
+
strokeWidth={2}
|
|
63
|
+
className="h-5 w-5"
|
|
64
|
+
>
|
|
65
|
+
<path
|
|
66
|
+
strokeLinecap="round"
|
|
67
|
+
strokeLinejoin="round"
|
|
68
|
+
d="M6 18L18 6M6 6l12 12"
|
|
69
|
+
/>
|
|
70
|
+
</svg>
|
|
71
|
+
</IconButton>
|
|
72
|
+
</div>
|
|
73
|
+
<Typography
|
|
74
|
+
variant="h4"
|
|
75
|
+
className="text-base md:text-xl font-semibold text-black-500 text-left w-full"
|
|
76
|
+
>
|
|
77
|
+
{scopeT("header")}
|
|
78
|
+
</Typography>
|
|
79
|
+
</DialogHeader>
|
|
80
|
+
<DialogBody className="flex flex-col gap-3 pl-1 pr-2 overflow-y-auto max-h-[55vh] md:max-h-[60vh]">
|
|
81
|
+
<Typography className="text-xs md:text-sm text-black-500 font-medium">
|
|
82
|
+
{scopeT("p1")}
|
|
83
|
+
</Typography>
|
|
84
|
+
<Typography className="text-xs md:text-sm text-black-500 font-medium">
|
|
85
|
+
{scopeT("p2")}
|
|
86
|
+
</Typography>
|
|
87
|
+
<Typography className="text-xs md:text-sm text-black-500 font-medium">
|
|
88
|
+
{scopeT("p3")}
|
|
89
|
+
</Typography>
|
|
90
|
+
<Typography className="text-xs md:text-sm text-black-500 font-medium">
|
|
91
|
+
{scopeT("p4a")}
|
|
92
|
+
<CustomNextLink
|
|
93
|
+
href={ROUTES.dashboard.support}
|
|
94
|
+
target="_blank"
|
|
95
|
+
onClick={undefined}
|
|
96
|
+
className="text-xs md:text-sm font-semibold text-purple-500 hover:text-purple-400 underline inline"
|
|
97
|
+
>
|
|
98
|
+
{scopeT("supportLinkText")}
|
|
99
|
+
</CustomNextLink>
|
|
100
|
+
{scopeT("p4b")}
|
|
101
|
+
</Typography>
|
|
102
|
+
<div className="flex items-start gap-2 pt-2">
|
|
103
|
+
<Checkbox
|
|
104
|
+
color="green"
|
|
105
|
+
checked={confirmed}
|
|
106
|
+
onChange={() => setConfirmed(!confirmed)}
|
|
107
|
+
disabled={actionLoading}
|
|
108
|
+
crossOrigin={undefined}
|
|
109
|
+
className="mt-0.5"
|
|
110
|
+
/>
|
|
111
|
+
<Typography className="text-xs md:text-sm text-black-500 font-medium">
|
|
112
|
+
{scopeT("checkbox")}
|
|
113
|
+
</Typography>
|
|
114
|
+
</div>
|
|
115
|
+
</DialogBody>
|
|
116
|
+
<DialogFooter className="flex justify-center items-center pt-2 shrink-0">
|
|
117
|
+
<ButtonCustom
|
|
118
|
+
icon={undefined}
|
|
119
|
+
disabled={actionLoading || !confirmed}
|
|
120
|
+
onClick={onConfirm}
|
|
121
|
+
loading={actionLoading}
|
|
122
|
+
>
|
|
123
|
+
{scopeT("nextBtn")}
|
|
124
|
+
</ButtonCustom>
|
|
125
|
+
</DialogFooter>
|
|
126
|
+
</Dialog>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
Dialog,
|
|
6
|
+
DialogBody,
|
|
7
|
+
DialogFooter,
|
|
8
|
+
Typography,
|
|
9
|
+
} from "@material-tailwind/react";
|
|
10
|
+
import React, { useCallback, useState } from "react";
|
|
11
|
+
import { IoRefresh } from "react-icons/io5";
|
|
12
|
+
|
|
13
|
+
import { _useScopedI18n } from "../../i18n/client";
|
|
14
|
+
import ButtonCustom from "../Button";
|
|
15
|
+
import LoadingIconComponent from "../LoadingIconComponent";
|
|
16
|
+
|
|
17
|
+
/** Same props as {@link RequestProcessingDialog} plus optional cancel confirmation before close. */
|
|
18
|
+
export type RequestProcessingWithCancelConfirmProps = {
|
|
19
|
+
open: boolean;
|
|
20
|
+
orderId: string;
|
|
21
|
+
paymentProcessFailed: boolean;
|
|
22
|
+
onRetry?: () => void;
|
|
23
|
+
setOpen: (value: boolean) => void;
|
|
24
|
+
paymentDetails?: React.ReactNode;
|
|
25
|
+
/** When true (with `onConfirmLeavePayment`), Cancel opens a confirmation dialog first. */
|
|
26
|
+
confirmBeforeClose?: boolean;
|
|
27
|
+
/** Called when the user confirms leaving the payment flow (e.g. navigate home). */
|
|
28
|
+
onConfirmLeavePayment?: () => void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Copy of the payment {@link RequestProcessingDialog} with an optional second dialog to confirm
|
|
33
|
+
* before closing during an active payment (e.g. NOWPayments deposit instructions).
|
|
34
|
+
*/
|
|
35
|
+
export function RequestProcessingWithCancelConfirm({
|
|
36
|
+
open,
|
|
37
|
+
setOpen,
|
|
38
|
+
orderId,
|
|
39
|
+
paymentProcessFailed,
|
|
40
|
+
onRetry,
|
|
41
|
+
paymentDetails,
|
|
42
|
+
confirmBeforeClose,
|
|
43
|
+
onConfirmLeavePayment,
|
|
44
|
+
}: RequestProcessingWithCancelConfirmProps) {
|
|
45
|
+
const scopeT = _useScopedI18n("payment.requestProcessingDialog");
|
|
46
|
+
const cancelT = _useScopedI18n("payment.cancelPaymentConfirm");
|
|
47
|
+
const hasPaymentDetails = Boolean(paymentDetails);
|
|
48
|
+
const [cancelConfirmOpen, setCancelConfirmOpen] = useState(false);
|
|
49
|
+
|
|
50
|
+
const useConfirmFlow = Boolean(
|
|
51
|
+
confirmBeforeClose && onConfirmLeavePayment,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const handleCloseClick = useCallback(() => {
|
|
55
|
+
if (useConfirmFlow) {
|
|
56
|
+
setCancelConfirmOpen(true);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
setOpen(false);
|
|
60
|
+
}, [useConfirmFlow, setOpen]);
|
|
61
|
+
|
|
62
|
+
const handleConfirmLeave = useCallback(() => {
|
|
63
|
+
setCancelConfirmOpen(false);
|
|
64
|
+
setOpen(false);
|
|
65
|
+
onConfirmLeavePayment?.();
|
|
66
|
+
}, [onConfirmLeavePayment, setOpen]);
|
|
67
|
+
|
|
68
|
+
const handleStayOnPayment = useCallback(() => {
|
|
69
|
+
setCancelConfirmOpen(false);
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
<Dialog
|
|
75
|
+
open={open}
|
|
76
|
+
size={hasPaymentDetails ? "md" : "xs"}
|
|
77
|
+
handler={() => {}}
|
|
78
|
+
className={`p-2 md:p-4 ${hasPaymentDetails ? "max-w-md w-[calc(100vw-1.5rem)]" : ""}`}
|
|
79
|
+
>
|
|
80
|
+
<DialogBody
|
|
81
|
+
className={
|
|
82
|
+
hasPaymentDetails
|
|
83
|
+
? "flex max-h-[80vh] flex-col gap-3 overflow-y-auto px-1 text-left sm:px-2"
|
|
84
|
+
: "flex flex-col items-center gap-8 text-center"
|
|
85
|
+
}
|
|
86
|
+
>
|
|
87
|
+
{hasPaymentDetails ? (
|
|
88
|
+
<>
|
|
89
|
+
<div className="w-full space-y-1 text-center">
|
|
90
|
+
<Typography
|
|
91
|
+
variant="h3"
|
|
92
|
+
className="text-xl font-semibold text-slate-900"
|
|
93
|
+
>
|
|
94
|
+
{scopeT("completePaymentTitle")}
|
|
95
|
+
</Typography>
|
|
96
|
+
<p className="text-sm text-slate-500">
|
|
97
|
+
{scopeT("orderId")}{" "}
|
|
98
|
+
<span className="font-mono font-medium text-slate-700">
|
|
99
|
+
{orderId}
|
|
100
|
+
</span>
|
|
101
|
+
</p>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
{paymentDetails}
|
|
105
|
+
|
|
106
|
+
{paymentProcessFailed ? (
|
|
107
|
+
<div className="text-center">
|
|
108
|
+
<Typography
|
|
109
|
+
variant="lead"
|
|
110
|
+
className="mb-3 text-sm font-medium text-slate-500"
|
|
111
|
+
>
|
|
112
|
+
{scopeT("errorMsg")}
|
|
113
|
+
</Typography>
|
|
114
|
+
|
|
115
|
+
<ButtonCustom
|
|
116
|
+
icon={<IoRefresh className="size-4" />}
|
|
117
|
+
onClick={onRetry}
|
|
118
|
+
>
|
|
119
|
+
{scopeT("retryBtn")}
|
|
120
|
+
</ButtonCustom>
|
|
121
|
+
</div>
|
|
122
|
+
) : null}
|
|
123
|
+
</>
|
|
124
|
+
) : (
|
|
125
|
+
<>
|
|
126
|
+
<LoadingIconComponent />
|
|
127
|
+
<div>
|
|
128
|
+
<Typography variant="h3" className="text-xl text-black-500">
|
|
129
|
+
{scopeT("title")}...
|
|
130
|
+
</Typography>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<div className="rounded-lg border border-slate-100 bg-gray-50 px-9 py-4">
|
|
134
|
+
<Typography
|
|
135
|
+
variant="h6"
|
|
136
|
+
className="text-xs font-medium leading-5 text-black-500"
|
|
137
|
+
>
|
|
138
|
+
{scopeT("orderId")} : {orderId}
|
|
139
|
+
</Typography>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div>
|
|
143
|
+
{paymentProcessFailed ? (
|
|
144
|
+
<>
|
|
145
|
+
<Typography
|
|
146
|
+
variant="lead"
|
|
147
|
+
className="mb-3 text-sm font-medium text-slate-500"
|
|
148
|
+
>
|
|
149
|
+
{scopeT("errorMsg")}
|
|
150
|
+
</Typography>
|
|
151
|
+
|
|
152
|
+
<ButtonCustom
|
|
153
|
+
icon={<IoRefresh className="size-4" />}
|
|
154
|
+
onClick={onRetry}
|
|
155
|
+
>
|
|
156
|
+
{scopeT("retryBtn")}
|
|
157
|
+
</ButtonCustom>
|
|
158
|
+
</>
|
|
159
|
+
) : (
|
|
160
|
+
<>
|
|
161
|
+
<Typography
|
|
162
|
+
variant="lead"
|
|
163
|
+
className="mb-3 text-sm font-medium text-slate-500"
|
|
164
|
+
>
|
|
165
|
+
{scopeT("subTitle")}
|
|
166
|
+
</Typography>
|
|
167
|
+
|
|
168
|
+
<Typography
|
|
169
|
+
variant="lead"
|
|
170
|
+
className="text-sm font-medium text-slate-500"
|
|
171
|
+
>
|
|
172
|
+
{scopeT("message")}
|
|
173
|
+
</Typography>
|
|
174
|
+
</>
|
|
175
|
+
)}
|
|
176
|
+
</div>
|
|
177
|
+
</>
|
|
178
|
+
)}
|
|
179
|
+
</DialogBody>
|
|
180
|
+
<DialogFooter className="flex justify-end border-0 p-0 pt-3 shadow-none sm:px-2">
|
|
181
|
+
<Button
|
|
182
|
+
variant="outlined"
|
|
183
|
+
color="blue-gray"
|
|
184
|
+
className="normal-case rounded-xl border-slate-300 px-4 py-2.5 text-sm font-semibold text-slate-700 shadow-sm hover:border-slate-400 hover:bg-slate-50"
|
|
185
|
+
onClick={handleCloseClick}
|
|
186
|
+
>
|
|
187
|
+
{cancelT("cancelBtn")}
|
|
188
|
+
</Button>
|
|
189
|
+
</DialogFooter>
|
|
190
|
+
</Dialog>
|
|
191
|
+
|
|
192
|
+
<Dialog
|
|
193
|
+
open={cancelConfirmOpen}
|
|
194
|
+
size="xs"
|
|
195
|
+
handler={handleStayOnPayment}
|
|
196
|
+
className="p-2 md:p-5 z-[10001]"
|
|
197
|
+
>
|
|
198
|
+
<DialogBody className="space-y-3 px-1 py-2">
|
|
199
|
+
<Typography
|
|
200
|
+
variant="h4"
|
|
201
|
+
className="text-base md:text-xl font-semibold text-black-500"
|
|
202
|
+
>
|
|
203
|
+
{cancelT("title")}
|
|
204
|
+
</Typography>
|
|
205
|
+
<Typography className="text-sm text-slate-600">
|
|
206
|
+
{cancelT("message")}
|
|
207
|
+
</Typography>
|
|
208
|
+
</DialogBody>
|
|
209
|
+
<DialogFooter className="flex flex-col-reverse gap-2 p-0 pt-2 sm:flex-row sm:justify-end">
|
|
210
|
+
<Button
|
|
211
|
+
variant="outlined"
|
|
212
|
+
color="blue-gray"
|
|
213
|
+
className="normal-case rounded-xl border-slate-300 px-4 py-2.5 text-sm font-semibold text-slate-700 shadow-sm hover:border-slate-400 hover:bg-slate-50"
|
|
214
|
+
onClick={handleStayOnPayment}
|
|
215
|
+
>
|
|
216
|
+
{cancelT("stayBtn")}
|
|
217
|
+
</Button>
|
|
218
|
+
<ButtonCustom icon={undefined} onClick={handleConfirmLeave}>
|
|
219
|
+
{cancelT("leaveBtn")}
|
|
220
|
+
</ButtonCustom>
|
|
221
|
+
</DialogFooter>
|
|
222
|
+
</Dialog>
|
|
223
|
+
</>
|
|
224
|
+
);
|
|
225
|
+
}
|
package/shared/constants/app.ts
CHANGED
|
@@ -347,6 +347,14 @@ export default {
|
|
|
347
347
|
errorMsg: "An error occurred during the process",
|
|
348
348
|
retryBtn: "Click here to retry",
|
|
349
349
|
},
|
|
350
|
+
cancelPaymentConfirm: {
|
|
351
|
+
title: "Leave this screen?",
|
|
352
|
+
message:
|
|
353
|
+
"If you complete your payment here, you're all set. If you leave now, this payment address won't be shown again, and your order will be cancelled.",
|
|
354
|
+
cancelBtn: "Close",
|
|
355
|
+
stayBtn: "Stay and pay",
|
|
356
|
+
leaveBtn: "Leave without paying",
|
|
357
|
+
},
|
|
350
358
|
paybyWalletItemComponent: {
|
|
351
359
|
insufficientBalanceMsg: "Insufficient wallet balance. Please recharge.",
|
|
352
360
|
avlBalance: "Avl Balance",
|
|
@@ -368,6 +376,19 @@ export default {
|
|
|
368
376
|
regenerateBtn: "Generate new payment",
|
|
369
377
|
regenerateLoading: "Generating…",
|
|
370
378
|
},
|
|
379
|
+
nowpaymentsDepositNoticeDialog: {
|
|
380
|
+
header: "Please read before sending funds",
|
|
381
|
+
p1: "This is a one-time deposit address generated exclusively for this order. It is valid for 10 minutes once shown (a countdown will appear on the next screen).",
|
|
382
|
+
p2: "You must send the exact amount shown to this address within the 10-minute window.",
|
|
383
|
+
p3: "If you send funds after the timer expires, HMall will be unable to automatically credit your order. HMall cannot guarantee that late deposits will be identified, attributed to your order, or manually processed. HMall accepts no liability for unattributed or late transfers.",
|
|
384
|
+
p4a:
|
|
385
|
+
"If you believe you have made a late or incorrect transfer, please contact ",
|
|
386
|
+
supportLinkText: "HMall support",
|
|
387
|
+
p4b: " with your Order ID and transaction hash. Manual review is at HMall's sole discretion and is not guaranteed.",
|
|
388
|
+
checkbox:
|
|
389
|
+
"I confirm I have read and understood the above before proceeding.",
|
|
390
|
+
nextBtn: "Next",
|
|
391
|
+
},
|
|
371
392
|
disclaimerAlertDialog: {
|
|
372
393
|
header: "Disclaimer Alert",
|
|
373
394
|
acceptCheckboxPrivacy: "I have read and accept membership",
|
|
@@ -336,6 +336,14 @@ export default {
|
|
|
336
336
|
errorMsg: "Si è verificato un errore durante il processo",
|
|
337
337
|
retryBtn: "Clicca qui per riprovare",
|
|
338
338
|
},
|
|
339
|
+
cancelPaymentConfirm: {
|
|
340
|
+
title: "Uscire da questa schermata?",
|
|
341
|
+
message:
|
|
342
|
+
"Se completi il pagamento qui, non devi fare altro. Se esci ora, questo indirizzo di pagamento non verrà più mostrato e l'ordine verrà annullato.",
|
|
343
|
+
cancelBtn: "Chiudi",
|
|
344
|
+
stayBtn: "Resta e paga",
|
|
345
|
+
leaveBtn: "Esci senza pagare",
|
|
346
|
+
},
|
|
339
347
|
paybyWalletItemComponent: {
|
|
340
348
|
insufficientBalanceMsg:
|
|
341
349
|
"Saldo del portafoglio insufficiente. Si prega di ricaricare.",
|
|
@@ -358,6 +366,19 @@ export default {
|
|
|
358
366
|
regenerateBtn: "Genera nuovo pagamento",
|
|
359
367
|
regenerateLoading: "Generazione…",
|
|
360
368
|
},
|
|
369
|
+
nowpaymentsDepositNoticeDialog: {
|
|
370
|
+
header: "Leggi attentamente prima di inviare fondi",
|
|
371
|
+
p1: "Questo è un indirizzo di deposito monouso generato esclusivamente per questo ordine. È valido per 10 minuti dal momento in cui viene mostrato (un conto alla rovescia apparirà nella schermata successiva).",
|
|
372
|
+
p2: "Devi inviare l'importo esatto indicato a questo indirizzo entro la finestra di 10 minuti.",
|
|
373
|
+
p3: "Se invii fondi dopo la scadenza del timer, HMall non potrà accreditare automaticamente il tuo ordine. HMall non garantisce che i depositi in ritardo vengano identificati, attribuiti al tuo ordine o elaborati manualmente. HMall non accetta responsabilità per trasferimenti non attribuiti o in ritardo.",
|
|
374
|
+
p4a:
|
|
375
|
+
"Se ritieni di aver effettuato un bonifico in ritardo o errato, contatta ",
|
|
376
|
+
supportLinkText: "assistenza HMall",
|
|
377
|
+
p4b: " con l'ID ordine e l'hash della transazione. La revisione manuale è a esclusiva discrezione di HMall e non è garantita.",
|
|
378
|
+
checkbox:
|
|
379
|
+
"Confermo di aver letto e compreso quanto sopra prima di procedere.",
|
|
380
|
+
nextBtn: "Avanti",
|
|
381
|
+
},
|
|
361
382
|
disclaimerAlertDialog: {
|
|
362
383
|
header: "Avviso di esclusione di responsabilità",
|
|
363
384
|
acceptCheckboxPrivacy: "Ho letto e accetto l'adesione",
|