@vtex/faststore-plugin-buyer-portal 1.1.115 → 1.1.116-poc-1

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 (32) hide show
  1. package/package.json +42 -42
  2. package/src/features/addresses/layouts/AddressDetailsLayout/AddressDetailsLayout.tsx +1 -0
  3. package/src/features/addresses/layouts/AddressesLayout/AddressesLayout.tsx +1 -0
  4. package/src/features/budgets/layouts/BudgetsDetailsLayout/BudgetsDetailsLayout.tsx +1 -0
  5. package/src/features/collections/layouts/CollectionsLayout/CollectionsLayout.tsx +1 -0
  6. package/src/features/contracts/hooks/index.ts +2 -0
  7. package/src/features/contracts/hooks/useContractDetails.ts +22 -0
  8. package/src/features/contracts/hooks/useContractsByOrgUnitId.ts +20 -0
  9. package/src/features/credit-cards/layouts/CreditCardsLayout/CreditCardLayout.tsx +1 -0
  10. package/src/features/custom-fields/layouts/CustomFieldsLayout/CustomFieldsLayout.tsx +1 -0
  11. package/src/features/org-units/hooks/index.ts +1 -0
  12. package/src/features/org-units/hooks/useOrgUnitBasicData.ts +20 -0
  13. package/src/features/org-units/layouts/OrgUnitDetailsLayout/OrgUnitDetailsLayout.tsx +31 -28
  14. package/src/features/payment-methods/layouts/PaymentMethodsLayout/PaymentMethodsLayout.tsx +1 -0
  15. package/src/features/profile/layouts/ProfileLayout/ProfileLayout.tsx +33 -16
  16. package/src/features/shared/components/Error/Error.tsx +12 -13
  17. package/src/features/shared/components/PageLoader/PageLoader.tsx +36 -11
  18. package/src/features/shared/components/withErrorBoundary/withErrorBoundary.tsx +6 -7
  19. package/src/features/shared/hooks/index.ts +1 -0
  20. package/src/features/shared/hooks/useAuth.ts +54 -0
  21. package/src/features/shared/hooks/useCookieMonitor.ts +2 -6
  22. package/src/features/shared/layouts/ContractTabsLayout/ContractTabsLayout.tsx +6 -4
  23. package/src/features/shared/layouts/ErrorTabsLayout/ErrorTabsLayout.tsx +1 -0
  24. package/src/features/shared/layouts/LoadingTabsLayout/LoadingTabsLayout.tsx +2 -27
  25. package/src/features/shared/types/AuthRouteProps.ts +2 -8
  26. package/src/features/shared/utils/withAuth.tsx +10 -62
  27. package/src/features/shared/utils/withAuthLoader.ts +0 -28
  28. package/src/features/shared/utils/withAuthProvider.tsx +11 -81
  29. package/src/features/shared/utils/withLoaderErrorBoundary.ts +71 -79
  30. package/src/features/shared/utils/withProviders.tsx +1 -2
  31. package/src/pages/org-unit-details.tsx +32 -58
  32. package/src/pages/profile.tsx +46 -64
