@opexa/portal-components 0.0.332 → 0.0.334

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/useSignUpMutation.d.ts +1 -1
  2. package/dist/client/hooks/useSignUpMutation.js +3 -0
  3. package/dist/client/hooks/useUpdateSessionMutation.js +2 -0
  4. package/dist/client/services/updateSession.d.ts +1 -0
  5. package/dist/components/PortalProvider/PortalProvider.js +3 -1
  6. package/dist/components/PortalProvider/SessionWatcher.d.ts +1 -0
  7. package/dist/components/PortalProvider/SessionWatcher.js +22 -0
  8. package/dist/components/PortalProvider/SetupBtag.d.ts +1 -0
  9. package/dist/components/PortalProvider/SetupBtag.js +29 -0
  10. package/dist/components/PortalProvider/SetupCellxpertCxd.js +1 -1
  11. package/dist/components/PortalProvider/SetupDomain.js +1 -1
  12. package/dist/components/SignIn/GoogleSignInTrigger.js +12 -12
  13. package/dist/components/SignUp/SignUpDefault/SignUpDefaultForm.js +0 -1
  14. package/dist/components/SignUp/SignUpKYC/SignUpKYCForm.js +0 -1
  15. package/dist/constants/StorageKey.d.ts +2 -1
  16. package/dist/constants/StorageKey.js +2 -1
  17. package/dist/handlers/getSession.js +12 -1
  18. package/dist/handlers/index.d.ts +7 -7
  19. package/dist/handlers/patchSession.js +9 -1
  20. package/dist/handlers/postAuthenticate.js +3 -0
  21. package/dist/handlers/postSession.js +3 -0
  22. package/dist/services/account.d.ts +4 -0
  23. package/dist/types/index.d.ts +5 -3
  24. package/dist/ui/AlertDialog/AlertDialog.d.ts +55 -55
  25. package/dist/ui/AlertDialog/alertDialog.recipe.d.ts +5 -5
  26. package/dist/ui/Checkbox/Checkbox.d.ts +23 -23
  27. package/dist/ui/Checkbox/checkbox.recipe.d.ts +3 -3
  28. package/dist/ui/Combobox/Combobox.d.ts +42 -42
  29. package/dist/ui/Combobox/combobox.recipe.d.ts +3 -3
  30. package/dist/ui/DatePicker/DatePicker.d.ts +72 -72
  31. package/dist/ui/DatePicker/datePicker.recipe.d.ts +3 -3
  32. package/dist/ui/Dialog/Dialog.d.ts +55 -55
  33. package/dist/ui/Dialog/dialog.recipe.d.ts +5 -5
  34. package/dist/ui/Drawer/Drawer.d.ts +33 -33
  35. package/dist/ui/Drawer/drawer.recipe.d.ts +3 -3
  36. package/dist/ui/Menu/Menu.d.ts +252 -252
  37. package/dist/ui/Menu/menu.recipe.d.ts +14 -14
  38. package/dist/ui/Popover/Popover.d.ts +121 -121
  39. package/dist/ui/Popover/popover.recipe.d.ts +11 -11
  40. package/dist/ui/Progress/Progress.d.ts +27 -27
  41. package/dist/ui/Progress/progress.recipe.d.ts +3 -3
  42. package/dist/ui/QrCode/QrCode.d.ts +25 -25
  43. package/dist/ui/QrCode/qrCode.recipe.d.ts +5 -5
  44. package/dist/ui/Select/Select.d.ts +45 -45
  45. package/dist/ui/Select/select.recipe.d.ts +3 -3
  46. package/dist/ui/Table/Table.d.ts +21 -21
  47. package/dist/ui/Table/table.anatomy.d.ts +1 -1
  48. package/dist/ui/Table/table.recipe.d.ts +3 -3
  49. package/dist/ui/Tabs/Tabs.d.ts +15 -15
  50. package/dist/ui/Tabs/tabs.recipe.d.ts +3 -3
  51. package/dist/ui/Tooltip/Tooltip.d.ts +30 -30
  52. package/dist/ui/Tooltip/tooltip.recipe.d.ts +5 -5
  53. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { type RegisterMemberAccountViaMobileInput } from '../../services/account';
