@retinalabsllc/zairusjs 15.0.85 → 15.0.95
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/index.d.mts +30 -37
- package/dist/index.d.ts +30 -37
- package/dist/index.js +458 -589
- package/dist/index.mjs +572 -702
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -370,12 +370,143 @@ var Header = ({
|
|
|
370
370
|
};
|
|
371
371
|
|
|
372
372
|
// src/components/PipleAuth.tsx
|
|
373
|
-
var
|
|
373
|
+
var import_react7 = __toESM(require("react"));
|
|
374
374
|
var import_navigation2 = require("next/navigation");
|
|
375
375
|
var import_react_hot_toast = __toESM(require("react-hot-toast"));
|
|
376
376
|
var import_react_google_recaptcha_v3 = require("react-google-recaptcha-v3");
|
|
377
377
|
var import_browser = require("@simplewebauthn/browser");
|
|
378
|
-
|
|
378
|
+
|
|
379
|
+
// src/components/TextInput.tsx
|
|
380
|
+
var import_react6 = __toESM(require("react"));
|
|
381
|
+
var InputSpinner = () => /* @__PURE__ */ import_react6.default.createElement("svg", { className: "animate-spin h-3 w-3 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react6.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react6.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
382
|
+
var FlagImage = ({ countryCode }) => {
|
|
383
|
+
const [loaded, setLoaded] = (0, import_react6.useState)(false);
|
|
384
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "relative w-6 h-6 rounded-full overflow-hidden flex items-center justify-center bg-neutral-100 shrink-0 border border-neutral-200" }, !loaded && /* @__PURE__ */ import_react6.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center" }, /* @__PURE__ */ import_react6.default.createElement(InputSpinner, null)), /* @__PURE__ */ import_react6.default.createElement(
|
|
385
|
+
"img",
|
|
386
|
+
{
|
|
387
|
+
src: `https://flagcdn.com/w40/${countryCode.toLowerCase()}.png`,
|
|
388
|
+
alt: countryCode,
|
|
389
|
+
className: `object-cover w-full h-full transition-opacity duration-300 ${loaded ? "opacity-100" : "opacity-0"}`,
|
|
390
|
+
onLoad: () => setLoaded(true)
|
|
391
|
+
}
|
|
392
|
+
));
|
|
393
|
+
};
|
|
394
|
+
var TextInput = ({
|
|
395
|
+
label,
|
|
396
|
+
value,
|
|
397
|
+
onChange,
|
|
398
|
+
placeholder,
|
|
399
|
+
maxLength,
|
|
400
|
+
disabled,
|
|
401
|
+
readOnly,
|
|
402
|
+
type = "text",
|
|
403
|
+
onClick
|
|
404
|
+
}) => /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-2 flex-1 w-full", onClick }, label && /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ import_react6.default.createElement(
|
|
405
|
+
"input",
|
|
406
|
+
{
|
|
407
|
+
type,
|
|
408
|
+
value,
|
|
409
|
+
onChange: (e) => onChange(e.target.value.substring(0, maxLength || 100)),
|
|
410
|
+
placeholder,
|
|
411
|
+
disabled,
|
|
412
|
+
readOnly,
|
|
413
|
+
autoComplete: "off",
|
|
414
|
+
spellCheck: "false",
|
|
415
|
+
className: `w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50 ${readOnly ? "cursor-pointer" : ""}`
|
|
416
|
+
}
|
|
417
|
+
));
|
|
418
|
+
var NumberInput = ({
|
|
419
|
+
label,
|
|
420
|
+
value,
|
|
421
|
+
onChange,
|
|
422
|
+
placeholder,
|
|
423
|
+
maxLength,
|
|
424
|
+
disabled
|
|
425
|
+
}) => /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-2 flex-1 w-full" }, label && /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ import_react6.default.createElement(
|
|
426
|
+
"input",
|
|
427
|
+
{
|
|
428
|
+
type: "text",
|
|
429
|
+
value,
|
|
430
|
+
onChange: (e) => {
|
|
431
|
+
const numOnly = e.target.value.replace(/[^0-9]/g, "");
|
|
432
|
+
onChange(numOnly.substring(0, maxLength || 20));
|
|
433
|
+
},
|
|
434
|
+
placeholder,
|
|
435
|
+
disabled,
|
|
436
|
+
autoComplete: "off",
|
|
437
|
+
spellCheck: "false",
|
|
438
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50"
|
|
439
|
+
}
|
|
440
|
+
));
|
|
441
|
+
var PhoneInput = ({
|
|
442
|
+
label,
|
|
443
|
+
value,
|
|
444
|
+
onChange,
|
|
445
|
+
selectedCountry,
|
|
446
|
+
onCountryClick,
|
|
447
|
+
placeholder,
|
|
448
|
+
disabled
|
|
449
|
+
}) => /* @__PURE__ */ import_react6.default.createElement("div", { className: "space-y-1.5 flex-1 w-full" }, label && /* @__PURE__ */ import_react6.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block" }, label), /* @__PURE__ */ import_react6.default.createElement("div", { className: `flex items-center gap-3 border-b border-neutral-200 focus-within:border-black transition-all duration-300 pb-2 ${disabled ? "opacity-50" : ""}` }, /* @__PURE__ */ import_react6.default.createElement(
|
|
450
|
+
"button",
|
|
451
|
+
{
|
|
452
|
+
type: "button",
|
|
453
|
+
disabled,
|
|
454
|
+
onClick: onCountryClick,
|
|
455
|
+
className: "flex items-center gap-1.5 outline-none hover:opacity-80 transition-opacity"
|
|
456
|
+
},
|
|
457
|
+
/* @__PURE__ */ import_react6.default.createElement(FlagImage, { countryCode: selectedCountry.code }),
|
|
458
|
+
/* @__PURE__ */ import_react6.default.createElement("span", { className: "text-sm text-black font-medium pl-1" }, selectedCountry.dialCode),
|
|
459
|
+
/* @__PURE__ */ import_react6.default.createElement("svg", { className: "w-3 h-3 text-neutral-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" }, /* @__PURE__ */ import_react6.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))
|
|
460
|
+
), /* @__PURE__ */ import_react6.default.createElement(
|
|
461
|
+
"input",
|
|
462
|
+
{
|
|
463
|
+
type: "tel",
|
|
464
|
+
value,
|
|
465
|
+
onChange: (e) => {
|
|
466
|
+
const numOnly = e.target.value.replace(/[^0-9]/g, "");
|
|
467
|
+
onChange(numOnly.substring(0, 15));
|
|
468
|
+
},
|
|
469
|
+
disabled,
|
|
470
|
+
required: true,
|
|
471
|
+
autoFocus: true,
|
|
472
|
+
autoComplete: "off",
|
|
473
|
+
spellCheck: "false",
|
|
474
|
+
className: "w-full text-sm bg-transparent text-black outline-none pt-1",
|
|
475
|
+
placeholder: placeholder || "0801 234 5678"
|
|
476
|
+
}
|
|
477
|
+
)));
|
|
478
|
+
|
|
479
|
+
// src/components/PipleAuth.tsx
|
|
480
|
+
var SUPPORTED_COUNTRIES = [
|
|
481
|
+
{ code: "NG", dialCode: "+234", name: "Nigeria" },
|
|
482
|
+
{ code: "GH", dialCode: "+233", name: "Ghana" },
|
|
483
|
+
{ code: "KE", dialCode: "+254", name: "Kenya" }
|
|
484
|
+
];
|
|
485
|
+
var InputSpinner2 = () => /* @__PURE__ */ import_react7.default.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react7.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react7.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
486
|
+
var CountrySelectorDialog = ({ isOpen, onClose, onSelect }) => {
|
|
487
|
+
if (!isOpen) return null;
|
|
488
|
+
return /* @__PURE__ */ import_react7.default.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "absolute inset-0", onClick: onClose }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full max-w-sm bg-white rounded-2xl shadow-2xl overflow-hidden relative z-10 animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
489
|
+
"button",
|
|
490
|
+
{
|
|
491
|
+
onClick: onClose,
|
|
492
|
+
className: "absolute top-4 right-4 p-2 text-neutral-700 hover:text-neutral-400 transition-colors outline-none"
|
|
493
|
+
},
|
|
494
|
+
/* @__PURE__ */ import_react7.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react7.default.createElement("path", { d: "M18 6 6 18" }), /* @__PURE__ */ import_react7.default.createElement("path", { d: "m6 6 12 12" }))
|
|
495
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "p-6 sm:p-8" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "mb-6 mt-2" }, /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-xl text-black tracking-tight mb-2" }, "Select Country"), /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-[13px] text-neutral-500 leading-relaxed" }, "Choose your region to continue.")), /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-2" }, SUPPORTED_COUNTRIES.map((c) => /* @__PURE__ */ import_react7.default.createElement(
|
|
496
|
+
"button",
|
|
497
|
+
{
|
|
498
|
+
key: c.code,
|
|
499
|
+
onClick: () => {
|
|
500
|
+
onSelect(c);
|
|
501
|
+
onClose();
|
|
502
|
+
},
|
|
503
|
+
className: "flex items-center gap-4 p-3 rounded-xl hover:bg-neutral-50 transition-colors text-left outline-none"
|
|
504
|
+
},
|
|
505
|
+
/* @__PURE__ */ import_react7.default.createElement(FlagImage, { countryCode: c.code }),
|
|
506
|
+
/* @__PURE__ */ import_react7.default.createElement("span", { className: "text-sm text-black flex-1 font-medium" }, c.name),
|
|
507
|
+
/* @__PURE__ */ import_react7.default.createElement("span", { className: "text-sm text-neutral-500 font-mono" }, c.dialCode)
|
|
508
|
+
))))));
|
|
509
|
+
};
|
|
379
510
|
function AuthFormInner({
|
|
380
511
|
companyName,
|
|
381
512
|
workspaceLabel = "Workspace",
|
|
@@ -391,29 +522,27 @@ function AuthFormInner({
|
|
|
391
522
|
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
392
523
|
const redirectUrl = searchParams.get("redirect") || defaultRedirectPath;
|
|
393
524
|
const captchaContext = useRecaptcha ? (0, import_react_google_recaptcha_v3.useGoogleReCaptcha)() : null;
|
|
394
|
-
const [mode, setMode] = (0,
|
|
395
|
-
const [step, setStep] = (0,
|
|
396
|
-
const getInitialSignupStep = () =>
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const [
|
|
400
|
-
const [
|
|
401
|
-
const [
|
|
402
|
-
const [
|
|
403
|
-
const [
|
|
404
|
-
const [firstName, setFirstName] = (0,
|
|
405
|
-
const [lastName, setLastName] = (0,
|
|
406
|
-
const [orgName, setOrgName] = (0,
|
|
407
|
-
const [agreedToTerms, setAgreedToTerms] = (0,
|
|
408
|
-
const [
|
|
409
|
-
const [
|
|
410
|
-
const [
|
|
411
|
-
const
|
|
412
|
-
const inputRefs = (0, import_react6.useRef)([]);
|
|
525
|
+
const [mode, setMode] = (0, import_react7.useState)("LOGIN");
|
|
526
|
+
const [step, setStep] = (0, import_react7.useState)("INPUT");
|
|
527
|
+
const getInitialSignupStep = () => "INVITATION";
|
|
528
|
+
const [signupStep, setSignupStep] = (0, import_react7.useState)(getInitialSignupStep());
|
|
529
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react7.useState)(false);
|
|
530
|
+
const [countdown, setCountdown] = (0, import_react7.useState)(0);
|
|
531
|
+
const [invitationCode, setInvitationCode] = (0, import_react7.useState)("");
|
|
532
|
+
const [phoneNumber, setPhoneNumber] = (0, import_react7.useState)("");
|
|
533
|
+
const [selectedCountry, setSelectedCountry] = (0, import_react7.useState)(SUPPORTED_COUNTRIES[0]);
|
|
534
|
+
const [isCountryDialogOpen, setIsCountryDialogOpen] = (0, import_react7.useState)(false);
|
|
535
|
+
const [firstName, setFirstName] = (0, import_react7.useState)("");
|
|
536
|
+
const [lastName, setLastName] = (0, import_react7.useState)("");
|
|
537
|
+
const [orgName, setOrgName] = (0, import_react7.useState)("");
|
|
538
|
+
const [agreedToTerms, setAgreedToTerms] = (0, import_react7.useState)(false);
|
|
539
|
+
const [userHasPasskey, setUserHasPasskey] = (0, import_react7.useState)(false);
|
|
540
|
+
const [authOptions, setAuthOptions] = (0, import_react7.useState)(null);
|
|
541
|
+
const [otp, setOtp] = (0, import_react7.useState)(["", "", "", "", "", ""]);
|
|
542
|
+
const inputRefs = (0, import_react7.useRef)([]);
|
|
413
543
|
const cleanAlpha = (val) => val.replace(/[^a-zA-Z]/g, "").substring(0, 50);
|
|
414
544
|
const cleanOrgName = (val) => val.replace(/[^a-zA-Z0-9\s]/g, "").substring(0, 50);
|
|
415
|
-
|
|
416
|
-
(0, import_react6.useEffect)(() => {
|
|
545
|
+
(0, import_react7.useEffect)(() => {
|
|
417
546
|
if (countdown > 0) {
|
|
418
547
|
const timer = setTimeout(() => setCountdown(countdown - 1), 1e3);
|
|
419
548
|
return () => clearTimeout(timer);
|
|
@@ -442,6 +571,10 @@ function AuthFormInner({
|
|
|
442
571
|
verifyOtpCode(newOtp.join(""));
|
|
443
572
|
}
|
|
444
573
|
};
|
|
574
|
+
const getFormattedPhoneNumber = () => {
|
|
575
|
+
const cleanNumber = phoneNumber.replace(/^0+/, "");
|
|
576
|
+
return `${selectedCountry.dialCode}${cleanNumber}`;
|
|
577
|
+
};
|
|
445
578
|
const handleAuthRequestSubmit = async (e) => {
|
|
446
579
|
if (e) e.preventDefault();
|
|
447
580
|
if (mode === "SIGNUP" && !agreedToTerms) {
|
|
@@ -456,7 +589,8 @@ function AuthFormInner({
|
|
|
456
589
|
recaptchaToken = await captchaContext.executeRecaptcha("auth_request");
|
|
457
590
|
}
|
|
458
591
|
const res = await onAuthRequest({
|
|
459
|
-
|
|
592
|
+
phoneNumber: getFormattedPhoneNumber(),
|
|
593
|
+
country: selectedCountry.code,
|
|
460
594
|
firstName: mode === "SIGNUP" && requireNames ? firstName : void 0,
|
|
461
595
|
lastName: mode === "SIGNUP" && requireNames ? lastName : void 0,
|
|
462
596
|
organizationName: mode === "SIGNUP" && requireOrganization ? orgName : void 0,
|
|
@@ -465,10 +599,9 @@ function AuthFormInner({
|
|
|
465
599
|
recaptchaToken
|
|
466
600
|
});
|
|
467
601
|
if (res.success) {
|
|
468
|
-
setUserHas2FA(!!res.has2FA);
|
|
469
602
|
setUserHasPasskey(!!res.hasPasskey);
|
|
470
603
|
if (res.passkeyOptions) setAuthOptions(res.passkeyOptions);
|
|
471
|
-
import_react_hot_toast.default.success(res.
|
|
604
|
+
import_react_hot_toast.default.success(res.needsPukSetup ? "Verification code sent" : "Security check required");
|
|
472
605
|
setStep("OTP");
|
|
473
606
|
setCountdown(60);
|
|
474
607
|
} else {
|
|
@@ -484,7 +617,10 @@ function AuthFormInner({
|
|
|
484
617
|
if (codeToVerify.length !== 6 || isSubmitting) return;
|
|
485
618
|
setIsSubmitting(true);
|
|
486
619
|
try {
|
|
487
|
-
const res = await onVerifyOtp({
|
|
620
|
+
const res = await onVerifyOtp({
|
|
621
|
+
phoneNumber: getFormattedPhoneNumber(),
|
|
622
|
+
code: codeToVerify
|
|
623
|
+
});
|
|
488
624
|
if (res.success) {
|
|
489
625
|
window.location.href = res.redirect || redirectUrl;
|
|
490
626
|
} else {
|
|
@@ -503,7 +639,11 @@ function AuthFormInner({
|
|
|
503
639
|
setIsSubmitting(true);
|
|
504
640
|
try {
|
|
505
641
|
const credentialResponse = await (0, import_browser.startAuthentication)({ optionsJSON: authOptions });
|
|
506
|
-
const res = await onVerifyOtp({
|
|
642
|
+
const res = await onVerifyOtp({
|
|
643
|
+
phoneNumber: getFormattedPhoneNumber(),
|
|
644
|
+
isPasskey: true,
|
|
645
|
+
passkeyCredential: credentialResponse
|
|
646
|
+
});
|
|
507
647
|
if (res.success) {
|
|
508
648
|
window.location.href = res.redirect || redirectUrl;
|
|
509
649
|
} else {
|
|
@@ -519,35 +659,42 @@ function AuthFormInner({
|
|
|
519
659
|
if (signupStep === "INVITATION") {
|
|
520
660
|
if (requireNames) setSignupStep("NAME");
|
|
521
661
|
else if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
522
|
-
else setSignupStep("
|
|
662
|
+
else setSignupStep("PHONE_ID");
|
|
523
663
|
} else if (signupStep === "NAME") {
|
|
524
664
|
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
525
|
-
else setSignupStep("
|
|
665
|
+
else setSignupStep("PHONE_ID");
|
|
526
666
|
} else if (signupStep === "ORGANIZATION") {
|
|
527
|
-
setSignupStep("
|
|
667
|
+
setSignupStep("PHONE_ID");
|
|
528
668
|
}
|
|
529
669
|
};
|
|
530
670
|
const isContinueDisabled = () => {
|
|
531
671
|
if (isSubmitting) return true;
|
|
532
|
-
if (mode === "LOGIN") return
|
|
672
|
+
if (mode === "LOGIN") return phoneNumber.length < 5;
|
|
533
673
|
if (mode === "SIGNUP") {
|
|
534
674
|
if (signupStep === "INVITATION") return invitationCode.trim().length > 0 && invitationCode.trim().length < 3;
|
|
535
675
|
if (signupStep === "NAME") return firstName.trim() === "" || lastName.trim() === "";
|
|
536
676
|
if (signupStep === "ORGANIZATION") return orgName.trim().length < 3;
|
|
537
|
-
if (signupStep === "
|
|
677
|
+
if (signupStep === "PHONE_ID") return phoneNumber.length < 5 || !agreedToTerms;
|
|
538
678
|
}
|
|
539
679
|
return false;
|
|
540
680
|
};
|
|
541
|
-
return /* @__PURE__ */
|
|
681
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(
|
|
682
|
+
CountrySelectorDialog,
|
|
683
|
+
{
|
|
684
|
+
isOpen: isCountryDialogOpen,
|
|
685
|
+
onClose: () => setIsCountryDialogOpen(false),
|
|
686
|
+
onSelect: setSelectedCountry
|
|
687
|
+
}
|
|
688
|
+
), /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full max-w-md mx-auto flex flex-col items-center gap-4 relative z-10 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "p-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, mode === "LOGIN" ? `${companyName} ${workspaceLabel}` : "Create Account"), /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-[13px] text-neutral-500" }, mode === "LOGIN" ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, "Don't have an account? ", /* @__PURE__ */ import_react7.default.createElement("button", { type: "button", onClick: () => {
|
|
542
689
|
setMode("SIGNUP");
|
|
543
690
|
setSignupStep(getInitialSignupStep());
|
|
544
|
-
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */
|
|
691
|
+
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, "Already have an account? ", /* @__PURE__ */ import_react7.default.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1" }, "Log in")))), /* @__PURE__ */ import_react7.default.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
545
692
|
e.preventDefault();
|
|
546
693
|
if (mode === "SIGNUP" && signupStep === "INVITATION") handleNextSignupStep();
|
|
547
694
|
else if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
548
695
|
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
549
696
|
else handleAuthRequestSubmit();
|
|
550
|
-
} }, mode === "SIGNUP" && signupStep === "INVITATION" && /* @__PURE__ */
|
|
697
|
+
} }, mode === "SIGNUP" && signupStep === "INVITATION" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Referral Code"), /* @__PURE__ */ import_react7.default.createElement(
|
|
551
698
|
"input",
|
|
552
699
|
{
|
|
553
700
|
type: "text",
|
|
@@ -557,10 +704,20 @@ function AuthFormInner({
|
|
|
557
704
|
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300 tracking-widest",
|
|
558
705
|
placeholder: "Referral Code (Optional)"
|
|
559
706
|
}
|
|
560
|
-
))), mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */
|
|
707
|
+
))), mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "First Name"), /* @__PURE__ */ import_react7.default.createElement("input", { type: "text", value: firstName, onChange: (e) => setFirstName(cleanAlpha(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "First name" })), /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Last Name"), /* @__PURE__ */ import_react7.default.createElement("input", { type: "text", value: lastName, onChange: (e) => setLastName(cleanAlpha(e.target.value)), required: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Last name" }))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react7.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, "Organization Name"), /* @__PURE__ */ import_react7.default.createElement("input", { type: "text", value: orgName, onChange: (e) => setOrgName(cleanOrgName(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "Acme Corporation" }))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "PHONE_ID") && /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-6 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
708
|
+
PhoneInput,
|
|
709
|
+
{
|
|
710
|
+
label: "Phone Number",
|
|
711
|
+
value: phoneNumber,
|
|
712
|
+
onChange: setPhoneNumber,
|
|
713
|
+
selectedCountry,
|
|
714
|
+
onCountryClick: () => setIsCountryDialogOpen(true),
|
|
715
|
+
disabled: isSubmitting
|
|
716
|
+
}
|
|
717
|
+
), mode === "SIGNUP" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ import_react7.default.createElement("input", { type: "checkbox", id: "zairus-terms", checked: agreedToTerms, onChange: (e) => setAgreedToTerms(e.target.checked), className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer", required: true }), /* @__PURE__ */ import_react7.default.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ import_react7.default.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Terms of Service"), " and ", /* @__PURE__ */ import_react7.default.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline " }, "Privacy Policy"), "."))), /* @__PURE__ */ import_react7.default.createElement(ThreeDActionButton, { type: "submit", disabled: isContinueDisabled(), isLoading: isSubmitting, className: "w-full mt-10" }, "Continue"))), step === "OTP" && /* @__PURE__ */ import_react7.default.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ import_react7.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react7.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter your 6-digit security passcode or OTP.")), /* @__PURE__ */ import_react7.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
|
|
561
718
|
e.preventDefault();
|
|
562
719
|
verifyOtpCode(otp.join(""));
|
|
563
|
-
} }, /* @__PURE__ */
|
|
720
|
+
} }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react7.default.createElement(
|
|
564
721
|
"input",
|
|
565
722
|
{
|
|
566
723
|
key: index,
|
|
@@ -577,27 +734,27 @@ function AuthFormInner({
|
|
|
577
734
|
},
|
|
578
735
|
className: "w-10 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
579
736
|
}
|
|
580
|
-
))), /* @__PURE__ */
|
|
737
|
+
))), /* @__PURE__ */ import_react7.default.createElement(ThreeDActionButton, { type: "submit", disabled: otp.join("").length < 6, isLoading: isSubmitting, className: "w-full" }, "Verify Code")), userHasPasskey && /* @__PURE__ */ import_react7.default.createElement("div", { className: "pt-6" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
581
738
|
"button",
|
|
582
739
|
{
|
|
583
740
|
onClick: triggerPasskeyLogin,
|
|
584
741
|
disabled: isSubmitting,
|
|
585
|
-
className: "w-full py-2.5 rounded-full text-black border border-neutral-200
|
|
742
|
+
className: "w-full py-2.5 rounded-full text-black border border-neutral-200 hover:bg-neutral-50 text-xs tracking-wide transition-colors outline-none disabled:opacity-50"
|
|
586
743
|
},
|
|
587
744
|
"Use Passkey / Biometrics"
|
|
588
|
-
))))));
|
|
745
|
+
)))))));
|
|
589
746
|
}
|
|
590
747
|
var PipleAuth = (props) => {
|
|
591
748
|
if (props.useRecaptcha && props.recaptchaSiteKey) {
|
|
592
|
-
return /* @__PURE__ */
|
|
749
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_react_google_recaptcha_v3.GoogleReCaptchaProvider, { reCaptchaKey: props.recaptchaSiteKey }, /* @__PURE__ */ import_react7.default.createElement(import_react7.Suspense, { fallback: /* @__PURE__ */ import_react7.default.createElement("div", { className: "h-64 flex items-center justify-center" }, /* @__PURE__ */ import_react7.default.createElement(InputSpinner2, null)) }, /* @__PURE__ */ import_react7.default.createElement(AuthFormInner, { ...props })));
|
|
593
750
|
}
|
|
594
|
-
return /* @__PURE__ */
|
|
751
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_react7.Suspense, { fallback: /* @__PURE__ */ import_react7.default.createElement("div", { className: "h-64 flex items-center justify-center" }, /* @__PURE__ */ import_react7.default.createElement(InputSpinner2, null)) }, /* @__PURE__ */ import_react7.default.createElement(AuthFormInner, { ...props }));
|
|
595
752
|
};
|
|
596
753
|
|
|
597
754
|
// src/components/Footer.tsx
|
|
598
|
-
var
|
|
755
|
+
var import_react8 = __toESM(require("react"));
|
|
599
756
|
var import_link3 = __toESM(require("next/link"));
|
|
600
|
-
var
|
|
757
|
+
var import_react9 = require("@hugeicons/react");
|
|
601
758
|
var Footer = ({
|
|
602
759
|
description,
|
|
603
760
|
columns,
|
|
@@ -605,20 +762,20 @@ var Footer = ({
|
|
|
605
762
|
copyrightText,
|
|
606
763
|
topSection
|
|
607
764
|
}) => {
|
|
608
|
-
const [openCol, setOpenCol] = (0,
|
|
765
|
+
const [openCol, setOpenCol] = (0, import_react8.useState)(null);
|
|
609
766
|
const toggleColumn = (idx) => {
|
|
610
767
|
setOpenCol(openCol === idx ? null : idx);
|
|
611
768
|
};
|
|
612
|
-
return /* @__PURE__ */
|
|
769
|
+
return /* @__PURE__ */ import_react8.default.createElement("div", { className: "" }, topSection && topSection, /* @__PURE__ */ import_react8.default.createElement("footer", { className: "relative px-6 overflow-hidden flex flex-col" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "relative w-full max-w-7xl mx-auto z-20 flex flex-col" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "relative py-12 md:py-16" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col lg:flex-row justify-between items-start gap-12 lg:gap-16 mb-12 text-left" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "w-full lg:max-w-sm flex flex-col items-start justify-between shrink-0" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-4 mb-4" }, /* @__PURE__ */ import_react8.default.createElement("img", { src: "https://retinalabs.company/assets/images/ndpr.avif", alt: "NDPR", className: "w-28 h-auto object-contain filter grayscale opacity-80" }), /* @__PURE__ */ import_react8.default.createElement("img", { src: "https://retinalabs.company/assets/images/gdpr.avif", alt: "GDPR", className: "w-12 h-12 object-contain filter grayscale opacity-80" })), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-neutral-600 leading-relaxed pr-4" }, description))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "w-full lg:flex-1 lg:max-w-2xl" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "hidden md:grid grid-cols-2 gap-x-16 lg:gap-x-24 gap-y-12" }, columns.map((col, idx) => /* @__PURE__ */ import_react8.default.createElement("div", { key: idx, className: "flex flex-col" }, /* @__PURE__ */ import_react8.default.createElement("h4", { className: "text-[11px] tracking-[0.2em] text-black mb-6 " }, col.title), /* @__PURE__ */ import_react8.default.createElement("ul", { className: "space-y-4 text-[13px] text-neutral-500" }, col.links.map((link, lIdx) => /* @__PURE__ */ import_react8.default.createElement("li", { key: lIdx }, link.isExternal ? /* @__PURE__ */ import_react8.default.createElement("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "hover:text-black transition-colors block truncate" }, link.label) : /* @__PURE__ */ import_react8.default.createElement(import_link3.default, { href: link.href, className: "hover:text-black transition-colors block truncate" }, link.label))))))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col md:hidden w-full border-t border-neutral-200 mt-4" }, columns.map((col, idx) => {
|
|
613
770
|
const isOpen = openCol === idx;
|
|
614
|
-
return /* @__PURE__ */
|
|
771
|
+
return /* @__PURE__ */ import_react8.default.createElement("div", { key: idx, className: "border-b border-neutral-200" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
615
772
|
"button",
|
|
616
773
|
{
|
|
617
774
|
onClick: () => toggleColumn(idx),
|
|
618
775
|
className: "w-full flex items-center justify-between py-5 text-left outline-none"
|
|
619
776
|
},
|
|
620
|
-
/* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
777
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] tracking-[0.2em] text-black " }, col.title),
|
|
778
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
622
779
|
"svg",
|
|
623
780
|
{
|
|
624
781
|
className: `w-4 h-4 text-neutral-400 transition-transform duration-300 ${isOpen ? "rotate-180" : ""}`,
|
|
@@ -626,10 +783,10 @@ var Footer = ({
|
|
|
626
783
|
viewBox: "0 0 24 24",
|
|
627
784
|
stroke: "currentColor"
|
|
628
785
|
},
|
|
629
|
-
/* @__PURE__ */
|
|
786
|
+
/* @__PURE__ */ import_react8.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M19 9l-7 7-7-7" })
|
|
630
787
|
)
|
|
631
|
-
), /* @__PURE__ */
|
|
632
|
-
})))), /* @__PURE__ */
|
|
788
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", { className: `grid transition-all duration-300 ease-in-out ${isOpen ? "grid-rows-[1fr] pb-6 opacity-100" : "grid-rows-[0fr] opacity-0"}` }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "overflow-hidden" }, /* @__PURE__ */ import_react8.default.createElement("ul", { className: "space-y-4 text-[13px] text-neutral-500 pt-2" }, col.links.map((link, lIdx) => /* @__PURE__ */ import_react8.default.createElement("li", { key: lIdx }, link.isExternal ? /* @__PURE__ */ import_react8.default.createElement("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "hover:text-black transition-colors" }, link.label) : /* @__PURE__ */ import_react8.default.createElement(import_link3.default, { href: link.href, className: "hover:text-black transition-colors" }, link.label)))))));
|
|
789
|
+
})))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "pt-8 mt-4 flex flex-col-reverse md:flex-row justify-between items-start md:items-center gap-6 relative z-20" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-neutral-400 tracking-widest text-left" }, copyrightText), socialLinks && socialLinks.length > 0 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-6" }, socialLinks.map((social, idx) => /* @__PURE__ */ import_react8.default.createElement(
|
|
633
790
|
"a",
|
|
634
791
|
{
|
|
635
792
|
key: idx,
|
|
@@ -638,38 +795,38 @@ var Footer = ({
|
|
|
638
795
|
rel: "noopener noreferrer",
|
|
639
796
|
className: "text-neutral-400 hover:text-black transition-colors"
|
|
640
797
|
},
|
|
641
|
-
/* @__PURE__ */
|
|
798
|
+
/* @__PURE__ */ import_react8.default.createElement(import_react9.HugeiconsIcon, { icon: social.icon, size: 20 })
|
|
642
799
|
))))))));
|
|
643
800
|
};
|
|
644
801
|
|
|
645
802
|
// src/components/MobileNav.tsx
|
|
646
|
-
var
|
|
803
|
+
var import_react10 = __toESM(require("react"));
|
|
647
804
|
var import_link4 = __toESM(require("next/link"));
|
|
648
805
|
var import_navigation3 = require("next/navigation");
|
|
649
|
-
var
|
|
806
|
+
var import_react11 = require("@hugeicons/react");
|
|
650
807
|
var MobileNav = ({ items }) => {
|
|
651
808
|
const pathname = (0, import_navigation3.usePathname)();
|
|
652
809
|
if (!items || items.length === 0) return null;
|
|
653
810
|
const pathMatches = items.some((item) => {
|
|
654
811
|
return item.href === "/" || item.href === "/app" ? pathname === "/" || pathname === "/app" : pathname === item.href || pathname?.startsWith(`${item.href}/`);
|
|
655
812
|
});
|
|
656
|
-
return /* @__PURE__ */
|
|
813
|
+
return /* @__PURE__ */ import_react10.default.createElement("div", { className: "fixed bottom-6 inset-x-0 z-100 flex justify-center pointer-events-none px-3 animate-in slide-in-from-bottom-8 fade-in duration-500 md:hidden" }, /* @__PURE__ */ import_react10.default.createElement("nav", { className: "pointer-events-auto w-full max-w-sm bg-white/50 backdrop-blur-xl shadow-[0_8px_30px_rgb(0,0,0,0.08)] rounded-full px-6 py-2.5 flex items-center justify-between" }, items.map((item, index) => {
|
|
657
814
|
const isActive = !pathMatches && index === 0 ? true : item.href === "/" || item.href === "/app" ? pathname === "/" || pathname === "/app" : pathname === item.href || pathname?.startsWith(`${item.href}/`);
|
|
658
|
-
return /* @__PURE__ */
|
|
815
|
+
return /* @__PURE__ */ import_react10.default.createElement(
|
|
659
816
|
import_link4.default,
|
|
660
817
|
{
|
|
661
818
|
key: item.label,
|
|
662
819
|
href: item.href,
|
|
663
820
|
className: "flex flex-col items-center justify-center gap-1 min-w-14 transition-transform active:scale-95 outline-none"
|
|
664
821
|
},
|
|
665
|
-
/* @__PURE__ */
|
|
666
|
-
|
|
822
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: `transition-colors duration-300 ${isActive ? "text-black" : "text-neutral-400 hover:text-neutral-600"}` }, /* @__PURE__ */ import_react10.default.createElement(
|
|
823
|
+
import_react11.HugeiconsIcon,
|
|
667
824
|
{
|
|
668
825
|
icon: item.icon,
|
|
669
826
|
size: 20
|
|
670
827
|
}
|
|
671
828
|
)),
|
|
672
|
-
/* @__PURE__ */
|
|
829
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
673
830
|
"span",
|
|
674
831
|
{
|
|
675
832
|
className: `text-[9px] tracking-wide transition-colors duration-300 ${isActive ? "text-black" : "text-neutral-400"}`
|
|
@@ -685,10 +842,10 @@ var import_react15 = __toESM(require("react"));
|
|
|
685
842
|
var import_react_hot_toast3 = __toESM(require("react-hot-toast"));
|
|
686
843
|
|
|
687
844
|
// src/components/ManagedToaster.tsx
|
|
688
|
-
var
|
|
845
|
+
var import_react12 = __toESM(require("react"));
|
|
689
846
|
var import_react_hot_toast2 = require("react-hot-toast");
|
|
690
847
|
var ManagedToaster = () => {
|
|
691
|
-
return /* @__PURE__ */
|
|
848
|
+
return /* @__PURE__ */ import_react12.default.createElement(
|
|
692
849
|
import_react_hot_toast2.Toaster,
|
|
693
850
|
{
|
|
694
851
|
position: "top-right",
|
|
@@ -719,56 +876,6 @@ var ManagedToaster = () => {
|
|
|
719
876
|
);
|
|
720
877
|
};
|
|
721
878
|
|
|
722
|
-
// src/components/TextInput.tsx
|
|
723
|
-
var import_react12 = __toESM(require("react"));
|
|
724
|
-
var TextInput = ({
|
|
725
|
-
label,
|
|
726
|
-
value,
|
|
727
|
-
onChange,
|
|
728
|
-
placeholder,
|
|
729
|
-
maxLength,
|
|
730
|
-
disabled,
|
|
731
|
-
readOnly,
|
|
732
|
-
type = "text",
|
|
733
|
-
onClick
|
|
734
|
-
}) => /* @__PURE__ */ import_react12.default.createElement("div", { className: "space-y-2 flex-1 w-full", onClick }, label && /* @__PURE__ */ import_react12.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, label), /* @__PURE__ */ import_react12.default.createElement(
|
|
735
|
-
"input",
|
|
736
|
-
{
|
|
737
|
-
type,
|
|
738
|
-
value,
|
|
739
|
-
onChange: (e) => onChange(e.target.value.substring(0, maxLength || 100)),
|
|
740
|
-
placeholder,
|
|
741
|
-
disabled,
|
|
742
|
-
readOnly,
|
|
743
|
-
autoComplete: "off",
|
|
744
|
-
spellCheck: "false",
|
|
745
|
-
className: `w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50 ${readOnly ? "cursor-pointer" : ""}`
|
|
746
|
-
}
|
|
747
|
-
));
|
|
748
|
-
var NumberInput = ({
|
|
749
|
-
label,
|
|
750
|
-
value,
|
|
751
|
-
onChange,
|
|
752
|
-
placeholder,
|
|
753
|
-
maxLength,
|
|
754
|
-
disabled
|
|
755
|
-
}) => /* @__PURE__ */ import_react12.default.createElement("div", { className: "space-y-2 flex-1 w-full" }, label && /* @__PURE__ */ import_react12.default.createElement("label", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block " }, label), /* @__PURE__ */ import_react12.default.createElement(
|
|
756
|
-
"input",
|
|
757
|
-
{
|
|
758
|
-
type: "text",
|
|
759
|
-
value,
|
|
760
|
-
onChange: (e) => {
|
|
761
|
-
const numOnly = e.target.value.replace(/[^0-9]/g, "");
|
|
762
|
-
onChange(numOnly.substring(0, maxLength || 20));
|
|
763
|
-
},
|
|
764
|
-
placeholder,
|
|
765
|
-
disabled,
|
|
766
|
-
autoComplete: "off",
|
|
767
|
-
spellCheck: "false",
|
|
768
|
-
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black disabled:opacity-50"
|
|
769
|
-
}
|
|
770
|
-
));
|
|
771
|
-
|
|
772
879
|
// src/components/Banner.tsx
|
|
773
880
|
var import_react13 = __toESM(require("react"));
|
|
774
881
|
var import_react14 = require("@hugeicons/react");
|
|
@@ -828,7 +935,7 @@ var Banner = ({
|
|
|
828
935
|
// src/components/UniversalOrganizationPage.tsx
|
|
829
936
|
var import_react16 = require("@hugeicons/react");
|
|
830
937
|
var import_core_free_icons3 = require("@hugeicons/core-free-icons");
|
|
831
|
-
var
|
|
938
|
+
var InputSpinner3 = () => /* @__PURE__ */ import_react15.default.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react15.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ import_react15.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
832
939
|
var UniversalOrganizationPage = ({
|
|
833
940
|
initialOrgName,
|
|
834
941
|
initialSlug,
|
|
@@ -960,7 +1067,7 @@ var UniversalOrganizationPage = ({
|
|
|
960
1067
|
className: "w-full px-2 py-3 text-sm bg-transparent text-black outline-none disabled:opacity-50 disabled:cursor-not-allowed",
|
|
961
1068
|
placeholder: "sovereign-user-handle"
|
|
962
1069
|
}
|
|
963
|
-
), /* @__PURE__ */ import_react15.default.createElement("span", { className: "text-neutral-400 text-sm py-3 pr-8 shrink-0 whitespace-nowrap" }, slugPrefixUrl), /* @__PURE__ */ import_react15.default.createElement("div", { className: "absolute right-2 top-1/2 -translate-y-1/2" }, isCheckingSlug && /* @__PURE__ */ import_react15.default.createElement(
|
|
1070
|
+
), /* @__PURE__ */ import_react15.default.createElement("span", { className: "text-neutral-400 text-sm py-3 pr-8 shrink-0 whitespace-nowrap" }, slugPrefixUrl), /* @__PURE__ */ import_react15.default.createElement("div", { className: "absolute right-2 top-1/2 -translate-y-1/2" }, isCheckingSlug && /* @__PURE__ */ import_react15.default.createElement(InputSpinner3, null), !isCheckingSlug && !isReadOnly && slug !== initialSlug && slug.length >= 3 && slugAvailable === false && /* @__PURE__ */ import_react15.default.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-red-100" }, /* @__PURE__ */ import_react15.default.createElement("svg", { className: "w-2 h-2 text-red-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react15.default.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" }))), !isCheckingSlug && !isReadOnly && slug !== initialSlug && slug.length >= 3 && slugAvailable === true && /* @__PURE__ */ import_react15.default.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-green-100" }, /* @__PURE__ */ import_react15.default.createElement("svg", { className: "w-2 h-2 text-green-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react15.default.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M16.707 5.293a1 1 0 00-1.414 0L8 12.586 4.707 9.293a1 1 0 10-1.414 1.414l4 4a1 1 0 001.414 0l8-8a1 1 0 000-1.414z" })))))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "pt-8 mt-2 flex items-center gap-4" }, /* @__PURE__ */ import_react15.default.createElement(
|
|
964
1071
|
ThreeDActionButton,
|
|
965
1072
|
{
|
|
966
1073
|
type: "submit",
|
|
@@ -992,14 +1099,14 @@ var import_core_free_icons4 = require("@hugeicons/core-free-icons");
|
|
|
992
1099
|
var UniversalProfileSettings = ({
|
|
993
1100
|
initialFirstName,
|
|
994
1101
|
initialLastName,
|
|
995
|
-
|
|
1102
|
+
phoneNumber,
|
|
996
1103
|
accountStatus = "GOOD",
|
|
997
1104
|
memberSince,
|
|
998
1105
|
isReadOnly = false,
|
|
999
1106
|
bannerProps,
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1107
|
+
hasPasscode = false,
|
|
1108
|
+
isPasscodeLoading = false,
|
|
1109
|
+
onSavePasscode,
|
|
1003
1110
|
onSaveProfile,
|
|
1004
1111
|
onBack
|
|
1005
1112
|
}) => {
|
|
@@ -1009,11 +1116,11 @@ var UniversalProfileSettings = ({
|
|
|
1009
1116
|
const [firstName, setFirstName] = (0, import_react17.useState)(initialFirstName);
|
|
1010
1117
|
const [lastName, setLastName] = (0, import_react17.useState)(initialLastName);
|
|
1011
1118
|
const [isSubmitting, setIsSubmitting] = (0, import_react17.useState)(false);
|
|
1012
|
-
const [
|
|
1013
|
-
const [
|
|
1014
|
-
const [
|
|
1015
|
-
const [
|
|
1016
|
-
const [
|
|
1119
|
+
const [isPasscodeModalOpen, setIsPasscodeModalOpen] = (0, import_react17.useState)(false);
|
|
1120
|
+
const [oldPasscode, setOldPasscode] = (0, import_react17.useState)("");
|
|
1121
|
+
const [newPasscode, setNewPasscode] = (0, import_react17.useState)("");
|
|
1122
|
+
const [confirmPasscode, setConfirmPasscode] = (0, import_react17.useState)("");
|
|
1123
|
+
const [isPasscodeSubmitting, setIsPasscodeSubmitting] = (0, import_react17.useState)(false);
|
|
1017
1124
|
(0, import_react17.useEffect)(() => {
|
|
1018
1125
|
setFirstName(initialFirstName || "");
|
|
1019
1126
|
setLastName(initialLastName || "");
|
|
@@ -1042,40 +1149,40 @@ var UniversalProfileSettings = ({
|
|
|
1042
1149
|
setIsSubmitting(false);
|
|
1043
1150
|
}
|
|
1044
1151
|
};
|
|
1045
|
-
const
|
|
1046
|
-
if (
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1152
|
+
const closePasscodeModal = () => {
|
|
1153
|
+
if (isPasscodeSubmitting) return;
|
|
1154
|
+
setIsPasscodeModalOpen(false);
|
|
1155
|
+
setOldPasscode("");
|
|
1156
|
+
setNewPasscode("");
|
|
1157
|
+
setConfirmPasscode("");
|
|
1051
1158
|
};
|
|
1052
|
-
const
|
|
1053
|
-
setter(val.replace(/\D/g, "").substring(0,
|
|
1159
|
+
const handlePasscodeInput = (val, setter) => {
|
|
1160
|
+
setter(val.replace(/\D/g, "").substring(0, 6));
|
|
1054
1161
|
};
|
|
1055
|
-
const
|
|
1162
|
+
const handlePasscodeSubmit = async (e) => {
|
|
1056
1163
|
e.preventDefault();
|
|
1057
|
-
if (!
|
|
1058
|
-
if (
|
|
1059
|
-
if (
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1164
|
+
if (!onSavePasscode) return;
|
|
1165
|
+
if (hasPasscode && oldPasscode.length !== 6) return import_react_hot_toast4.default.error("Old Passcode must be exactly 6-digits.");
|
|
1166
|
+
if (newPasscode.length !== 6) return import_react_hot_toast4.default.error("New Passcode must be exactly 6-digits.");
|
|
1167
|
+
if (newPasscode !== confirmPasscode) return import_react_hot_toast4.default.error("New Passcodes do not match.");
|
|
1168
|
+
setIsPasscodeSubmitting(true);
|
|
1062
1169
|
try {
|
|
1063
|
-
const action =
|
|
1064
|
-
const res = await
|
|
1170
|
+
const action = hasPasscode ? "change_passcode" : "create_passcode";
|
|
1171
|
+
const res = await onSavePasscode({
|
|
1065
1172
|
action,
|
|
1066
|
-
|
|
1067
|
-
|
|
1173
|
+
oldPasscode: hasPasscode ? oldPasscode : void 0,
|
|
1174
|
+
newPasscode
|
|
1068
1175
|
});
|
|
1069
1176
|
if (res.success) {
|
|
1070
|
-
import_react_hot_toast4.default.success(res.message || "
|
|
1071
|
-
|
|
1177
|
+
import_react_hot_toast4.default.success(res.message || "Passcode updated successfully.");
|
|
1178
|
+
closePasscodeModal();
|
|
1072
1179
|
} else {
|
|
1073
|
-
import_react_hot_toast4.default.error(res.error || "Failed to update
|
|
1180
|
+
import_react_hot_toast4.default.error(res.error || "Failed to update Passcode.");
|
|
1074
1181
|
}
|
|
1075
1182
|
} catch (error) {
|
|
1076
1183
|
import_react_hot_toast4.default.error("Uh oh! Something went wrong.");
|
|
1077
1184
|
} finally {
|
|
1078
|
-
|
|
1185
|
+
setIsPasscodeSubmitting(false);
|
|
1079
1186
|
}
|
|
1080
1187
|
};
|
|
1081
1188
|
const hasChanges = firstName !== initialFirstName || lastName !== initialLastName;
|
|
@@ -1088,7 +1195,7 @@ var UniversalProfileSettings = ({
|
|
|
1088
1195
|
},
|
|
1089
1196
|
/* @__PURE__ */ import_react17.default.createElement(import_react18.HugeiconsIcon, { icon: import_core_free_icons4.ArrowLeft01Icon, size: 16 }),
|
|
1090
1197
|
" Back"
|
|
1091
|
-
)), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col max-w-3xl w-full mx-auto rounded-2xl p-6 bg-white
|
|
1198
|
+
)), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col max-w-3xl w-full mx-auto rounded-2xl p-6 bg-white gap-8 animate-in fade-in duration-300" }, /* @__PURE__ */ import_react17.default.createElement(ManagedToaster, null), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col sm:flex-row sm:items-start justify-between gap-3 sm:gap-4" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react17.default.createElement("h1", { className: "text-black text-xl mb-1 truncate tracking-tight" }, "Personal Settings"), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-xs text-neutral-500 truncate" }, "Manage your personal account profile.")), isReadOnly && /* @__PURE__ */ import_react17.default.createElement("span", { className: "p-2 w-9 h-9 bg-neutral-100 text-neutral-400 rounded-full shrink-0" }, /* @__PURE__ */ import_react17.default.createElement(import_react18.HugeiconsIcon, { icon: import_core_free_icons4.CircleLock02Icon, size: 18, className: "text-current" }))), bannerProps && /* @__PURE__ */ import_react17.default.createElement(Banner, { ...bannerProps }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "w-full max-w-5xl" }, /* @__PURE__ */ import_react17.default.createElement("form", { className: "flex flex-col gap-8", onSubmit: handleSave, autoComplete: "off" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col sm:flex-row gap-6" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
1092
1199
|
TextInput,
|
|
1093
1200
|
{
|
|
1094
1201
|
label: "First Name",
|
|
@@ -1109,17 +1216,17 @@ var UniversalProfileSettings = ({
|
|
|
1109
1216
|
))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-2 min-w-0" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
1110
1217
|
TextInput,
|
|
1111
1218
|
{
|
|
1112
|
-
label: "
|
|
1113
|
-
value:
|
|
1219
|
+
label: "Registered Phone Number",
|
|
1220
|
+
value: phoneNumber,
|
|
1114
1221
|
onChange: () => {
|
|
1115
1222
|
},
|
|
1116
1223
|
disabled: true
|
|
1117
1224
|
}
|
|
1118
|
-
), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-[11px] text-neutral-500 mt-1 truncate" }, "To change your
|
|
1225
|
+
), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-[11px] text-neutral-500 mt-1 truncate" }, "To change your primary number, please contact support.")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between pt-8 mt-2 gap-6 sm:gap-4" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-6 min-w-0" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block truncate" }, "Account Status"), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-xs text-black block truncate" }, accountStatus)), /* @__PURE__ */ import_react17.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-[11px] text-neutral-400 tracking-[0.2em] block truncate" }, "Member Since"), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-xs text-black block truncate" }, memberSince ? new Date(memberSince).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" }) : "N/A")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "min-w-0 pl-4" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
1119
1226
|
"button",
|
|
1120
1227
|
{
|
|
1121
1228
|
type: "button",
|
|
1122
|
-
onClick: () =>
|
|
1229
|
+
onClick: () => setIsPasscodeModalOpen(true),
|
|
1123
1230
|
className: "w-9 h-9 flex items-center justify-center border border-neutral-200 rounded-full text-black hover:bg-neutral-50 transition-colors outline-none"
|
|
1124
1231
|
},
|
|
1125
1232
|
/* @__PURE__ */ import_react17.default.createElement(import_react18.HugeiconsIcon, { icon: import_core_free_icons4.LockKeyIcon, size: 17, className: "text-black" })
|
|
@@ -1143,48 +1250,48 @@ var UniversalProfileSettings = ({
|
|
|
1143
1250
|
className: "min-w-32 w-full sm:w-auto"
|
|
1144
1251
|
},
|
|
1145
1252
|
"Save Changes"
|
|
1146
|
-
))))),
|
|
1253
|
+
))))), isPasscodeModalOpen && /* @__PURE__ */ import_react17.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "absolute inset-0 bg-black/40", onClick: closePasscodeModal }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react17.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, hasPasscode ? "Change Passcode" : "Create Security Passcode"), /* @__PURE__ */ import_react17.default.createElement("button", { onClick: closePasscodeModal, disabled: isPasscodeSubmitting, className: "text-neutral-400 hover:text-black transition-colors outline-none disabled:opacity-50" }, /* @__PURE__ */ import_react17.default.createElement(import_react18.HugeiconsIcon, { icon: import_core_free_icons4.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "p-6" }, isPasscodeLoading ? /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col items-center justify-center py-10" }, /* @__PURE__ */ import_react17.default.createElement(import_react18.HugeiconsIcon, { icon: import_core_free_icons4.Loading03Icon, size: 28, className: "animate-spin text-neutral-400 mb-4" })) : /* @__PURE__ */ import_react17.default.createElement("form", { onSubmit: handlePasscodeSubmit, className: "flex flex-col gap-6" }, hasPasscode && /* @__PURE__ */ import_react17.default.createElement(
|
|
1147
1254
|
TextInput,
|
|
1148
1255
|
{
|
|
1149
1256
|
type: "password",
|
|
1150
|
-
label: "Old
|
|
1151
|
-
maxLength:
|
|
1152
|
-
disabled:
|
|
1153
|
-
value:
|
|
1154
|
-
onChange: (val) =>
|
|
1155
|
-
placeholder: "\u2022\u2022\u2022\u2022"
|
|
1257
|
+
label: "Old 6-Digit Passcode",
|
|
1258
|
+
maxLength: 6,
|
|
1259
|
+
disabled: isPasscodeSubmitting,
|
|
1260
|
+
value: oldPasscode,
|
|
1261
|
+
onChange: (val) => handlePasscodeInput(val, setOldPasscode),
|
|
1262
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
1156
1263
|
}
|
|
1157
1264
|
), /* @__PURE__ */ import_react17.default.createElement(
|
|
1158
1265
|
TextInput,
|
|
1159
1266
|
{
|
|
1160
1267
|
type: "password",
|
|
1161
|
-
label:
|
|
1162
|
-
maxLength:
|
|
1163
|
-
disabled:
|
|
1164
|
-
value:
|
|
1165
|
-
onChange: (val) =>
|
|
1166
|
-
placeholder: "\u2022\u2022\u2022\u2022"
|
|
1268
|
+
label: hasPasscode ? "New 6-Digit Passcode" : "Enter 6-Digit Passcode",
|
|
1269
|
+
maxLength: 6,
|
|
1270
|
+
disabled: isPasscodeSubmitting,
|
|
1271
|
+
value: newPasscode,
|
|
1272
|
+
onChange: (val) => handlePasscodeInput(val, setNewPasscode),
|
|
1273
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
1167
1274
|
}
|
|
1168
1275
|
), /* @__PURE__ */ import_react17.default.createElement(
|
|
1169
1276
|
TextInput,
|
|
1170
1277
|
{
|
|
1171
1278
|
type: "password",
|
|
1172
|
-
label: "Retype New
|
|
1173
|
-
maxLength:
|
|
1174
|
-
disabled:
|
|
1175
|
-
value:
|
|
1176
|
-
onChange: (val) =>
|
|
1177
|
-
placeholder: "\u2022\u2022\u2022\u2022"
|
|
1279
|
+
label: "Retype New Passcode",
|
|
1280
|
+
maxLength: 6,
|
|
1281
|
+
disabled: isPasscodeSubmitting,
|
|
1282
|
+
value: confirmPasscode,
|
|
1283
|
+
onChange: (val) => handlePasscodeInput(val, setConfirmPasscode),
|
|
1284
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
1178
1285
|
}
|
|
1179
1286
|
), /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
1180
1287
|
ThreeDActionButton,
|
|
1181
1288
|
{
|
|
1182
1289
|
type: "submit",
|
|
1183
|
-
disabled:
|
|
1184
|
-
isLoading:
|
|
1290
|
+
disabled: isPasscodeSubmitting || newPasscode.length !== 6 || confirmPasscode.length !== 6 || hasPasscode && oldPasscode.length !== 6,
|
|
1291
|
+
isLoading: isPasscodeSubmitting,
|
|
1185
1292
|
className: "w-full"
|
|
1186
1293
|
},
|
|
1187
|
-
|
|
1294
|
+
hasPasscode ? "Update Passcode" : "Set Passcode"
|
|
1188
1295
|
))))))));
|
|
1189
1296
|
};
|
|
1190
1297
|
|
|
@@ -1503,48 +1610,15 @@ var UniversalTransactionPage = ({
|
|
|
1503
1610
|
var import_react25 = __toESM(require("react"));
|
|
1504
1611
|
var import_react26 = require("@hugeicons/react");
|
|
1505
1612
|
var import_core_free_icons8 = require("@hugeicons/core-free-icons");
|
|
1506
|
-
var renderKMT = (val, currencySymbol) => {
|
|
1507
|
-
let formatted = val;
|
|
1508
|
-
let suffix = "";
|
|
1509
|
-
if (val >= 1e12) {
|
|
1510
|
-
formatted = val / 1e12;
|
|
1511
|
-
suffix = "T";
|
|
1512
|
-
} else if (val >= 1e6) {
|
|
1513
|
-
formatted = val / 1e6;
|
|
1514
|
-
suffix = "M";
|
|
1515
|
-
} else if (val >= 1e3) {
|
|
1516
|
-
formatted = val / 1e3;
|
|
1517
|
-
suffix = "k";
|
|
1518
|
-
}
|
|
1519
|
-
const displayStr = parseFloat(formatted.toFixed(2)).toString();
|
|
1520
|
-
return /* @__PURE__ */ import_react25.default.createElement("span", { className: "flex items-baseline mt-1" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[13px] text-neutral-800 mr-0.5 " }, currencySymbol), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-xl text-neutral-800 tracking-tight " }, displayStr), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[14px] text-neutral-600 ml-0.5 " }, suffix));
|
|
1521
|
-
};
|
|
1522
|
-
var renderKMT2 = (val, currencySymbol) => {
|
|
1523
|
-
let formatted = val;
|
|
1524
|
-
let suffix = "";
|
|
1525
|
-
if (val >= 1e12) {
|
|
1526
|
-
formatted = val / 1e12;
|
|
1527
|
-
suffix = "T";
|
|
1528
|
-
} else if (val >= 1e6) {
|
|
1529
|
-
formatted = val / 1e6;
|
|
1530
|
-
suffix = "M";
|
|
1531
|
-
} else if (val >= 1e3) {
|
|
1532
|
-
formatted = val / 1e3;
|
|
1533
|
-
suffix = "k";
|
|
1534
|
-
}
|
|
1535
|
-
const displayStr = parseFloat(formatted.toFixed(2)).toString();
|
|
1536
|
-
return /* @__PURE__ */ import_react25.default.createElement("span", { className: "flex items-baseline mt-1" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[13px] text-white mr-0.5 " }, currencySymbol), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-xl text-white tracking-tight " }, displayStr), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[14px] text-white/50 ml-0.5 " }, suffix));
|
|
1537
|
-
};
|
|
1538
1613
|
var UniversalHomeView = ({
|
|
1539
1614
|
fullName = "",
|
|
1540
1615
|
avatarSrc,
|
|
1541
|
-
balanceLabel = "
|
|
1616
|
+
balanceLabel = "Pending Balance",
|
|
1542
1617
|
balanceAmount,
|
|
1543
1618
|
balanceCurrency = "$",
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
secondaryAction,
|
|
1619
|
+
calculatorAction,
|
|
1620
|
+
buyCryptoAction,
|
|
1621
|
+
referralAction,
|
|
1548
1622
|
notifications = [],
|
|
1549
1623
|
notificationPage = 1,
|
|
1550
1624
|
notificationTotalPages = 1,
|
|
@@ -1608,7 +1682,7 @@ var UniversalHomeView = ({
|
|
|
1608
1682
|
setShowNotifDialog(true);
|
|
1609
1683
|
setSelectedNotif(null);
|
|
1610
1684
|
},
|
|
1611
|
-
className: "relative w-10 h-10 flex items-center justify-center rounded-full bg-white
|
|
1685
|
+
className: "relative w-10 h-10 flex items-center justify-center rounded-full bg-white outline-none hover:bg-neutral-50 transition-colors"
|
|
1612
1686
|
},
|
|
1613
1687
|
/* @__PURE__ */ import_react25.default.createElement(import_react26.HugeiconsIcon, { icon: import_core_free_icons8.Notification01Icon, size: 20, className: "text-black" }),
|
|
1614
1688
|
hasUnreadNotifs && /* @__PURE__ */ import_react25.default.createElement("span", { className: "absolute top-2.5 right-2.5 w-2 h-2 bg-red-500 rounded-full border border-white" })
|
|
@@ -1619,35 +1693,44 @@ var UniversalHomeView = ({
|
|
|
1619
1693
|
className: "text-neutral-400 hover:text-white transition-colors outline-none"
|
|
1620
1694
|
},
|
|
1621
1695
|
/* @__PURE__ */ import_react25.default.createElement(import_react26.HugeiconsIcon, { icon: isBalanceHidden ? import_core_free_icons8.ViewIcon : import_core_free_icons8.ViewOffSlashIcon, size: 16 })
|
|
1622
|
-
)), /* @__PURE__ */ import_react25.default.createElement("p", { className: `text-2xl text-white tracking-tight mb-6 tabular-nums flex items-baseline transition-all duration-300 ${isBalanceHidden ? "blur-sm opacity-40 select-none" : ""}` }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-lg text-neutral-400 mr-1" }, balanceCurrency), intPart, decPart && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-lg text-neutral-400" }, ".", decPart)), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center
|
|
1696
|
+
)), /* @__PURE__ */ import_react25.default.createElement("p", { className: `text-2xl text-white tracking-tight mb-6 tabular-nums flex items-baseline transition-all duration-300 ${isBalanceHidden ? "blur-sm opacity-40 select-none" : ""}` }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-lg text-neutral-400 mr-1" }, balanceCurrency), intPart, decPart && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-lg text-neutral-400" }, ".", decPart)), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center w-full" }, calculatorAction && /* @__PURE__ */ import_react25.default.createElement(
|
|
1623
1697
|
"button",
|
|
1624
1698
|
{
|
|
1625
|
-
onClick:
|
|
1626
|
-
className: "px-6 py-2 bg-white text-
|
|
1699
|
+
onClick: calculatorAction.onClick,
|
|
1700
|
+
className: "px-6 py-2 bg-transparent border border-white/20 text-white truncate text-[12px] rounded-full transition-colors hover:bg-white/10 outline-none text-center"
|
|
1627
1701
|
},
|
|
1628
|
-
"
|
|
1629
|
-
),
|
|
1630
|
-
"
|
|
1702
|
+
calculatorAction.label || "Rate Calculator"
|
|
1703
|
+
)))), /* @__PURE__ */ import_react25.default.createElement("div", { className: "grid grid-cols-2 gap-2" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
1704
|
+
"div",
|
|
1631
1705
|
{
|
|
1632
|
-
onClick:
|
|
1633
|
-
className: "
|
|
1706
|
+
onClick: buyCryptoAction?.onClick,
|
|
1707
|
+
className: "bg-[#143731] rounded-2xl p-5 relative overflow-hidden flex flex-col h-32 sm:h-36 cursor-pointer hover:opacity-90 transition-opacity"
|
|
1634
1708
|
},
|
|
1635
|
-
"
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1709
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "relative z-10 flex flex-col h-full justify-between" }, /* @__PURE__ */ import_react25.default.createElement("p", { className: "text-[15px] sm:text-[15px] text-white font-medium" }, "Buy Crypto"), /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-8 h-8 rounded-full bg-white/10 border border-white/10 flex items-center justify-center" }, /* @__PURE__ */ import_react25.default.createElement(import_react26.HugeiconsIcon, { icon: import_core_free_icons8.ArrowUpRight01Icon, size: 16, className: "text-white" }))),
|
|
1710
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
1711
|
+
"img",
|
|
1712
|
+
{
|
|
1713
|
+
src: "https://retinalabs.company/assets/images/save_box.avif",
|
|
1714
|
+
alt: "Buy Crypto",
|
|
1715
|
+
className: "absolute bottom-4 right-2 translate-x-1/4 translate-y-1/2 w-32 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
|
|
1716
|
+
}
|
|
1717
|
+
)
|
|
1718
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
1719
|
+
"div",
|
|
1645
1720
|
{
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
}
|
|
1650
|
-
|
|
1721
|
+
onClick: referralAction?.onClick,
|
|
1722
|
+
className: "bg-[#ceff8a] rounded-2xl p-5 relative overflow-hidden flex flex-col h-32 sm:h-36 cursor-pointer hover:opacity-90 transition-opacity"
|
|
1723
|
+
},
|
|
1724
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "relative z-10 flex flex-col h-full justify-between" }, /* @__PURE__ */ import_react25.default.createElement("p", { className: "text-[15px] sm:text-[15px] text-black font-medium" }, "Referral"), /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-8 h-8 rounded-full bg-black/5 border border-black/5 flex items-center justify-center" }, /* @__PURE__ */ import_react25.default.createElement(import_react26.HugeiconsIcon, { icon: import_core_free_icons8.ArrowRight01Icon, size: 16, className: "text-black" }))),
|
|
1725
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
1726
|
+
"img",
|
|
1727
|
+
{
|
|
1728
|
+
src: "https://retinalabs.company/assets/images/gift_box.avif",
|
|
1729
|
+
alt: "Referral",
|
|
1730
|
+
className: "absolute bottom-4 right-2 translate-x-1/4 translate-y-1/2 w-32 h-auto object-contain z-0 pointer-events-none drop-shadow-md"
|
|
1731
|
+
}
|
|
1732
|
+
)
|
|
1733
|
+
))), customContent && /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-full" }, customContent), /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-full mt-2" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
1651
1734
|
UniversalTransactionPage,
|
|
1652
1735
|
{
|
|
1653
1736
|
...transactionsProps,
|
|
@@ -1965,6 +2048,7 @@ var UniversalWalletPage = ({
|
|
|
1965
2048
|
// src/components/UniversalCardPage.tsx
|
|
1966
2049
|
var import_react31 = __toESM(require("react"));
|
|
1967
2050
|
var import_navigation4 = require("next/navigation");
|
|
2051
|
+
var import_react_hot_toast7 = __toESM(require("react-hot-toast"));
|
|
1968
2052
|
var import_react32 = require("@hugeicons/react");
|
|
1969
2053
|
var import_core_free_icons11 = require("@hugeicons/core-free-icons");
|
|
1970
2054
|
var UniversalCardPage = ({
|
|
@@ -1972,10 +2056,8 @@ var UniversalCardPage = ({
|
|
|
1972
2056
|
actionPath = "/app/cards/action/",
|
|
1973
2057
|
onReveal,
|
|
1974
2058
|
onFreeze,
|
|
1975
|
-
onSetLimits,
|
|
1976
2059
|
onDelete,
|
|
1977
|
-
onFundCard
|
|
1978
|
-
onCreateCard
|
|
2060
|
+
onFundCard
|
|
1979
2061
|
}) => {
|
|
1980
2062
|
const router = (0, import_navigation4.useRouter)();
|
|
1981
2063
|
const sortedCards = import_react31.default.useMemo(() => {
|
|
@@ -1989,7 +2071,6 @@ var UniversalCardPage = ({
|
|
|
1989
2071
|
const activeCard = sortedCards[activeTabIndex];
|
|
1990
2072
|
const [isBgLoaded, setIsBgLoaded] = (0, import_react31.useState)(false);
|
|
1991
2073
|
const [isFreezing, setIsFreezing] = (0, import_react31.useState)(false);
|
|
1992
|
-
const [isOverlayActionLoading, setIsOverlayActionLoading] = (0, import_react31.useState)(false);
|
|
1993
2074
|
const [showDeleteDialog, setShowDeleteDialog] = (0, import_react31.useState)(false);
|
|
1994
2075
|
const [isDeleting, setIsDeleting] = (0, import_react31.useState)(false);
|
|
1995
2076
|
(0, import_react31.useEffect)(() => {
|
|
@@ -1997,134 +2078,67 @@ var UniversalCardPage = ({
|
|
|
1997
2078
|
if (!activeCard?.cardBgSrc) return;
|
|
1998
2079
|
const img = new Image();
|
|
1999
2080
|
img.src = activeCard.cardBgSrc;
|
|
2000
|
-
img.onload = () =>
|
|
2001
|
-
setTimeout(() => setIsBgLoaded(true), 300);
|
|
2002
|
-
};
|
|
2081
|
+
img.onload = () => setIsBgLoaded(true);
|
|
2003
2082
|
}, [activeCard?.cardBgSrc]);
|
|
2004
2083
|
if (!activeCard || sortedCards.length === 0) {
|
|
2005
|
-
return /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative min-h-100 justify-center" },
|
|
2006
|
-
"button",
|
|
2007
|
-
{
|
|
2008
|
-
onClick: onCreateCard,
|
|
2009
|
-
className: "fixed bottom-24 right-6 sm:right-50 z-50 w-11 h-11 rounded-full bg-white shadow-xl flex items-center justify-center text-black transition-all outline-none"
|
|
2010
|
-
},
|
|
2011
|
-
/* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.PlusSignIcon, size: 18 })
|
|
2012
|
-
), /* @__PURE__ */ import_react31.default.createElement("div", { className: "p-6 w-full max-w-md mx-auto text-center" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-8 flex justify-center" }, /* @__PURE__ */ import_react31.default.createElement(
|
|
2013
|
-
"svg",
|
|
2014
|
-
{
|
|
2015
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
2016
|
-
viewBox: "0 0 24 24",
|
|
2017
|
-
className: "w-12 h-12 fill-neutral-100"
|
|
2018
|
-
},
|
|
2019
|
-
/* @__PURE__ */ import_react31.default.createElement("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" })
|
|
2020
|
-
)), /* @__PURE__ */ import_react31.default.createElement("h1", { className: "text-xl text-black tracking-tight mb-4" }, "No cards available"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-[13px] leading-[1.8] text-neutral-600 mb-12" }, "You do not have any virtual or physical cards generated yet.")));
|
|
2084
|
+
return /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative min-h-100 justify-center" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "p-6 w-full max-w-md mx-auto text-center" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-8 flex justify-center" }, /* @__PURE__ */ import_react31.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", className: "w-12 h-12 fill-neutral-100" }, /* @__PURE__ */ import_react31.default.createElement("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" }))), /* @__PURE__ */ import_react31.default.createElement("h1", { className: "text-xl text-black tracking-tight mb-4" }, "No cards available"), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-[13px] leading-[1.8] text-neutral-600 mb-12" }, "You do not have any active cards on your account.")));
|
|
2021
2085
|
}
|
|
2022
2086
|
const isActivated = activeCard.status === "ACTIVATED";
|
|
2023
2087
|
const isFrozen = activeCard.status === "FROZEN";
|
|
2024
2088
|
const isUnactivated = activeCard.status === "UNACTIVATED";
|
|
2025
2089
|
const isDead = ["BLOCKED", "EXPIRED", "DELETED"].includes(activeCard.status);
|
|
2026
|
-
const
|
|
2027
|
-
const
|
|
2028
|
-
const
|
|
2029
|
-
const
|
|
2030
|
-
const
|
|
2031
|
-
|
|
2032
|
-
const buttonClasses = activeCard.contentDark ? "bg-black/10 text-black hover:bg-black/20 font-medium" : "bg-white/25 text-white hover:bg-white/35";
|
|
2033
|
-
const handleToggleFreeze = () => {
|
|
2034
|
-
if (freezeDisabled || isFreezing) return;
|
|
2090
|
+
const actionsDisabled = !isActivated && !isFrozen || isDead;
|
|
2091
|
+
const showActionOverlay = !isActivated && isBgLoaded || isFrozen;
|
|
2092
|
+
const overlayClasses = activeCard.contentDark ? "bg-white/30 backdrop-blur-[3px]" : "bg-black/30 backdrop-blur-[3px]";
|
|
2093
|
+
const buttonClasses = activeCard.contentDark ? "bg-black text-white hover:bg-black/80 font-medium" : "bg-white text-black hover:bg-neutral-100 font-medium";
|
|
2094
|
+
const handleToggleFreeze = async () => {
|
|
2095
|
+
if (actionsDisabled || isFreezing || !onFreeze) return;
|
|
2035
2096
|
setIsFreezing(true);
|
|
2036
|
-
|
|
2037
|
-
|
|
2097
|
+
try {
|
|
2098
|
+
await onFreeze(activeCard.id);
|
|
2099
|
+
} finally {
|
|
2038
2100
|
setIsFreezing(false);
|
|
2039
|
-
}
|
|
2101
|
+
}
|
|
2040
2102
|
};
|
|
2041
2103
|
const confirmDelete = async () => {
|
|
2042
2104
|
setIsDeleting(true);
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
setShowDeleteDialog(false);
|
|
2047
|
-
}, 1200);
|
|
2105
|
+
if (onDelete) onDelete(activeCard.id);
|
|
2106
|
+
setIsDeleting(false);
|
|
2107
|
+
setShowDeleteDialog(false);
|
|
2048
2108
|
};
|
|
2049
|
-
const formatTabLabel = (
|
|
2050
|
-
|
|
2051
|
-
const capitalizedTier = card.tier.charAt(0).toUpperCase() + card.tier.slice(1).toLowerCase();
|
|
2052
|
-
return `${capitalizedTier}`;
|
|
2053
|
-
}
|
|
2054
|
-
const capitalizedType = card.type.charAt(0).toUpperCase() + card.type.slice(1).toLowerCase();
|
|
2055
|
-
return `${capitalizedType}`;
|
|
2109
|
+
const formatTabLabel = (type) => {
|
|
2110
|
+
return type.charAt(0).toUpperCase() + type.slice(1).toLowerCase();
|
|
2056
2111
|
};
|
|
2057
|
-
return /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ import_react31.default.createElement("h1", { className: "text-2xl mt-2 text-black tracking-tight mb-2 text-center" }, "My Cards"),
|
|
2112
|
+
return /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ import_react31.default.createElement("h1", { className: "text-2xl mt-2 text-black tracking-tight mb-2 text-center" }, "My Cards"), sortedCards.length > 1 && /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center justify-center mb-6 w-full px-2 gap-3" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-center bg-white rounded-full p-1 max-w-full overflow-x-auto custom-scrollbar" }, sortedCards.map((tab, idx) => /* @__PURE__ */ import_react31.default.createElement(
|
|
2058
2113
|
"button",
|
|
2059
2114
|
{
|
|
2060
|
-
|
|
2061
|
-
|
|
2115
|
+
key: tab.id,
|
|
2116
|
+
onClick: () => setActiveTabIndex(idx),
|
|
2117
|
+
className: `px-4 py-1.5 rounded-full text-[11px] transition-all duration-200 outline-none whitespace-nowrap shrink-0 ${activeTabIndex === idx ? "bg-neutral-100 text-black" : "text-neutral-500 hover:text-black hover:bg-neutral-50/50"}`
|
|
2062
2118
|
},
|
|
2063
|
-
|
|
2064
|
-
),
|
|
2065
|
-
|
|
2066
|
-
return /* @__PURE__ */ import_react31.default.createElement(
|
|
2067
|
-
"button",
|
|
2068
|
-
{
|
|
2069
|
-
key: tab.id,
|
|
2070
|
-
onClick: () => setActiveTabIndex(idx),
|
|
2071
|
-
className: `px-4 py-1.5 rounded-full text-[11px] transition-all duration-200 outline-none whitespace-nowrap shrink-0 ${isActive ? "bg-neutral-100 text-black" : "text-neutral-500 hover:text-black hover:bg-neutral-50/50"}`
|
|
2072
|
-
},
|
|
2073
|
-
formatTabLabel(tab)
|
|
2074
|
-
);
|
|
2075
|
-
}))), /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full pt-2 pb-2 flex justify-center" }, /* @__PURE__ */ import_react31.default.createElement(
|
|
2076
|
-
"div",
|
|
2119
|
+
formatTabLabel(tab.type)
|
|
2120
|
+
)))), /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full pt-2 pb-6 flex justify-center" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "relative w-full max-w-85", style: { height: 179 } }, !isBgLoaded && /* @__PURE__ */ import_react31.default.createElement("div", { className: "absolute inset-0 w-full h-full bg-white rounded-2xl flex items-center justify-center z-50" }, /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.Loading03Icon, size: 28, className: "animate-spin text-black" })), showActionOverlay && /* @__PURE__ */ import_react31.default.createElement("div", { className: `absolute inset-0 z-40 w-full h-full rounded-2xl flex flex-col items-center justify-center transition-all ${overlayClasses}` }, isUnactivated && /* @__PURE__ */ import_react31.default.createElement(
|
|
2121
|
+
"button",
|
|
2077
2122
|
{
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
!isBgLoaded && /* @__PURE__ */ import_react31.default.createElement("div", { className: "absolute inset-0 w-full h-full bg-white rounded-2xl flex items-center justify-center z-50" }, /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.Loading03Icon, size: 28, className: "animate-spin text-black" })),
|
|
2082
|
-
showActionOverlay && /* @__PURE__ */ import_react31.default.createElement("div", { className: `absolute inset-0 z-40 w-full h-full rounded-2xl flex flex-col items-center justify-center transition-all ${overlayClasses}` }, isUnactivated && /* @__PURE__ */ import_react31.default.createElement(
|
|
2083
|
-
"button",
|
|
2084
|
-
{
|
|
2085
|
-
onClick: (e) => {
|
|
2086
|
-
e.stopPropagation();
|
|
2087
|
-
router.push(`${actionPath}${activeCard.id}`);
|
|
2088
|
-
},
|
|
2089
|
-
className: `px-6 py-2 text-[11px] rounded-full transition-all outline-none active:scale-95 ${buttonClasses}`
|
|
2123
|
+
onClick: (e) => {
|
|
2124
|
+
e.stopPropagation();
|
|
2125
|
+
router.push(`${actionPath}${activeCard.id}`);
|
|
2090
2126
|
},
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
className: `px-6 py-2.5 text-[12px] rounded-full transition-all outline-none active:scale-95 flex items-center gap-2 disabled:opacity-80 ${buttonClasses}`
|
|
2097
|
-
},
|
|
2098
|
-
isOverlayActionLoading ? /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.Loading03Icon, size: 16, className: `animate-spin ${activeCard.contentDark ? "text-black" : "text-white"}` }) : "Card Frozen"
|
|
2099
|
-
)),
|
|
2100
|
-
/* @__PURE__ */ import_react31.default.createElement("div", { className: `absolute inset-0 w-full h-full rounded-2xl overflow-hidden transition-all duration-700 ${isBgLoaded ? "opacity-100 scale-100" : "opacity-0 scale-105"}` }, /* @__PURE__ */ import_react31.default.createElement(
|
|
2101
|
-
"div",
|
|
2102
|
-
{
|
|
2103
|
-
className: "absolute inset-0 bg-cover bg-center",
|
|
2104
|
-
style: { backgroundImage: `url(${activeCard.cardBgSrc})` }
|
|
2105
|
-
}
|
|
2106
|
-
), /* @__PURE__ */ import_react31.default.createElement("div", { className: "relative z-10 w-full h-full p-5 flex flex-col justify-between" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-start justify-end w-full gap-4" }, activeCard.prepaid && /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col items-end gap-1 text-right" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-[9px] tracking-widest ${activeCard.contentDark ? "text-black/60" : "text-white/60"}` }, "Card Tier"), /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-[11px] tracking-widest font-medium ${activeCard.contentDark ? "text-black" : "text-white"}` }, activeCard.tier))), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex justify-between items-end w-full" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-[9px] tracking-widest ${activeCard.contentDark ? "text-black/60" : "text-white/60"}` }, activeCard.prepaid ? "Card Balance" : "Card Tier"), /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-[12px] tracking-widest font-medium ${activeCard.contentDark ? "text-black" : "text-white"}` }, activeCard.prepaid ? activeCard.balance || "$0.00" : activeCard.tier)), activeCard.networkLogoSrc && /* @__PURE__ */ import_react31.default.createElement(
|
|
2107
|
-
"img",
|
|
2108
|
-
{
|
|
2109
|
-
src: activeCard.networkLogoSrc,
|
|
2110
|
-
alt: "Network Logo",
|
|
2111
|
-
className: "h-7 w-auto max-w-20 object-contain opacity-90"
|
|
2112
|
-
}
|
|
2113
|
-
))))
|
|
2114
|
-
)), activeCard.bannerProps ? /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-6 w-full mt-2" }, /* @__PURE__ */ import_react31.default.createElement(Banner, { ...activeCard.bannerProps })) : isPreordered ? /* @__PURE__ */ import_react31.default.createElement("div", { className: "mb-6 w-full mt-2" }, /* @__PURE__ */ import_react31.default.createElement(
|
|
2115
|
-
Banner,
|
|
2127
|
+
className: `px-6 py-2 text-[11px] rounded-full transition-all outline-none ${buttonClasses}`
|
|
2128
|
+
},
|
|
2129
|
+
"Activate Card"
|
|
2130
|
+
), isFrozen && /* @__PURE__ */ import_react31.default.createElement("div", { className: `px-6 py-2.5 text-[12px] rounded-full flex items-center gap-2 ${buttonClasses}` }, "Card Frozen")), /* @__PURE__ */ import_react31.default.createElement("div", { className: `absolute inset-0 w-full h-full rounded-2xl overflow-hidden transition-all duration-700 ${isBgLoaded ? "opacity-100 scale-100" : "opacity-0 scale-105"}` }, /* @__PURE__ */ import_react31.default.createElement(
|
|
2131
|
+
"div",
|
|
2116
2132
|
{
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
message: `Your ${activeCard.tier} ${activeCard.type.toLowerCase()} card has been pre-ordered successfully and is pending batch processing.`,
|
|
2120
|
-
isDismissible: false
|
|
2133
|
+
className: "absolute inset-0 bg-cover bg-center",
|
|
2134
|
+
style: { backgroundImage: `url(${activeCard.cardBgSrc})` }
|
|
2121
2135
|
}
|
|
2122
|
-
)) :
|
|
2136
|
+
), /* @__PURE__ */ import_react31.default.createElement("div", { className: "relative z-10 w-full h-full p-5 flex flex-col justify-between" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex items-start justify-end w-full gap-4" }, activeCard.networkLogoSrc && /* @__PURE__ */ import_react31.default.createElement("img", { src: activeCard.networkLogoSrc, alt: "Network Logo", className: "h-7 w-auto max-w-20 object-contain opacity-90" })), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex justify-between items-end w-full" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-[10px] tracking-widest ${activeCard.contentDark ? "text-black/60" : "text-white/70"} drop-shadow-sm` }, "Balance"), /* @__PURE__ */ import_react31.default.createElement("span", { className: `text-[16px] tracking-widest font-medium ${activeCard.contentDark ? "text-black" : "text-white"} drop-shadow-sm` }, activeCard.balance))))))), /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full flex flex-col gap-4 mt-1" }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react31.default.createElement(
|
|
2123
2137
|
MenuRow,
|
|
2124
2138
|
{
|
|
2125
2139
|
icon: import_core_free_icons11.PlusSignIcon,
|
|
2126
2140
|
title: "Fund Card",
|
|
2127
|
-
subtitle: "Add money to card",
|
|
2141
|
+
subtitle: "Add money to card balance",
|
|
2128
2142
|
onClick: () => {
|
|
2129
2143
|
if (!actionsDisabled && onFundCard) onFundCard(activeCard.id);
|
|
2130
2144
|
},
|
|
@@ -2137,9 +2151,9 @@ var UniversalCardPage = ({
|
|
|
2137
2151
|
title: "Reveal Information",
|
|
2138
2152
|
subtitle: "Show secure card details",
|
|
2139
2153
|
onClick: () => {
|
|
2140
|
-
if (!
|
|
2154
|
+
if (!actionsDisabled && onReveal) onReveal(activeCard.id);
|
|
2141
2155
|
},
|
|
2142
|
-
disabled:
|
|
2156
|
+
disabled: actionsDisabled
|
|
2143
2157
|
}
|
|
2144
2158
|
), /* @__PURE__ */ import_react31.default.createElement(
|
|
2145
2159
|
MenuRow,
|
|
@@ -2151,19 +2165,7 @@ var UniversalCardPage = ({
|
|
|
2151
2165
|
isToggle: true,
|
|
2152
2166
|
toggleState: isFrozen,
|
|
2153
2167
|
toggleLoading: isFreezing,
|
|
2154
|
-
disabled:
|
|
2155
|
-
isLast: activeCard.prepaid
|
|
2156
|
-
}
|
|
2157
|
-
), !activeCard.prepaid && /* @__PURE__ */ import_react31.default.createElement(
|
|
2158
|
-
MenuRow,
|
|
2159
|
-
{
|
|
2160
|
-
icon: import_core_free_icons11.SlidersHorizontalIcon,
|
|
2161
|
-
title: "Set Limits",
|
|
2162
|
-
subtitle: "Set card limits",
|
|
2163
|
-
onClick: () => {
|
|
2164
|
-
if (!actionsDisabled && onSetLimits) onSetLimits(activeCard.id);
|
|
2165
|
-
},
|
|
2166
|
-
disabled: actionsDisabled,
|
|
2168
|
+
disabled: isUnactivated || isDead,
|
|
2167
2169
|
isLast: true
|
|
2168
2170
|
}
|
|
2169
2171
|
)), /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react31.default.createElement(
|
|
@@ -2183,7 +2185,7 @@ var UniversalCardPage = ({
|
|
|
2183
2185
|
{
|
|
2184
2186
|
isOpen: showDeleteDialog,
|
|
2185
2187
|
title: "Delete Card",
|
|
2186
|
-
message: "
|
|
2188
|
+
message: "Are you sure you want to delete this card? This action is permanent and cannot be undone.",
|
|
2187
2189
|
confirmText: "Delete",
|
|
2188
2190
|
isDestructive: true,
|
|
2189
2191
|
isProcessing: isDeleting,
|
|
@@ -2192,28 +2194,7 @@ var UniversalCardPage = ({
|
|
|
2192
2194
|
}
|
|
2193
2195
|
));
|
|
2194
2196
|
};
|
|
2195
|
-
var MenuRow = ({
|
|
2196
|
-
icon,
|
|
2197
|
-
title,
|
|
2198
|
-
subtitle,
|
|
2199
|
-
onClick,
|
|
2200
|
-
iconColor = "text-black",
|
|
2201
|
-
titleColor = "text-black",
|
|
2202
|
-
isLast = false,
|
|
2203
|
-
isToggle = false,
|
|
2204
|
-
toggleState = false,
|
|
2205
|
-
toggleLoading = false,
|
|
2206
|
-
disabled = false
|
|
2207
|
-
}) => /* @__PURE__ */ import_react31.default.createElement(
|
|
2208
|
-
"div",
|
|
2209
|
-
{
|
|
2210
|
-
onClick: disabled ? void 0 : onClick,
|
|
2211
|
-
className: `flex items-center p-3 transition-colors ${!isLast ? "" : ""} ${disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer hover:bg-neutral-50"}`
|
|
2212
|
-
},
|
|
2213
|
-
/* @__PURE__ */ import_react31.default.createElement("div", { className: "w-9 h-9 rounded-full border border-neutral-200 flex items-center justify-center shrink-0 mr-4" }, /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon, size: 16, className: iconColor })),
|
|
2214
|
-
/* @__PURE__ */ import_react31.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react31.default.createElement("p", { className: `text-[13px] truncate ${titleColor}` }, title), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-[11px] text-neutral-500 truncate" }, subtitle)),
|
|
2215
|
-
isToggle ? /* @__PURE__ */ import_react31.default.createElement("div", { className: `relative w-11 h-6 rounded-full transition-colors duration-300 ml-2 shrink-0 ${toggleState ? "bg-black" : "bg-neutral-100"} ${disabled ? "opacity-50" : ""}` }, /* @__PURE__ */ import_react31.default.createElement("div", { className: `absolute top-1 left-1 w-4 h-4 rounded-full bg-white shadow-sm transition-transform duration-300 flex items-center justify-center ${toggleState ? "translate-x-5" : "translate-x-0"}` }, toggleLoading && /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.Loading03Icon, size: 10, className: "animate-spin text-black" }))) : /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.ArrowRight01Icon, size: 18, className: "text-neutral-400 shrink-0 ml-2" })
|
|
2216
|
-
);
|
|
2197
|
+
var MenuRow = ({ icon, title, subtitle, onClick, isLast = false, isToggle = false, toggleState = false, toggleLoading = false, disabled = false }) => /* @__PURE__ */ import_react31.default.createElement("div", { onClick: disabled ? void 0 : onClick, className: `flex items-center p-3 transition-colors ${disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer hover:bg-neutral-50"}` }, /* @__PURE__ */ import_react31.default.createElement("div", { className: "w-9 h-9 rounded-full border border-neutral-200 flex items-center justify-center shrink-0 mr-4" }, /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon, size: 16, className: "text-black" })), /* @__PURE__ */ import_react31.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-[13px] truncate text-black" }, title), /* @__PURE__ */ import_react31.default.createElement("p", { className: "text-[11px] text-neutral-500 truncate" }, subtitle)), isToggle ? /* @__PURE__ */ import_react31.default.createElement("div", { className: `relative w-11 h-6 rounded-full transition-colors duration-300 ml-2 shrink-0 ${toggleState ? "bg-black" : "bg-neutral-100"} ${disabled ? "opacity-50" : ""}` }, /* @__PURE__ */ import_react31.default.createElement("div", { className: `absolute top-1 left-1 w-4 h-4 rounded-full bg-white shadow-sm transition-transform duration-300 flex items-center justify-center ${toggleState ? "translate-x-5" : "translate-x-0"}` }, toggleLoading && /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.Loading03Icon, size: 10, className: "animate-spin text-black" }))) : /* @__PURE__ */ import_react31.default.createElement(import_react32.HugeiconsIcon, { icon: import_core_free_icons11.ArrowRight01Icon, size: 18, className: "text-neutral-400 shrink-0 ml-2" }));
|
|
2217
2198
|
|
|
2218
2199
|
// src/components/UniversalProfilePage.tsx
|
|
2219
2200
|
var import_react33 = __toESM(require("react"));
|
|
@@ -2464,7 +2445,7 @@ var import_image2 = __toESM(require("next/image"));
|
|
|
2464
2445
|
|
|
2465
2446
|
// src/components/WaitlistDialog.tsx
|
|
2466
2447
|
var import_react37 = __toESM(require("react"));
|
|
2467
|
-
var
|
|
2448
|
+
var import_react_hot_toast8 = require("react-hot-toast");
|
|
2468
2449
|
var WaitlistDialog = ({ isOpen, onClose }) => {
|
|
2469
2450
|
const [email, setEmail] = (0, import_react37.useState)("");
|
|
2470
2451
|
const [isLoading, setIsLoading] = (0, import_react37.useState)(false);
|
|
@@ -2472,7 +2453,7 @@ var WaitlistDialog = ({ isOpen, onClose }) => {
|
|
|
2472
2453
|
const handleSubmit = async (e) => {
|
|
2473
2454
|
e.preventDefault();
|
|
2474
2455
|
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
2475
|
-
|
|
2456
|
+
import_react_hot_toast8.toast.error("Please enter a valid email address.");
|
|
2476
2457
|
return;
|
|
2477
2458
|
}
|
|
2478
2459
|
setIsLoading(true);
|
|
@@ -2486,14 +2467,14 @@ var WaitlistDialog = ({ isOpen, onClose }) => {
|
|
|
2486
2467
|
});
|
|
2487
2468
|
const data = await response.json();
|
|
2488
2469
|
if (response.ok && data.success) {
|
|
2489
|
-
|
|
2470
|
+
import_react_hot_toast8.toast.success(data.message || "You've been added to the waitlist!");
|
|
2490
2471
|
setEmail("");
|
|
2491
2472
|
onClose();
|
|
2492
2473
|
} else {
|
|
2493
|
-
|
|
2474
|
+
import_react_hot_toast8.toast.error(data.error || "Something went wrong. Please try again.");
|
|
2494
2475
|
}
|
|
2495
2476
|
} catch (error) {
|
|
2496
|
-
|
|
2477
|
+
import_react_hot_toast8.toast.error("Network error. Please check your connection.");
|
|
2497
2478
|
} finally {
|
|
2498
2479
|
setIsLoading(false);
|
|
2499
2480
|
}
|
|
@@ -2742,105 +2723,28 @@ var AppBento2 = ({ tagline, headline, features }) => {
|
|
|
2742
2723
|
|
|
2743
2724
|
// src/components/UniversalSecurityPage.tsx
|
|
2744
2725
|
var import_react41 = __toESM(require("react"));
|
|
2745
|
-
var
|
|
2726
|
+
var import_react_hot_toast9 = __toESM(require("react-hot-toast"));
|
|
2746
2727
|
var import_react42 = require("@hugeicons/react");
|
|
2747
2728
|
var import_core_free_icons14 = require("@hugeicons/core-free-icons");
|
|
2748
2729
|
var import_browser2 = require("@simplewebauthn/browser");
|
|
2749
2730
|
var UniversalSecurityPage = ({
|
|
2750
|
-
|
|
2731
|
+
hasPasscode,
|
|
2751
2732
|
hasPasskey,
|
|
2752
|
-
|
|
2753
|
-
is2FALoading = false,
|
|
2733
|
+
isPasscodeLoading = false,
|
|
2754
2734
|
isPasskeyLoading = false,
|
|
2755
2735
|
onBack,
|
|
2756
|
-
|
|
2757
|
-
onVerifyAndEnable2FA,
|
|
2758
|
-
onVerifyAndDisable2FA,
|
|
2736
|
+
onSavePasscode,
|
|
2759
2737
|
onRequestPasskeySetup,
|
|
2760
2738
|
onVerifyAndEnablePasskey,
|
|
2761
2739
|
onDisablePasskey
|
|
2762
2740
|
}) => {
|
|
2763
|
-
const [show2FASetupModal, setShow2FASetupModal] = (0, import_react41.useState)(false);
|
|
2764
|
-
const [show2FADisableModal, setShow2FADisableModal] = (0, import_react41.useState)(false);
|
|
2765
2741
|
const [showPasskeyModal, setShowPasskeyModal] = (0, import_react41.useState)(false);
|
|
2766
|
-
const [twoFaSecret, setTwoFaSecret] = (0, import_react41.useState)("");
|
|
2767
|
-
const [twoFaQr, setTwoFaQr] = (0, import_react41.useState)("");
|
|
2768
|
-
const [isFetchingSetup, setIsFetchingSetup] = (0, import_react41.useState)(false);
|
|
2769
|
-
const [otp, setOtp] = (0, import_react41.useState)(Array(6).fill(""));
|
|
2770
2742
|
const [isSubmitting, setIsSubmitting] = (0, import_react41.useState)(false);
|
|
2771
|
-
const
|
|
2772
|
-
const
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
const handleOtpChange = (index, value) => {
|
|
2777
|
-
const sanitizedValue = value.replace(/\D/g, "").slice(-1);
|
|
2778
|
-
const newOtp = [...otp];
|
|
2779
|
-
newOtp[index] = sanitizedValue;
|
|
2780
|
-
setOtp(newOtp);
|
|
2781
|
-
if (sanitizedValue && index < 5) {
|
|
2782
|
-
inputRefs.current[index + 1]?.focus();
|
|
2783
|
-
}
|
|
2784
|
-
};
|
|
2785
|
-
const handlePaste = (e) => {
|
|
2786
|
-
e.preventDefault();
|
|
2787
|
-
const pastedData = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
|
|
2788
|
-
if (!pastedData) return;
|
|
2789
|
-
const newOtp = [...otp];
|
|
2790
|
-
for (let i = 0; i < pastedData.length; i++) {
|
|
2791
|
-
newOtp[i] = pastedData[i];
|
|
2792
|
-
}
|
|
2793
|
-
setOtp(newOtp);
|
|
2794
|
-
const focusIndex = Math.min(pastedData.length, 5);
|
|
2795
|
-
inputRefs.current[focusIndex]?.focus();
|
|
2796
|
-
};
|
|
2797
|
-
const handleCopySecret = async (secret) => {
|
|
2798
|
-
try {
|
|
2799
|
-
if (navigator?.clipboard?.writeText && window.isSecureContext) {
|
|
2800
|
-
await navigator.clipboard.writeText(secret);
|
|
2801
|
-
import_react_hot_toast8.default.success("Secret copied to clipboard");
|
|
2802
|
-
} else {
|
|
2803
|
-
throw new Error("Clipboard API not available");
|
|
2804
|
-
}
|
|
2805
|
-
} catch (e) {
|
|
2806
|
-
try {
|
|
2807
|
-
const textArea = document.createElement("textarea");
|
|
2808
|
-
textArea.value = secret;
|
|
2809
|
-
textArea.style.position = "fixed";
|
|
2810
|
-
textArea.style.left = "-999999px";
|
|
2811
|
-
textArea.style.top = "-999999px";
|
|
2812
|
-
document.body.appendChild(textArea);
|
|
2813
|
-
textArea.focus();
|
|
2814
|
-
textArea.select();
|
|
2815
|
-
document.execCommand("copy");
|
|
2816
|
-
textArea.remove();
|
|
2817
|
-
import_react_hot_toast8.default.success("Secret copied to clipboard");
|
|
2818
|
-
} catch (err) {
|
|
2819
|
-
import_react_hot_toast8.default.error("Unable to copy. Please manually copy the key.");
|
|
2820
|
-
}
|
|
2821
|
-
}
|
|
2822
|
-
};
|
|
2823
|
-
const handleToggle2FA = async () => {
|
|
2824
|
-
if (is2FALoading) return;
|
|
2825
|
-
if (has2FA) {
|
|
2826
|
-
resetOtp();
|
|
2827
|
-
setShow2FADisableModal(true);
|
|
2828
|
-
} else {
|
|
2829
|
-
if (!onRequest2FASetup) return;
|
|
2830
|
-
setIsFetchingSetup(true);
|
|
2831
|
-
try {
|
|
2832
|
-
const data = await onRequest2FASetup();
|
|
2833
|
-
setTwoFaSecret(data.secret);
|
|
2834
|
-
setTwoFaQr(data.qrCodeUrl);
|
|
2835
|
-
resetOtp();
|
|
2836
|
-
setShow2FASetupModal(true);
|
|
2837
|
-
} catch (error) {
|
|
2838
|
-
import_react_hot_toast8.default.error("Failed to initialize 2FA setup");
|
|
2839
|
-
} finally {
|
|
2840
|
-
setIsFetchingSetup(false);
|
|
2841
|
-
}
|
|
2842
|
-
}
|
|
2843
|
-
};
|
|
2743
|
+
const [isPasscodeModalOpen, setIsPasscodeModalOpen] = (0, import_react41.useState)(false);
|
|
2744
|
+
const [oldPasscode, setOldPasscode] = (0, import_react41.useState)("");
|
|
2745
|
+
const [newPasscode, setNewPasscode] = (0, import_react41.useState)("");
|
|
2746
|
+
const [confirmPasscode, setConfirmPasscode] = (0, import_react41.useState)("");
|
|
2747
|
+
const [isPasscodeSubmitting, setIsPasscodeSubmitting] = (0, import_react41.useState)(false);
|
|
2844
2748
|
const handleTogglePasskey = () => {
|
|
2845
2749
|
if (isPasskeyLoading) return;
|
|
2846
2750
|
if (hasPasskey) {
|
|
@@ -2849,38 +2753,40 @@ var UniversalSecurityPage = ({
|
|
|
2849
2753
|
setShowPasskeyModal(true);
|
|
2850
2754
|
}
|
|
2851
2755
|
};
|
|
2852
|
-
const
|
|
2853
|
-
if (
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
import_react_hot_toast8.default.success("2FA Enabled Successfully");
|
|
2859
|
-
setShow2FASetupModal(false);
|
|
2860
|
-
} else {
|
|
2861
|
-
import_react_hot_toast8.default.error("Invalid verification code");
|
|
2862
|
-
}
|
|
2863
|
-
} catch (error) {
|
|
2864
|
-
import_react_hot_toast8.default.error("Verification failed");
|
|
2865
|
-
} finally {
|
|
2866
|
-
setIsSubmitting(false);
|
|
2867
|
-
}
|
|
2756
|
+
const closePasscodeModal = () => {
|
|
2757
|
+
if (isPasscodeSubmitting) return;
|
|
2758
|
+
setIsPasscodeModalOpen(false);
|
|
2759
|
+
setOldPasscode("");
|
|
2760
|
+
setNewPasscode("");
|
|
2761
|
+
setConfirmPasscode("");
|
|
2868
2762
|
};
|
|
2869
|
-
const
|
|
2870
|
-
|
|
2871
|
-
|
|
2763
|
+
const handlePasscodeInput = (val, setter) => {
|
|
2764
|
+
setter(val.replace(/\D/g, "").substring(0, 6));
|
|
2765
|
+
};
|
|
2766
|
+
const handlePasscodeSubmit = async (e) => {
|
|
2767
|
+
e.preventDefault();
|
|
2768
|
+
if (!onSavePasscode) return;
|
|
2769
|
+
if (hasPasscode && oldPasscode.length !== 6) return import_react_hot_toast9.default.error("Old Passcode must be exactly 6-digits.");
|
|
2770
|
+
if (newPasscode.length !== 6) return import_react_hot_toast9.default.error("New Passcode must be exactly 6-digits.");
|
|
2771
|
+
if (newPasscode !== confirmPasscode) return import_react_hot_toast9.default.error("New Passcodes do not match.");
|
|
2772
|
+
setIsPasscodeSubmitting(true);
|
|
2872
2773
|
try {
|
|
2873
|
-
const
|
|
2774
|
+
const action = hasPasscode ? "change_passcode" : "create_passcode";
|
|
2775
|
+
const res = await onSavePasscode({
|
|
2776
|
+
action,
|
|
2777
|
+
oldPasscode: hasPasscode ? oldPasscode : void 0,
|
|
2778
|
+
newPasscode
|
|
2779
|
+
});
|
|
2874
2780
|
if (res.success) {
|
|
2875
|
-
|
|
2876
|
-
|
|
2781
|
+
import_react_hot_toast9.default.success(res.message || "Passcode updated successfully.");
|
|
2782
|
+
closePasscodeModal();
|
|
2877
2783
|
} else {
|
|
2878
|
-
|
|
2784
|
+
import_react_hot_toast9.default.error(res.error || "Failed to update Passcode.");
|
|
2879
2785
|
}
|
|
2880
2786
|
} catch (error) {
|
|
2881
|
-
|
|
2787
|
+
import_react_hot_toast9.default.error("Uh oh! Something went wrong.");
|
|
2882
2788
|
} finally {
|
|
2883
|
-
|
|
2789
|
+
setIsPasscodeSubmitting(false);
|
|
2884
2790
|
}
|
|
2885
2791
|
};
|
|
2886
2792
|
const submitEnablePasskey = async () => {
|
|
@@ -2899,13 +2805,13 @@ var UniversalSecurityPage = ({
|
|
|
2899
2805
|
}
|
|
2900
2806
|
const res = await onVerifyAndEnablePasskey(credentialResponse);
|
|
2901
2807
|
if (res.success) {
|
|
2902
|
-
|
|
2808
|
+
import_react_hot_toast9.default.success("Passkey Created Successfully");
|
|
2903
2809
|
setShowPasskeyModal(false);
|
|
2904
2810
|
} else {
|
|
2905
|
-
|
|
2811
|
+
import_react_hot_toast9.default.error("Failed to verify device passkey.");
|
|
2906
2812
|
}
|
|
2907
2813
|
} catch (error) {
|
|
2908
|
-
|
|
2814
|
+
import_react_hot_toast9.default.error(error.message || "Passkey setup interrupted.");
|
|
2909
2815
|
} finally {
|
|
2910
2816
|
setIsSubmitting(false);
|
|
2911
2817
|
}
|
|
@@ -2914,20 +2820,18 @@ var UniversalSecurityPage = ({
|
|
|
2914
2820
|
"button",
|
|
2915
2821
|
{
|
|
2916
2822
|
onClick: onBack,
|
|
2917
|
-
className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px]
|
|
2823
|
+
className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none"
|
|
2918
2824
|
},
|
|
2919
2825
|
/* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.ArrowLeft01Icon, size: 16 }),
|
|
2920
2826
|
" Back"
|
|
2921
2827
|
)), /* @__PURE__ */ import_react41.default.createElement("div", { className: "w-full flex flex-col gap-4" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "w-full bg-white rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react41.default.createElement(
|
|
2922
2828
|
MenuRow3,
|
|
2923
2829
|
{
|
|
2924
|
-
icon: import_core_free_icons14.
|
|
2925
|
-
title: "
|
|
2926
|
-
subtitle: "
|
|
2927
|
-
onClick:
|
|
2928
|
-
isToggle:
|
|
2929
|
-
toggleState: has2FA,
|
|
2930
|
-
toggleLoading: is2FALoading || isFetchingSetup
|
|
2830
|
+
icon: import_core_free_icons14.LockKeyIcon,
|
|
2831
|
+
title: "Security Passcode",
|
|
2832
|
+
subtitle: hasPasscode ? "Change your 6-digit passcode" : "Create a 6-digit passcode",
|
|
2833
|
+
onClick: () => setIsPasscodeModalOpen(true),
|
|
2834
|
+
isToggle: false
|
|
2931
2835
|
}
|
|
2932
2836
|
), /* @__PURE__ */ import_react41.default.createElement(
|
|
2933
2837
|
MenuRow3,
|
|
@@ -2941,86 +2845,49 @@ var UniversalSecurityPage = ({
|
|
|
2941
2845
|
toggleLoading: isPasskeyLoading,
|
|
2942
2846
|
isLast: true
|
|
2943
2847
|
}
|
|
2944
|
-
))),
|
|
2945
|
-
|
|
2946
|
-
{
|
|
2947
|
-
type: "button",
|
|
2948
|
-
onClick: () => handleCopySecret(twoFaSecret),
|
|
2949
|
-
className: "text-neutral-400 hover:text-black transition-colors outline-none shrink-0 ml-2"
|
|
2950
|
-
},
|
|
2951
|
-
/* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.Copy01Icon, size: 16 })
|
|
2952
|
-
)))), /* @__PURE__ */ import_react41.default.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ import_react41.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react41.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the 6-digit code from your app")), /* @__PURE__ */ import_react41.default.createElement("form", { className: "space-y-4", autoComplete: "off", onSubmit: (e) => {
|
|
2953
|
-
e.preventDefault();
|
|
2954
|
-
submitEnable2FA(otp.join(""));
|
|
2955
|
-
} }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex justify-between gap-2 pb-6", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react41.default.createElement(
|
|
2956
|
-
"input",
|
|
2848
|
+
))), isPasscodeModalOpen && /* @__PURE__ */ import_react41.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "absolute inset-0 bg-black/40", onClick: closePasscodeModal }), /* @__PURE__ */ import_react41.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react41.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, hasPasscode ? "Change Passcode" : "Create Security Passcode"), /* @__PURE__ */ import_react41.default.createElement("button", { onClick: closePasscodeModal, disabled: isPasscodeSubmitting, className: "text-neutral-400 hover:text-black transition-colors outline-none disabled:opacity-50" }, /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react41.default.createElement("div", { className: "p-6" }, isPasscodeLoading ? /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex flex-col items-center justify-center py-10" }, /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.Loading03Icon, size: 28, className: "animate-spin text-neutral-400 mb-4" })) : /* @__PURE__ */ import_react41.default.createElement("form", { onSubmit: handlePasscodeSubmit, className: "flex flex-col gap-6" }, hasPasscode && /* @__PURE__ */ import_react41.default.createElement(
|
|
2849
|
+
TextInput,
|
|
2957
2850
|
{
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
value: digit,
|
|
2966
|
-
onChange: (e) => handleOtpChange(index, e.target.value),
|
|
2967
|
-
onKeyDown: (e) => {
|
|
2968
|
-
if (e.key === "Backspace" && !otp[index] && index > 0) {
|
|
2969
|
-
inputRefs.current[index - 1]?.focus();
|
|
2970
|
-
}
|
|
2971
|
-
},
|
|
2972
|
-
className: "w-8 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
2851
|
+
type: "password",
|
|
2852
|
+
label: "Old 6-Digit Passcode",
|
|
2853
|
+
maxLength: 6,
|
|
2854
|
+
disabled: isPasscodeSubmitting,
|
|
2855
|
+
value: oldPasscode,
|
|
2856
|
+
onChange: (val) => handlePasscodeInput(val, setOldPasscode),
|
|
2857
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
2973
2858
|
}
|
|
2974
|
-
))), /* @__PURE__ */ import_react41.default.createElement(
|
|
2975
|
-
ThreeDActionButton,
|
|
2976
|
-
{
|
|
2977
|
-
type: "submit",
|
|
2978
|
-
disabled: otp.join("").length < 6,
|
|
2979
|
-
isLoading: isSubmitting,
|
|
2980
|
-
className: "w-full py-3.5"
|
|
2981
|
-
},
|
|
2982
|
-
"Verify & Enable"
|
|
2983
2859
|
), /* @__PURE__ */ import_react41.default.createElement(
|
|
2984
|
-
|
|
2985
|
-
{
|
|
2986
|
-
type: "button",
|
|
2987
|
-
onClick: () => handleCopySecret(twoFaSecret),
|
|
2988
|
-
className: "w-full flex items-center justify-center py-2.5 rounded-full border border-neutral-200 text-black hover:bg-neutral-50 outline-none text-xs tracking-wide transition-colors mt-2"
|
|
2989
|
-
},
|
|
2990
|
-
/* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.Copy01Icon, size: 16, className: "mr-2" }),
|
|
2991
|
-
"Copy Secret Key"
|
|
2992
|
-
))))), show2FADisableModal && /* @__PURE__ */ import_react41.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShow2FADisableModal(false) }), /* @__PURE__ */ import_react41.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0 " }, /* @__PURE__ */ import_react41.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Disable 2FA"), /* @__PURE__ */ import_react41.default.createElement("button", { onClick: () => !isSubmitting && setShow2FADisableModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react41.default.createElement("div", { className: "p-6" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "text-center mb-8 mt-2" }, /* @__PURE__ */ import_react41.default.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight" }, "Security Check"), /* @__PURE__ */ import_react41.default.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the code from your authenticator app to disable 2FA.")), /* @__PURE__ */ import_react41.default.createElement("form", { className: "space-y-8", autoComplete: "off", onSubmit: (e) => {
|
|
2993
|
-
e.preventDefault();
|
|
2994
|
-
submitDisable2FA(otp.join(""));
|
|
2995
|
-
} }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ import_react41.default.createElement(
|
|
2996
|
-
"input",
|
|
2860
|
+
TextInput,
|
|
2997
2861
|
{
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
value: digit,
|
|
3006
|
-
onChange: (e) => handleOtpChange(index, e.target.value),
|
|
3007
|
-
onKeyDown: (e) => {
|
|
3008
|
-
if (e.key === "Backspace" && !otp[index] && index > 0) {
|
|
3009
|
-
inputRefs.current[index - 1]?.focus();
|
|
3010
|
-
}
|
|
3011
|
-
},
|
|
3012
|
-
className: "w-10 h-12 text-center text-lg bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
2862
|
+
type: "password",
|
|
2863
|
+
label: hasPasscode ? "New 6-Digit Passcode" : "Enter 6-Digit Passcode",
|
|
2864
|
+
maxLength: 6,
|
|
2865
|
+
disabled: isPasscodeSubmitting,
|
|
2866
|
+
value: newPasscode,
|
|
2867
|
+
onChange: (val) => handlePasscodeInput(val, setNewPasscode),
|
|
2868
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
3013
2869
|
}
|
|
3014
|
-
)
|
|
2870
|
+
), /* @__PURE__ */ import_react41.default.createElement(
|
|
2871
|
+
TextInput,
|
|
2872
|
+
{
|
|
2873
|
+
type: "password",
|
|
2874
|
+
label: "Retype New Passcode",
|
|
2875
|
+
maxLength: 6,
|
|
2876
|
+
disabled: isPasscodeSubmitting,
|
|
2877
|
+
value: confirmPasscode,
|
|
2878
|
+
onChange: (val) => handlePasscodeInput(val, setConfirmPasscode),
|
|
2879
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022"
|
|
2880
|
+
}
|
|
2881
|
+
), /* @__PURE__ */ import_react41.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react41.default.createElement(
|
|
3015
2882
|
ThreeDActionButton,
|
|
3016
2883
|
{
|
|
3017
2884
|
type: "submit",
|
|
3018
|
-
disabled:
|
|
3019
|
-
isLoading:
|
|
3020
|
-
className: "w-full
|
|
2885
|
+
disabled: isPasscodeSubmitting || newPasscode.length !== 6 || confirmPasscode.length !== 6 || hasPasscode && oldPasscode.length !== 6,
|
|
2886
|
+
isLoading: isPasscodeSubmitting,
|
|
2887
|
+
className: "w-full"
|
|
3021
2888
|
},
|
|
3022
|
-
"
|
|
3023
|
-
))))), showPasskeyModal && /* @__PURE__ */ import_react41.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShowPasskeyModal(false) }), /* @__PURE__ */ import_react41.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, /* @__PURE__ */ import_react41.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable Passkey"), /* @__PURE__ */ import_react41.default.createElement("button", { onClick: () => !isSubmitting && setShowPasskeyModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react41.default.createElement("div", { className: "p-6 text-center" }, /* @__PURE__ */ import_react41.default.createElement("h2", { className: "text-lg text-black mb-2 tracking-tight" }, "Simplify your Sign In"), /* @__PURE__ */ import_react41.default.createElement("p", { className: "text-[13px] text-neutral-500 mb-8 leading-relaxed" }, "Use your device's biometrics (Face ID, Touch ID, or PIN) to securely sign into your account without needing a password."), /* @__PURE__ */ import_react41.default.createElement(
|
|
2889
|
+
hasPasscode ? "Update Passcode" : "Set Passcode"
|
|
2890
|
+
)))))), showPasskeyModal && /* @__PURE__ */ import_react41.default.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "absolute inset-0 bg-black/40 ", onClick: () => !isSubmitting && setShowPasskeyModal(false) }), /* @__PURE__ */ import_react41.default.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react41.default.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, /* @__PURE__ */ import_react41.default.createElement("h3", { className: "text-[15px] text-black tracking-tight" }, "Enable Passkey"), /* @__PURE__ */ import_react41.default.createElement("button", { onClick: () => !isSubmitting && setShowPasskeyModal(false), className: "text-neutral-400 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.CancelCircleIcon, size: 18 }))), /* @__PURE__ */ import_react41.default.createElement("div", { className: "p-6 text-center" }, /* @__PURE__ */ import_react41.default.createElement("h2", { className: "text-lg text-black mb-2 tracking-tight" }, "Simplify your Sign In"), /* @__PURE__ */ import_react41.default.createElement("p", { className: "text-[13px] text-neutral-500 mb-8 leading-relaxed" }, "Use your device's biometrics (Face ID, Touch ID, or PIN) to securely sign into your account without needing a password."), /* @__PURE__ */ import_react41.default.createElement(
|
|
3024
2891
|
ThreeDActionButton,
|
|
3025
2892
|
{
|
|
3026
2893
|
onClick: submitEnablePasskey,
|
|
@@ -3048,8 +2915,8 @@ var MenuRow3 = ({
|
|
|
3048
2915
|
onClick: disabled ? void 0 : onClick,
|
|
3049
2916
|
className: `flex items-center p-4 transition-colors ${!isLast ? "" : ""} ${disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer hover:bg-neutral-50"}`
|
|
3050
2917
|
},
|
|
3051
|
-
/* @__PURE__ */ import_react41.default.createElement("div", { className: "w-9 h-9 rounded-full
|
|
3052
|
-
/* @__PURE__ */ import_react41.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react41.default.createElement("p", { className: `text-[14px]
|
|
2918
|
+
/* @__PURE__ */ import_react41.default.createElement("div", { className: "w-9 h-9 rounded-full border border-neutral-200 flex items-center justify-center shrink-0 mr-4" }, /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon, size: 16, className: iconColor })),
|
|
2919
|
+
/* @__PURE__ */ import_react41.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react41.default.createElement("p", { className: `text-[14px] truncate ${titleColor}` }, title), /* @__PURE__ */ import_react41.default.createElement("p", { className: "text-[12px] text-neutral-500 truncate" }, subtitle)),
|
|
3053
2920
|
isToggle ? /* @__PURE__ */ import_react41.default.createElement("div", { className: `relative w-11 h-6 rounded-full transition-colors duration-300 ml-2 shrink-0 ${toggleState ? "bg-black" : "bg-neutral-100"} ${disabled ? "opacity-50" : ""}` }, /* @__PURE__ */ import_react41.default.createElement("div", { className: `absolute top-1 left-1 w-4 h-4 rounded-full bg-white shadow-sm transition-transform duration-300 flex items-center justify-center ${toggleState ? "translate-x-5" : "translate-x-0"}` }, toggleLoading && /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.Loading03Icon, size: 10, className: "animate-spin text-black" }))) : /* @__PURE__ */ import_react41.default.createElement(import_react42.HugeiconsIcon, { icon: import_core_free_icons14.ArrowRight01Icon, size: 18, className: "text-neutral-400 shrink-0 ml-2" })
|
|
3054
2921
|
);
|
|
3055
2922
|
|
|
@@ -3979,7 +3846,7 @@ var UniversalVerificationPage = ({
|
|
|
3979
3846
|
// src/components/UniversalRewardPage.tsx
|
|
3980
3847
|
var import_react67 = __toESM(require("react"));
|
|
3981
3848
|
var import_axios = __toESM(require("axios"));
|
|
3982
|
-
var
|
|
3849
|
+
var import_react_hot_toast10 = __toESM(require("react-hot-toast"));
|
|
3983
3850
|
var import_react_confetti = __toESM(require("react-confetti"));
|
|
3984
3851
|
var import_react_use = require("react-use");
|
|
3985
3852
|
var import_react68 = require("@hugeicons/react");
|
|
@@ -4030,7 +3897,7 @@ var UniversalRewardPage = ({
|
|
|
4030
3897
|
const res = await import_axios.default.post(selectedReward.endpoint, selectedReward.config);
|
|
4031
3898
|
if (res.data.success) {
|
|
4032
3899
|
setShowConfetti(true);
|
|
4033
|
-
|
|
3900
|
+
import_react_hot_toast10.default.success(res.data.message || "Reward claimed successfully!");
|
|
4034
3901
|
setSelectedReward(null);
|
|
4035
3902
|
onRefresh();
|
|
4036
3903
|
setTimeout(() => {
|
|
@@ -4038,7 +3905,7 @@ var UniversalRewardPage = ({
|
|
|
4038
3905
|
}, 6e3);
|
|
4039
3906
|
}
|
|
4040
3907
|
} catch (error) {
|
|
4041
|
-
|
|
3908
|
+
import_react_hot_toast10.default.error(error.response?.data?.error || "Failed to claim reward. Please try again.");
|
|
4042
3909
|
} finally {
|
|
4043
3910
|
setIsClaiming(false);
|
|
4044
3911
|
}
|
|
@@ -4088,7 +3955,7 @@ var UniversalRewardPage = ({
|
|
|
4088
3955
|
|
|
4089
3956
|
// src/components/UniversalReferralPage.tsx
|
|
4090
3957
|
var import_react69 = __toESM(require("react"));
|
|
4091
|
-
var
|
|
3958
|
+
var import_react_hot_toast11 = __toESM(require("react-hot-toast"));
|
|
4092
3959
|
var import_react70 = require("@hugeicons/react");
|
|
4093
3960
|
var import_core_free_icons23 = require("@hugeicons/core-free-icons");
|
|
4094
3961
|
var PageSpinner5 = () => /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex justify-center items-center py-12" }, /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.Loading03Icon, size: 32, className: "animate-spin mb-4 text-black" }));
|
|
@@ -4102,6 +3969,8 @@ var formatDate = (dateInput) => {
|
|
|
4102
3969
|
var UniversalReferralPage = ({
|
|
4103
3970
|
referralCode,
|
|
4104
3971
|
totalCount,
|
|
3972
|
+
referralCoins = 0,
|
|
3973
|
+
// Default to 0
|
|
4105
3974
|
referrals,
|
|
4106
3975
|
isLoading,
|
|
4107
3976
|
currentPage,
|
|
@@ -4116,9 +3985,9 @@ var UniversalReferralPage = ({
|
|
|
4116
3985
|
if (!referralCode) return;
|
|
4117
3986
|
try {
|
|
4118
3987
|
await navigator.clipboard.writeText(referralCode);
|
|
4119
|
-
|
|
3988
|
+
import_react_hot_toast11.default.success("Referral code copied!");
|
|
4120
3989
|
} catch {
|
|
4121
|
-
|
|
3990
|
+
import_react_hot_toast11.default.error("Failed to copy code.");
|
|
4122
3991
|
}
|
|
4123
3992
|
};
|
|
4124
3993
|
const AvatarLogo2 = ({ src, alt, name, sizeClass = "w-10 h-10" }) => {
|
|
@@ -4127,7 +3996,7 @@ var UniversalReferralPage = ({
|
|
|
4127
3996
|
const finalSrc = src || fallbackUrl;
|
|
4128
3997
|
return /* @__PURE__ */ import_react69.default.createElement("div", { className: `relative shrink-0 rounded-full bg-neutral-100 flex items-center justify-center overflow-hidden border-2 border-white ${sizeClass}` }, !isLoaded && /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.Loading03Icon, size: 16, className: "animate-spin text-neutral-400 absolute" }), /* @__PURE__ */ import_react69.default.createElement("img", { src: finalSrc, alt, onLoad: () => setIsLoaded(true), className: `w-full h-full object-cover transition-opacity duration-300 ${isLoaded ? "opacity-100" : "opacity-0"}` }));
|
|
4129
3998
|
};
|
|
4130
|
-
return /* @__PURE__ */ import_react69.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ import_react69.default.createElement(ManagedToaster, null), /* @__PURE__ */ import_react69.default.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ import_react69.default.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.ArrowLeft01Icon, size: 16 }), " Back")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-3xl bg-white w-full" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-4 mb-2" }, /* @__PURE__ */ import_react69.default.createElement("div", null, /* @__PURE__ */ import_react69.default.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, "Your Referrals"), /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-xs text-neutral-500" }, "Invite friends and earn rewards when they verify and activate cards.")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "border border-neutral-200 rounded-xl p-4 flex items-center justify-between mt-2" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400 " }, "Invitation Code"), isLoading && !referralCode ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "h-6 w-24 bg-neutral-50 animate-pulse rounded mt-1" }) : /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-lg
|
|
3999
|
+
return /* @__PURE__ */ import_react69.default.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ import_react69.default.createElement(ManagedToaster, null), /* @__PURE__ */ import_react69.default.createElement("div", { className: "mb-6 flex w-full items-center px-1" }, /* @__PURE__ */ import_react69.default.createElement("button", { onClick: onBackHandler, className: "flex items-center gap-2 text-neutral-500 hover:text-black transition-colors text-[13px] outline-none" }, /* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.ArrowLeft01Icon, size: 16 }), " Back")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-3xl bg-white w-full" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-4 mb-2" }, /* @__PURE__ */ import_react69.default.createElement("div", null, /* @__PURE__ */ import_react69.default.createElement("h1", { className: "text-black text-xl mb-1 tracking-tight" }, "Your Referrals"), /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-xs text-neutral-500" }, "Invite friends and earn rewards when they verify and activate cards.")), /* @__PURE__ */ import_react69.default.createElement("div", { className: "border border-neutral-200 rounded-xl p-4 flex items-center justify-between mt-2" }, /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] tracking-widest text-neutral-400 " }, "Invitation Code"), isLoading && !referralCode ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "h-6 w-24 bg-neutral-50 animate-pulse rounded mt-1" }) : /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-lg text-black tracking-widest" }, referralCode)), /* @__PURE__ */ import_react69.default.createElement(
|
|
4131
4000
|
"button",
|
|
4132
4001
|
{
|
|
4133
4002
|
onClick: handleCopyCode,
|
|
@@ -4135,7 +4004,7 @@ var UniversalReferralPage = ({
|
|
|
4135
4004
|
className: "w-10 h-10 rounded-full bg-white flex items-center justify-center text-neutral-500 hover:text-black transition-colors outline-none disabled:opacity-50"
|
|
4136
4005
|
},
|
|
4137
4006
|
/* @__PURE__ */ import_react69.default.createElement(import_react70.HugeiconsIcon, { icon: import_core_free_icons23.Copy01Icon, size: 18 })
|
|
4138
|
-
)), /* @__PURE__ */ import_react69.default.createElement("div", { className: "text-[13px]
|
|
4007
|
+
)), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex items-center justify-between text-[13px] text-black px-1 mt-2" }, /* @__PURE__ */ import_react69.default.createElement("span", null, "Total Invited: ", isLoading && !totalCount ? "-" : totalCount), /* @__PURE__ */ import_react69.default.createElement("span", null, "Points: ", isLoading && !referralCoins && referralCoins !== 0 ? "-" : referralCoins))), /* @__PURE__ */ import_react69.default.createElement("div", { className: "w-full overflow-hidden" }, isLoading ? /* @__PURE__ */ import_react69.default.createElement(PageSpinner5, null) : /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react69.default.createElement("div", null, referrals.length === 0 ? /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex flex-col items-center justify-center py-12 opacity-50" }, /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-xs text-neutral-500 text-center" }, "You haven't referred anyone yet.")) : referrals.map((ref, idx) => /* @__PURE__ */ import_react69.default.createElement(
|
|
4139
4008
|
"div",
|
|
4140
4009
|
{
|
|
4141
4010
|
key: `${ref.profile.username}-${idx}`,
|
|
@@ -4148,8 +4017,8 @@ var UniversalReferralPage = ({
|
|
|
4148
4017
|
alt: ref.profile.username,
|
|
4149
4018
|
name: formatWeb3Name2(ref.profile.web3Name)
|
|
4150
4019
|
}
|
|
4151
|
-
), /* @__PURE__ */ import_react69.default.createElement("div", { className: "min-w-0 flex-1 flex flex-col gap-0.5 pr-4" }, /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-[14px]
|
|
4152
|
-
/* @__PURE__ */ import_react69.default.createElement("div", { className: "shrink-0 flex flex-col items-end gap-1 text-right" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] text-neutral-400" }, "Joined"), /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[12px]
|
|
4020
|
+
), /* @__PURE__ */ import_react69.default.createElement("div", { className: "min-w-0 flex-1 flex flex-col gap-0.5 pr-4" }, /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-[14px] text-black truncate" }, formatWeb3Name2(ref.profile.web3Name)), /* @__PURE__ */ import_react69.default.createElement("p", { className: "text-[12px] text-neutral-500 truncate" }, "@", ref.profile.username))),
|
|
4021
|
+
/* @__PURE__ */ import_react69.default.createElement("div", { className: "shrink-0 flex flex-col items-end gap-1 text-right" }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] text-neutral-400" }, "Joined"), /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[12px] text-black" }, formatDate(ref.joinedAt)))
|
|
4153
4022
|
))), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex items-center justify-between pt-6 mt-2 " }, /* @__PURE__ */ import_react69.default.createElement("span", { className: "text-[11px] text-neutral-400 tracking-[0.2em]" }, "Page ", currentPage, " of ", totalPages === 0 ? 1 : totalPages), /* @__PURE__ */ import_react69.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react69.default.createElement(
|
|
4154
4023
|
"button",
|
|
4155
4024
|
{
|