package/package.json CHANGED
@@ -1,44 +1,44 @@
1
1
  {
2
- "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.1.115",
4
- "description": "A plugin for faststore with buyer portal",
5
- "main": "index.js",
6
- "scripts": {
7
- "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
8
- "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
9
- "prepare": "husky"
10
- },
11
- "lint-staged": {
12
- "*.{js,jsx,ts,tsx}": [
13
- "eslint --fix"
14
- ]
15
- },
16
- "dependencies": {
17
- "@types/react-dom": "^19.0.3",
18
- "react-dom": "^19.0.0"
19
- },
20
- "devDependencies": {
21
- "@eslint/js": "^9.29.0",
22
- "@faststore/core": "^3.41.5",
23
- "@faststore/ui": "^3.41.5",
24
- "@types/react": "^18.2.42",
25
- "cypress": "13",
26
- "eslint": "^9.29.0",
27
- "eslint-config-prettier": "^10.1.5",
28
- "eslint-plugin-import": "^2.32.0",
29
- "eslint-plugin-prettier": "^5.5.1",
30
- "eslint-plugin-react": "^7.37.5",
31
- "globals": "^16.2.0",
32
- "husky": "^9.1.7",
33
- "lint-staged": "^16.1.2",
34
- "next": "13.5.7",
35
- "typescript": "4.7.3",
36
- "typescript-eslint": "^8.35.0"
37
- },
38
- "peerDependencies": {
39
- "react": "^18.2.0",
40
- "react-dom": "^18.2.0"
41
- },
42
- "license": "MIT",
43
- "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
2
+ "name": "@vtex/faststore-plugin-buyer-portal",
3
+ "version": "1.1.116-poc-1",
4
+ "description": "A plugin for faststore with buyer portal",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
8
+ "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
9
+ "prepare": "husky"
10
+ },
11
+ "lint-staged": {
12
+ "*.{js,jsx,ts,tsx}": [
13
+ "eslint --fix"
14
+ ]
15
+ },
16
+ "dependencies": {
17
+ "@types/react-dom": "^19.0.3",
18
+ "react-dom": "^19.0.0"
19
+ },
20
+ "devDependencies": {
21
+ "@eslint/js": "^9.29.0",
22
+ "@faststore/core": "^3.41.5",
23
+ "@faststore/ui": "^3.41.5",
24
+ "@types/react": "^18.2.42",
25
+ "cypress": "13",
26
+ "eslint": "^9.29.0",
27
+ "eslint-config-prettier": "^10.1.5",
28
+ "eslint-plugin-import": "^2.32.0",
29
+ "eslint-plugin-prettier": "^5.5.1",
30
+ "eslint-plugin-react": "^7.37.5",
31
+ "globals": "^16.2.0",
32
+ "husky": "^9.1.7",
33
+ "lint-staged": "^16.1.2",
34
+ "next": "13.5.7",
35
+ "typescript": "4.7.3",
36
+ "typescript-eslint": "^8.35.0"
37
+ },
38
+ "peerDependencies": {
39
+ "react": "^18.2.0",
40
+ "react-dom": "^18.2.0"
41
+ },
42
+ "license": "MIT",
43
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
44
44
  }
@@ -124,6 +124,7 @@ export const AddressDetailsLayout = ({
124
124
  image: undefined,
125
125
  name: user?.name ?? "",
126
126
  role: user?.role ?? "",
127
+ id: user?.id ?? "",
127
128
  }}
128
129
  >
129
130
  <section data-fs-address-details-section>
@@ -114,6 +114,7 @@ export const AddressLayout = ({
114
114
  image: undefined,
115
115
  name: user?.name ?? "",
116
116
  role: user?.role ?? "",
117
+ id: user?.id ?? "",
117
118
  }}
118
119
  >
119
120
  <section data-fs-addresses-section>
@@ -151,6 +151,7 @@ export const BudgetsDetailsLayout = ({ budget }: BudgetsDetailsLayoutProps) => {
151
151
  image: undefined,
152
152
  name: user?.name ?? "",
153
153
  role: user?.role ?? "",
154
+ id: user?.id ?? "",
154
155
  }}
155
156
  >
156
157
  <div data-fs-bp-budgets-details-layout>
@@ -72,6 +72,7 @@ export const CollectionsLayout = ({
72
72
  image: undefined,
73
73
  name: user?.name ?? "",
74
74
  role: user?.role ?? "",
75
+ id: user?.id ?? "",
75
76
  }}
76
77
  >
77
78
  <section data-fs-bp-collections-container>
@@ -1 +1,3 @@
1
1
  export { useUpdateContractStatus } from "./useUpdateContractStatus";