2
2
  import type { Mutation } from '../../types';
3
- export interface SignUpMutationInput extends Omit<RegisterMemberAccountViaMobileInput, 'domain' | 'cellxpertCxd'> {
3
+ export interface SignUpMutationInput extends Omit<RegisterMemberAccountViaMobileInput, 'btag' | 'domain' | 'cellxpertCxd'> {
4
4
  }
5
5
  export declare const useSignUpMutation: Mutation<void, SignUpMutationInput>;
@@ -10,6 +10,9 @@ export const useSignUpMutation = (config) => {
10
10
  const session = await getSession();
11
11
  return await registerMemberAccountViaMobile({
12
12
  ...input,
13
+ ...(session.btag && {
14
+ btag: session.btag,
15
+ }),
13
16
  ...(session.cellxpertCxd && {
14
17
  cellxpertCxd: session.cellxpertCxd,
15
18
  }),
@@ -14,11 +14,13 @@ export const useUpdateSessionMutation = (config) => {
14
14
  if (!prev)
15
15
  return prev;
16
16
  const domain = input.domain ?? prev.domain;
17
+ const btag = input.btag ?? prev.btag;
17
18
  const cellxpertCxd = input.cellxpertCxd ?? prev.cellxpertCxd;
18
19
  if (prev.status === 'unauthenticated') {
19
20
  return {
20
21
  status: 'unauthenticated',
21
22
  domain,
23
+ btag,
22
24
  cellxpertCxd,
23
25
  };
24
26
  }
@@ -1,6 +1,7 @@
1
1
  import { type HttpRequestOptions } from '../../services/httpRequest';
2
2
  export interface UpdateSessionInput {
3
3
  domain?: string;
4
+ btag?: string;
4
5
  cellxpertCxd?: string;
5
6
  }
6
7
  export declare const updateSession: (input: UpdateSessionInput, options?: HttpRequestOptions) => Promise<boolean>;
@@ -9,6 +9,8 @@ import { getQueryClient } from '../../utils/getQueryClient.js';
9
9
  import { FeatureFlag } from './FeatureFlag.js';
10
10
  import { LinkGoogleAccountObserver } from './LinkGoogleAccountObserver.js';
11
11
  import { Providers } from './Providers.js';
12
+ import { SessionWatcher } from './SessionWatcher.js';
13
+ import { SetupBtag } from './SetupBtag.js';
12
14
  import { SetupCellxpertCxd } from './SetupCellxpertCxd.js';
13
15
  import { SetupDomain } from './SetupDomain.js';
14
16
  import { Snackbar } from './Snackbar.js';
@@ -20,5 +22,5 @@ export async function PortalProvider({ recaptchaSiteKey, children, }) {
20
22
  prefetchAccountQuery(),
21
23
  prefetchWalletQuery(),
22
24
  ]);
23
- return (_jsxs(Fragment, { children: [_jsx(Providers, { recaptchaSiteKey: recaptchaSiteKey, children: _jsxs(HydrationBoundary, { state: dehydrate(queryClient), children: [children, _jsx(Suspense, { children: _jsx(SetupDomain, {}) }), _jsx(Suspense, { children: _jsx(SetupCellxpertCxd, {}) })] }) }), _jsx(Snackbar, {}), _jsx(Suspense, { children: _jsx(LinkGoogleAccountObserver, {}) }), _jsx(Suspense, { children: _jsx(FeatureFlag, {}) })] }));
25
+ return (_jsxs(Fragment, { children: [_jsx(Providers, { recaptchaSiteKey: recaptchaSiteKey, children: _jsxs(HydrationBoundary, { state: dehydrate(queryClient), children: [children, _jsx(SessionWatcher, {}), _jsx(Suspense, { children: _jsx(SetupDomain, {}) }), _jsx(Suspense, { children: _jsx(SetupCellxpertCxd, {}) }), _jsx(Suspense, { children: _jsx(SetupBtag, {}) })] }) }), _jsx(Snackbar, {}), _jsx(Suspense, { children: _jsx(LinkGoogleAccountObserver, {}) }), _jsx(Suspense, { children: _jsx(FeatureFlag, {}) })] }));
24
26
  }
@@ -0,0 +1 @@
1
+ export declare function SessionWatcher(): null;
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ import { useRouter } from 'next/navigation';
3
+ import { useTimeout } from 'usehooks-ts';
4
+ import { useSessionHealthQuery } from '../../client/hooks/useSessionHealthQuery.js';
5
+ import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
6
+ import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
7
+ export function SessionWatcher() {
8
+ const router = useRouter();
9
+ const sessionQuery = useSessionQuery();
10
+ const sessionHealthQuery = useSessionHealthQuery({
11
+ enabled: sessionQuery.data?.status === 'authenticated',
12
+ refetchInterval: 1000 * 5,
13
+ });
14
+ const signOutMutation = useSignOutMutation({
15
+ onSuccess() {
16
+ router.refresh();
17
+ },
18
+ });
19
+ const healthy = sessionHealthQuery.data ?? true;
20
+ useTimeout(() => signOutMutation.mutate(), !healthy ? 250 : null);
21
+ return null;
22
+ }
@@ -0,0 +1 @@
1
+ export declare function SetupBtag(): null;
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+ import { useSearchParams } from 'next/navigation';
3
+ import { useTimeout } from 'usehooks-ts';
4
+ import { z } from 'zod';
5
+ import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
6
+ import { useUpdateSessionMutation } from '../../client/hooks/useUpdateSessionMutation.js';
7
+ const BtagSchema = z
8
+ .string()
9
+ .min(1)
10
+ .max(100)
11
+ .trim()
12
+ .optional()
13
+ .nullable()
14
+ .catch(null);
15
+ export function SetupBtag() {
16
+ const query = useSessionQuery();
17
+ const mutation = useUpdateSessionMutation();
18
+ const params = useSearchParams();
19
+ useTimeout(() => {
20
+ const oldValue = query.data?.btag;
21
+ const newValue = BtagSchema.parse(params.get('btag'));
22
+ if (oldValue === newValue)
23
+ return;
24
+ if (!newValue)
25
+ return;
26
+ mutation.mutate({ btag: newValue });
27
+ }, query.data?.status === 'unauthenticated' ? 250 : null);
28
+ return null;
29
+ }
@@ -23,6 +23,6 @@ export function SetupCellxpertCxd() {
23
23
  if (!newValue)
24
24
  return;
25
25
  mutation.mutate({ cellxpertCxd: newValue });
26
- }, query.data?.status !== 'unauthenticated' ? null : 1000);
26
+ }, query.data?.status === 'unauthenticated' ? 250 : null);
27
27
  return null;
