Skip to content

Feat: Thinking in react (Product Table) #4

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

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ jobs:
cache: "yarn"
- run: yarn install
- run: yarn build
- run: yarn prettier -c .
- run: yarn reformat:check
# - run: yarn test
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export default [
"react/react-in-jsx-scope": "off",
"no-plusplus": "off",
"react/no-array-index-key": "off",
"@typescript-eslint/no-explicit-any": "warn",
},
},
];
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"reformat-all": "prettier --write .",
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md}\" --config ./.prettierrc.json"
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md}\" --config ./.prettierrc.json",
"reformat:check": "prettier -c ."
},
"eslintConfig": {
"extends": [
Expand Down
2 changes: 1 addition & 1 deletion src/App.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.App {
text-align: center;
/* text-align: center; */
}

.App-logo {
Expand Down
25 changes: 9 additions & 16 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import React from "react";
import "./App.css";
import Board from "./components/TicTacToe/Board";
import { ConfigProvider, theme } from "antd";
import FilterableProductTable from "./components/FilterableProductTable";

function App() {
// const [count, setCount] = React.useState(0);

// function handleClick(){
// setCount(count+1);
// console.log(`Button clicked ${count} times`);
// }
return (
<div className="App">
{/* <h1>Welcome to my App!</h1>
<MyButton count={count} OnClick={handleClick}/>
<br/>
<MyButton count={count} OnClick={handleClick}/>
<ProfileCard />
<br/> */}
{/* <TicTacToe /> */}
<Board />
<ConfigProvider
theme={{
algorithm: theme.defaultAlgorithm,
}}
>
<FilterableProductTable />
</ConfigProvider>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default function ProductCategoryRow({ category }: { category: string }) {
return (
<div>
<div
style={{
display: "flex",
width: "500px",
flexDirection: "row",
borderBottom: "1px solid #ccc",
padding: "8px 0",
fontWeight: "bold",
}}
>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
{category}
</span>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
Name
</span>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
Price
</span>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
In Stock
</span>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { IProduct } from "../../model";

export default function ProductRow({ product }: { product: IProduct }) {
console.log(product);
return (
<div
style={{
display: "flex",
width: "500px",
flexDirection: "row",
borderBottom: "1px solid #ccc",
padding: "8px 0",
color: !product.stocked ? "Red" : "Black",
}}
>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
{product.category}
</span>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
{product.name}
</span>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
{product.price}
</span>
<span style={{ flex: 1, textAlign: "left", padding: "0 8px" }}>
{product.stocked ? "True" : "False"}
</span>
</div>
);
}
51 changes: 51 additions & 0 deletions src/components/FilterableProductTable/ProductTable/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { uniq } from "lodash-es";
import ProductCategoryRow from "./ProductCategoryRow";
import ProductRow from "./ProductRow";
import { IProduct } from "../model";

interface IProductCategoryRow {
categoryComponent: React.ReactElement<typeof ProductCategoryRow>;
productComponents: React.ReactElement<typeof ProductRow>[];
}

export default function ProductTable({
ProductData,
}: {
ProductData: IProduct[];
}) {
const categories: string[] = ProductData.map((product) => product.category);
const uniqCategories: string[] = uniq(categories);

const productsByCategory = new Map<string, IProduct[]>();

uniqCategories.forEach((category) => {
productsByCategory.set(
category,
ProductData.filter((product) => product.category === category)
);
});

const productCaregoriesComponents: Map<string, IProductCategoryRow> =
new Map<string, IProductCategoryRow>();

const tableRows: JSX.Element[] = [];

productsByCategory.forEach((value, key) => {
productCaregoriesComponents.set(key, {
categoryComponent: <ProductCategoryRow category={key} />,
productComponents: value.map((product, index) => (
<ProductRow product={product} key={index} />
)),
});
tableRows.push(<ProductCategoryRow category={key} />);
tableRows.push(
...value.map((product, index) => (
<ProductRow product={product} key={index} />
))
);
});

console.log("hellooo", Object.fromEntries(productCaregoriesComponents));

return <div>{tableRows}</div>;
}
57 changes: 57 additions & 0 deletions src/components/FilterableProductTable/SearchBar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Button, Checkbox, Input } from "antd";
import { useState } from "react";
import type { ButtonProps, CheckboxProps, InputProps } from "antd";

export default function SearchTable() {
const [checked, setChecked] = useState(false);

const [searchVal, setSearchVal] = useState("");

const onChange: CheckboxProps["onChange"] = (e) => {
setChecked(e.target.checked);
};

const OnSearchClicked: ButtonProps["onClick"] = () => {
console.log(checked);
};

const OnSearchInput: InputProps["onInput"] = (e: any) => {
console.log(e.target.value);
setSearchVal(e.target.value);
};

return (
<div
style={{
display: "flex",
flexDirection: "column",
width: "500px",
alignItems: "center",
gap: "10px",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
gap: "10px",
}}
>
<Input
placeholder="Search"
style={{ width: "200px" }}
value={searchVal}
onInput={OnSearchInput}
/>
<Button type="primary" onClick={OnSearchClicked}>
Search
</Button>
</div>
<Checkbox onChange={onChange} checked={checked}>
Only show products in stock
</Checkbox>
</div>
);
}
25 changes: 25 additions & 0 deletions src/components/FilterableProductTable/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { IProduct } from "./model";
import ProductTable from "./ProductTable";
import SearchTable from "./SearchBar";

const ProductData: IProduct[] = [
{ category: "Fruits", price: "$1", stocked: true, name: "Apple" },
{ category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
{ category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
{ category: "Vegetables", price: "$2", stocked: true, name: "Spinach" },
{ category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin" },
{ category: "Vegetables", price: "$1", stocked: true, name: "Peas" },
];

export default function FilterableProductTable() {
return (
<div
style={{
padding: "5px",
}}
>
<SearchTable />
<ProductTable ProductData={ProductData} />
</div>
);
}
6 changes: 6 additions & 0 deletions src/components/FilterableProductTable/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface IProduct {
category: string;
price: string;
stocked: boolean;
name: string;
}
2 changes: 0 additions & 2 deletions src/components/ProfileCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// import { Card } from "antd";

const user = {
name: "Iron Man",
imgSrc: "https://www.shutterstock.com/shutterstock/photos/2061533240/display_1500/stock-photo-mountain-view-california-october-iron-man-cardstock-mask-of-marvel-book-character-2061533240.jpg",
Expand Down
5 changes: 5 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
/* html, body {
padding: 0;
margin: 0;
background: #000;
} */
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
"jsx": "react-jsx",
"baseUrl": "./"
},
"include": ["src"]
}
Loading