Skip to content

Commit

Permalink
task: Port home page (product listing)
Browse files Browse the repository at this point in the history
  • Loading branch information
YoNG-Zaii committed Mar 12, 2023
1 parent 3c9b8c6 commit 9a29443
Show file tree
Hide file tree
Showing 19 changed files with 692 additions and 5 deletions.
113 changes: 113 additions & 0 deletions apps/web/lib/merch/services/api.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
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_APP_API_ORIGIN || "";
}

// http methods
async get(urlPath: string): Promise<Record<string, any>> {
const response = await fetch(`${this.API_ORIGIN}${urlPath}`);
return response.json();
}

/*
// 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: any) {
throw new Error(e);
}
}

/*
// 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();
80 changes: 80 additions & 0 deletions apps/web/lib/merch/typings/cart.tsx
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>;
34 changes: 34 additions & 0 deletions apps/web/lib/merch/typings/order.tsx
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;
};
14 changes: 14 additions & 0 deletions apps/web/lib/merch/typings/product.tsx
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;
};
27 changes: 27 additions & 0 deletions apps/web/lib/merch/utils/constants/order-status.ts
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";
}
};
9 changes: 9 additions & 0 deletions apps/web/lib/merch/utils/constants/queryKeys.ts
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",
}
17 changes: 17 additions & 0 deletions apps/web/lib/merch/utils/constants/routes.ts
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;
20 changes: 20 additions & 0 deletions apps/web/lib/merch/utils/functions/cart.ts
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 "";
}
7 changes: 7 additions & 0 deletions apps/web/lib/merch/utils/functions/currency.ts
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}`
}
Loading

0 comments on commit 9a29443

Please sign in to comment.