28
28
  }
@@ -32,6 +32,6 @@ export function SetupDomain() {
32
32
  if (oldDomain === newDomain)
33
33
  return;
34
34
  return mutation.mutate({ domain: newDomain });
35
- }, query.isPending ? null : 1000);
35
+ }, query.isPending ? null : 250);
36
36
  return null;
37
37
  }
@@ -16,31 +16,31 @@ export const GoogleSignInTrigger = (props) => {
16
16
  return null;
17
17
  return (_jsx(GoogleOAuthProvider, { clientId: googleClientId, children: _jsx(Trigger, { ...props }) }));
18
18
  };
19
- const Trigger = ({ children, asChild, onClick, ...props }) => {
20
- const signIn = useSignInMutation();
19
+ const Trigger = ({ children, disabled, asChild, onClick, ...props }) => {
20
+ const signIn = useSignInMutation({
21
+ onError() {
22
+ toaster.error({
23
+ title: 'Account Not Found',
24
+ description: 'The Google account you used isn’t connected to any existing account in our system. Please connect it to continue.',
25
+ });
26
+ },
27
+ });
21
28
  const signInGoogle = useGoogleLogin({
22
29
  flow: 'auth-code',
23
30
  scope: 'openid profile email phone',
24
31
  state: encodeURIComponent(`${window.location.origin},${PLATFORM_CODE}`),
25
32
  ux_mode: 'popup',
26
33
  redirect_uri: 'postmessage',
27
- onSuccess: async (cred) => {
28
- const { token } = await httpRequest.json(`${AUTH_ENDPOINT}/google/auth?state=${cred.state}&code=${cred.code}&scope=${cred.scope}`);
34
+ onSuccess: async (res) => {
35
+ const { token } = await httpRequest.json(`${AUTH_ENDPOINT}/google/auth?state=${res.state}&code=${res.code}&scope=${res.scope}`);
29
36
  signIn.mutate({
30
37
  type: 'SOCIALS',
31
38
  token,
32
- }, {
33
- onError: () => {
34
- toaster.error({
35
- title: 'Account Not Found',
36
- description: 'The Google account you used isn’t connected to any existing account in our system. Please connect it to continue.',
37
- });
38
- },
39
39
  });
40
40
  },
41
41
  });
42
42
  return (_jsx(ark.button, { type: "button", onClick: (e) => {
43
43
  onClick?.(e);
44
44
  signInGoogle();
45
- }, asChild: !children ? true : asChild, ...props, children: children ?? (_jsxs(Button, { variant: "outline", colorScheme: "gray", className: "bg-bg-primary", children: [_jsx(GoogleIcon, { className: "size-6" }), "Continue with Google"] })) }));
45
+ }, asChild: !children ? true : asChild, disabled: signIn.isPending || disabled, ...props, children: children ?? (_jsxs(Button, { variant: "outline", colorScheme: "gray", className: "bg-bg-primary", children: [_jsx(GoogleIcon, { className: "size-6" }), "Continue with Google"] })) }));
46
46
  };
