@opexa/portal-components 0.0.141 → 0.0.143

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.
Files changed (53) hide show
  1. package/dist/client/hooks/useApproveMemberVerification.d.ts +4 -0
  2. package/dist/client/hooks/useApproveMemberVerification.js +31 -0
  3. package/dist/client/hooks/useCreateMemberVerificationMutation.js +4 -4
  4. package/dist/client/hooks/useUpdateMemberVerificationMutation.js +1 -0
  5. package/dist/components/Bonuses/Bonuses.client.js +7 -4
  6. package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/OnlineBankDepositContext.d.ts +2 -2
  7. package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/useOnlineBankDeposit.d.ts +1 -1
  8. package/dist/components/DepositWithdrawal/Deposit/QRPHDeposit/QRPHDepositContext.d.ts +2 -2
  9. package/dist/components/DepositWithdrawal/Deposit/QRPHDeposit/useQRPHDeposit.d.ts +1 -1
  10. package/dist/components/GCashFailed/GCashFailed.d.ts +8 -0
  11. package/dist/components/GCashFailed/GCashFailed.js +17 -0
  12. package/dist/components/GCashFailed/index.d.ts +1 -0
  13. package/dist/components/GCashFailed/index.js +1 -0
  14. package/dist/components/GCashSuccess/GCashSuccess.d.ts +9 -0
  15. package/dist/components/GCashSuccess/GCashSuccess.js +88 -0
  16. package/dist/components/GCashSuccess/index.d.ts +1 -0
  17. package/dist/components/GCashSuccess/index.js +1 -0
  18. package/dist/components/KYC/BasicInformation.js +4 -0
  19. package/dist/components/KYC/IdentityVerification.js +2 -4
  20. package/dist/components/KYC/KYC.lazy.js +2 -2
  21. package/dist/components/KYC/PersonalInformation.js +30 -26
  22. package/dist/components/Messages/Message.js +6 -8
  23. package/dist/components/Messages/MessageIcon.d.ts +7 -0
  24. package/dist/components/Messages/MessageIcon.js +20 -0
  25. package/dist/components/Messages/MessagePopup.js +2 -3
  26. package/dist/components/SignUp/SignUp.lazy.d.ts +2 -0
  27. package/dist/components/SignUp/SignUpForm.js +14 -8
  28. package/dist/constants/Branches.d.ts +2 -0
  29. package/dist/constants/Branches.js +42 -0
  30. package/dist/constants/index.d.ts +1 -1
  31. package/dist/constants/index.js +1 -1
  32. package/dist/icons/AnnotationInfoIcon.d.ts +2 -0
  33. package/dist/icons/AnnotationInfoIcon.js +4 -0
  34. package/dist/icons/BellRinging04Icon.d.ts +2 -0
  35. package/dist/icons/BellRinging04Icon.js +4 -0
  36. package/dist/icons/ConfettiIcon.d.ts +2 -0
  37. package/dist/icons/ConfettiIcon.js +4 -0
  38. package/dist/icons/XCircleIcon.d.ts +1 -0
  39. package/dist/icons/XCircleIcon.js +4 -0
  40. package/dist/services/account.d.ts +22 -2
  41. package/dist/services/account.js +12 -1
  42. package/dist/services/queries.d.ts +1 -0
  43. package/dist/services/queries.js +15 -0
  44. package/dist/types/index.d.ts +5 -1
  45. package/dist/ui/Button/button.recipe.d.ts +2 -2
  46. package/dist/ui/Button/button.recipe.js +1 -1
  47. package/dist/ui/IconButton/iconButton.recipe.d.ts +2 -2
  48. package/dist/ui/Tooltip/Tooltip.d.ts +30 -30
  49. package/dist/ui/Tooltip/tooltip.recipe.d.ts +5 -5
  50. package/dist/ui/Tooltip/tooltip.recipe.js +1 -1
  51. package/dist/utils/mutationKeys.d.ts +1 -0
  52. package/dist/utils/mutationKeys.js +4 -0
  53. package/package.json +1 -1
@@ -0,0 +1,4 @@
1
+ import type { SetOptional } from 'type-fest';
2
+ import { type ApproveMemberVerificationInput } from '../../services/account';
3
+ import type { Mutation } from '../../types';
4
+ export declare const useApproveMemberVerification: Mutation<string, SetOptional<ApproveMemberVerificationInput, 'id'>>;
@@ -0,0 +1,31 @@
1
+ import { useMutation } from '@tanstack/react-query';
2
+ import invariant from 'tiny-invariant';
3
+ import { approveMemberVerification__next, } from '../../services/account.js';
4
+ import { getQueryClient } from '../../utils/getQueryClient.js';
5
+ import { getApproveMemberVerificationQueryKey } from '../../utils/mutationKeys.js';
6
+ import { getAccountQueryKey } from '../../utils/queryKeys.js';
7
+ import { getSession } from '../services/getSession.js';
8
+ export const useApproveMemberVerification = (config) => {
9
+ const mutation = useMutation({
10
+ ...config,
11
+ mutationKey: getApproveMemberVerificationQueryKey(),
12
+ mutationFn: async (data) => {
13
+ const session = await getSession();
14
+ const queryClient = getQueryClient();
15
+ invariant(session.status === 'authenticated');
16
+ await approveMemberVerification__next({
17
+ id: data.id || '',
18
+ }, { headers: { Authorization: `Bearer ${session.token}` } });
19
+ queryClient.setQueryData(getAccountQueryKey(), (prev) => {
20
+ if (!prev)
21
+ return prev;
22
+ return {
23
+ ...prev,
24
+ verificationStatus: 'PENDING',
25
+ };
26
+ });
27
+ return data.id || '';
28
+ },
29
+ });
30
+ return mutation;
31
+ };
@@ -25,9 +25,9 @@ export const useCreateMemberVerificationMutation = (config) => {
25
25
  return {
26
26
  id,
27
27
  ...data,
28
- status: 'PENDING',
29
- selfieImage: { id: data.selfieImage, status: 'UPLOADING' },
30
- idFrontImage: { id: data.idFrontImage, status: 'UPLOADING' },
28
+ status: 'UNVERIFIED',
29
+ selfieImage: { id: data.selfieImage ?? '', status: 'UPLOADING' },
30
+ idFrontImage: { id: data.idFrontImage ?? '', status: 'UPLOADING' },
31
31
  };
32
32
  });