2
+ export { useContractsByOrgUnitId } from "./useContractsByOrgUnitId";
3
+ export { useContractDetails } from "./useContractDetails";
@@ -0,0 +1,22 @@
1
+ import { type QueryOptions, useQuery } from "../../shared/hooks";
2
+ import { getContractDetailsService } from "../services";
3
+
4
+ export const useContractDetails = (
5
+ contractId: string,
6
+ unitId: string,
7
+ options?: QueryOptions<AwaitedType<typeof getContractDetailsService>>
8
+ ) => {
9
+ const { data, error, isLoading, refetch } = useQuery(
10
+ `api/contract-details/${unitId}`,
11
+ ({ cookie }) =>
12
+ getContractDetailsService({ contractId, cookie, unitId: unitId }),
13
+ options
14
+ );
15
+
16
+ return {
17
+ contract: data,
18
+ hasContractError: error,
19
+ isContractLoading: isLoading,
20
+ refetchContract: refetch,
21
+ };
22
+ };
@@ -0,0 +1,20 @@
1
+ import { type QueryOptions, useQuery } from "../../shared/hooks";
2
+ import { getContractsByOrgUnitIdService } from "../services";
3
+
4
+ export const useContractsByOrgUnitId = (
5
+ orgUnitId: string,
6
+ options?: QueryOptions<AwaitedType<typeof getContractsByOrgUnitIdService>>
7
+ ) => {
8
+ const { data, error, isLoading, refetch } = useQuery(
9
+ `api/contracts-by-org-unit-id/${orgUnitId}`,
10
+ ({ cookie }) => getContractsByOrgUnitIdService({ orgUnitId, cookie }),
11
+ options
12
+ );
13
+
14
+ return {
15
+ contracts: data ?? [],
16
+ hasContractsError: error,
17
+ isContractsLoading: isLoading,
18
+ refetchContracts: refetch,
19
+ };
20
+ };
@@ -126,6 +126,7 @@ export const CreditCardLayout = ({ data }: CreditCardsLayoutProps) => {
126
126
  image: undefined,
127
127
  name: user?.name ?? "",
128
128
  role: user?.role ?? "",
129
+ id: user?.id ?? "",
129
130
  }}
130
131
  >
131
132
  <section data-fs-credit-card-section>
@@ -214,6 +214,7 @@ export const CustomFieldsLayout = ({
214
214
  image: undefined,
215
215
  name: user?.name ?? "",
216
216
  role: user?.role ?? "",
217
+ id: user?.id ?? "",
217
218
  }}
218
219
  >
219
220
  <section data-fs-bp-custom-field-container>
@@ -5,3 +5,4 @@ export { useUpdateOrgUnit } from "./useUpdateOrgUnit";
5
5
  export { useChildrenOrgUnits } from "./useChildrenOrgUnits";
6
6
  export { useOrgUnitByUser } from "./useOrgUnitByUser";
7
7
  export { useSearchOrgUnits } from "./useSearchOrgUnits";
8
+ export { useOrgUnitBasicData } from "./useOrgUnitBasicData";
@@ -0,0 +1,20 @@
1
+ import { type QueryOptions, useQuery } from "../../shared/hooks";
2
+ import { getOrgUnitBasicDataService } from "../services";
3
+
4
+ export const useOrgUnitBasicData = (
5
+ id: string,
6
+ options?: QueryOptions<AwaitedType<typeof getOrgUnitBasicDataService>>
7
+ ) => {
8
+ const { data, error, isLoading, refetch } = useQuery(
9
+ `api/org-unit-basic-data/${id}`,
10
+ ({ cookie }) => getOrgUnitBasicDataService({ id, cookie }),
11
+ options
12
+ );
13
+
14
+ return {
15
+ orgUnit: data,
16
+ hasOrgUnitError: error,
17
+ isOrgUnitLoading: isLoading,
18
+ refetchOrgUnit: refetch,
19
+ };
20
+ };
@@ -5,6 +5,7 @@ import {
5
5
  Skeleton,
6
6
  } from "@faststore/ui";
7
7
 
