Skip to content

Commit

Permalink
Revert "Sprint/41" (#849)
Browse files Browse the repository at this point in the history
Revert "Sprint/41 (#847)"

This reverts commit dd61634.
  • Loading branch information
BrianJiang2021 authored Nov 15, 2023
1 parent dd61634 commit 5ad183d
Show file tree
Hide file tree
Showing 28 changed files with 222 additions and 323 deletions.
106 changes: 42 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# B2B Buyer Portal

A monorepo frontend application designed for the BigCommerce B2B Edition Buyer portal. It's built using Turborepo, TypeScript, and React.

## Index

- [Prerequisites](#-prerequisites)
- [Core Technologies](#-core-technologies)
- [Workspaces](#-workspaces)
- [Tools and Libraries](#-tools-and-libraries)
Expand All @@ -13,23 +13,6 @@ A monorepo frontend application designed for the BigCommerce B2B Edition Buyer p
- [Contribution](#-contribution)
- [Contact & Support](#-contact--support)

## ☑ Prerequisites

Before you begin, ensure you have the BigCommerce B2B Edition App installed. To set up your storefront with B2B capabilities, follow the steps below:

### Step 1: Access the Storefronts Manager
After installing the B2B Edition App, go to the app's dashboard and select the 'Storefronts' section.

<img width="200" alt="image" src="https://github.com/B3BC/b2b-buyer-portal/assets/140021227/0d733ddb-e59c-4e5a-8801-4a744940d66b">

### Step 2: Enable B2B on Your Channel
Choose the channel where you wish to enable B2B functionality. Initially, B2B features can be activated on a single channel only.

<img width="480" alt="image" src="https://github.com/B3BC/b2b-buyer-portal/assets/140021227/b425115c-54d9-4382-9371-4e81888eb0af">

### Step 3: Contact Us for Additional Support
For assistance with activating the remote buyer portal or to inquire about multi-storefront support, which allows you to utilize B2B features across multiple channels, please reach out to our team at b2b@bigcommerce.com, or raise an issue right here in this repository.

## 🚀 Core Technologies

- **Monorepo Management:** Turborepo
Expand All @@ -41,6 +24,7 @@ For assistance with activating the remote buyer portal or to inquire about multi

- **Application:** `/apps/storefront` - A next-gen B2B Edition storefront application.
- You can run multiple apps concurrently via turborepo [tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks).

- **Packages:**
- `/packages/eslint-config-b3` - Shared ESLint configurations.
- `/packages/tsconfig` - Shared TypeScript configurations.
Expand All @@ -61,66 +45,60 @@ For assistance with activating the remote buyer portal or to inquire about multi
- **Node:** Ensure you have Node.js version >=18.0.0.
- **Package Manager:** This project uses Yarn v1.22.17.

## ⚙ Local Development
## ⚙ Local Development

1. Installation of Node and Yarn.
1. Installation of Node and Yarn.
- For Node, we recommend using [nvm](https://github.com/nvm-sh/nvm).
- Once Node is installed, you can install Yarn by using `npm i -g yarn`. If you'd rather use `pnpm`, visit this [guide](https://dev.to/andreychernykh/yarn-npm-to-pnpm-migration-guide-2n04).
2. Clone the repository.
3. Install dependencies using `yarn`.
4. Copy environment variables: `cp apps/storefront/.env-example apps/storefront/.env`.
5. Update the following values in `.env`:

- `VITE_B2B_URL`: The URL of the B2B Edition API.
- `VITE_B2B_SOCKET_URL`: The URL of the B2B Edition WebSocket API.
- `VITE_TRANSLATION_SERVICE_URL`: The URL of the translation service API.
- `VITE_CHANNEL_ID`: The ID of the channel to use for the storefront.
- `VITE_STORE_HASH`: The hash of the store to use for the storefront.
- `VITE_CATPCHA_SETKEY`: The reCAPTCHA site key (optional).
- `VITE_B2B_CLIENT_ID`: The client ID of the BigCommerce App from the [developer portal](https://devtools.bigcommerce.com/).
- `VITE_LOCAL_DEBUG`: Set to "FALSE". This is for connecting our local development with the B2B Edition GraphQL API.

- `VITE_B2B_URL`: The URL of the B2B Edition API.
- `VITE_B2B_SOCKET_URL`: The URL of the B2B Edition WebSocket API.
- `VITE_TRANSLATION_SERVICE_URL`: The URL of the translation service API.
- `VITE_CHANNEL_ID`: The ID of the channel to use for the storefront.
- `VITE_STORE_HASH`: The hash of the store to use for the storefront.
- `VITE_CATPCHA_SETKEY`: The reCAPTCHA site key (optional).
- `VITE_B2B_CLIENT_ID`: The client ID of the BigCommerce App from the [developer portal](https://devtools.bigcommerce.com/).
- `VITE_LOCAL_DEBUG`: Set to "FALSE". This is for connecting our local development with the B2B Edition GraphQL API.
6. Start the development server: `yarn RUN dev`.

## Running Project Locally

1. Activate store channel in the Channels Manager.
2. Configure header and footer scripts:

- Navigate to Channels Manager -> Scripts.
- Add two scripts (e.g., B2BEdition-header, B2BEdition-footer). Ensure you set the correct port for your localhost in the script URLs.
- Edit the header script:

```html
<script>
{{#if customer.id}}
{{#contains page_type "account"}}
var b2bHideBodyStyle = document.createElement('style');
b2bHideBodyStyle.id = 'b2b-account-page-hide-body';
b2bHideBodyStyle.innerHTML = 'body { display: none !important }';
document.head.appendChild(b2bHideBodyStyle);
{{/contains}}
{{/if}}
</script>
<script type="module">
import RefreshRuntime from 'http://localhost:3001/@react-refresh'
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
<script type="module" src="http://localhost:3001/@vite/client"></script>
<script
type="module"
src="http://localhost:3001/index.html?html-proxy&index=0.js"
></script>
```

- Edit the footer script:

```html
<script type="module" src="http://localhost:3001/src/main.ts"></script>
```
- Navigate to Channels Manager -> Scripts.
- Add two scripts (e.g., B2BEdition-header, B2BEdition-footer). Ensure you set the correct port for your localhost in the script URLs.
- Edit the header script:

```html
<script>
{{#if customer.id}}
{{#contains page_type "account"}}
var b2bHideBodyStyle = document.createElement('style');
b2bHideBodyStyle.id = 'b2b-account-page-hide-body';
b2bHideBodyStyle.innerHTML = 'body { display: none !important }';
document.head.appendChild(b2bHideBodyStyle);
{{/contains}}
{{/if}}
</script>
<script type="module">
import RefreshRuntime from "http://localhost:3001/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
<script type="module" src="http://localhost:3001/@vite/client"></script>
<script type="module" src="http://localhost:3001/index.html?html-proxy&index=0.js"></script>
```
- Edit the footer script:

```html
<script type="module" src="http://localhost:3001/src/main.ts"></script>
```

3. Verify correct values in the .env file, especially the client_id for the draft app.

Expand Down
44 changes: 17 additions & 27 deletions apps/storefront/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import {
getStoreTaxZoneRates,
getTemPlateConfig,
handleHideRegisterPage,
isUserGotoLogin,
loginInfo,
openPageByClick,
removeBCMenus,
Expand Down Expand Up @@ -196,7 +195,6 @@ export default function App() {
role: +role,
isAgenting,
}

if (!customerId || isRelogin) {
const info = await getCurrentCustomerInfo(dispatch)
if (info) {
Expand All @@ -209,7 +207,7 @@ export default function App() {
!href.includes('checkout') &&
!(customerId && !window.location.hash)
) {
await gotoAllowedAppPage(+userInfo.role, gotoPage)
gotoAllowedAppPage(+userInfo.role, gotoPage)
}

if (customerId) {
Expand Down Expand Up @@ -262,34 +260,26 @@ export default function App() {
}, [isOpen])

useEffect(() => {
const init = async () => {
if (isClickEnterBtn && isPageComplete && currentClickedUrl) {
// graphql bc

const gotoUrl = openPageByClick({
href: currentClickedUrl,
role,
isRegisterAndLogin,
isAgenting,
})
if (isClickEnterBtn && isPageComplete && currentClickedUrl) {
const gotoUrl = openPageByClick({
href: currentClickedUrl,
role,
isRegisterAndLogin,
isAgenting,
})

const isGotoLogin = await isUserGotoLogin(gotoUrl)
setOpenPage({
isOpen: true,
openUrl: gotoUrl,
})

setOpenPage({
isOpen: true,
openUrl: isGotoLogin ? '/login' : gotoUrl
showPageMask(dispatch, false)
storeDispatch(
setGlabolCommonState({
isClickEnterBtn: false,
})

showPageMask(dispatch, false)
storeDispatch(
setGlabolCommonState({
isClickEnterBtn: false,
})
)
}
)
}

init()
}, [isPageComplete, currentClickedUrl, clickTimeTarget])

useEffect(() => {
Expand Down
13 changes: 7 additions & 6 deletions apps/storefront/src/components/HeadlessController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
addProductsToDraftQuote,
} from '@/hooks/dom/utils'
import { addProductsToShoppingList } from '@/pages/pdp/PDP'
import { CustomStyleContext } from '@/shared/customStyleButtton'
import { GlobaledContext } from '@/shared/global'
import { superAdminCompanies } from '@/shared/service/b2b'
import B3Request from '@/shared/service/request/b3Fetch'
Expand Down Expand Up @@ -133,9 +132,6 @@ export default function HeadlessController({
registerEnabled,
},
} = useContext(GlobaledContext)
const {
state: { addQuoteBtn },
} = useContext(CustomStyleContext)
const { addToQuote: addProductFromPageToQuote } =
addProductFromProductPageToQuote(setOpenPage)
const { addToQuote: addProductsFromCart } =
Expand Down Expand Up @@ -193,7 +189,6 @@ export default function HeadlessController({
addProductsFromCart: () => addProductsFromCart(),
addProducts: (items) => addProductsToDraftQuote(items, setOpenPage),
getCurrent: getDraftQuote,
getButtonInfo: () => addQuoteBtn,
},
user: {
getProfile: () => ({ ...customerRef.current, role }),
Expand Down Expand Up @@ -227,12 +222,18 @@ export default function HeadlessController({
salesRepCompanyId: salesRepCompanyIdRef.current,
B3UserId: B3UserIdRef.current,
}),
logInWithStorefrontToken: (customerJWTToken: string) =>
getCurrentCustomerInfo(dispatch, customerJWTToken),
graphqlBCProxy: B3Request.graphqlBCProxy,
loginWithB2BStorefrontToken: async (
b2bStorefrontJWTToken: string
) => {
B3SStorage.set('B2BToken', b2bStorefrontJWTToken)
await getCurrentCustomerInfo(dispatch, b2bStorefrontJWTToken)
await getCurrentCustomerInfo(
dispatch,
undefined,
b2bStorefrontJWTToken
)
},
},
shoppingList: {
Expand Down
4 changes: 3 additions & 1 deletion apps/storefront/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ declare interface Window {
getCurrent: () => {
productList: import('@/components').FormatedQuoteItem[]
}
getButtonInfo: () => import('@/shared/customStyleButtton/context/config').AddQuoteBtnProperties
}
user: {
getProfile: () => Record<string, string | number>
Expand All @@ -33,6 +32,9 @@ declare interface Window {
getB2BToken: () => string
setMasqueradeCompany: (companyId: number) => Promise<void>
endMasquerade: () => Promise<void>
logInWithStorefrontToken: (
customerJWTToken: string
) => Promise<{ role: number; userType: string } | undefined>
graphqlBCProxy: typeof import('@/shared/service/request/b3Fetch').default.graphqlBCProxy
loginWithB2BStorefrontToken: (
b2bStorefrontJWTToken: string
Expand Down
11 changes: 1 addition & 10 deletions apps/storefront/src/pages/accountSetting/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,7 @@ function sendEmail(data: any, extraFields: any) {
const val = formFields.find(
(field: Partial<Fields>) => field.name === item.bcLabel
).value
if (item.type === 'date') {
const time = val.split('-')
if (!val && time.length !== 3) return
const [year, month, day] = time
formData.append(`FormFieldYear[1][${key}]`, year)
formData.append(`FormFieldMonth[1][${key}]`, month)
formData.append(`FormFieldDay[1][${key}]`, day)
} else {
formData.append(`FormField[1][${key}]`, val)
}
formData.append(`FormField[1][${key}]`, val)
}
})
}
Expand Down
34 changes: 14 additions & 20 deletions apps/storefront/src/pages/login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import {
getBCForcePasswordReset,
superAdminEndMasquerade,
} from '@/shared/service/b2b'
import { b2bLogin, customerLoginAPI } from '@/shared/service/bc'
import { B3SStorage, getCurrentCustomerInfo, storeHash } from '@/utils'
import { bcLogin } from '@/shared/service/bc'
import { B3SStorage, getCurrentCustomerInfo } from '@/utils'

import LoginWidget from './component/LoginWidget'
import {
Expand Down Expand Up @@ -64,7 +64,6 @@ export default function Login(props: RegisteredProps) {
const [flag, setLoginFlag] = useState<string>('')
const [loginAccount, setLoginAccount] = useState<LoginConfig>({
emailAddress: '',
password: '',
})
const location = useLocation()

Expand Down Expand Up @@ -196,9 +195,6 @@ export default function Login(props: RegisteredProps) {
case '5':
str = b3Lang('login.loginTipInfo.accountPrelaunch')
break
case '6':
str = b3Lang('login.loginText.deviceCrowdingLogIn')
break
default:
str = ''
}
Expand Down Expand Up @@ -253,23 +249,21 @@ export default function Login(props: RegisteredProps) {
}
} else {
try {
const loginData = {
const getBCFieldsValue = {
email: data.emailAddress,
password: data.password,
storeHash: storeHash as string,
channelId: B3SStorage.get('B3channelId'),
pass: data.password,
}
const {
login: {
result: { token, storefrontLoginToken },
errors,
},
} = await b2bLogin({ loginData })
const { data: bcData, errors } = await bcLogin(getBCFieldsValue)

B3SStorage.set('B2BToken', token)
customerLoginAPI(storefrontLoginToken)
if (bcData?.login?.customer) {
B3SStorage.set('loginCustomer', {
emailAddress: bcData.login.customer.email,
phoneNumber: bcData.login.customer.phone,
...bcData.login.customer,
})
}

if (errors?.length || !token) {
if (errors?.length || !bcData) {
if (errors?.length) {
const { message } = errors[0]
if (
Expand All @@ -283,7 +277,7 @@ export default function Login(props: RegisteredProps) {
}
getforcePasswordReset(data.emailAddress)
} else {
const info = await getCurrentCustomerInfo(dispatch, token)
const info = await getCurrentCustomerInfo(dispatch)

if (info?.userType === 3 && info?.role === 3) {
navigate('/dashboard')
Expand Down
4 changes: 2 additions & 2 deletions apps/storefront/src/pages/login/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface QuoteConfig {

export type LoginConfig = {
emailAddress: string
password: string
password?: string
}

export interface LoginInfoInit {
Expand Down Expand Up @@ -182,4 +182,4 @@ export const logout = () => new Promise<boolean>((resolve, reject) => {
}).catch(e => {
reject(e)
})
})
})
Loading

0 comments on commit 5ad183d

Please sign in to comment.