33
33
  queryClient.setQueryData(getAccountQueryKey(), (prev) => {
@@ -35,7 +35,7 @@ export const useCreateMemberVerificationMutation = (config) => {
35
35
  return prev;
36
36
  return {
37
37
  ...prev,
38
- verificationStatus: 'PENDING',
38
+ verificationStatus: 'UNVERIFIED',
39
39
  };
40
40
  });
41
41
  return id;
@@ -30,6 +30,7 @@ export const useUpdateMemberVerificationMutation = (config) => {
30
30
  selfieImage: data.selfieImage
31
31
  ? { id: data.selfieImage, status: 'UPLOADING' }
32
32
  : prev.selfieImage,
33
+ status: 'UNVERIFIED',
33
34
  };
34
35
  });
35
36
  },
@@ -20,6 +20,7 @@ import piggyBank from '../../images/piggy-bank.png';
20
20
  import ribbonEnvelope from '../../images/ribbon-envelope.png';
21
21
  import { Badge } from '../../ui/Badge/index.js';
22
22
  import { Button } from '../../ui/Button/index.js';
23
+ import { Popover } from '../../ui/Popover/index.js';
23
24
  import { Progress } from '../../ui/Progress/index.js';
24
25
  import { SegmentGroup } from '../../ui/SegmentGroup/index.js';
25
26
  import { capitalize } from '../../utils/capitalize.js';
@@ -91,11 +92,13 @@ function CashbackBonus(props) {
91
92
  currency: localeInfo.currency.code,
92
93
  }) }), _jsx("div", { className: "text-text-secondary-700 mt-2 line-clamp-1 text-center text-sm", dangerouslySetInnerHTML: {
93
94
  __html: cashback.description,
94
- } }), _jsx("div", { className: "grow" }), _jsx(Button, { size: "sm", className: "mt-6", disabled: claimCashbackBonusMutation.isPending || disabled, onClick: () => {
95
+ } }), _jsx("div", { className: "grow" }), disabled ? (_jsxs(Popover.Root, { lazyMount: true, unmountOnExit: true, positioning: {
96
+ placement: 'top',
97
+ }, children: [_jsx(Button, { size: "sm", className: "mt-6", "aria-disabled": true, asChild: true, children: _jsx(Popover.Trigger, { children: "Claim" }) }), _jsx(Popover.Positioner, { children: _jsxs(Popover.Content, { className: "bg-bg-quaternary rounded-md px-2.5 py-2 text-sm font-medium", children: [_jsx(Popover.Arrow, { className: "arrow-bg-bg-quaternary arrow-size-3", children: _jsx(Popover.ArrowTip, {}) }), "You need", ' ', formatNumber(minimumCashback - balance, {
98
+ currency: localeInfo.currency.code,
99
+ }), ' ', "to claim this cashback."] }) })] })) : (_jsx(Button, { size: "sm", className: "mt-6", disabled: claimCashbackBonusMutation.isPending || disabled, onClick: () => {
95
100
  claimCashbackBonusMutation.mutate(bonus.id);
96
- }, title: disabled
97
- ? `You need ${formatNumber(minimumCashback - balance)} to claim this cashback.`
98
- : undefined, children: "Claim" })] })] }));
101
+ }, children: "Claim" }))] })] }));
99
102
  }