@@ -229,7 +229,6 @@ export function SignUpDefaultForm() {
229
229
  mobileNumber: mobileNumberParser.format(mobileNumber),
230
230
  verificationCode: verificationCode.join(''),
231
231
  referralCode: search.get('referralCode') ?? undefined,
232
- btag: search.get('btag') ?? undefined,
233
232
  });
234
233
  const name = mobileNumberParser.format(mobileNumber);
235
234
  const password = `${name}${id}`;
@@ -314,7 +314,6 @@ export function SignUpKYCForm() {
314
314
  mobileNumber: mobileNumberParser.format(mobileNumber),
315
315
  verificationCode: verificationCode.join(''),
316
316
  referralCode: search.get('referralCode') ?? undefined,
317
- btag: search.get('btag') ?? undefined,
318
317
  });
319
318
  const name = mobileNumberParser.format(mobileNumber);
320
319
  const password = `${name}${id}`;
@@ -1,5 +1,6 @@
1
1
  export declare const ACCESS_TOKEN_COOKIE_NAME: string;
2
2
  export declare const REFRESH_TOKEN_COOKIE_NAME: string;
3
3
  export declare const DOMAIN_COOKIE_NAME: string;
4
- export declare const FEATURE_FLAG_LOCAL_STORAGE_KEY: string;
4
+ export declare const BTAG_COOKIE_NAME: string;
5
5
  export declare const CELLXPERT_CXD_COOKIE_NAME: string;
6
+ export declare const FEATURE_FLAG_LOCAL_STORAGE_KEY: string;
@@ -1,5 +1,6 @@
1
1
  export const ACCESS_TOKEN_COOKIE_NAME = 'WebPortalAuthAccessToken';
2
2
  export const REFRESH_TOKEN_COOKIE_NAME = 'WebPortalAuthRefreshToken';
3
3
  export const DOMAIN_COOKIE_NAME = 'WebPortalDomain';
