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

Add merch promotions page #149

Merged
merged 25 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 3 additions & 0 deletions apps/cms/src/@types/IPromotion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Promotion } from "./Promotion";

export class IPromotion extends Promotion {}
8 changes: 8 additions & 0 deletions apps/cms/src/@types/Promotion.ts
chanbakjsd marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class Promotion {
constructor(
public promotion_id = "",
public name = "",
public discount_percentage = "",
public category = ""
) {}
}
5 changes: 5 additions & 0 deletions apps/cms/src/admin/components/AfterNavLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ const merchRoutes = [
label: "Products",
href: "/admin/merch/products",
},
{
id: "merch_promotions",
label: "Promotions",
href: "/admin/merch/promotions",
},
];

const MerchLinks: React.FC = () => {
Expand Down
3 changes: 2 additions & 1 deletion apps/cms/src/admin/views/MerchProducts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const MerchProducts: AdminView = ({ user, canAccessAdmin }) => {
const sampleProduct = data[0];
const keys = Object.keys(sampleProduct);
for (const key of keys) {
const renderCell: React.FC<{ children?: React.ReactNode }> = RenderCellFactory.get(sampleProduct, key);
const renderCell: React.FC<{ children?: React.ReactNode }> =
RenderCellFactory.get(sampleProduct, key);
const col: Column = {
accessor: key,
components: {
Expand Down
137 changes: 137 additions & 0 deletions apps/cms/src/admin/views/MerchPromotion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, { useEffect, useState } from "react";
import { Button } from "payload/components/elements";
import { AdminView } from "payload/config";
import ViewTemplate from "./ViewTemplate";
import { Column } from "payload/dist/admin/components/elements/Table/types";
import { Promotion } from "../../@types/Promotion";
import { IPromotion } from "../../@types/IPromotion";
import PromotionsApi from "../../apis/promotions.api";
import { RenderCellFactory } from "../utils/RenderCellFactory";
import SortedColumn from "../utils/SortedColumn";
import { Table } from "payload/dist/admin/components/elements/Table";

const MerchPromotion: AdminView = ({ user, canAccessAdmin }) => {
// Get data from API
const [data, setData] = useState<IPromotion[]>(null);
useEffect(() => {
PromotionsApi.getPromotions()
.then((res: IPromotion[]) => setData(res))
.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 <div> Loading... </div>;
}

const tableCols = new Array<Column>();
for (const key of Object.keys(new Promotion())) {
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: (
<SortedColumn
label={prettifyKey(key)}
name={key}
data={data as never[]}
/>
),
renderCell: renderCell,
},
label: "",
name: "",
active: true,
};
tableCols.push(col);
}

const editColumn: Column = {
accessor: "edit",
components: {
Heading: <div>Edit</div>,
renderCell: ({ children }) => (
<Button onClick={() => handleEdit(children as string)}>Edit</Button>
),
},
label: "Edit",
name: "edit",
active: true,
};

tableCols.push(editColumn);

const deleteColumn: Column = {
accessor: "delete",
components: {
Heading: <div>Delete</div>,
renderCell: ({ children }) => (
<Button onClick={() => handleDelete(children as string)}>Delete</Button>
),
},
label: "Delete",
name: "delete",
active: true,
};

tableCols.push(deleteColumn);

const handleEdit = (promotionID: string) => {
console.log(`Dummy. Promotion ID: ${promotionID}`);
};

const handleDelete = (promotionID: string) => {
console.log(`Dummy. Promotion ID: ${promotionID}`);
};

const handleCreatePromotion = () => {
console.log("Creating a new promotion...");
};

console.log(tableCols);

return (
<ViewTemplate
user={user}
canAccessAdmin={canAccessAdmin}
description=""
keywords=""
title="Merchandise Promotion"
>
<div style={{ position: "relative" }}>
<Button el="link" to={"/admin"} buttonStyle="primary">
Go to Main Admin View
</Button>
<div
style={{
position: "absolute",
top: 0,
right: 0,
}}
>
<Button onClick={handleCreatePromotion} buttonStyle="primary">
Create Promotion
</Button>
</div>
</div>

<Table data={data} columns={tableCols} />
</ViewTemplate>
);
};

export default MerchPromotion;
28 changes: 28 additions & 0 deletions apps/cms/src/apis/promotions.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { IPromotion } from "../@types/IPromotion";
chanbakjsd marked this conversation as resolved.
Show resolved Hide resolved

// todo turn into real api
class OrdersApi {
// eslint-disable-next-line @typescript-eslint/require-await
async getPromotions(): Promise<IPromotion[]> {
const res: IPromotion[] = [];
const item1: IPromotion = {
promotion_id: "1",
name: "March Sales",
discount_percentage: "10%",
category: "T-shirts",
};
res.push(item1);

const item2: IPromotion = {
promotion_id: "2",
name: "Summer Sales",
discount_percentage: "10%",
category: "Tote bags",
};
res.push(item2);

return res;
}
}

export default new OrdersApi();
19 changes: 12 additions & 7 deletions apps/cms/src/payload.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import AfterNavLinks from "./admin/components/AfterNavLinks";
import MerchSales from "./admin/views/MerchSales";
import MerchOverview from "./admin/views/MerchOverview";
import MerchProducts from "./admin/views/MerchProducts";
import MerchPromotion from "./admin/views/MerchPromotion";
import { SCSEIcon, SCSELogo } from "./admin/graphics/Logos";
import BeforeNavLinks from "./admin/components/BeforeNavLinks";
import Order from "./collections/Orders";
Expand Down Expand Up @@ -51,6 +52,10 @@ export default buildConfig({
path: "/merch/products",
Component: MerchProducts,
},
{
path: "/merch/promotions",
Component: MerchPromotion,
},
],
beforeNavLinks: BeforeNavLinks,
afterNavLinks: AfterNavLinks,
Expand Down Expand Up @@ -78,13 +83,13 @@ export default buildConfig({
},
plugins: isUsingCloudStore()
? [
cloudStorage({
collections: {
media: {
adapter: adapter,
cloudStorage({
collections: {
media: {
adapter: adapter,
},
},
},
}),
]
}),
]
: [],
});
Loading