@vtex/faststore-plugin-buyer-portal 1.0.14 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "dependencies": {},
package/plugin.config.js CHANGED
@@ -2,7 +2,7 @@ module.exports = {
2
2
  name: "poc-plugin",
3
3
  pages: {
4
4
  home: {
5
- path: "/buyer-portal",
5
+ path: "/buyer-portal/[[...contractMode]]",
6
6
  appLayout: false,
7
7
  },
8
8
  "org-units": {
package/src/global.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  declare module "*.module.scss";
2
+ declare module "*discovery.config";
@@ -23,9 +23,9 @@ export const HomeLayout = ({ data }: HomeLayoutProps) => (
23
23
  <UsersCard users={data.users} />
24
24
 
25
25
  {/* Remove this comments when mocks be removed */}
26
- {/* {data.contracts.length === 1 && ( */}
27
- <AddressesCard addresses={data.addresses} />
28
- {/* )} */}
26
+ {data.contracts.length === 1 && (
27
+ <AddressesCard addresses={data.addresses} />
28
+ )}
29
29
  <OrganizationalUnitsCard
30
30
  organizationalUnits={data.orgUnitsHierarchy.nodes}
31
31
  />
@@ -1,15 +1,15 @@
1
+ import React from 'react'
2
+
1
3
  import { InternalTopBar } from "../../components/InternalTopbar/InternalTopbar";
2
- import { getTreeDepth } from "../../utils/getTreeDepth";
3
- import { OrgUnitsHierarchyTree } from "../../components/OrgUnitsHierarchyTree/OrgUnitsHierarchyTree";
4
- import { Structure } from "../../components/HierarchyTree/HierarchyTree";
5
4
  import { ContractData } from "../../types/ContractData";
6
5
  import { GlobalLayout } from "../GlobalLayout/GlobalLayout";
7
- import { Icon } from "../../components/Icon";
6
+
8
7
 
9
8
  export type ProfileLayoutProps = {
10
- data: ContractData;
9
+ data: ContractData | null
11
10
  };
12
11
 
12
+
13
13
  export const ProfileLayout = ({ data }: ProfileLayoutProps) => {
14
14
  return (
15
15
  <GlobalLayout>
@@ -24,40 +24,42 @@ export const ProfileLayout = ({ data }: ProfileLayoutProps) => {
24
24
  showActions={false}
25
25
  />
26
26
 
27
- <div data-fs-bp-profile-details>
28
- <span data-fs-bp-profile-details-title>
29
- Details
30
- </span>
31
- <hr data-fs-bp-profile-divider />
27
+ {data && (
28
+ <div data-fs-bp-profile-details>
29
+ <span data-fs-bp-profile-details-title>
30
+ Details
31
+ </span>
32
+ <hr data-fs-bp-profile-divider />
32
33
 
33
- <div data-fs-bp-profile-details-row>
34
- <span data-fs-bp-profile-details-row-label>Name</span>
35
- <span data-fs-bp-profile-details-row-value>{data.name}</span>
36
- </div>
34
+ <div data-fs-bp-profile-details-row>
35
+ <span data-fs-bp-profile-details-row-label>Name</span>
36
+ <span data-fs-bp-profile-details-row-value>{data.name}</span>
37
+ </div>
37
38
 
38
- <hr data-fs-bp-profile-divider />
39
+ <hr data-fs-bp-profile-divider />
39
40
 
40
- <div data-fs-bp-profile-details-row>
41
- <span data-fs-bp-profile-details-row-label>Email</span>
42
- <span data-fs-bp-profile-details-row-value>{data.email}</span>
43
- </div>
41
+ <div data-fs-bp-profile-details-row>
42
+ <span data-fs-bp-profile-details-row-label>Email</span>
43
+ <span data-fs-bp-profile-details-row-value>{data.email}</span>
44
+ </div>
44
45
 
45
- <hr data-fs-bp-profile-divider />
46
+ <hr data-fs-bp-profile-divider />
46
47
 
47
- <div data-fs-bp-profile-details-row>
48
- <span data-fs-bp-profile-details-row-label>ID</span>
49
- <span data-fs-bp-profile-details-row-value>{data.id}</span>
50
- </div>
48
+ <div data-fs-bp-profile-details-row>
49
+ <span data-fs-bp-profile-details-row-label>ID</span>
50
+ <span data-fs-bp-profile-details-row-value>{data.id}</span>
51
+ </div>
51
52
 
52
- <hr data-fs-bp-profile-divider />
53
+ <hr data-fs-bp-profile-divider />
53
54
 
54
- <div data-fs-bp-profile-details-row>
55
- <span data-fs-bp-profile-details-row-label>Creation Date</span>
56
- <span data-fs-bp-profile-details-row-value>{data.creationDate}</span>
57
- </div>
55
+ <div data-fs-bp-profile-details-row>
56
+ <span data-fs-bp-profile-details-row-label>Creation Date</span>
57
+ <span data-fs-bp-profile-details-row-value>{data.creationDate}</span>
58
+ </div>
58
59
 
59
- <hr data-fs-bp-profile-divider />
60
- </div>
60
+ <hr data-fs-bp-profile-divider />
61
+ </div>
62
+ )}
61
63
  </section>
62
64
  </GlobalLayout>
63
65
  );
@@ -2,34 +2,34 @@ import { ContractData } from "../types/ContractData";
2
2
 
3
3
  export const contractsData: ContractData[] = [
4
4
  // Uncomment to test with a single contract
5
- {
6
- name: "ByTech",
7
- email: "bytech@demo.com",
8
- id: "12-32-DDDD",
9
- status: false,
10
- creationDate: "October 10, 2024"
11
- }
12
-
13
- // Comment to test with single contract
14
5
  // {
15
6
  // name: "ByTech",
16
7
  // email: "bytech@demo.com",
17
8
  // id: "12-32-DDDD",
18
9
  // status: false,
19
10
  // creationDate: "October 10, 2024"
20
- // },
21
- // {
22
- // name: "ByTech South",
23
- // email: "bytech@demo.com",
24
- // id: "12-32-AAAA",
25
- // status: true,
26
- // creationDate: "May 5, 2024"
27
- // },
28
- // {
29
- // name: "Stellar Inc",
30
- // email: "Stellar@stellar.com",
31
- // id: "32-32-32",
32
- // status: true,
33
- // creationDate: "January 1, 2025"
34
- // },
11
+ // }
12
+
13
+ // Comment to test with single contract
14
+ {
15
+ name: "ByTech",
16
+ email: "bytech@demo.com",
17
+ id: "12-32-DDDD",
18
+ status: false,
19
+ creationDate: "October 10, 2024"
20
+ },
21
+ {
22
+ name: "ByTech South",
23
+ email: "bytech@demo.com",
24
+ id: "12-32-AAAA",
25
+ status: true,
26
+ creationDate: "May 5, 2024"
27
+ },
28
+ {
29
+ name: "Stellar Inc",
30
+ email: "Stellar@stellar.com",
31
+ id: "32-32-32",
32
+ status: true,
33
+ creationDate: "January 1, 2025"
34
+ },
35
35
  ];
@@ -4,17 +4,19 @@ import {
4
4
  GetContractsServiceProps,
5
5
  } from "../services/get-contracts.service";
6
6
  import { ContractData } from "../types/ContractData";
7
+ import { getCustomerIdFromCookieServerSide } from "../utils/cookie";
8
+
7
9
 
8
10
  export type ContractsPageData = { data: ContractData[] };
9
11
 
10
12
  export type ContractsPageContext = {
11
- query: GetContractsServiceProps;
13
+ req: {
14
+ cookies: Record<string, string>
15
+ };
12
16
  };
13
17
 
14
- export async function loader({
15
- query,
16
- }: ContractsPageContext): Promise<ContractsPageData> {
17
- return { data: await getContractsService(query) };
18
+ export async function loader(data: ContractsPageContext): Promise<ContractsPageData> {
19
+ return { data: await getContractsService({ customerId: getCustomerIdFromCookieServerSide(data), cookie: JSON.stringify(data?.req?.cookies).replace(/[{}]/g, '') }) };
18
20
  }
19
21
 
20
22
  const ContractsPage = ({ data }: ContractsPageData) => (
@@ -4,8 +4,14 @@ import { OrganizationData } from "../types/OrganizationData";
4
4
 
5
5
  export type HomePageData = { data: OrganizationData };
6
6
 
7
- export async function loader(): Promise<HomePageData> {
8
- return { data: await getOrganizationService() };
7
+ type HomePageLoaderContext = {
8
+ query: {
9
+ contractMode?: string[]
10
+ }
11
+ }
12
+
13
+ export async function loader(data: HomePageLoaderContext): Promise<HomePageData> {
14
+ return { data: await getOrganizationService(data.query.contractMode ? data.query.contractMode[0] : '') };
9
15
  }
10
16
 
11
17
  const HomePage = ({ data }: HomePageData) => {
@@ -4,19 +4,16 @@ import {
4
4
  GetContractsServiceProps,
5
5
  } from "../services/get-contracts.service";
6
6
  import { ContractData } from "../types/ContractData";
7
+ import { getCustomerIdFromCookieServerSide } from "../utils/cookie";
8
+ import type { ContractsPageContext } from "./contracts";
7
9
 
8
- export type ContractsPageData = { data: ContractData };
10
+ export type ContractsPageData = { data: ContractData | null };
9
11
 
10
- export type ContractsPageContext = {
11
- query: GetContractsServiceProps;
12
- };
12
+ export async function loader(data: ContractsPageContext): Promise<ContractsPageData> {
13
+ const contracts = await getContractsService({ customerId: getCustomerIdFromCookieServerSide(data), cookie: JSON.stringify(data?.req?.cookies).replace(/[{}]/g, '') })
13
14
 
14
- export async function loader({
15
- query,
16
- }: ContractsPageContext): Promise<ContractsPageData> {
17
- const contracts = await getContractsService(query)
18
-
19
- return { data: contracts[0] };
15
+ // We should deal with a better error boundary here later, this is just so an empty array doesn't break the render
16
+ return { data: contracts && contracts.length ? contracts[0] : null };
20
17
  }
21
18
 
22
19
  const ContractsPage = ({ data }: ContractsPageData) => (
@@ -1,19 +1,47 @@
1
- import { contractsData } from "../mock/contracts-data";
2
1
  import { ContractData } from "../types/ContractData";
3
2
  import { statusFilters } from "../utils/search";
3
+ import { API_URL } from '../utils/constants';
4
+ import storeConfig from '../../../../discovery.config'
5
+
4
6
 
5
7
  export type GetContractsServiceProps = {
6
8
  search: string;
9
+ customerId: string;
7
10
  status: string;
8
11
  sort: string;
12
+ cookie: string;
9
13
  };
10
14
 
11
15
  export const getContractsService = async ({
12
16
  search = "",
17
+ customerId,
13
18
  status,
14
19
  sort,
20
+ cookie,
15
21
  }: Partial<GetContractsServiceProps> = {}): Promise<ContractData[]> => {
16
- return contractsData
22
+ const getContracts = async () => {
23
+ try {
24
+ if (!customerId) {
25
+ return []
26
+ }
27
+ const headers = {
28
+ "Content-type": "application/json",
29
+ 'Cookie': cookie ?? '',
30
+ }
31
+
32
+ const url = `${API_URL(storeConfig?.secureSubdomain ?? '', 'getContracts')}/${customerId}`
33
+
34
+ const response = await (await fetch(url, { method: 'GET', credentials: 'include', headers })).json()
35
+
36
+ return response?.data?.contracts ?? []
37
+ } catch (err) {
38
+ console.log('>> err', err)
39
+ return []
40
+ }
41
+ }
42
+ const contractsData = await getContracts() as ContractData[]
43
+
44
+ return contractsData && contractsData
17
45
  .filter((contract) => {
18
46
  const matchesName = contract.name
19
47
  .toLowerCase()
@@ -1,6 +1,13 @@
1
1
  import { organizationData } from "../mock/organization-data";
2
2
  import { OrganizationData } from "../types/OrganizationData";
3
3
 
4
- export const getOrganizationService = async (): Promise<OrganizationData> => {
5
- return organizationData;
4
+ export const getOrganizationService = async (contractMode: string): Promise<OrganizationData> => {
5
+ let mockOrganizationData = organizationData
6
+ console.log('>>>', contractMode)
7
+
8
+ if (contractMode === 'single') {
9
+ mockOrganizationData = { ...organizationData, contracts: [organizationData.contracts[0]] }
10
+ }
11
+
12
+ return mockOrganizationData;
6
13
  };
@@ -0,0 +1,2 @@
1
+ export const AUT_COOKIE_KEY = 'VtexIdclientAutCookie'
2
+ export const API_URL = (checkoutUrl: string, operation: string) => `${checkoutUrl}/_v/buyer-portal/${operation}`
@@ -0,0 +1,27 @@
1
+ import { AUT_COOKIE_KEY } from "./constants"
2
+ import storeConfig from '../../../../discovery.config'
3
+
4
+
5
+ type LoaderData = {
6
+ req: {
7
+ cookies: Record<string, string>
8
+ }
9
+ }
10
+
11
+ export function getAuthCookie(data: LoaderData) {
12
+ const authCookie = data?.req?.cookies[`${AUT_COOKIE_KEY}_${storeConfig?.api.storeId}`] ?? ''
13
+
14
+ return authCookie
15
+ }
16
+
17
+ export function getCustomerIdFromCookieServerSide(data: LoaderData) {
18
+ const authCookie = getAuthCookie(data)
19
+
20
+ const parsedCookie = parseJwt(authCookie)
21
+
22
+ return parsedCookie.customerId
23
+ }
24
+
25
+ function parseJwt(token: string) {
26
+ return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
27
+ }