100
103
  function SpotBonus() {
101
104
  const globalStore = useGlobalStore(useShallow((ctx) => ({
@@ -1,6 +1,6 @@
1
1
  export declare const OnlineBankDepositContext: (props: {
2
2
  value: {
3
- view: "vca" | "form";
3
+ view: "form" | "vca";
4
4
  status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
5
5
  verify: () => void;
6
6
  reset: () => void;
@@ -13,7 +13,7 @@ export declare const OnlineBankDepositContext: (props: {
13
13
  } & {
14
14
  children?: import("react").ReactNode | undefined;
15
15
  }) => React.ReactNode, useOnlineBankDepositContext: () => {
16
- view: "vca" | "form";
16
+ view: "form" | "vca";
17
17
  status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
18
18
  verify: () => void;
19
19
  reset: () => void;
@@ -1,7 +1,7 @@
1
1
  import type { Deposit } from '../../../../types';
2
2
  export type UseOnlineBankDepositReturn = ReturnType<typeof useOnlineBankDeposit>;
3
3
  export declare function useOnlineBankDeposit(): {
4
- view: "vca" | "form";
4
+ view: "form" | "vca";
5
5
  status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
6
6
  verify: () => void;
7
7
  reset: () => void;
@@ -1,6 +1,6 @@
1
1
  export declare const QRPHDepositContext: (props: {
2
2
  value: {
3
- view: "qrCode" | "form";
3
+ view: "form" | "qrCode";
4
4
  status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
5
5
  verify: () => void;
6
6
  reset: () => void;
@@ -13,7 +13,7 @@ export declare const QRPHDepositContext: (props: {
13
13
  } & {
14
14
  children?: import("react").ReactNode | undefined;
15
15
  }) => React.ReactNode, useQRPHDepositContext: () => {
16
- view: "qrCode" | "form";
16
+ view: "form" | "qrCode";
17
17
  status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
18
18
  verify: () => void;
19
19
  reset: () => void;
@@ -1,7 +1,7 @@
1
1
  import type { Deposit } from '../../../../types';
2
2
  export type UseQRPHDepositReturn = ReturnType<typeof useQRPHDeposit>;
3
3
  export declare function useQRPHDeposit(): {
4
- view: "qrCode" | "form";
4
+ view: "form" | "qrCode";
5
5
  status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
6
6
  verify: () => void;
7
7
  reset: () => void;
@@ -0,0 +1,8 @@
1
+ import type { ImageProps } from 'next/image';
2
+ import type { CSSProperties } from 'react';
3
+ export interface GCashFailedProps {
4
+ logo: ImageProps['src'];
5
+ style?: CSSProperties;
6
+ className?: string;
7
+ }
8
+ export declare function GCashFailed(props: GCashFailedProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import Image from 'next/image';
4
+ import { useRouter } from 'next/navigation';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { useCooldown } from '../../client/hooks/useCooldown.js';
7
+ import { XCircleIcon } from '../../icons/XCircleIcon.js';
8
+ export function GCashFailed(props) {
9
+ const router = useRouter();
10
+ const cooldown = useCooldown({
11
+ autoplay: true,
12
+ onCooldown() {
13
+ router.replace('/');
14
+ },
15
+ });
16
+ return (_jsx("div", { style: props.style, className: twMerge('flex min-h-dvh items-center p-4 py-8', props.className), children: _jsxs("div", { className: "bg-bg-primary-alt mx-auto w-full max-w-[26.25rem] rounded-xl p-10", children: [_jsx(Image, { src: props.logo, alt: "", width: 200, height: 100, className: "mx-auto block h-7.5 w-auto" }), _jsxs("div", { className: "mt-16", children: [_jsx(XCircleIcon, { className: "text-utility-error-500 mx-auto size-[3.75rem]" }), _jsx("h2", { className: "mt-6 text-center text-3xl font-bold", children: "Deposit Error" }), _jsx("p", { className: "text-text-tertiary-600 mt-3 text-center", children: "Sorry, we encountered an error while processing your deposit request. Please try again later." }), _jsxs("div", { className: "text-text-tertiary-600 mt-[4.875rem] text-center text-sm", children: [_jsx("p", { children: "You will be redirected shortly," }), _jsxs("p", { children: ["in about", ' ', _jsx("span", { className: "text-brand-400 text-lg font-bold", children: cooldown.countdown }), ' ', "second/s."] })] })] })] }) }));
17
+ }
@@ -0,0 +1 @@
1
+ export * from './GCashFailed';
@@ -0,0 +1 @@
1
+ export * from './GCashFailed.js';
@@ -0,0 +1,9 @@
1
+ import type { ImageProps } from 'next/image';
2
+ import { type CSSProperties } from 'react';
3
+ interface GCashSuccessProps {
4
+ logo: ImageProps['src'];
5
+ style?: CSSProperties;
6
+ className?: string;
7
+ }
8
+ export declare function GCashSuccess(props: GCashSuccessProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,88 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import Image from 'next/image';
4
+ import Link from 'next/link';
5
+ import { useRouter } from 'next/navigation';
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { twMerge } from 'tailwind-merge';
8
+ import { useCooldown } from '../../client/hooks/useCooldown.js';
9
+ import { getSession } from '../../client/services/getSession.js';
10
+ import { CheckCircleIcon } from '../../icons/CheckCircleIcon.js';
11
+ import { SpinnerIcon } from '../../icons/SpinnerIcon.js';
12
+ import { getDepositRecords } from '../../services/report.js';
13
+ import { getDeposit, touchGCashDeposit } from '../../services/wallet.js';
14
+ import { Button } from '../../ui/Button/index.js';
15
+ import { createPoll } from '../../utils/createPoll.js';
16
+ export function GCashSuccess(props) {
17
+ const router = useRouter();
18
+ const [loading, setLoading] = useState(true);
19
+ const cooldown = useCooldown({
20
+ autoplay: true,
21
+ onCooldown() {
22
+ router.replace('/');
23
+ },
24
+ });
25
+ const init = useCallback(async () => {
26
+ try {
27
+ const session = await getSession();
28
+ if (session.status !== 'authenticated') {
29
+ router.replace('/');
30
+ return;
31
+ }
32
+ const depositRecords = await getDepositRecords({
33
+ first: 1,
34
+ filter: {
35
+ status: {
36
+ equal: 'ACCEPTED',
37
+ },
38
+ },
39
+ }, {
40
+ headers: {
41
+ Authorization: `Bearer ${session.token}`,
42
+ },
43
+ });
44
+ const depositRecord = depositRecords.edges.at(0)?.node;
45
+ if (!depositRecord) {
46
+ router.replace('/');
47
+ return;
48
+ }
49
+ await touchGCashDeposit(depositRecord.deposit, {
50
+ headers: {
51
+ Authorization: `Bearer ${session.token}`,
52
+ },
53
+ });
54
+ setLoading(false);
55
+ cooldown.start();
56
+ const deposit = await createPoll(() => getDeposit(depositRecord.deposit, {
57
+ headers: {
58
+ Authorization: `Bearer ${session.token}`,
59
+ },
60
+ }), {
61
+ until: (r) => {
62
+ if (r?.status === 'APPROVED' ||
63
+ r?.status === 'REJECTED' ||
64
+ r?.status === 'CONFIRMED') {
65
+ return true;
66
+ }
67
+ else {
68
+ return false;
69
+ }
70
+ },
71
+ interval: 1000,
72
+ maxAttempt: 10,
73
+ })();
74
+ if (deposit?.status === 'APPROVED' ||
75
+ deposit?.status === 'REJECTED' ||
76
+ deposit?.status === 'CONFIRMED') {
77
+ router.replace('/');
78
+ }
79
+ }
80
+ catch {
81
+ router.replace('/');
82
+ }
83
+ }, [cooldown, router]);
84
+ useEffect(() => {
85
+ init();
86
+ }, [init]);
87
+ return (_jsx("div", { style: props.style, className: twMerge('flex min-h-dvh items-center p-4 py-8', props.className), children: _jsxs("div", { className: "bg-bg-primary-alt mx-auto w-full max-w-[26.25rem] rounded-xl p-10", children: [_jsx(Image, { src: props.logo, alt: "", width: 200, height: 100, className: "mx-auto block h-7.5 w-auto" }), _jsx("div", { className: "mt-16", children: loading ? (_jsx(SpinnerIcon, { className: "mx-auto size-8" })) : (_jsxs(_Fragment, { children: [_jsx(CheckCircleIcon, { className: "text-utility-success-500 mx-auto size-[3.75rem]" }), _jsx("h2", { className: "mt-6 text-center text-3xl font-bold", children: "Success" }), _jsx("p", { className: "text-text-tertiary-600 mt-3 text-center", children: "Your deposit request has succeeded." }), _jsxs("div", { className: "text-text-tertiary-600 mt-10 text-center text-sm", children: [_jsx("p", { children: "You will be redirected shortly," }), _jsxs("p", { children: ["in about", ' ', _jsx("span", { className: "text-brand-400 text-lg font-bold", children: cooldown.countdown }), ' ', "second/s."] })] }), _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { href: "/", replace: true, className: "mt-14", children: "Proceed" }) })] })) })] }) }));
88
+ }
@@ -0,0 +1 @@
1
+ export * from './GCashSuccess';
@@ -0,0 +1 @@
1
+ export * from './GCashSuccess.js';
@@ -64,6 +64,10 @@ export function BasicInformation() {
64
64
  },
65
65
  onSuccess() {
66
66
  kyc.setStep(2);
67
+ toaster.success({
68
+ title: 'Success',
69
+ description: 'Basic information has been set successfully.',
70
+ });
67
71
  },
68
72
  });
69
73
  useEffect(() => {
@@ -28,7 +28,6 @@ export function IdentityVerification() {
28
28
  toaster.success({
29
29
  title: 'ID Front Image & Selfie Image uploaded successfully',
30
30
  });
31
- kyc.setStep(3);
32
31
  },
33
32
  onError: (error) => {
34
33
  toaster.error({
@@ -42,7 +41,6 @@ export function IdentityVerification() {
42
41
  toaster.success({
43
42
  title: 'ID Front Image & Selfie Image updated successfully',
44
43
  });
45
- kyc.setStep(3);
46
44
  },
47
45
  onError: (error) => {
48
46
  toaster.error({
@@ -75,6 +73,7 @@ export function IdentityVerification() {
75
73
  placeOfBirth: '',
76
74
  sourceOfIncome: '',
77
75
  });
76
+ kyc.setStep(3);
78
77
  }
79
78
  else {
80
79
  updateMemberVerification({
@@ -84,6 +83,7 @@ export function IdentityVerification() {
84
83
  idFrontImage: values.idFrontImage,
85
84
  },
86
85
  });
86
+ kyc.setStep(3);
87
87
  }
88
88
  }
89
89
  useEffect(() => {
@@ -100,8 +100,6 @@ export function IdentityVerification() {
100
100
  } }, "id-front-image-upload"), _jsx(Field.ErrorText, { children: form.formState.errors.idFrontImage?.message })] }), _jsxs(Field.Root, { className: "mt-3", invalid: !!form.formState.errors.selfieImage, children: [_jsxs(Field.Label, { className: "flex items-center gap-1.5", children: [_jsx("span", { children: "Selfie holding your ID" }), _jsx(HelpCircleIcon, { className: "text-text-quinary size-4" })] }), _jsx(FileUpload, { value: kyc.selfieImageId || '', name: "selfieImage", captureObject: "SELFIE", onChange: (file) => {
101
101
  form.setValue('selfieImage', file);
102
102
  } }, "selfie-image-upload"), _jsx(Field.ErrorText, { children: form.formState.errors.selfieImage?.message })] }), _jsx(Button, { type: "submit", className: "mt-6", disabled: createPending || updatePending, children: "Continue" }), _jsx(Button, { variant: "outline", colorScheme: "gray", className: "mt-lg", type: "button", onClick: () => {
103
- kyc.setStep(3);
104
- kyc.setDone(true);
105
103
  globalStore.kyc.setOpen(false);
106
104
  }, children: "Skip for now" })] }), _jsx(Dialog.Root, { lazyMount: true, unmountOnExit: true, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { children: _jsx(Dialog.Content, { className: "bg-bg-primary-alt mx-auto min-h-full w-full p-3xl lg:h-auto lg:w-[400px]" }) })] }) })] }));
107
105
  }
@@ -34,8 +34,8 @@ export function KYC(props) {
34
34
  else if (memberStatus === 'REJECTED') {
35
35
  kyc.setStep(2);
36
36
  }
37
- else if (isBasicInfoVerified) {
38
- kyc.setStep(isMemberUploaded ? 3 : 2);
37
+ else if (isBasicInfoVerified && isMemberUploaded) {
38
+ kyc.setStep(3);
39
39
  }
40
40
  }, [isBasicInfoVerified, isMemberUploaded, memberStatus, kyc]);
41
41
  const globalStore = useGlobalStore(useShallow((ctx) => ({
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { zodResolver } from '@hookform/resolvers/zod';
3
- import { useEffect } from 'react';
4
3
  import { useForm } from 'react-hook-form';
5
4
  import { z } from 'zod';
6
5
  import { useShallow } from 'zustand/shallow';
6
+ import { useApproveMemberVerification } from '../../client/hooks/useApproveMemberVerification.js';
7
7
  import { useCreateMemberVerificationMutation } from '../../client/hooks/useCreateMemberVerificationMutation.js';
8
8
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
9
9
  import { useMemberVerificationQuery } from '../../client/hooks/useMemberVerificationQuery.js';
@@ -29,7 +29,8 @@ export function PersonalInformation() {
29
29
  kyc: ctx.kyc,
30
30
  })));
31
31
  const memberVerificationQuery = useMemberVerificationQuery();
32
- const memberVerification = memberVerificationQuery.data;
32
+ const memberVerificationId = memberVerificationQuery.data?.id;
33
+ const approveMemberVerificationMutation = useApproveMemberVerification();
33
34
  const updateMemberVerificationMutation = useUpdateMemberVerificationMutation({
34
35
  onError(error) {
35
36
  toaster.error({
@@ -39,6 +40,10 @@ export function PersonalInformation() {
39
40
  onSuccess() {
40
41
  kyc.setDone(true);
41
42
  globalStore.kyc.setOpen(false);
43
+ toaster.success({
44
+ title: 'Success',
45
+ description: 'Personal information has been set successfully.',
46
+ });
42
47
  },
43
48
  });
44
49
  const createMemberVerificationMutation = useCreateMemberVerificationMutation({
@@ -50,6 +55,10 @@ export function PersonalInformation() {
50
55
  onSuccess() {
51
56
  kyc.setDone(true);
52
57
  globalStore.kyc.setOpen(false);
58
+ toaster.success({
59
+ title: 'Success',
60
+ description: 'Personal information has been set successfully.',
61
+ });
53
62
  },
54
63
  });
55
64
  const form = useForm({
@@ -63,32 +72,28 @@ export function PersonalInformation() {
63
72
  },
64
73
  mode: 'all',
65
74
  });
66
- useEffect(() => {
67
- if (memberVerification) {
68
- form.reset(memberVerification);
75
+ async function onSubmit(values) {
76
+ if (!memberVerificationId) {
77
+ createMemberVerificationMutation.mutate({
78
+ ...values,
79
+ });
80
+ }
81
+ else {
82
+ await updateMemberVerificationMutation.mutateAsync({
83
+ id: memberVerificationId,
84
+ data: {
85
+ ...values,
86
+ },
87
+ });
88
+ //approve status of member to be pending
89
+ await approveMemberVerificationMutation.mutateAsync({
90
+ id: memberVerificationId,
91
+ });
69
92
  }
70
- }, [form, memberVerification]);
93
+ }
71
94
  const address = form.watch('address');
72
95
  const permanentAddress = form.watch('permanentAddress');
73
- return (_jsxs("div", { children: [_jsx(Dialog.Title, { className: "text-center text-lg font-semibold", children: "Personal Information" }), _jsx(Dialog.Description, { className: "text-text-secondary-700 mt-xs text-center text-sm", children: "Provide your basic details and work info." }), _jsxs("form", { className: "mt-7", onSubmit: form.handleSubmit((data) => {
74
- if (memberVerification) {
75
- updateMemberVerificationMutation.mutate({
76
- id: memberVerification.id,
77
- data: {
78
- ...data,
79
- selfieImage: '',
80
- idFrontImage: '',
81
- },
82
- });
83
- }
84
- else {
85
- createMemberVerificationMutation.mutate({
86
- ...data,
87
- selfieImage: '',
88
- idFrontImage: '',
89
- });
90
- }
91
- }), children: [_jsxs(Field.Root, { invalid: !!form.formState.errors.permanentAddress, children: [_jsx(Field.Label, { children: "Permanent address" }), _jsx(Field.Input, { placeholder: "Enter your permanent address", ...form.register('permanentAddress') }), _jsx(Field.ErrorText, { children: form.formState.errors.permanentAddress?.message })] }), _jsxs(Field.Root, { className: "mt-2xl", invalid: !!form.formState.errors.address, children: [_jsx(Field.Label, { children: "Current address" }), _jsx(Field.Input, { placeholder: "Enter your current address", ...form.register('address') }), _jsx(Field.ErrorText, { children: form.formState.errors.address?.message })] }), _jsxs(Checkbox.Root, { className: "mt-md", checked: address !== '' &&
96
+ return (_jsxs("div", { children: [_jsx(Dialog.Title, { className: "text-center text-lg font-semibold", children: "Personal Information" }), _jsx(Dialog.Description, { className: "text-text-secondary-700 mt-xs text-center text-sm", children: "Provide your basic details and work info." }), _jsxs("form", { className: "mt-7", onSubmit: form.handleSubmit(onSubmit), children: [_jsxs(Field.Root, { invalid: !!form.formState.errors.permanentAddress, children: [_jsx(Field.Label, { children: "Permanent address" }), _jsx(Field.Input, { placeholder: "Enter your permanent address", ...form.register('permanentAddress') }), _jsx(Field.ErrorText, { children: form.formState.errors.permanentAddress?.message })] }), _jsxs(Field.Root, { className: "mt-2xl", invalid: !!form.formState.errors.address, children: [_jsx(Field.Label, { children: "Current address" }), _jsx(Field.Input, { placeholder: "Enter your current address", ...form.register('address') }), _jsx(Field.ErrorText, { children: form.formState.errors.address?.message })] }), _jsxs(Checkbox.Root, { className: "mt-md", checked: address !== '' &&
92
97
  permanentAddress !== '' &&
93
98
  address === permanentAddress, onCheckedChange: (details) => {
94
99
  if (details.checked === true) {
@@ -100,7 +105,6 @@ export function PersonalInformation() {
100
105
  }
101
106
  }, disabled: !permanentAddress, children: [_jsx(Checkbox.Control, { children: _jsx(Checkbox.Indicator, { asChild: true, children: _jsx(CheckIcon, {}) }) }), _jsx(Checkbox.Label, { children: "Use permanent address as current address" }), _jsx(Checkbox.HiddenInput, {})] }), _jsxs(Field.Root, { className: "mt-2xl", invalid: !!form.formState.errors.sourceOfIncome, children: [_jsx(Field.Label, { children: "Source of income" }), _jsx(Field.Input, { placeholder: "Enter your source of income", ...form.register('sourceOfIncome') }), _jsx(Field.ErrorText, { children: form.formState.errors.sourceOfIncome?.message })] }), _jsxs(Field.Root, { className: "mt-2xl", invalid: !!form.formState.errors.natureOfWork, children: [_jsx(Field.Label, { children: "Work Description" }), _jsx(Field.Input, { placeholder: "Enter your work description", ...form.register('natureOfWork') }), _jsx(Field.ErrorText, { children: form.formState.errors.natureOfWork?.message })] }), _jsxs(Field.Root, { className: "mt-2xl", invalid: !!form.formState.errors.placeOfBirth, children: [_jsx(Field.Label, { children: "Place of birth" }), _jsx(Field.Input, { placeholder: "Enter your place of birth", ...form.register('placeOfBirth') }), _jsx(Field.ErrorText, { children: form.formState.errors.placeOfBirth?.message })] }), _jsxs(Field.Root, { className: "mt-2xl", invalid: !!form.formState.errors.nationality, children: [_jsx(Field.Label, { children: "Nationality" }), _jsx(Field.Input, { placeholder: "Enter your nationality", ...form.register('nationality') }), _jsx(Field.ErrorText, { children: form.formState.errors.nationality?.message })] }), _jsx(Button, { type: "submit", className: "mt-4xl", disabled: updateMemberVerificationMutation.isPending ||
102
107
  createMemberVerificationMutation.isPending, children: "Continue" }), _jsx(Button, { variant: "outline", colorScheme: "gray", className: "mt-lg", onClick: () => {
103
- kyc.setDone(true);
104
108
  globalStore.kyc.setOpen(false);
105
109
  }, disabled: updateMemberVerificationMutation.isPending ||
106
110
  createMemberVerificationMutation.isPending, children: "Skip for now" })] })] }));
@@ -7,7 +7,7 @@ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
7
7
  import { useLocaleInfo } from '../../client/hooks/useLocaleInfo.js';
8
8
  import { useMarkMessageAsReadMutation } from '../../client/hooks/useMarkMessageAsReadMutation.js';
9
9
  import { useMessageContext } from './MessageContext.js';
10
- import { getMessageIcon } from './utils.js';
10
+ import { MessageIcon } from './MessageIcon.js';
11
11
  export function Message() {
12
12
  const message = useMessageContext();
13
13
  const localeInfo = useLocaleInfo();
@@ -16,7 +16,6 @@ export function Message() {
16
16
  messages: ctx.messages,
17
17
  })));
18
18
  const markMessageAsReadMutation = useMarkMessageAsReadMutation();
19
- const Icon = getMessageIcon(message.icon);
20
19
  const handleViewMessage = async () => {
21
20
  globalStore.message.setData(message);
22
21
  globalStore.message.setOpen(true);
@@ -24,12 +23,11 @@ export function Message() {
24
23
  if (!message.markedAsRead)
25
24
  markMessageAsReadMutation.mutate(message.id);
26
25
  };
27
- const handleActionClick = (e) => {
28
- e.stopPropagation();
29
- globalStore.messages.setOpen(false);
30
- globalStore.messages.setTab('ALL');
31
- };
32
26
  return (_jsxs("div", { role: "button", tabIndex: 0, className: "border-border-secondary rounded-xs bg-bg-secondary flex h-auto flex-shrink-0 cursor-pointer flex-col border px-3.5 py-2.5", onClick: handleViewMessage, "aria-pressed": "false", children: [_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx("p", { className: "text-text-tertiary-600 text-xs font-normal", children: format(new Date(message.dateTimeCreated), 'M/d/yyyy - h:mma', {
33
27
  in: tz(localeInfo.timezone),
34
- }) }), !message.markedAsRead && (_jsx("div", { className: "bg-utility-success-500 h-2.5 w-2.5 rounded-full" }))] }), _jsxs("div", { className: "mb-2 flex items-center space-x-2", children: [_jsx(Icon, { className: "text-brand-400" }), _jsx("p", { className: "text-text-primary-brand text-sm font-semibold", children: message.title })] }), _jsx("p", { className: "line-clamp-3 text-wrap text-sm font-normal", dangerouslySetInnerHTML: { __html: message.content } }), message.actions.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap items-center justify-end gap-2", children: message.actions.map((action, index) => (_jsx(Link, { className: "border-button-secondary-border text-button-secondary-fg rounded-md border px-3 py-2 text-sm", href: action.url, onClick: handleActionClick, children: action.name }, index))) }))] }));
28
+ }) }), !message.markedAsRead && (_jsx("div", { className: "bg-utility-success-500 h-2.5 w-2.5 rounded-full" }))] }), _jsxs("div", { className: "mb-2 flex items-center space-x-2", children: [_jsx(MessageIcon, { type: message.icon, className: "text-brand-400 size-5" }), _jsx("p", { className: "text-text-primary-brand text-sm font-semibold", children: message.title })] }), _jsx("p", { className: "line-clamp-3 text-wrap text-sm font-normal", dangerouslySetInnerHTML: { __html: message.content } }), message.actions.length > 0 && (_jsx("div", { className: "mt-2 flex flex-wrap items-center justify-end gap-2", children: message.actions.map((action, index) => (_jsx(Link, { className: "border-button-secondary-border text-button-secondary-fg rounded-md border px-3 py-2 text-sm", href: action.url, onClick: (e) => {
29
+ e.stopPropagation();
30
+ globalStore.messages.setOpen(false);
31
+ globalStore.messages.setTab('ALL');
32
+ }, children: action.name }, index))) }))] }));
35
33
  }
@@ -0,0 +1,7 @@
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import type { Merge } from 'type-fest';
3
+ import type { MessageIcon as TMessageIcon } from '../../types';
4
+ export type MessageIconProps = Merge<ComponentPropsWithRef<'svg'>, {
5
+ type: TMessageIcon;
6
+ }>;
7
+ export declare function MessageIcon(props: MessageIconProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { AlertTriangleIcon } from '../../icons/AlertTriangle.js';
3
+ import { AnnotationInfoIcon } from '../../icons/AnnotationInfoIcon.js';
4
+ import { BellRinging04Icon } from '../../icons/BellRinging04Icon.js';
5
+ import { CheckCircleIcon } from '../../icons/CheckCircleIcon.js';
6
+ import { ConfettiIcon } from '../../icons/ConfettiIcon.js';
7
+ import { Gift01Icon } from '../../icons/Gift01Icon.js';
8
+ const MAP = {
9
+ ALERT: AlertTriangleIcon,
10
+ CELEBRATE: ConfettiIcon,
11
+ CHECK: CheckCircleIcon,
12
+ MESSAGE: BellRinging04Icon,
13
+ CONGRATS: Gift01Icon,
14
+ INFO: AnnotationInfoIcon,
15
+ };
16
+ export function MessageIcon(props) {
17
+ const { type, ...rest } = props;
18
+ const Component = MAP[type];
19
+ return _jsx(Component, { ...rest });
20
+ }
@@ -6,13 +6,12 @@ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
6
6
  import { XIcon } from '../../icons/XIcon.js';
7
7
  import { Dialog } from '../../ui/Dialog/index.js';
8
8
  import { Portal } from '../../ui/Portal/index.js';
9
- import { getMessageIcon } from './utils.js';
9
+ import { MessageIcon } from './MessageIcon.js';
10
10
  export const MessagePopup = () => {
11
11
  const globalStore = useGlobalStore(useShallow((ctx) => ({ message: ctx.message })));
12
- const Icon = getMessageIcon(globalStore.message.data?.icon ?? 'MESSAGE');
13
12
  return (_jsx(Dialog.Root, { lazyMount: true, unmountOnExit: true, open: globalStore.message.open, onOpenChange: ({ open }) => {
14
13
  globalStore.message.setOpen(open);
15
- }, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "!z-[calc(var(--z-dialog)+1)]" }), _jsx(Dialog.Positioner, { className: "!z-[calc(var(--z-dialog)+2)] flex items-center justify-center", children: _jsxs(Dialog.Content, { className: "min-h-auto mx-auto min-w-[21.438rem] max-w-[21.438rem] rounded-xl px-xl pb-0 pt-5 shadow-xl", children: [_jsx(Dialog.CloseTrigger, { children: _jsx(XIcon, {}) }), _jsxs("div", { className: "pb-6", children: [_jsx("div", { className: "bg-bg-brand-secondary mx-auto w-fit rounded-full p-3", children: _jsx(Icon, { className: "text-text-brand", height: "24", width: "24" }) }), _jsx("p", { className: "text-text-primary-brand mt-lg text-center text-lg font-semibold leading-tight", children: globalStore.message.data?.title }), _jsx("div", { className: "text-shadow-text-secondary-700 mt-xs text-center text-sm font-normal leading-tight", dangerouslySetInnerHTML: {
14
+ }, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "!z-[calc(var(--z-dialog)+1)]" }), _jsx(Dialog.Positioner, { className: "!z-[calc(var(--z-dialog)+2)] flex items-center justify-center", children: _jsxs(Dialog.Content, { className: "min-h-auto mx-auto min-w-[21.438rem] max-w-[21.438rem] rounded-xl px-xl pb-0 pt-5 shadow-xl", children: [_jsx(Dialog.CloseTrigger, { children: _jsx(XIcon, {}) }), _jsxs("div", { className: "pb-6", children: [_jsx("div", { className: "bg-bg-brand-secondary mx-auto w-fit rounded-full p-3", children: _jsx(MessageIcon, { type: globalStore.message.data?.icon ?? 'INFO', className: "text-text-brand size-6" }) }), _jsx("p", { className: "text-text-primary-brand mt-lg text-center text-lg font-semibold leading-tight", children: globalStore.message.data?.title }), _jsx("div", { className: "text-shadow-text-secondary-700 mt-xs text-center text-sm font-normal leading-tight", dangerouslySetInnerHTML: {
16
15
  __html: globalStore.message.data?.content ?? '',
17
16
  } })] }), globalStore.message.data?.actions.length ? (_jsx("div", { className: "flex flex-col space-y-2 px-4 pb-8 pt-6 text-center", children: globalStore.message.data.actions.map((action, index) => (_jsx(Link, { className: "bg-button-primary-bg rounded-xs text-button-primary-fg w-full px-4 py-2.5 text-base font-semibold", href: action.url, onClick: () => {
18
17
  globalStore.message.setOpen(false);
@@ -1,10 +1,12 @@
1
1
  import { type ImageProps } from 'next/image';
2
2
  import { type ReactNode } from 'react';
3
+ import type { Branch } from '../../types';
3
4
  export interface SignUpProps {
4
5
  logo: ImageProps['src'];
5
6
  children?: ReactNode;
6
7
  /** @default "/terms-and-conditions" */
7
8
  termsAndConditionsUrl?: string;
8
9
  className?: string;
10
+ branches?: Branch[];
9
11
  }
10
12
  export declare function SignUp(props: SignUpProps): import("react/jsx-runtime").JSX.Element;
@@ -21,7 +21,7 @@ import { useSignInMutation } from '../../client/hooks/useSignInMutation.js';
21
21
  import { useSignUpMutation } from '../../client/hooks/useSignUpMutation.js';
22
22
  import { useUpdateAccountMutation } from '../../client/hooks/useUpdateAccountMutation.js';
23
23
  import { toaster } from '../../client/utils/toaster.js';
24
- import { BRANCH_CODES } from '../../constants/index.js';
24
+ import { BRANCHES } from '../../constants/index.js';
25
25
  import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
26
26
  import { CalendarIcon } from '../../icons/CalendarIcon.js';
27
27
  import { CheckIcon } from '../../icons/CheckIcon.js';
@@ -39,13 +39,16 @@ import { Select } from '../../ui/Select/index.js';
39
39
  import { Tooltip } from '../../ui/Tooltip/index.js';
40
40
  import { createPoll } from '../../utils/createPoll.js';
41
41
  import { useSignUpPropsContext } from './SignUpContext.js';
42
- const branchCollection = createListCollection({
43
- items: BRANCH_CODES,
44
- itemToValue: (item) => item.code,
45
- itemToString: (item) => `${item.code} - ${item.name}`,
46
- });
47
42
  export function SignUpForm() {
48
43
  const signUpProps = useSignUpPropsContext();
44
+ const branchCollection = createListCollection({
45
+ items: signUpProps.branches ?? BRANCHES,
46
+ itemToValue: (item) => item.code,
47
+ itemToString: (item) => `${item.code} - ${item.name}`,
48
+ });
49
+ const globalStore = useGlobalStore(useShallow((ctx) => ({
50
+ kyc: ctx.kyc,
51
+ })));
49
52
  const [step, setStep] = useState(1);
50
53
  const dialog = useDialogContext();
51
54
  const search = useSearchParams();
@@ -114,7 +117,7 @@ export function SignUpForm() {
114
117
  defaultValues: {
115
118
  mobileNumber: '',
116
119
  termsAccepted: false,
117
- branchCode: BRANCH_CODES[0].code,
120
+ branchCode: signUpProps?.branches?.[0]?.code ?? BRANCHES[0].code,
118
121
  realName: '',
119
122
  },
120
123
  });
@@ -160,7 +163,9 @@ export function SignUpForm() {
160
163
  }, onBlur: () => {
161
164
  step1Form.trigger('birthDay');
162
165
  } }), _jsx(Field.ErrorText, { children: step1Form.formState.errors.birthDay?.message })] }), _jsxs(Field.Root, { invalid: !!step1Form.formState.errors.branchCode, className: "mt-xl", children: [_jsxs(Select.Root, { value: [branchCode], onValueChange: (details) => {
163
- step1Form.setValue('branchCode', details.value.at(0) ?? BRANCH_CODES[0].code, {
166
+ step1Form.setValue('branchCode', details.value.at(0) ??
167
+ signUpProps?.branches?.[0]?.code ??
168
+ BRANCHES[0].code, {
164
169
  shouldDirty: true,
165
170
  shouldTouch: true,
166
171
  shouldValidate: true,
@@ -237,6 +242,7 @@ export function SignUpForm() {
237
242
  dialog.setOpen(false);
238
243
  step1Form.reset();
239
244
  step2Form.reset();
245
+ globalStore.kyc.setOpen(true);
240
246
  setStep(1);
241
247
  }
242
248
  catch (error) {