8
+ import { useContractsByOrgUnitId } from "../../../contracts/hooks";
8
9
  import {
9
10
  BasicCard,
10
11
  BasicDropdownMenu,
@@ -21,13 +22,14 @@ import {
21
22
  getOrganizationSettingsLinks,
22
23
  } from "../../../shared/utils";
23
24
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
25
+ import { useGetUserById } from "../../../users/hooks";
24
26
  import {
25
27
  AddAllToOrgUnitDropdown,
26
28
  OrgUnitBreadcrumb,
27
29
  OrgUnitDetailsNavbar,
28
30
  OrgUnitsDropdownMenu,
29
31
  } from "../../components";
30
- import { useOrgUnitByUser } from "../../hooks";
32
+ import { useOrgUnitBasicData, useOrgUnitByUser } from "../../hooks";
31
33
 
32
34
  import {
33
35
  MAX_DESKTOP_BREADCRUMB_ITEMS,
@@ -35,28 +37,29 @@ import {
35
37
  QUERY_TABLET,
36
38
  } from "./utils";
37
39
 
38
- import type { ContractData } from "../../../contracts/types";
39
- import type { UserData } from "../../../users/types";
40
- import type { OrgUnitBasicData } from "../../types";
41
-
42
40
  export type OrgUnitsDetailsLayoutProps = {
43
- data: {
44
- orgUnit: OrgUnitBasicData;
45
- contracts: ContractData[];
46
- user: UserData | null;
47
- };
41
+ orgUnitId: string;
42
+ userId: string;
48
43
  loading?: boolean;
49
44
  };
50
45
 
51
46
  export const OrgUnitsDetailsLayout = ({
52
- data: { orgUnit, contracts, user },
53
- loading = false,
47
+ orgUnitId,
48
+ userId,
49
+ loading = true,
54
50
  }: OrgUnitsDetailsLayoutProps) => {
51
+ const { orgUnit, isOrgUnitLoading } = useOrgUnitBasicData(orgUnitId);
52
+
53
+ const { contracts, isContractsLoading } = useContractsByOrgUnitId(orgUnitId);
54
+
55
+ const { user, isUserLoading } = useGetUserById({ orgUnitId, userId });
56
+
57
+ loading = isOrgUnitLoading || isContractsLoading || isUserLoading;
55
58
  const isMobile = useMediaQuery(QUERY_TABLET);
56
59
 
57
60
  const isSingleContract = contracts.length <= 1;
58
61
 
59
- const { orgUnit: userUnit } = useOrgUnitByUser(user?.id ?? "");
62
+ const { orgUnit: userUnit } = useOrgUnitByUser(userId);
60
63
 
61
64
  const orgUnitList = orgUnit?.path.ids.split("/").slice(1) ?? [];
62
65
 
@@ -67,7 +70,7 @@ export const OrgUnitsDetailsLayout = ({
67
70
  const breadcrumbList = orgUnitList.map((orgUnitId, index) => ({
68
71
  unitId: orgUnitId,
69
72
  item: buyerPortalRoutes.orgUnitDetails({ orgUnitId }),
70
- name: orgUnit.path.names.split("/")[index],
73
+ name: orgUnit?.path.names.split("/")[index] ?? "",
71
74
  position: index + 1,
72
75
  enabled: index >= userUnitIndex,
73
76
  }));
@@ -76,7 +79,7 @@ export const OrgUnitsDetailsLayout = ({
76
79
  <GlobalLayout>
77
80
  {/* TODO: Add person here */}
78
81
  <OrgUnitDetailsNavbar
79
- orgName={orgUnit.name}
82
+ orgName={orgUnit?.name ?? ""}
80
83
  person={{
81
84
  name: user?.name ?? "",
82
85
  role: user?.roles?.[0] ?? "",
@@ -107,8 +110,8 @@ export const OrgUnitsDetailsLayout = ({
107
110
  <BasicDropdownMenu.Trigger />
108
111
  <OrgUnitsDropdownMenu
109
112
  isComplete={false}
110
- id={orgUnit.id}
111
- name={orgUnit.name}
113
+ id={orgUnitId}
114
+ name={orgUnit?.name ?? ""}
112
115
  />
113
116
  </Dropdown>
114
117
  <Dropdown>
@@ -118,8 +121,8 @@ export const OrgUnitsDetailsLayout = ({
118
121
  <AddAllToOrgUnitDropdown
119
122
  isSingleContract={isSingleContract}
120
123
  contractId={contracts[0]?.id}
121
- unitId={orgUnit?.id}
122
- unitName={orgUnit?.name}
124
+ unitId={orgUnitId}
125
+ unitName={orgUnit?.name ?? ""}
123
126
  />
124
127
  </Dropdown>
125
128
  </HeaderInside>
@@ -129,13 +132,13 @@ export const OrgUnitsDetailsLayout = ({
129
132
  data-fs-bp-contracts-settings-card
130
133
  footerMessage="Manage contract settings"
131
134
  footerLink={buyerPortalRoutes.profileDetails({
132
- orgUnitId: orgUnit.id,
135
+ orgUnitId: orgUnitId,
133
136
  contractId: contracts[0]?.id ?? "",
134
137
  })}
135
138
  enableFooter
136
139
  >
137
- <LetterHighlight letter={orgUnit.name[0]} />
138
- <VerticalNav.Menu title={orgUnit.name} loading={loading}>
140
+ <LetterHighlight letter={orgUnit?.name?.[0] ?? ""} />
141
+ <VerticalNav.Menu title={orgUnit?.name ?? ""} loading={loading}>
139
142
  {loading
140
143
  ? Array(8)
141
144
  .fill(null)
@@ -150,7 +153,7 @@ export const OrgUnitsDetailsLayout = ({
150
153
  </li>
151
154
  ))
152
155
  : getContractSettingsLinks({
153
- orgUnitId: orgUnit.id,
156
+ orgUnitId: orgUnitId,
154
157
  contractId: contracts[0]?.id ?? "",
155
158
  }).map(({ name, link }) => (
156
159
  <VerticalNav.Link key={name} link={link}>
@@ -177,7 +180,7 @@ export const OrgUnitsDetailsLayout = ({
177
180
  />
178
181
  }
179
182
  href={buyerPortalRoutes.profileDetails({
180
- orgUnitId: orgUnit.id,
183
+ orgUnitId: orgUnitId,
181
184
  contractId: contract.id,
182
185
  })}
183
186
  menu={
@@ -196,12 +199,12 @@ export const OrgUnitsDetailsLayout = ({
196
199
  data-fs-bp-organizations-settings-card
197
200
  footerMessage="Manage organization settings"
198
201
  footerLink={buyerPortalRoutes.users({
199
- orgUnitId: orgUnit.id,
202
+ orgUnitId: orgUnitId,
200
203
  })}
201
204
  enableFooter
202
205
  >
203
206
  <VerticalNav.Menu title="Organization">
204
- {getOrganizationSettingsLinks(orgUnit.id).map((option) => (
207
+ {getOrganizationSettingsLinks(orgUnitId).map((option) => (
205
208
  <VerticalNav.Link key={option.name} link={option.link}>
206
209
  {option.name}
207
210
  </VerticalNav.Link>
@@ -212,14 +215,14 @@ export const OrgUnitsDetailsLayout = ({
212
215
  data-fs-bp-compliance-settings-card
213
216
  footerMessage="Manage finance and compliance settings"
214
217
  footerLink={buyerPortalRoutes.buyingPolicies({
215
- orgUnitId: orgUnit.id,
218
+ orgUnitId: orgUnitId,
216
219
  contractId: contracts[0]?.id,
217
220
  })}
218
221
  enableFooter
219
222
  >
220
223
  <VerticalNav.Menu title="Finance and Compliance">
221
224
  {getFinanceSettingsLinks({
222
- orgUnitId: orgUnit.id,
225
+ orgUnitId: orgUnitId,
223
226
  contractId: contracts[0]?.id ?? "",
224
227
  }).map((option) => (
225
228
  <VerticalNav.Link key={option.name} link={option.link}>
@@ -168,6 +168,7 @@ export const PaymentMethodsLayout = ({
168
168
  image: undefined,
169
169
  name: user?.name ?? "",
170
170
  role: user?.role ?? "",
171
+ id: user?.id ?? "",
171
172
  }}
172
173
  >
173
174
  <section data-fs-payment-methods-section>
@@ -1,18 +1,33 @@
1
+ import { useContractDetails } from "../../../contracts/hooks";
2
+ import { useOrgUnitBasicData } from "../../../org-units/hooks";
1
3
  import { HeaderInside } from "../../../shared/components";
2
- import { useBuyerPortal } from "../../../shared/hooks";
3
4
  import { GlobalLayout, ContractTabsLayout } from "../../../shared/layouts";
4
-
5
- import type { ContractData } from "../../../contracts/types";
5
+ import { useGetUserById } from "../../../users/hooks";
6
6
 
7
7
  export type ProfileLayoutProps = {
8
- data: ContractData | null;
8
+ orgUnitId: string;
9
+ contractId: string;
10
+ userId: string;
9
11
  };
10
12
 
11
- export const ProfileLayout = ({ data }: ProfileLayoutProps) => {
12
- const { currentOrgUnit: orgUnit, currentUser: user } = useBuyerPortal();
13
+ export const ProfileLayout = ({
14
+ orgUnitId,
15
+ contractId,
16
+ userId,
17
+ }: ProfileLayoutProps) => {
18
+ const { orgUnit, isOrgUnitLoading } = useOrgUnitBasicData(orgUnitId);
19
+
20
+ const { contract, isContractLoading } = useContractDetails(
21
+ contractId,
22
+ orgUnitId
23
+ );
24
+
25
+ const { user, isUserLoading } = useGetUserById({ orgUnitId, userId });
26
+
27
+ const loading = isContractLoading || isOrgUnitLoading || isUserLoading;
13
28
 
14
- const creationDate = data
15
- ? new Date(data.creationDate).toLocaleDateString("en-US", {
29
+ const creationDate = contract
30
+ ? new Date(contract.creationDate).toLocaleDateString("en-US", {
16
31
  year: "numeric",
17
32
  month: "long",
18
33
  day: "numeric",
@@ -23,30 +38,32 @@ export const ProfileLayout = ({ data }: ProfileLayoutProps) => {
23
38
  <GlobalLayout>
24
39
  <ContractTabsLayout
25
40
  orgUnitName={orgUnit?.name ?? ""}
26
- orgUnitId={orgUnit?.id ?? ""}
27
- contractName={data?.name ?? ""}
28
- contractId={data?.id ?? ""}
41
+ orgUnitId={orgUnitId}
42
+ contractName={contract?.name ?? ""}
43
+ contractId={contract?.id ?? ""}
29
44
  pageName="Contract"
30
45
  person={{
31
46
  image: undefined,
32
47
  name: user?.name ?? "",
33
- role: user?.role ?? "",
48
+ role: user?.roles?.[0] ?? "",
49
+ id: userId,
34
50
  }}
51
+ loading={loading}
35
52
  >
36
53
  <section data-fs-bp-profile>
37
54
  <HeaderInside title="Profile" />
38
55
 
39
- {data && (
56
+ {contract && (
40
57
  <div data-fs-bp-profile-details>
41
58
  <span data-fs-bp-profile-details-title>Details</span>
42
59
 
43
- {!!data.name && (
60
+ {!!contract.name && (
44
61
  <>
45
62
  <hr data-fs-bp-profile-divider />
46
63
  <div data-fs-bp-profile-details-row>
47
64
  <span data-fs-bp-profile-details-row-label>Name</span>
48
65
  <span data-fs-bp-profile-details-row-value>
49
- {data.name}
66
+ {contract.name}
50
67
  </span>
51
68
  </div>
52
69
  </>
@@ -57,7 +74,7 @@ export const ProfileLayout = ({ data }: ProfileLayoutProps) => {
57
74
  <div data-fs-bp-profile-details-row>
58
75
  <span data-fs-bp-profile-details-row-label>Email</span>
59
76
  <span data-fs-bp-profile-details-row-value>
60
- <a href={`mailto:${data.email}`}>{data.email}</a>
77
+ <a href={`mailto:${contract.email}`}>{contract.email}</a>
61
78
  </span>
62
79
  </div>
63
80
 
@@ -1,4 +1,4 @@
1
- // import { isDevelopment } from "../../utils/environment";
1
+ import { isDevelopment } from "../../utils/environment";
2
2
  import { Icon } from "../Icon";
3
3
 
4
4
  export type ErrorProps = {
@@ -20,18 +20,17 @@ export default function Error({ error }: ErrorProps) {
20
20
  <button data-fs-bp-error-button onClick={() => window.location.reload()}>
21
21
  Try again
22
22
  </button>
23
- <div data-fs-bp-error-details>
24
- <span data-fs-bp-error-details-type>{error?.tags?.errorType}</span>
25
- <h2 data-fs-bp-error-details-title>Error Details</h2>
26
- <p data-fs-bp-error-details-message>{error?.error.message}</p>
27
- <p data-fs-bp-error-details-stack>Stack: {error?.error.stack}</p>
28
- <p data-fs-bp-error-details-component>
29
- Component: {error?.tags?.component}
30
- </p>
31
- <p data-fs-bp-error-details-query>
32
- Query: {JSON.stringify(error?.query)}
33
- </p>
34
- </div>
23
+ {isDevelopment() ? (
24
+ <div data-fs-bp-error-details>
25
+ <span data-fs-bp-error-details-type>{error?.tags?.errorType}</span>
26
+ <h2 data-fs-bp-error-details-title>Error Details</h2>
27
+ <p data-fs-bp-error-details-message>{error?.error.message}</p>
28
+ <p data-fs-bp-error-details-stack>Stack: {error?.error.stack}</p>
29
+ <p data-fs-bp-error-details-component>
30
+ Component: {error?.tags?.component}
31
+ </p>
32
+ </div>
33
+ ) : null}
35
34
  </div>
36
35
  );
37
36
  }
@@ -1,22 +1,47 @@
1
1
  import { Skeleton } from "@faststore/ui";
2
2
 
3
+ import { useBuyerPortal } from "../../hooks";
4
+ import { BaseTabsLayout } from "../../layouts";
5
+
3
6
  /**
4
7
  * PageLoader component displays skeleton loaders while page data is being fetched.
5
8
  * Used when cookies are not yet available during pre-fetch scenarios.
6
9
  */
7
10
  export const PageLoader = () => {
11
+ const { currentOrgUnit, currentUser } = useBuyerPortal();
8
12
  return (
9
- <div data-fs-bp-page-loader>
10
- <div data-fs-bp-page-loader-header>
11
- <Skeleton size={{ width: "12rem", height: "2rem" }} />
12
- <Skeleton size={{ width: "8rem", height: "1.5rem" }} />
13
- </div>
13
+ <BaseTabsLayout data-fs-bp-page-loader>
14
+ <BaseTabsLayout.Navbar
15
+ orgUnit={currentOrgUnit}
16
+ pageName="Loading"
17
+ person={{
18
+ name: currentUser?.name ?? "",
19
+ role: currentUser?.role ?? "",
20
+ id: currentUser?.id ?? "",
21
+ }}
22
+ loading={true}
23
+ />
24
+ <BaseTabsLayout.Container>
25
+ <BaseTabsLayout.SidebarMenu
26
+ verticalLinks={[]}
27
+ showLetterHighlight={false}
28
+ loading={true}
29
+ />
30
+ <BaseTabsLayout.Content>
31
+ <div data-fs-bp-page-loader>
32
+ <div data-fs-bp-page-loader-header>
33
+ <Skeleton size={{ width: "12rem", height: "2rem" }} />
34
+ <Skeleton size={{ width: "8rem", height: "1.5rem" }} />
35
+ </div>
14
36
 
15
- <div data-fs-bp-page-loader-content>
16
- <Skeleton size={{ width: "100%", height: "4rem" }} />
17
- <Skeleton size={{ width: "100%", height: "8rem" }} />
18
- <Skeleton size={{ width: "100%", height: "8rem" }} />
19
- </div>
20
- </div>
37
+ <div data-fs-bp-page-loader-content>
38
+ <Skeleton size={{ width: "100%", height: "4rem" }} />
39
+ <Skeleton size={{ width: "100%", height: "8rem" }} />
40
+ <Skeleton size={{ width: "100%", height: "8rem" }} />
41
+ </div>
42
+ </div>
43
+ </BaseTabsLayout.Content>
44
+ </BaseTabsLayout.Container>
45
+ </BaseTabsLayout>
21
46
  );
22
47
  };
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React from "react";
4
4
 
5
- // import { ErrorBoundary } from "../ErrorBoundary/ErrorBoundary";
5
+ import { ErrorBoundary } from "../ErrorBoundary/ErrorBoundary";
6
6
 
7
7
  type WithErrorBoundaryOptions = {
8
8
  fallback?: React.ReactNode;
@@ -15,16 +15,15 @@ type WithErrorBoundaryOptions = {
15
15
 
16
16
  export function withErrorBoundary<P extends Record<string, unknown>>(
17
17
  WrappedComponent: React.ComponentType<P>,
18
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
- _options: WithErrorBoundaryOptions = {}
18
+ options: WithErrorBoundaryOptions = {}
20
19
  ) {
21
- // const { onError, tags } = options;
20
+ const { onError, tags } = options;
22
21
 
23
22
  const ComponentWithErrorBoundary = (props: P) => {
24
23
  return (
25
- // <ErrorBoundary onError={onError} tags={tags}>
26
- <WrappedComponent {...props} />
27
- // </ErrorBoundary>
24
+ <ErrorBoundary onError={onError} tags={tags}>
25
+ <WrappedComponent {...props} />
26
+ </ErrorBoundary>
28
27
  );
29
28
  };
30
29
 
@@ -13,3 +13,4 @@ export { useAddToScope } from "./useAddToScope";
13
13
  export { useRemoveFromScope } from "./useRemoveFromScope";
14
14
  export { usePageItems, type UsePageItemsProps } from "./usePageItems";
15
15
  export { useRouterLoading } from "./useRouterLoading";
16
+ export { useAuth, type UseAuthResult } from "./useAuth";