-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
task: Port home page (product listing)
- Loading branch information
Showing
19 changed files
with
696 additions
and
5 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { ProductType } from "../typings/product"; | ||
|
||
export class Api { | ||
private API_ORIGIN: string; | ||
|
||
constructor() { | ||
if (!process.env.MERCH_API_ORIGIN) { | ||
throw new Error("MERCH_API_ORIGIN environment variable is not set") | ||
} | ||
this.API_ORIGIN = process.env.MERCH_API_ORIGIN || ""; | ||
} | ||
|
||
// http methods | ||
async get(urlPath: string): Promise<Record<string, ProductType[]>> { | ||
const response = await fetch(`${this.API_ORIGIN}${urlPath}`); | ||
const convert = response.json() as unknown; // Convert to unknown type | ||
return convert as Record<string, ProductType[]> | ||
} | ||
|
||
/* | ||
// eslint-disable-next-line class-methods-use-this | ||
async post(urlPath: string, data: any): Promise<any> { | ||
const response = await fetch(`${this.API_ORIGIN}${urlPath}`, { | ||
method: "POST", // *GET, POST, PUT, DELETE, etc. | ||
mode: "cors", // no-cors, *cors, same-origin | ||
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached | ||
credentials: "same-origin", // include, *same-origin, omit | ||
headers: { | ||
"Content-Type": "application/json", | ||
// 'Content-Type': 'application/x-www-form-urlencoded', | ||
}, | ||
redirect: "follow", // manual, *follow, error | ||
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url | ||
body: JSON.stringify(data), // body data type must match | ||
}); | ||
return response.json(); | ||
} | ||
*/ | ||
|
||
// eslint-disable-next-line class-methods-use-this | ||
async getProducts(): Promise<ProductType[]> { | ||
try { | ||
const res = await this.get("/products"); | ||
console.log("product-list", res); | ||
return res?.products ?? []; | ||
} catch (e) { | ||
if(e instanceof Error){ | ||
throw new Error(e.message); | ||
} | ||
return [] | ||
} | ||
} | ||
|
||
/* | ||
// eslint-disable-next-line class-methods-use-this | ||
async getProduct(productId: string) { | ||
try { | ||
const res = await this.get(`/products/${productId}`); | ||
console.log("product res", res); | ||
return res; | ||
} catch (e: any) { | ||
throw new Error(e); | ||
} | ||
} | ||
async getOrder(userId: string, orderId: string) { | ||
try { | ||
const res = await this.get(`/orders/${orderId}`); | ||
console.log("Order Summary response:", res); | ||
return res; | ||
} catch (e: any) { | ||
throw new Error(e); | ||
} | ||
} | ||
async getOrderHistory(userId: string) { | ||
try { | ||
const res = await this.get(`/orders/${userId}`); | ||
console.log("Order Summary response:", res); | ||
return res.json(); | ||
} catch (e: any) { | ||
throw new Error(e); | ||
} | ||
} | ||
async postCheckoutCart( | ||
items: CartItemType[], | ||
email: string, | ||
promoCode: string | null | ||
) { | ||
try { | ||
const res = await this.post(`/cart/checkout`, { | ||
items, | ||
promoCode: promoCode ?? "", | ||
email, | ||
}); | ||
return res; | ||
} catch (e: any) { | ||
throw new Error(e); | ||
} | ||
} | ||
async postQuotation(items: CartItemType[], promoCode: string | null) { | ||
try { | ||
const res = await this.post(`/cart/quotation`, { | ||
items, | ||
promoCode: promoCode ?? "", | ||
}); | ||
return res; | ||
} catch (e: any) { | ||
throw new Error(e); | ||
} | ||
} | ||
*/ | ||
} | ||
|
||
export const api = new Api(); |
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,80 @@ | ||
export type CartItemType = { | ||
productId: string; | ||
size: string; | ||
colorway: string; | ||
quantity: number; | ||
}; | ||
|
||
/** | ||
* @Title CartItemType | ||
* @description Displayed on FE in shopping-cart | ||
*/ | ||
|
||
export type CartStateType = { | ||
voucher: string | null; | ||
items: CartItemType[]; | ||
name: string; | ||
billingEmail: string; | ||
}; | ||
export type ProductInfoType = { | ||
name: string; | ||
image: string; | ||
price: number; | ||
}; | ||
|
||
export type CartPriceType = { | ||
currency: string; | ||
subtotal: number; | ||
discount: number; | ||
grandTotal: number; | ||
}; | ||
|
||
export type CartResponseDto = { | ||
items: [ | ||
{ | ||
id: string; | ||
name: string; | ||
price: number; | ||
images: string[]; | ||
sizes: string; | ||
productCategory: string; | ||
isAvailable: boolean; | ||
quantity: number; | ||
} | ||
]; | ||
price: { | ||
currency: string; | ||
subtotal: number; | ||
discount: number; | ||
grandTotal: number; | ||
}; | ||
}; | ||
|
||
export type CheckoutResponseDto = { | ||
orderId: string; | ||
items: [ | ||
{ | ||
id: string; | ||
name: string; | ||
price: number; | ||
images: string[]; | ||
sizes: string[]; | ||
productCategory: string; | ||
isAvailable: boolean; | ||
quantity: number; | ||
} | ||
]; | ||
price: { | ||
currency: string; | ||
subtotal: number; | ||
discount: number; | ||
grandTotal: number; | ||
}; | ||
payment: { | ||
paymentGateway: string; | ||
clientSecret: string; | ||
}; | ||
email: string; | ||
}; | ||
|
||
export type ProductInfoMapType = Record<string, ProductInfoType>; |
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,34 @@ | ||
// eslint-disable-next-line no-shadow | ||
export enum OrderStatusType { | ||
RECEIVED, | ||
PROCESSING, | ||
READY_TO_COLLECT, | ||
DELAY, | ||
COLLECTED, | ||
} | ||
|
||
export type OrderItemType = { | ||
id: string; | ||
image: string; | ||
size: string; | ||
colorway: string; | ||
price: number; | ||
quantity: number; | ||
name: string; | ||
}; | ||
|
||
export type OrderBillingType = { | ||
total: number; | ||
subtotal: number; | ||
appliedVoucher?: null; | ||
}; | ||
|
||
export type OrderType = { | ||
userId: string; | ||
orderID: string; | ||
orderItems: OrderItemType[]; | ||
status: OrderStatusType; | ||
billing: OrderBillingType; | ||
orderDateTime: string | Date; | ||
lastUpdate: string | Date | undefined; | ||
}; |
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,14 @@ | ||
export type ProductCategoryType = string; | ||
|
||
export type ProductType = { | ||
id: string; | ||
name: string; | ||
price: number; | ||
stock: { [colorway: string]: { [sizeIndex: string]: number } }; // stock[colorway][size] = qty | ||
sizes: string[]; | ||
sizeChart: string; | ||
colorways: string[]; | ||
images?: string[]; | ||
productCategory?: ProductCategoryType; | ||
isAvailable: boolean; | ||
}; |
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,27 @@ | ||
import { OrderStatusType } from "../../typings/order"; | ||
|
||
export const renderOrderStatus = (status: OrderStatusType) => { | ||
switch (status) { | ||
case OrderStatusType.COLLECTED: | ||
return "Order Collected"; | ||
case OrderStatusType.PROCESSING: | ||
return "Processing"; | ||
case OrderStatusType.RECEIVED: | ||
return "Order Received"; | ||
default: | ||
return "Item Delayed"; | ||
} | ||
}; | ||
|
||
export const getOrderStatusColor = (status: OrderStatusType) => { | ||
switch (status) { | ||
case OrderStatusType.COLLECTED: | ||
return "green.500"; | ||
case OrderStatusType.PROCESSING: | ||
return "primary.400"; | ||
case OrderStatusType.RECEIVED: | ||
return "primary.600"; | ||
default: | ||
return "red.500"; | ||
} | ||
}; |
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,9 @@ | ||
export enum QueryKeys { | ||
PRODUCTS = "PRODUCTS", | ||
PRODUCT = "PRODUCT", | ||
VOUCHER = "VOUCHER", | ||
ORDER = "ORDER", | ||
ORDERS = "ORDERS", | ||
EMAIL = "EMAIL", | ||
CHECKOUT = "CHECKOUT", | ||
} |
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,17 @@ | ||
type Routes = { | ||
HOME: string; | ||
PRODUCT: string; | ||
CART: string; | ||
CHECKOUT: string; | ||
ORDER_SUMMARY: string; | ||
}; | ||
|
||
export const routes: Routes = { | ||
HOME: "/merch", | ||
PRODUCT: "/merch/product", | ||
CART: "/merch/cart", | ||
CHECKOUT: "/merch/checkout", | ||
ORDER_SUMMARY: "/merch/order-summary", | ||
}; | ||
|
||
export default routes; |
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,20 @@ | ||
import { CartItemType } from "../../typings/cart"; | ||
|
||
export const getQtyInCart = (cartItems: CartItemType[], productId: string, colorway: string, size: string) : number => { | ||
const cartItem = cartItems.find((item) => { | ||
return (item.productId === productId) && (item.size === size) && (item.colorway === colorway); | ||
}) | ||
|
||
if (cartItem) { | ||
return cartItem.quantity; | ||
} | ||
return 0; | ||
} | ||
|
||
export const displayQtyInCart = (cartItems: CartItemType[], productId: string, colorway: string, size: string) : string => { | ||
const qty = getQtyInCart(cartItems, productId, colorway, size); | ||
if (qty > 0) { | ||
return `You have already added ${qty} to your cart.`; | ||
} | ||
return ""; | ||
} |
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,7 @@ | ||
export const displayPrice = (amountInCents: number): string => { | ||
const amountStr = amountInCents.toString() | ||
const dollarStr = amountStr.slice(0, -2).padStart(1, '0') | ||
const centStr = amountStr.slice(-2).padStart(2, '0') | ||
const priceStr = dollarStr.concat(".").concat(centStr) | ||
return `$${priceStr}` | ||
} |
Oops, something went wrong.