Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ecommerce Cart - Integrate PDP with cart #233

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ecommerce-examples/example1/back-end/javascript/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
siteName: 'SITE_ID',
API_KEY: 'API_KEY'
}
48 changes: 48 additions & 0 deletions ecommerce-examples/example1/back-end/javascript/fetch-estimates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const fetch = require('node-fetch');
const { siteName, API_KEY } = require('./constants');

let credentialError = null;
if (siteName === 'SITE_ID' || !siteName) {
credentialError =
'Error: Kindly provide your Chargebee Site name at the Backend';
}
if (API_KEY === 'API_KEY' || !API_KEY) {
credentialError =
'Error: Kindly provide your Chargebee Site API key at the Backend';
}
if (credentialError) {
throw Error(credentialError);
}
module.exports = async (req, res) => {
let data = '',
itemsLength = req.query?.purchase_items?.index?.length || 0;
for (let i = 0; i < itemsLength; i++) {
data = `${data}purchase_items[index][${i}]=${
i + 1
}&purchase_items[item_price_id][${i}]=${
req.query.purchase_items.item_price_id[i]
}&`;
if (req.query.purchase_items.quantity) {
data = `${data}purchase_items[quantity][${i}]=${req.query.purchase_items.quantity[i]}&`;
}
}
if (req.query.customer_id) {
data = data + 'customer_id=' + req.query.customer_id;
}
const response = await fetch(
`https://${siteName}.chargebee.com/api/v2/purchases/estimate?${data}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
Authorization: `Basic ${Buffer.from(API_KEY).toString('base64')}`
}
}
);
const est = await response.json();
if (est?.estimate?.invoice_estimates) {
res.status(200).json(est.estimate.invoice_estimates[0]);
} else {
res.status(400).json(est);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const fetchItems = (req, res) => {
//handle error
console.log(error);
} else {
var item;
var item = {};
if (result.list.length) {
item = result.list[0].item;
}
Expand Down
31 changes: 31 additions & 0 deletions ecommerce-examples/example1/back-end/javascript/fetch-product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const fetch = require('node-fetch');
const { siteName, API_KEY } = require('./constants');

let credentialError = null;
if (siteName === 'SITE_ID' || !siteName) {
credentialError =
'Error: Kindly provide your Chargebee Site name at the Backend';
}
if (API_KEY === 'API_KEY' || !API_KEY) {
credentialError =
'Error: Kindly provide your Chargebee Site API key at the Backend';
}
if (credentialError) {
throw Error(credentialError);
}
module.exports = async (req, res) => {
try {
const response = await fetch(
`https://${siteName}.chargebee.com/api/v2/products/${req.query.product_id}`,
{
headers: {
Authorization: `Basic ${Buffer.from(API_KEY).toString('base64')}`
}
}
);
const productWrapper = await response.json();
res.status(200).json(productWrapper.product);
} catch (err) {
console.log(err);
}
};
31 changes: 17 additions & 14 deletions ecommerce-examples/example1/back-end/javascript/fetch-variants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const fetch = require('node-fetch');
const siteName = 'SITE_ID';
const API_KEY = 'API_KEY';
const { siteName, API_KEY } = require('./constants');

