From 13d26b77c3c66b13f0fb480644dd28894e00550a Mon Sep 17 00:00:00 2001 From: limivann <71662324+limivann@users.noreply.github.com> Date: Mon, 2 Sep 2024 22:46:49 +0800 Subject: [PATCH] Added toast for error messages, fix inconsistency issues --- apps/cms/package.json | 1 + apps/cms/src/@types/Order.ts | 6 +- apps/cms/src/admin/views/MerchProducts.tsx | 10 +- apps/cms/src/admin/views/MerchPromotion.tsx | 10 +- apps/cms/src/admin/views/MerchSales.tsx | 104 ++++++++++---------- apps/cms/src/admin/views/ViewTemplate.tsx | 2 + apps/cms/src/collections/Orders.ts | 6 +- apps/cms/src/types.ts | 6 +- apps/cms/src/utilities/prettifyKey.ts | 9 ++ apps/web/features/merch/services/api.ts | 2 +- 10 files changed, 76 insertions(+), 80 deletions(-) create mode 100644 apps/cms/src/utilities/prettifyKey.ts diff --git a/apps/cms/package.json b/apps/cms/package.json index 1585d165..41f9a087 100644 --- a/apps/cms/package.json +++ b/apps/cms/package.json @@ -30,6 +30,7 @@ "payload": "^2.27.0", "querystring-es3": "^0.2.1", "react": "^18.0.0", + "react-toastify": "10.0.5", "tsconfig": "*" }, "devDependencies": { diff --git a/apps/cms/src/@types/Order.ts b/apps/cms/src/@types/Order.ts index 98cb193a..d064f7b3 100644 --- a/apps/cms/src/@types/Order.ts +++ b/apps/cms/src/@types/Order.ts @@ -5,9 +5,9 @@ export class Order { constructor( public id = '', - public transaction_id = '', - public transaction_time = '', - public payment_method = '', + public transactionId = '', + public transactionTime = '', + public paymentMethod = '', public customerEmail = '', public status = '', public updatedAt = '', diff --git a/apps/cms/src/admin/views/MerchProducts.tsx b/apps/cms/src/admin/views/MerchProducts.tsx index abc5ad09..c06a44f9 100644 --- a/apps/cms/src/admin/views/MerchProducts.tsx +++ b/apps/cms/src/admin/views/MerchProducts.tsx @@ -8,6 +8,7 @@ import SortedColumn from "../utils/SortedColumn"; import { Table } from "payload/dist/admin/components/elements/Table"; import { Product } from "types"; import ProductsApi from "../../apis/products.api"; +import { prettifyKey } from "../../utilities/prettifyKey"; const MerchProducts: AdminViewComponent = ({ user, canAccessAdmin }) => { // Get data from API @@ -18,15 +19,6 @@ const MerchProducts: AdminViewComponent = ({ user, canAccessAdmin }) => { .catch((error) => console.log(error)); }, []); - // Output human-readable table headers based on the attribute names from the API - function prettifyKey(str: string): string { - let res = ""; - for (const i of str.split("_")) { - res += i.charAt(0).toUpperCase() + i.slice(1) + " "; - } - return res; - } - // Do not load table until we receive the data if (data == null) { return
Loading...
; diff --git a/apps/cms/src/admin/views/MerchPromotion.tsx b/apps/cms/src/admin/views/MerchPromotion.tsx index 11ff14bb..ce4eeb29 100644 --- a/apps/cms/src/admin/views/MerchPromotion.tsx +++ b/apps/cms/src/admin/views/MerchPromotion.tsx @@ -9,6 +9,7 @@ import { Table } from "payload/dist/admin/components/elements/Table"; import { Promotion } from "types"; import PromotionsApi from "../../apis/promotions.api"; import './MerchPromotion.scss'; +import { prettifyKey } from "../../utilities/prettifyKey"; const MerchPromotion: AdminViewComponent = ({ user, canAccessAdmin }) => { // Get data from API @@ -19,15 +20,6 @@ const MerchPromotion: AdminViewComponent = ({ user, canAccessAdmin }) => { .catch((error) => console.log(error)); }, []); - // Output human-readable table headers based on the attribute names from the API - function prettifyKey(str: string): string { - let res = ""; - for (const i of str.split("_")) { - res += i.charAt(0).toUpperCase() + i.slice(1) + " "; - } - return res; - } - // Do not load table until we receive the data if (data == null) { return
Loading...
; diff --git a/apps/cms/src/admin/views/MerchSales.tsx b/apps/cms/src/admin/views/MerchSales.tsx index de5ef720..bc012e0e 100644 --- a/apps/cms/src/admin/views/MerchSales.tsx +++ b/apps/cms/src/admin/views/MerchSales.tsx @@ -9,10 +9,11 @@ import { RenderCellFactory } from "../utils/RenderCellFactory"; import SortedColumn from "../utils/SortedColumn"; import { Table } from "payload/dist/admin/components/elements/Table"; import { useHistory } from 'react-router-dom'; - +import { toast } from "react-toastify"; +import { prettifyKey } from "../../utilities/prettifyKey"; const MerchSales: AdminViewComponent = ({ user, canAccessAdmin }) => { - // Get data from API + // Get data from API const [data, setData] = useState(null); const history = useHistory(); useEffect(() => { @@ -21,75 +22,75 @@ const MerchSales: AdminViewComponent = ({ user, canAccessAdmin }) => { const orders: Order[] = await OrdersApi.getOrders(); setData(orders); } catch (error) { - console.error(error); setData([]); + if (error instanceof Error) { + toast.error(error.message); + } else { + toast.error("An unknown error occurred"); + } } }; // eslint-disable-next-line @typescript-eslint/no-floating-promises fetchOrders(); }, []); - // Output human-readable table headers based on the attribute names from the API - function prettifyKey(str: string): string { - let res = ""; - for (const i of str.split("_")) { - res += i.charAt(0).toUpperCase() + i.slice(1) + " "; - } - return res; - } - // Do not load table until we receive the data if (data == null) { return
Loading...
; } const tableCols = new Array(); - for (const key of Object.keys(new Order())) { - const renderCellComponent = RenderCellFactory.get(data[0], key); - const renderCell: React.FC<{ children?: React.ReactNode }> = - renderCellComponent instanceof Promise - ? renderCellComponent - : renderCellComponent; + if (data && data.length > 0) { + for (const key of Object.keys(new Order())) { + const renderCellComponent = RenderCellFactory.get(data[0], key); + const renderCell: React.FC<{ children?: React.ReactNode }> = + renderCellComponent instanceof Promise + ? renderCellComponent + : renderCellComponent; + + const col: Column = { + accessor: key, + components: { + Heading: ( + + ), + renderCell: renderCell, + }, + label: prettifyKey(key), // Assigning the prettified key to the label + name: key, + active: true, + }; + + tableCols.push(col); + } - const col: Column = { - accessor: key, + // Add the "Edit" column + const editColumn: Column = { + accessor: "edit", components: { - Heading: ( - + Heading:
Edit
, + renderCell: (data: Order) => ( + ), - renderCell: renderCell, }, - label: "", - name: "", + label: "Edit", + name: "edit", active: true, }; - tableCols.push(col); - } - - const editColumn: Column = { - accessor: "edit", - components: { - Heading:
Edit
, - renderCell: (data: Order) => ( - - ), - }, - label: "Edit", - name: "edit", - active: true, - }; - tableCols.push(editColumn); + tableCols.push(editColumn); - const handleEdit = (data: Order) => { - const orderId = data.id; - // Navigate to edit - history.push(`/admin/collections/orders/${orderId}`) - }; + // Handle Edit functionality + const handleEdit = (data: Order) => { + const orderId = data.id; + // Navigate to the edit page + history.push(`/admin/collections/orders/${orderId}`); + }; + } return ( { - - + {data && data.length > 0 &&
} ); }; diff --git a/apps/cms/src/admin/views/ViewTemplate.tsx b/apps/cms/src/admin/views/ViewTemplate.tsx index 734049ab..6cca24da 100644 --- a/apps/cms/src/admin/views/ViewTemplate.tsx +++ b/apps/cms/src/admin/views/ViewTemplate.tsx @@ -7,6 +7,7 @@ import { Eyebrow } from "payload/components/elements"; import { AdminViewComponent } from "payload/config"; import { useStepNav } from "payload/components/hooks"; import { Meta } from "payload/components/utilities"; +import { Slide, ToastContainer } from "react-toastify"; type ViewTemplateProps = React.ComponentProps & { description: string; @@ -54,6 +55,7 @@ const ViewTemplate = ({

{title}

{children} + ); }; diff --git a/apps/cms/src/collections/Orders.ts b/apps/cms/src/collections/Orders.ts index 18f7ed1a..34424523 100644 --- a/apps/cms/src/collections/Orders.ts +++ b/apps/cms/src/collections/Orders.ts @@ -57,7 +57,7 @@ const Orders: CollectionConfig = { minRows: 1, }, { - name: "transaction_id", + name: "transactionId", label: "Transaction ID", admin: { description: "Transaction ID provided by Payment Gateway", @@ -66,7 +66,7 @@ const Orders: CollectionConfig = { required: true, }, { - name: "transaction_time", + name: "transactionTime", label: "Transaction Time", type: "date", admin: { @@ -77,7 +77,7 @@ const Orders: CollectionConfig = { required: true, }, { - name: "payment_method", + name: "paymentMethod", label: "Payment Method", type: "text", required: true, diff --git a/apps/cms/src/types.ts b/apps/cms/src/types.ts index 7fb8dfc5..87bbc7cc 100644 --- a/apps/cms/src/types.ts +++ b/apps/cms/src/types.ts @@ -144,9 +144,9 @@ export interface User { export interface Order { id: string; items?: OrderItem; - transaction_id: string; - transaction_time: string; - payment_method: string; + transactionId: string; + transactionTime: string; + paymentMethod: string; customerEmail: string; status: 'pending' | 'paid' | 'delivered'; updatedAt: string; diff --git a/apps/cms/src/utilities/prettifyKey.ts b/apps/cms/src/utilities/prettifyKey.ts new file mode 100644 index 00000000..c1df9efa --- /dev/null +++ b/apps/cms/src/utilities/prettifyKey.ts @@ -0,0 +1,9 @@ +/* +Convert a camelCase string to a human - readable format with proper spacing and capitalization +*/ + +export function prettifyKey(str: string): string { + let res = str.replace(/([A-Z])/g, ' $1'); // Add a space before each uppercase letter + res = res.charAt(0).toUpperCase() + res.slice(1); // Capitalize the first letter + return res; +} \ No newline at end of file diff --git a/apps/web/features/merch/services/api.ts b/apps/web/features/merch/services/api.ts index ea2f92a8..167b9ae5 100644 --- a/apps/web/features/merch/services/api.ts +++ b/apps/web/features/merch/services/api.ts @@ -93,7 +93,7 @@ export class Api { return new Promise((res, rej) => { setTimeout(() => { res({ - disabled: false, + disabled: true, displayText: "We are currently preparing for the next merch sale. Please look forward to our email!", });