-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cart and order data persistence on the server side
- Loading branch information
Marcin Slezak
committed
Oct 30, 2023
1 parent
0404be1
commit c50197b
Showing
17 changed files
with
269 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Cart, CartItem } from '@composable/types' | ||
import products from './products.json' | ||
import { randomUUID } from 'crypto' | ||
|
||
const findProductById = (id: string) => { | ||
return products.find((product) => product.id === id) ?? products[0] | ||
} | ||
|
||
export const generateEmptyCart = (cartId?: string): Cart => ({ | ||
id: cartId || randomUUID(), | ||
items: [], | ||
summary: {}, | ||
}) | ||
|
||
export const generateCartItem = (productId: string, quantity: number) => { | ||
const _product = findProductById(productId) | ||
return { | ||
brand: _product.brand, | ||
category: _product.category, | ||
id: _product.id, | ||
image: _product.images[0], | ||
name: _product.name, | ||
price: _product.price, | ||
quantity: quantity ?? 1, | ||
sku: _product.sku, | ||
slug: _product.slug, | ||
type: _product.type, | ||
} | ||
} | ||
|
||
export const calculateCartSummary = (cartItems: CartItem[]) => { | ||
const subtotal = cartItems.reduce((_subtotal, item) => { | ||
return _subtotal + item.price * (item.quantity ?? 1) | ||
}, 0) | ||
const taxes = subtotal * 0.07 | ||
const total = subtotal + taxes | ||
|
||
return { | ||
subtotalPrice: subtotal.toFixed(2), | ||
taxes: taxes.toFixed(2), | ||
totalPrice: total.toFixed(2), | ||
shipping: 'Free', | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import storage from 'node-persist' | ||
import path from 'path' | ||
import os from 'os' | ||
import { Order, Cart } from '@composable/types' | ||
|
||
const storageFolderPath = path.join(os.tmpdir(), 'composable-ui-storage') | ||
|
||
storage.init({ | ||
dir: storageFolderPath, | ||
}) | ||
|
||
export const getOrder = async (orderId: string): Promise<Order | undefined> => { | ||
return storage.getItem(`order-${orderId}`) | ||
} | ||
|
||
export const saveOrder = async (order: Order) => { | ||
await storage.setItem(`order-${order.id}`, order) | ||
return order | ||
} | ||
|
||
export const getCart = async (cartId: string): Promise<Cart | undefined> => { | ||
return storage.getItem(`cart-${cartId}`) | ||
} | ||
|
||
export const saveCart = async (cart: Cart) => { | ||
await storage.setItem(`cart-${cart.id}`, cart) | ||
return cart | ||
} | ||
|
||
export const deleteCart = async (cartId: string) => { | ||
const result = await storage.del(`cart-${cartId}`) | ||
return result.removed | ||
} |
26 changes: 19 additions & 7 deletions
26
packages/commerce-generic/src/services/cart/add-cart-item.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,30 @@ | ||
import { CommerceService } from '@composable/types' | ||
import { generateCartData } from '../../data/generateCartData' | ||
import cart from '../../data/cart.json' | ||
import { getCart, saveCart } from '../../data/persit' | ||
import { | ||
generateCartItem, | ||
calculateCartSummary, | ||
generateEmptyCart, | ||
} from '../../data/generate-cart-data' | ||
|
||
export const addCartItem: CommerceService['addCartItem'] = async ({ | ||
cartId, | ||
productId, | ||
quantity, | ||
variantId, | ||
}) => { | ||
const { items, summary } = generateCartData({ productId, quantity }) | ||
const cart = (await getCart(cartId)) || generateEmptyCart(cartId) | ||
|
||
return { | ||
...cart, | ||
items, | ||
summary, | ||
const isProductInCartAlready = cart.items.some( | ||
(item) => item.id === productId | ||
) | ||
|
||
if (isProductInCartAlready) { | ||
cart.items.find((item) => item.id === productId)!.quantity++ | ||
} else { | ||
const newItem = generateCartItem(productId, quantity) | ||
cart.items.push(newItem) | ||
} | ||
cart.summary = calculateCartSummary(cart.items) | ||
|
||
return saveCart(cart) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { CommerceService } from '@composable/types' | ||
import cart from '../../data/cart.json' | ||
import { saveCart } from '../../data/persit' | ||
import { generateEmptyCart } from '../../data/generate-cart-data' | ||
|
||
export const createCart: CommerceService['createCart'] = async () => { | ||
return cart | ||
return saveCart(generateEmptyCart()) | ||
} |
17 changes: 15 additions & 2 deletions
17
packages/commerce-generic/src/services/cart/delete-cart-item.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,22 @@ | ||
import { CommerceService } from '@composable/types' | ||
import cart from '../../data/cart.json' | ||
import { getCart, saveCart } from '../../data/persit' | ||
|
||
import { calculateCartSummary } from '../../data/generate-cart-data' | ||
|
||
export const deleteCartItem: CommerceService['deleteCartItem'] = async ({ | ||
cartId, | ||
productId, | ||
}) => { | ||
return cart | ||
const cart = await getCart(cartId) | ||
|
||
if (!cart) { | ||
throw new Error( | ||
`[deleteCartItem] Could not found cart with requested cart id: ${cartId}` | ||
) | ||
} | ||
|
||
cart.items = cart.items.filter((item) => item.id !== productId) | ||
cart.summary = calculateCartSummary(cart.items) | ||
|
||
return saveCart(cart) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,10 @@ | ||
import { CommerceService } from '@composable/types' | ||
import { generateCartData } from '../../data/generateCartData' | ||
import cart from '../../data/cart.json' | ||
import { getCart as getCartFromStorage } from '../../data/persit' | ||
|
||
export const getCart: CommerceService['getCart'] = async ({ cartId }) => { | ||
if (!cartId) { | ||
return null | ||
} | ||
|
||
const { items, summary } = generateCartData() | ||
|
||
return { | ||
...cart, | ||
items, | ||
summary, | ||
} | ||
return (await getCartFromStorage(cartId)) || null | ||
} |
29 changes: 22 additions & 7 deletions
29
packages/commerce-generic/src/services/cart/update-cart-item.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,32 @@ | ||
import { CommerceService } from '@composable/types' | ||
import { generateCartData } from '../../data/generateCartData' | ||
import cart from '../../data/cart.json' | ||
import { getCart, saveCart } from '../../data/persit' | ||
|
||
import { calculateCartSummary } from '../../data/generate-cart-data' | ||
|
||
export const updateCartItem: CommerceService['updateCartItem'] = async ({ | ||
cartId, | ||
productId, | ||
quantity, | ||
}) => { | ||
const { items, summary } = generateCartData({ productId, quantity }) | ||
const cart = await getCart(cartId) | ||
|
||
if (!cart) { | ||
throw new Error( | ||
`[updateCartItem] Could not found cart with requested cart id: ${cartId}` | ||
) | ||
} | ||
|
||
const cartItem = cart.items.find((item) => item.id === productId) | ||
|
||
return { | ||
...cart, | ||
items, | ||
summary, | ||
if (!cartItem) { | ||
throw new Error( | ||
`[updateCartItem] Could not found cart item with requested product id: ${productId}` | ||
) | ||
} | ||
|
||
cartItem.quantity = quantity | ||
|
||
cart.summary = calculateCartSummary(cart.items) | ||
|
||
return saveCart(cart) | ||
} |
50 changes: 41 additions & 9 deletions
50
packages/commerce-generic/src/services/checkout/create-order.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,48 @@ | ||
import { CommerceService } from '@composable/types' | ||
import { generateCartData } from '../../data/generateCartData' | ||
import order from '../../data/order.json' | ||
import { Cart, CheckoutInput, CommerceService, Order } from '@composable/types' | ||
import { getCart } from '../../data/persit' | ||
import { saveOrder } from '../../data/persit' | ||
import shippingMethods from '../../data/shipping-methods.json' | ||
import { randomUUID } from 'crypto' | ||
|
||
export const createOrder: CommerceService['createOrder'] = async ({ | ||
checkout, | ||
}) => { | ||
const cartItems = generateCartData() | ||
const generateOrderFromCart = ( | ||
cart: Cart, | ||
checkoutInput: CheckoutInput | ||
): Order => { | ||
return { | ||
...order, | ||
...cartItems, | ||
id: randomUUID(), | ||
status: 'complete', | ||
payment: 'unpaid', | ||
shipping: 'unfulfilled', | ||
customer: { | ||
email: checkoutInput.customer.email, | ||
}, | ||
shipping_address: { | ||
phone_number: '', | ||
city: '', | ||
...checkoutInput.shipping_address, | ||
}, | ||
billing_address: { | ||
phone_number: '', | ||
city: '', | ||
...checkoutInput.billing_address, | ||
}, | ||
shipping_method: shippingMethods[0], | ||
created_at: Date.now(), | ||
items: cart.items, | ||
summary: cart.summary, | ||
} | ||
} | ||
|
||
export const createOrder: CommerceService['createOrder'] = async ({ | ||
checkout, | ||
}) => { | ||
const cart = await getCart(checkout.cartId) | ||
|
||
if (!cart) { | ||
throw new Error( | ||
`[createOrder] Could not find cart by id: ${checkout.cartId}` | ||
) | ||
} | ||
|
||
return saveOrder(generateOrderFromCart(cart, checkout)) | ||
} |
10 changes: 7 additions & 3 deletions
10
packages/commerce-generic/src/services/checkout/get-order.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export interface CheckoutInput { | ||
cartId: string | ||
customer: { | ||
id?: string | ||
email: string | ||
|
Oops, something went wrong.