let credentialError = null;
if (siteName === 'SITE_ID' || !siteName) {
Expand All @@ -15,19 +14,23 @@ if (credentialError) {
throw Error(credentialError);
}
module.exports = async (req, res) => {
let variants = [];
const response = await fetch(
`https://${siteName}.chargebee.com/api/v2/products/${req.query.product_id}/variants`,
{
headers: {
Authorization: `Basic ${Buffer.from(API_KEY).toString('base64')}`
try {
let variants = [];
const response = await fetch(
`https://${siteName}.chargebee.com/api/v2/products/${req.query.product_id}/variants`,
{
headers: {
Authorization: `Basic ${Buffer.from(API_KEY).toString('base64')}`
}
}
);
const varJson = await response.json();
for (let i = 0; i < varJson.list?.length; i++) {
const variant = varJson.list[i].variant;
variants.push(variant);
}
);
const varJson = await response.json();
for (let i = 0; i < varJson.list.length; i++) {
const variant = varJson.list[i].variant;
variants.push(variant);
res.status(200).json({ list: variants });
} catch (err) {
console.log(err);
}
res.status(200).json({ list: variants });
};
34 changes: 29 additions & 5 deletions ecommerce-examples/example1/back-end/javascript/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ const path = require('path');
const fetchItems = require('./fetch-items');
const fetchItemPrices = require('./fetch-item-prices');
const fetchVariants = require('./fetch-variants');
const fetchProduct = require('./fetch-product');
const checkoutNew = require('./new-checkout');
const estimates = require('./fetch-estimates');
const { siteName, API_KEY } = require('./constants');

// CORS is enabled only for demo. Please dont use this in production unless you know about CORS
const cors = require('cors');
const siteName = 'SITE_ID';
const API_KEY = 'API_KEY';

let credentialError = null;
if (siteName === 'SITE_ID' || !siteName) {
credentialError = 'Error: Kindly provide your Chargebee Site name at the Backend'
credentialError =
'Error: Kindly provide your Chargebee Site name at the Backend';
}
if (API_KEY === 'API_KEY' || !API_KEY) {
credentialError =
Expand All @@ -28,7 +30,8 @@ chargebee.configure({
});
const app = express();

app.use(express.urlencoded());
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(cors());

// Configure your static file paths here. Images, CSS and JS files should be inside this path
Expand All @@ -54,16 +57,37 @@ app.get('/api/variants', async (req, res) => {
await fetchVariants(req, res);
});

/*
Fetch Product API
request params - Product ID
*/
app.get('/api/product', async (req, res) => {
await fetchProduct(req, res);
});

/*
Fetch Checkout Link
request params - Item Price ID, Customer ID (optional)
*/
app.post('/api/generate_checkout_new_url', checkoutNew);

/*
Fetch Estimates for the Cart items
*/
app.post('/api/calculate_estimates', async (req, res) => {
await estimates(req, res);
});

// Configure the path of your HTML file to be loaded
app.get('/', (req, res) => {
res.sendFile(
path.join(__dirname, '../../front-end/javascript/cb-widget.html')
path.join(__dirname, '../../front-end/javascript/widget/cb-widget.html')
);
});

app.get('/cart', (req, res) => {
res.sendFile(
path.join(__dirname, '../../front-end/javascript/cart/cb-cart.html')
);
});

Expand Down
169 changes: 169 additions & 0 deletions ecommerce-examples/example1/front-end/javascript/cart/cb-cart.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
.cb-cart-container {
width: 25%;
height: 100vh;
position: fixed;
top: 0;
right: 0;
background: white;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
z-index: 1;
transition: all 0.3s ease;
transform: translateX(100%);
}

.cb-cart-container.open {
transform: translateX(0%);
}

.cb-cart-container.open .cb-cart-icon {
display: none;
}

.cb-cart-container.close .cb-close-icon {
display: none;
}

.cb-cart-button {
position: absolute;
transform: translateX(-100%);
padding: 10px 10px 10px 15px;
background: white;
border-radius: 20px 0px 0px 20px;
top: 20px;
box-shadow: -10px 6px 13px #f4f4f4;
cursor: pointer;
}

.cb-cart-quantity {
position: absolute;
top: -12px;
left: -12px;
background: #022938;
padding: 5px 10px;
border-radius: 50%;
color: white;
font-family: var(--cb-font-family);
}

.cb-cart-empty {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
flex-direction: column;
}

.cb-clear-cart {
display: flex;
justify-content: flex-end;
margin-bottom: 30px;
}

.cb-clear-cart .cb-cta-secondary {
margin-right: 20px;
}

.cb-cart-items-wrapper {
padding: 0 30px;
overflow: auto;
max-height: 70vh;
}

.cb-cart-item-remove {
font-size: 12px;
cursor: pointer;
color: #c81f1f;
font-weight: 600;
display: inline-block;
}

.cb-delivery-info {
font-size: 12px;
}

.cb-cart-total-price {
padding: 30px 50px;
display: flex;
justify-content: space-between;
font-size: 24px;
font-weight: 600;
position: absolute;
bottom: 0;
left: 0;
width: 20vw;
background: white;
box-shadow: rgba(0, 0, 0, 0.35) 15px 5px 15px;
}

.cb-cart-total-price div:first-child {
margin-right: 50px;
}

.cb-customer-info {
margin: auto;
width: 70%;
}

.cb-customer-info input,
.cb-customer-info select {
height: 32px;
width: 100%;
margin: 10px 0;
padding: 0 10px;
border-radius: 5px;
border: 1px solid #9797a5;
}

.cb-item-image img {
width: 125px;
border-radius: 5px;
}

.cb-cart-item-container {
display: flex;
padding: 15px 0;
border-top: 1px solid #9797a5;
align-items: center;
}

.cb-item-detail {
padding: 0 15px;
}

.cb-productInfo,
.cb-unitPrice,
.cb-cart-item-quantity {
margin-bottom: 10px;
}

.cb-cart-item-quantity {
display: flex;
justify-content: space-between;
align-items: center;
}

.cb-cart-item-container .cb-quantity-wrapper {
border: none;
}

.cb-cart-item-container .cb-quantity-wrapper button {
border-radius: 50%;
border: 1px solid #d7d5dd;
padding: 5px 10px;
background: #d7d5dd;
cursor: pointer;
}

.cb-continue-shopping {
padding: 10px 20px;
background-color: var(--cb-cta-bg);
color: var(--cb-cta-text);
border-radius: var(--cb-border-radius);
text-decoration: none;
display: block;
text-align: center;
border: none;
width: 80%;
margin: 30px auto;
cursor: pointer;
}
Loading