4
- export const FEATURE_FLAG_LOCAL_STORAGE_KEY = 'WebPortalFeatureFlag';
4
+ export const BTAG_COOKIE_NAME = 'WebPortalBtag';
5
5
  export const CELLXPERT_CXD_COOKIE_NAME = 'WebPortalCellxpertCxd';
6
+ export const FEATURE_FLAG_LOCAL_STORAGE_KEY = 'WebPortalFeatureFlag';
@@ -1,11 +1,12 @@
1
1
  import { addMinutes } from 'date-fns';
2
2
  import { NextResponse } from 'next/server';
3
- import { ACCESS_TOKEN_COOKIE_NAME, CELLXPERT_CXD_COOKIE_NAME, DOMAIN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, } from '../constants/index.js';
3
+ import { ACCESS_TOKEN_COOKIE_NAME, BTAG_COOKIE_NAME, CELLXPERT_CXD_COOKIE_NAME, DOMAIN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME, } from '../constants/index.js';
4
4
  import { refreshSession } from '../services/auth.js';
5
5
  export async function getSession(request) {
6
6
  const accessToken = request.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value;
7
7
  const refreshToken = request.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value;
8
8
  const domain = request.cookies.get(DOMAIN_COOKIE_NAME)?.value;
9
+ const btag = request.cookies.get(BTAG_COOKIE_NAME)?.value;
9
10
  const cellxpertCxd = request.cookies.get(CELLXPERT_CXD_COOKIE_NAME)?.value;
10
11
  if (!refreshToken) {
11
12
  const response = NextResponse.json({
@@ -13,6 +14,7 @@ export async function getSession(request) {
13
14
  data: {
14
15
  status: 'unauthenticated',
15
16
  domain,
17
+ btag,
16
18
  cellxpertCxd,
17
19
  },
18
20
  });
@@ -22,9 +24,17 @@ export async function getSession(request) {
22
24
  }
23
25
  if (!accessToken) {
24
26
  try {
27
+ const forwarded = request.headers.get('x-forwarded-for');
28
+ const ipaddress = forwarded?.split(',')[0];
25
29
  const data = await refreshSession({
26
30
  headers: {
27
31
  Authorization: `Bearer ${refreshToken}`,
32
+ ...(ipaddress && {
33
+ 'X-Forwarded-For': ipaddress,
34
+ }),
35
+ ...(ipaddress && {
36
+ 'X-User-Real-Ip': ipaddress,
37
+ }),
28
38
  },
29
39
  });
30
40
  const response = NextResponse.json({
@@ -48,6 +58,7 @@ export async function getSession(request) {
48
58
  data: {
49
59
  status: 'unauthenticated',
50
60
  domain,
61
+ btag,
51
62
  cellxpertCxd,
52
63
  },
53
64
  });
@@ -6,26 +6,26 @@ interface Context {
6
6
  params: Promise<Params>;
7
7
  }
8
8
  export declare const GET: (req: NextRequest, { params }: Context) => Promise<NextResponse<{
9
- ok: true;
10
- data?: never;
11
- } | {
12
9
  ok: false;
13
10
  message: string;
14
11
  __error?: unknown;
12
+ } | {
13
+ ok: true;
14
+ data: import("../types").Session;
15
15
  }> | NextResponse<{
16
+ ok: true;
17
+ data?: never;
18
+ } | {
16
19
  ok: false;
17
20
  message: string;
18
21
  __error?: unknown;
19
- } | {
20
- ok: true;
21
- data: Record<string, unknown>;
22
22
  }> | NextResponse<{
23
23
  ok: false;
24
24
  message: string;
25
25
  __error?: unknown;
26
26
  } | {
27
27
  ok: true;
28
- data: import("../types").Session;
28
+ data: Record<string, unknown>;
29
29
  }>>;
30
30
  export declare const DELETE: (req: NextRequest, { params }: Context) => Promise<NextResponse<{
31
31
  ok: true;
@@ -1,9 +1,10 @@
1
1
  import { addDays, addHours } from 'date-fns';
2
2
  import { NextResponse } from 'next/server';
3
3
  import { z } from 'zod';
4
- import { CELLXPERT_CXD_COOKIE_NAME, DOMAIN_COOKIE_NAME } from '../constants/index.js';
4
+ import { BTAG_COOKIE_NAME, CELLXPERT_CXD_COOKIE_NAME, DOMAIN_COOKIE_NAME, } from '../constants/index.js';
5
5
  const UpdateSessionDefinition = z.object({
6
6
  domain: z.string().optional().nullable(),
7
+ btag: z.string().optional().nullable(),
7
8
  cellxpertCxd: z.string().optional().nullable(),
8
9
  });
9
10
  export async function patchSession(request) {
@@ -30,5 +31,12 @@ export async function patchSession(request) {
30
31
  sameSite: 'strict',
31
32
  });
32
33
  }
34
+ if (parsed.data.btag) {
35
+ response.cookies.set(BTAG_COOKIE_NAME, parsed.data.btag, {
36
+ expires: addDays(new Date(), 30),
37
+ httpOnly: true,
38
+ sameSite: 'strict',
39
+ });
40
+ }
33
41
  return response;
34
42
  }
@@ -38,6 +38,9 @@ export async function postAuthenticate(request) {
38
38
  ...(ipaddress && {
39
39
  'X-Forwarded-For': ipaddress,
40
40
  }),
41
+ ...(ipaddress && {
42
+ 'X-User-Real-Ip': ipaddress,
43
+ }),
41
44
  },
42
45
  });
43
46
  const response = NextResponse.json({ ok: true }, { status: 201 });
@@ -56,6 +56,9 @@ export async function postSession(request) {
56
56
  ...(ipaddress && {
57
57
  'X-Forwarded-For': ipaddress,
58
58
  }),
59
+ ...(ipaddress && {
60
+ 'X-User-Real-Ip': ipaddress,
61
+ }),
59
62
  },
60
63
  });
61
64
  if (res.authenticator) {
@@ -37,6 +37,7 @@ export interface RegisterMemberAccountMutationVariables {
37
37
  password: string;
38
38
  mobileNumber: string;
39
39
  birthDay: string;
40
+ /** @deprecated Attach domain as header instead */
40
41
  domain?: string;
41
42
  btag?: string;
42
43
  };
@@ -53,6 +54,7 @@ export interface RegisterMemberAccountViaMobileMutationVariables {
53
54
  id: string;
54
55
  mobileNumber: string;
55
56
  btag?: string;
57
+ /** @deprecated Attach domain as header instead */
56
58
  domain?: string;
57
59
  cellxpertCxd?: string;
58
60
  };
@@ -91,6 +93,7 @@ export interface RegisterMemberAccountMutationVariables__Next {
91
93
  name: string;
92
94
  password: string;
93
95
  mobileNumber?: string;
96
+ /** @deprecated Attach domain as header instead */
94
97
  domain?: string;
95
98
  btag?: string;
96
99
  };
@@ -331,6 +334,7 @@ export interface RegisterMayaMemberAccountMutationVariables {
331
334
  input: {
332
335
  name: string;
333
336
  password: string;
337
+ /** @deprecated Attach domain as header instead */
334
338
  domain?: string;
335
339
  };
336
340
  }
@@ -7,13 +7,15 @@ import type { ImageProps } from 'next/image';
7
7
  */
8
8
  export type Session = {
9
9
  status: 'authenticated';
10
- domain?: string;
11
10
  token: string;
12
- cellxpertCxd?: string;
11
+ domain?: string;
12
+ btag?: never;
13
+ cellxpertCxd?: never;
13
14
  } | {
14
15
  status: 'unauthenticated';
15
- domain?: string;
16
16
  token?: never;
17
+ domain?: string;
18
+ btag?: string;
17
19
  cellxpertCxd?: string;
18
20
  };
19
21
  /**