From bfa2ffe87c659678b8400f12a6268ab2a24076fb Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Mon, 23 Sep 2024 16:50:17 +0530 Subject: [PATCH 1/9] Feat: Initial setup --- src/App.tsx | 4 ++- .../ProductTable/ProductCategoryRow/index.tsx | 7 +++++ .../ProductTable/ProductRow/index.tsx | 7 +++++ .../ProductTable/index.tsx | 12 ++++++++ .../SearchBar/index.tsx | 7 +++++ .../FilterableProductTable/index.tsx | 29 +++++++++++++++++++ 6 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx create mode 100644 src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx create mode 100644 src/components/FilterableProductTable/ProductTable/index.tsx create mode 100644 src/components/FilterableProductTable/SearchBar/index.tsx create mode 100644 src/components/FilterableProductTable/index.tsx diff --git a/src/App.tsx b/src/App.tsx index e72f9fd..b0c0950 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ import React from 'react'; import './App.css'; import Board from './components/TicTacToe/Board'; +import FilterableProductTable from './components/FilterableProductTable'; function App() { // const [count, setCount] = React.useState(0); @@ -18,7 +19,8 @@ function App() {
*/} {/* */} - + {/* */} + ); } diff --git a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx new file mode 100644 index 0000000..d493fe9 --- /dev/null +++ b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx @@ -0,0 +1,7 @@ +export default function ProductCategoryRow(){ + return ( +
+

Product Category Row

+
+ ) +} \ No newline at end of file diff --git a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx new file mode 100644 index 0000000..31d0262 --- /dev/null +++ b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx @@ -0,0 +1,7 @@ +export default function ProductRow(){ + return ( +
+

Product Row

+
+ ) +} \ No newline at end of file diff --git a/src/components/FilterableProductTable/ProductTable/index.tsx b/src/components/FilterableProductTable/ProductTable/index.tsx new file mode 100644 index 0000000..8c54f8f --- /dev/null +++ b/src/components/FilterableProductTable/ProductTable/index.tsx @@ -0,0 +1,12 @@ +import ProductCategoryRow from "./ProductCategoryRow"; +import ProductRow from "./ProductRow"; + +export default function ProductTable(){ + return ( +
+

Product Table

+ + +
+ ) +} \ No newline at end of file diff --git a/src/components/FilterableProductTable/SearchBar/index.tsx b/src/components/FilterableProductTable/SearchBar/index.tsx new file mode 100644 index 0000000..b40a43f --- /dev/null +++ b/src/components/FilterableProductTable/SearchBar/index.tsx @@ -0,0 +1,7 @@ +export default function SearchTable(){ + return ( +
+

Search Table

+
+ ) +} \ No newline at end of file diff --git a/src/components/FilterableProductTable/index.tsx b/src/components/FilterableProductTable/index.tsx new file mode 100644 index 0000000..a8fc599 --- /dev/null +++ b/src/components/FilterableProductTable/index.tsx @@ -0,0 +1,29 @@ +import Search from "antd/es/transfer/search"; +import ProductTable from "./ProductTable"; +import SearchTable from "./SearchBar"; + +interface IProduct{ + category: string; + price: string; + stocked: boolean; + name: string; +} + +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 ( +
+

FilterableProductTable

+ + +
+ ) +} \ No newline at end of file From 57e61f801f643716b0071f80bdb6bdbe306b3918 Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Mon, 23 Sep 2024 16:52:03 +0530 Subject: [PATCH 2/9] Fix: codefactor code-smells --- src/App.tsx | 1 - src/components/FilterableProductTable/index.tsx | 17 ++++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b0c0950..b166f63 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,5 @@ import React from 'react'; import './App.css'; -import Board from './components/TicTacToe/Board'; import FilterableProductTable from './components/FilterableProductTable'; function App() { diff --git a/src/components/FilterableProductTable/index.tsx b/src/components/FilterableProductTable/index.tsx index a8fc599..61be5a9 100644 --- a/src/components/FilterableProductTable/index.tsx +++ b/src/components/FilterableProductTable/index.tsx @@ -1,4 +1,3 @@ -import Search from "antd/es/transfer/search"; import ProductTable from "./ProductTable"; import SearchTable from "./SearchBar"; @@ -9,14 +8,14 @@ interface IProduct{ name: string; } -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" } - ]; +// 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 ( From aa7e96d3feae9d7329241bd63214d0d5be3611f5 Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Mon, 23 Sep 2024 16:52:55 +0530 Subject: [PATCH 3/9] Fix: codefactor code-smell --- src/components/FilterableProductTable/index.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/FilterableProductTable/index.tsx b/src/components/FilterableProductTable/index.tsx index 61be5a9..3550d0c 100644 --- a/src/components/FilterableProductTable/index.tsx +++ b/src/components/FilterableProductTable/index.tsx @@ -1,12 +1,12 @@ import ProductTable from "./ProductTable"; import SearchTable from "./SearchBar"; -interface IProduct{ - category: string; - price: string; - stocked: boolean; - name: string; -} +// interface IProduct{ +// category: string; +// price: string; +// stocked: boolean; +// name: string; +// } // const ProductData: IProduct[] = [ // { category: "Fruits", price: "$1", stocked: true, name: "Apple" }, From a8d501c10d7fafb1efd57a12139c3978e09162c7 Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Wed, 25 Sep 2024 23:49:45 +0530 Subject: [PATCH 4/9] Feat: Static verison of the product table --- package.json | 4 ++ src/App.css | 2 +- src/App.tsx | 28 +++++------- .../ProductTable/ProductCategoryRow/index.tsx | 16 ++++++- .../ProductTable/ProductRow/index.tsx | 19 ++++++-- .../ProductTable/index.tsx | 39 ++++++++++++++-- .../SearchBar/index.tsx | 44 ++++++++++++++++++- .../FilterableProductTable/index.tsx | 35 ++++++++------- src/components/ProfileCard/index.tsx | 3 -- src/index.css | 5 +++ yarn.lock | 17 +++++++ 11 files changed, 164 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 4e744b1..fc6d64f 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "antd": "^5.20.6", + "lodash-es": "^4.17.21", "react": "^18.3.1", "react-dom": "^18.3.1", "react-scripts": "5.0.1", @@ -43,5 +44,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12" } } diff --git a/src/App.css b/src/App.css index 74b5e05..3f478cf 100644 --- a/src/App.css +++ b/src/App.css @@ -1,5 +1,5 @@ .App { - text-align: center; + /* text-align: center; */ } .App-logo { diff --git a/src/App.tsx b/src/App.tsx index b166f63..6d35b51 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,25 +1,21 @@ -import React from 'react'; import './App.css'; +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 (
- {/*

Welcome to my App!

- -
- - -
*/} - {/* */} - {/* */} - + + + {/* + + + */} +
); } diff --git a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx index d493fe9..45b2d8b 100644 --- a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx @@ -1,7 +1,19 @@ -export default function ProductCategoryRow(){ +export default function ProductCategoryRow({category}: {category: string}){ return (
-

Product Category Row

+
+ {category} + Name + Price + In Stock +
) } \ No newline at end of file diff --git a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx index 31d0262..8624eb3 100644 --- a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx @@ -1,7 +1,20 @@ -export default function ProductRow(){ +import { IProduct } from "../.."; + +export default function ProductRow({product}: {product: IProduct}){ + console.log(product); return ( -
-

Product Row

+
+ {product.category} + {product.name} + {product.price} + {product.stocked ? "True" : "False"}
) } \ No newline at end of file diff --git a/src/components/FilterableProductTable/ProductTable/index.tsx b/src/components/FilterableProductTable/ProductTable/index.tsx index 8c54f8f..f264c47 100644 --- a/src/components/FilterableProductTable/ProductTable/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/index.tsx @@ -1,12 +1,43 @@ +import { uniq } from "lodash-es"; +import { IProduct } from ".."; import ProductCategoryRow from "./ProductCategoryRow"; import ProductRow from "./ProductRow"; -export default function ProductTable(){ +interface IProductCategoryRow { + categoryComponent: React.ReactElement; + productComponents: React.ReactElement[]; +} + + +export default function ProductTable({ProductData}: {ProductData: IProduct[]}){ + + const categories: string[] = ProductData.map((product) => product.category); + const uniqCategories: string[] = uniq(categories); + + const productsByCategory = new Map(); + + uniqCategories.forEach((category) => { + productsByCategory.set(category, ProductData.filter((product) => product.category === category)); + }); + + let productCaregoriesComponents: Map = new Map(); + + const tableRows: JSX.Element[] = []; + + productsByCategory.forEach((value, key) => { + productCaregoriesComponents.set(key, { + categoryComponent: , + productComponents: value.map((product) => ) + }); + tableRows.push(); + tableRows.push(...value.map((product) => )); + }) + + console.log("hellooo", Object.fromEntries(productCaregoriesComponents)); + return (
-

Product Table

- - + {tableRows}
) } \ No newline at end of file diff --git a/src/components/FilterableProductTable/SearchBar/index.tsx b/src/components/FilterableProductTable/SearchBar/index.tsx index b40a43f..d05fe93 100644 --- a/src/components/FilterableProductTable/SearchBar/index.tsx +++ b/src/components/FilterableProductTable/SearchBar/index.tsx @@ -1,7 +1,47 @@ +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'] = (e) => { + console.log(checked); + } + + const OnSearchInput: InputProps['onInput'] = (e: any) => { + console.log(e.target.value); + setSearchVal(e.target.value); + } + return ( -
-

Search Table

+
+
+ + +
+ Only show products in stock
) } \ No newline at end of file diff --git a/src/components/FilterableProductTable/index.tsx b/src/components/FilterableProductTable/index.tsx index 3550d0c..ccb1e33 100644 --- a/src/components/FilterableProductTable/index.tsx +++ b/src/components/FilterableProductTable/index.tsx @@ -1,28 +1,29 @@ import ProductTable from "./ProductTable"; import SearchTable from "./SearchBar"; -// interface IProduct{ -// category: string; -// price: string; -// stocked: boolean; -// name: string; -// } +export interface IProduct{ + category: string; + price: string; + stocked: boolean; + name: string; +} -// 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" } -// ]; +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 ( -
-

FilterableProductTable

+
- +
) } \ No newline at end of file diff --git a/src/components/ProfileCard/index.tsx b/src/components/ProfileCard/index.tsx index 78a6f24..a977c54 100644 --- a/src/components/ProfileCard/index.tsx +++ b/src/components/ProfileCard/index.tsx @@ -1,6 +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", diff --git a/src/index.css b/src/index.css index ec2585e..b992ff9 100644 --- a/src/index.css +++ b/src/index.css @@ -11,3 +11,8 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } +/* html, body { + padding: 0; + margin: 0; + background: #000; +} */ \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 5d888b8..5477777 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2242,6 +2242,18 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/lodash-es@^4.17.12": + version "4.17.12" + resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.12.tgz#65f6d1e5f80539aa7cfbfc962de5def0cf4f341b" + integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*": + version "4.17.9" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.9.tgz#0dc4902c229f6b8e2ac5456522104d7b1a230290" + integrity sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w== + "@types/mime@^1": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" @@ -6721,6 +6733,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" From 4d9093984935bd43999b3afcb4d233af974a31d2 Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Thu, 26 Sep 2024 01:24:46 +0530 Subject: [PATCH 5/9] Chore: Setup prettier --- .github/workflows/build.yml | 43 +++--- .prettierignore | 4 + .prettierrc.json | 6 + package.json | 101 +++++++------- public/index.html | 43 +++--- public/manifest.json | 46 +++---- src/App.css | 42 +++--- src/App.test.tsx | 16 +-- src/App.tsx | 32 ++--- .../ProductTable/ProductCategoryRow/index.tsx | 40 ++++-- .../ProductTable/ProductRow/index.tsx | 42 +++--- .../ProductTable/index.tsx | 62 +++++---- .../SearchBar/index.tsx | 72 +++++----- .../FilterableProductTable/index.tsx | 32 +++-- src/components/MyButton/index.tsx | 20 +-- src/components/ProfileCard/index.tsx | 61 +++++---- src/components/TicTacToe/Board/index.tsx | 129 +++++++++++------- src/components/TicTacToe/Square/index.tsx | 19 ++- src/components/TicTacToe/Square/styles.css | 40 +++--- src/components/TicTacToe/index.tsx | 10 +- src/index.css | 18 +-- src/index.tsx | 26 ++-- src/reportWebVitals.ts | 26 ++-- src/setupTests.ts | 2 +- tsconfig.json | 42 +++--- yarn.lock | 5 + 26 files changed, 538 insertions(+), 441 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e8f280..f6e3ca2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,28 +4,27 @@ name: Build on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] + push: + branches: ["main"] + pull_request: + branches: ["main"] jobs: - build: + build: + runs-on: ubuntu-latest - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Get Node version from package.json - id: get-version - run: echo ::set-output name=node::$(jq -r .engines.node ./package.json) - - name: Print node version - run: echo ${{ steps.get-version.outputs.node }} - - name: Use Node.js ${{ steps.get-version.outputs.node }} - uses: actions/setup-node@v4 - with: - node-version: ${{ steps.get-version.outputs.node }} - cache: 'yarn' - - run: yarn install - - run: yarn build - # - run: yarn test + steps: + - uses: actions/checkout@v4 + - name: Get Node version from package.json + id: get-version + run: echo ::set-output name=node::$(jq -r .engines.node ./package.json) + - name: Print node version + run: echo ${{ steps.get-version.outputs.node }} + - name: Use Node.js ${{ steps.get-version.outputs.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ steps.get-version.outputs.node }} + cache: "yarn" + - run: yarn install + - run: yarn build + # - run: yarn test diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ebf20f1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +node_modules +# Ignore artifacts: +build +coverage \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..87cf9d6 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 4, + "semi": false, + "singleQuote": false +} diff --git a/package.json b/package.json index fc6d64f..ea3d688 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,54 @@ { - "name": "react-typescript", - "version": "0.1.0", - "private": true, - "engines": { - "node": "20" - }, - "dependencies": { - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^13.0.0", - "@testing-library/user-event": "^13.2.1", - "@types/jest": "^27.0.1", - "@types/node": "^16.7.13", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "antd": "^5.20.6", - "lodash-es": "^4.17.21", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-scripts": "5.0.1", - "typescript": "^4.4.2", - "web-vitals": "^2.1.0" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "@types/lodash-es": "^4.17.12" - } + "name": "react-typescript", + "version": "0.1.0", + "private": true, + "engines": { + "node": "20" + }, + "dependencies": { + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^13.0.0", + "@testing-library/user-event": "^13.2.1", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "antd": "^5.20.6", + "lodash-es": "^4.17.21", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-scripts": "5.0.1", + "typescript": "^4.4.2", + "web-vitals": "^2.1.0" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject", + "reformat-react": "prettier --write 'src/**/*.{ts,tsx,js,jsx,json,css,scss,md}'", + "reformat-all": "prettier --write ." + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12", + "prettier": "^3.3.3" + } } diff --git a/public/index.html b/public/index.html index aa069f2..e57c7a8 100644 --- a/public/index.html +++ b/public/index.html @@ -1,21 +1,21 @@ - + - - - - - - - - - - - React App - - - -
- - + --> diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..f01493f 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/src/App.css b/src/App.css index 3f478cf..6f73220 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,38 @@ .App { - /* text-align: center; */ + /* text-align: center; */ } .App-logo { - height: 40vmin; - pointer-events: none; + height: 40vmin; + pointer-events: none; } @media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } + .App-logo { + animation: App-logo-spin infinite 20s linear; + } } .App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; } .App-link { - color: #61dafb; + color: #61dafb; } @keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } } diff --git a/src/App.test.tsx b/src/App.test.tsx index 2a68616..ff957b7 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from "react" +import { render, screen } from "@testing-library/react" +import App from "./App" -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); +test("renders learn react link", () => { + render() + const linkElement = screen.getByText(/learn react/i) + expect(linkElement).toBeInTheDocument() +}) diff --git a/src/App.tsx b/src/App.tsx index 6d35b51..80547d7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,23 +1,23 @@ -import './App.css'; -import { ConfigProvider, theme } from 'antd'; -import FilterableProductTable from './components/FilterableProductTable'; +import "./App.css" +import { ConfigProvider, theme } from "antd" +import FilterableProductTable from "./components/FilterableProductTable" function App() { - return ( -
- - - {/* + return ( +
+ + + {/* */} - -
- ); +
+
+ ) } -export default App; +export default App diff --git a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx index 45b2d8b..a1bc69c 100644 --- a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx @@ -1,19 +1,29 @@ -export default function ProductCategoryRow({category}: {category: string}){ +export default function ProductCategoryRow({ category }: { category: string }) { return (
-
- {category} - Name - Price - In Stock -
+
+ + {category} + + + Name + + + Price + + + In Stock + +
) -} \ No newline at end of file +} diff --git a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx index 8624eb3..9601234 100644 --- a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx @@ -1,20 +1,30 @@ -import { IProduct } from "../.."; +import { IProduct } from "../.." -export default function ProductRow({product}: {product: IProduct}){ - console.log(product); +export default function ProductRow({ product }: { product: IProduct }) { + console.log(product) return ( -
- {product.category} - {product.name} - {product.price} - {product.stocked ? "True" : "False"} +
+ + {product.category} + + + {product.name} + + + {product.price} + + + {product.stocked ? "True" : "False"} +
) -} \ No newline at end of file +} diff --git a/src/components/FilterableProductTable/ProductTable/index.tsx b/src/components/FilterableProductTable/ProductTable/index.tsx index f264c47..06bea4d 100644 --- a/src/components/FilterableProductTable/ProductTable/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/index.tsx @@ -1,43 +1,51 @@ -import { uniq } from "lodash-es"; -import { IProduct } from ".."; -import ProductCategoryRow from "./ProductCategoryRow"; -import ProductRow from "./ProductRow"; +import { uniq } from "lodash-es" +import { IProduct } from ".." +import ProductCategoryRow from "./ProductCategoryRow" +import ProductRow from "./ProductRow" interface IProductCategoryRow { - categoryComponent: React.ReactElement; - productComponents: React.ReactElement[]; + categoryComponent: React.ReactElement + productComponents: React.ReactElement[] } +export default function ProductTable({ + ProductData, +}: { + ProductData: IProduct[] +}) { + const categories: string[] = ProductData.map((product) => product.category) + const uniqCategories: string[] = uniq(categories) -export default function ProductTable({ProductData}: {ProductData: IProduct[]}){ - - const categories: string[] = ProductData.map((product) => product.category); - const uniqCategories: string[] = uniq(categories); - - const productsByCategory = new Map(); + const productsByCategory = new Map() uniqCategories.forEach((category) => { - productsByCategory.set(category, ProductData.filter((product) => product.category === category)); - }); + productsByCategory.set( + category, + ProductData.filter((product) => product.category === category) + ) + }) - let productCaregoriesComponents: Map = new Map(); + let productCaregoriesComponents: Map = new Map< + string, + IProductCategoryRow + >() - const tableRows: JSX.Element[] = []; + const tableRows: JSX.Element[] = [] productsByCategory.forEach((value, key) => { productCaregoriesComponents.set(key, { categoryComponent: , - productComponents: value.map((product) => ) - }); - tableRows.push(); - tableRows.push(...value.map((product) => )); + productComponents: value.map((product) => ( + + )), + }) + tableRows.push() + tableRows.push( + ...value.map((product) => ) + ) }) - console.log("hellooo", Object.fromEntries(productCaregoriesComponents)); + console.log("hellooo", Object.fromEntries(productCaregoriesComponents)) - return ( -
- {tableRows} -
- ) -} \ No newline at end of file + return
{tableRows}
+} diff --git a/src/components/FilterableProductTable/SearchBar/index.tsx b/src/components/FilterableProductTable/SearchBar/index.tsx index d05fe93..3c6b6c7 100644 --- a/src/components/FilterableProductTable/SearchBar/index.tsx +++ b/src/components/FilterableProductTable/SearchBar/index.tsx @@ -1,47 +1,57 @@ -import { Button, Checkbox, Input } from "antd"; -import { useState } from "react"; -import type { ButtonProps, CheckboxProps, InputProps } from "antd"; +import { Button, Checkbox, Input } from "antd" +import { useState } from "react" +import type { ButtonProps, CheckboxProps, InputProps } from "antd" -export default function SearchTable(){ +export default function SearchTable() { + const [checked, setChecked] = useState(false) - const [checked, setChecked] = useState(false); + const [searchVal, setSearchVal] = useState("") - const [searchVal, setSearchVal] = useState(""); - - const onChange: CheckboxProps['onChange'] = (e) => { - setChecked(e.target.checked); + const onChange: CheckboxProps["onChange"] = (e) => { + setChecked(e.target.checked) } - const OnSearchClicked: ButtonProps['onClick'] = (e) => { - console.log(checked); + const OnSearchClicked: ButtonProps["onClick"] = (e) => { + console.log(checked) } - const OnSearchInput: InputProps['onInput'] = (e: any) => { - console.log(e.target.value); - setSearchVal(e.target.value); + const OnSearchInput: InputProps["onInput"] = (e: any) => { + console.log(e.target.value) + setSearchVal(e.target.value) } return ( -
-
- - + }} + > +
+ +
- Only show products in stock + + Only show products in stock +
) -} \ No newline at end of file +} diff --git a/src/components/FilterableProductTable/index.tsx b/src/components/FilterableProductTable/index.tsx index ccb1e33..f458ca5 100644 --- a/src/components/FilterableProductTable/index.tsx +++ b/src/components/FilterableProductTable/index.tsx @@ -1,11 +1,11 @@ -import ProductTable from "./ProductTable"; -import SearchTable from "./SearchBar"; +import ProductTable from "./ProductTable" +import SearchTable from "./SearchBar" -export interface IProduct{ - category: string; - price: string; - stocked: boolean; - name: string; +export interface IProduct { + category: string + price: string + stocked: boolean + name: string } const ProductData: IProduct[] = [ @@ -14,16 +14,18 @@ const ProductData: IProduct[] = [ { 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" } - ]; + { category: "Vegetables", price: "$1", stocked: true, name: "Peas" }, +] -export default function FilterableProductTable(){ +export default function FilterableProductTable() { return ( -
+
- +
) -} \ No newline at end of file +} diff --git a/src/components/MyButton/index.tsx b/src/components/MyButton/index.tsx index 5a01a69..c345605 100644 --- a/src/components/MyButton/index.tsx +++ b/src/components/MyButton/index.tsx @@ -1,20 +1,24 @@ -import {Button} from 'antd'; -import { MouseEventHandler } from 'react'; +import { Button } from "antd" +import { MouseEventHandler } from "react" // function handleClick(count: number, setCount: Function){ // alert("Button Clicked"); // setCount(count+1); // } -export default function MyButton({count, OnClick}: {count: number, OnClick: MouseEventHandler}){ +export default function MyButton({ + count, + OnClick, +}: { + count: number + OnClick: MouseEventHandler +}) { // const [count, setCount] = useState(0); - console.log("Rendering MyButton"); // why is this being called twice? + console.log("Rendering MyButton") // why is this being called twice? // function handleClick(){ // setCount(count+1); // console.log(`Button clicked ${count} times`); // } - return( - - ) -} \ No newline at end of file + return +} diff --git a/src/components/ProfileCard/index.tsx b/src/components/ProfileCard/index.tsx index a977c54..e91525f 100644 --- a/src/components/ProfileCard/index.tsx +++ b/src/components/ProfileCard/index.tsx @@ -2,37 +2,50 @@ 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", imageSize: 90, - altDesc: "Iron Man profile photo" + altDesc: "Iron Man profile photo", } interface IProduct { - title: string; - id: number; - isFruit: boolean; + title: string + id: number + isFruit: boolean } const products: IProduct[] = [ - { title: 'Cabbage', isFruit: false, id: 1 }, - { title: 'Garlic', isFruit: false, id: 2 }, - { title: 'Apple', isFruit: true, id: 3 }, -]; + { title: "Cabbage", isFruit: false, id: 1 }, + { title: "Garlic", isFruit: false, id: 2 }, + { title: "Apple", isFruit: true, id: 3 }, +] export default function ProfileCard() { - let title: JSX.Element | null; - let image: JSX.Element | null; - let productsList: JSX.Element[] = products.map((product) =>
  • {product.title}
  • ); + let title: JSX.Element | null + let image: JSX.Element | null + let productsList: JSX.Element[] = products.map((product) => ( +
  • + {product.title} +
  • + )) if (user.name.length !== 0) { - title =

    {user.name}

    ; - image = {user.altDesc}; - - } - else { - title =

    John Doe

    ; - image = Profile; + title =

    {user.name}

    + image = ( + {user.altDesc} + ) + } else { + title =

    John Doe

    + image = ( + Profile + ) } return (
    @@ -40,5 +53,5 @@ export default function ProfileCard() { {image}
      {productsList}
    - ); -} \ No newline at end of file + ) +} diff --git a/src/components/TicTacToe/Board/index.tsx b/src/components/TicTacToe/Board/index.tsx index 7e663d9..ba92159 100644 --- a/src/components/TicTacToe/Board/index.tsx +++ b/src/components/TicTacToe/Board/index.tsx @@ -1,15 +1,17 @@ -import { useState } from "react"; -import Square from "../Square"; -import { Button } from "antd"; +import { useState } from "react" +import Square from "../Square" +import { Button } from "antd" -export default function Board(){ - const [currentMove, setCurrentMove] = useState(0); +export default function Board() { + const [currentMove, setCurrentMove] = useState(0) - const IsXNext = currentMove % 2 === 0; + const IsXNext = currentMove % 2 === 0 - const [history, setHistory] = useState>>([Array(9).fill(null)]); + const [history, setHistory] = useState>>([ + Array(9).fill(null), + ]) - const currentState = history[currentMove]; + const currentState = history[currentMove] const calculateWinner = () => { const lines = [ @@ -20,47 +22,49 @@ export default function Board(){ [1, 4, 7], [2, 5, 8], [0, 4, 8], - [2, 4, 6] - ]; - - for(let i = 0; i { - const squaresCopy = currentState.slice(); - if(squaresCopy[i] || calculateWinner()){ - return; + const squaresCopy = currentState.slice() + if (squaresCopy[i] || calculateWinner()) { + return } - squaresCopy[i] = IsXNext ? 'X' : 'O'; - const currentHistory = history.slice(0, currentMove+1); - currentHistory.push(squaresCopy); - setHistory(currentHistory); - setCurrentMove(currentMove + 1); + squaresCopy[i] = IsXNext ? "X" : "O" + const currentHistory = history.slice(0, currentMove + 1) + currentHistory.push(squaresCopy) + setHistory(currentHistory) + setCurrentMove(currentMove + 1) } const status = () => { - const winner = calculateWinner(); - if(winner){ - return `Winner is ${winner}`; + const winner = calculateWinner() + if (winner) { + return `Winner is ${winner}` } } const jumpTo = (step: number) => { - setCurrentMove(step); + setCurrentMove(step) } const moves = history.map((squares, move) => { - const desc = move ? "Go to move #" + move : "Go to game start"; + const desc = move ? "Go to move #" + move : "Go to game start" return (
  • @@ -70,26 +74,51 @@ export default function Board(){ return ( <> -
    - handleClick(0)} /> - handleClick(1)} /> - handleClick(2)} /> +
    + handleClick(0)} + /> + handleClick(1)} + /> + handleClick(2)} + />
    -
    - handleClick(3)} /> - handleClick(4)} /> - handleClick(5)} /> +
    + handleClick(3)} + /> + handleClick(4)} + /> + handleClick(5)} + />
    -
    - handleClick(6)} /> - handleClick(7)} /> - handleClick(8)} /> +
    + handleClick(6)} + /> + handleClick(7)} + /> + handleClick(8)} + />
    -
    {status()}
    -

    Game Moves:

    -
      - {moves} -
    +
    {status()}
    +

    Game Moves:

    +
      {moves}
    ) -} \ No newline at end of file +} diff --git a/src/components/TicTacToe/Square/index.tsx b/src/components/TicTacToe/Square/index.tsx index b66319c..a6a23bf 100644 --- a/src/components/TicTacToe/Square/index.tsx +++ b/src/components/TicTacToe/Square/index.tsx @@ -1,9 +1,16 @@ -import { Button } from 'antd'; -import { MouseEventHandler } from 'react'; +import { Button } from "antd" +import { MouseEventHandler } from "react" -export default function Square({value, OnSquareClicked}: {value: String | null, OnSquareClicked: MouseEventHandler}){ - +export default function Square({ + value, + OnSquareClicked, +}: { + value: String | null + OnSquareClicked: MouseEventHandler +}) { return ( - + ) -} \ No newline at end of file +} diff --git a/src/components/TicTacToe/Square/styles.css b/src/components/TicTacToe/Square/styles.css index efa939a..f911cb9 100644 --- a/src/components/TicTacToe/Square/styles.css +++ b/src/components/TicTacToe/Square/styles.css @@ -1,26 +1,26 @@ .square { - background: #fff; - border: 1px solid #999; - float: left; - font-size: 24px; - font-weight: bold; - line-height: 34px; - height: 34px; - margin-right: -1px; - margin-top: -1px; - padding: 0; - text-align: center; - width: 34px; + background: #fff; + border: 1px solid #999; + float: left; + font-size: 24px; + font-weight: bold; + line-height: 34px; + height: 34px; + margin-right: -1px; + margin-top: -1px; + padding: 0; + text-align: center; + width: 34px; } .board-row:after { - clear: both; - content: ''; - display: table; + clear: both; + content: ""; + display: table; } -.board-row{ - display: flex; - flex-direction: row; - justify-content: center; -} \ No newline at end of file +.board-row { + display: flex; + flex-direction: row; + justify-content: center; +} diff --git a/src/components/TicTacToe/index.tsx b/src/components/TicTacToe/index.tsx index 6ca73fb..a6d7ffe 100644 --- a/src/components/TicTacToe/index.tsx +++ b/src/components/TicTacToe/index.tsx @@ -1,9 +1,3 @@ export default function TicTacToe() { - return ( - <> - - - - - ) -} \ No newline at end of file + return <> +} diff --git a/src/index.css b/src/index.css index b992ff9..dca8484 100644 --- a/src/index.css +++ b/src/index.css @@ -1,18 +1,18 @@ body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", + "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", + "Helvetica Neue", sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; } /* html, body { padding: 0; margin: 0; background: #000; -} */ \ No newline at end of file +} */ diff --git a/src/index.tsx b/src/index.tsx index dc10ced..0121158 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,20 +1,18 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import './components/TicTacToe/Square/styles.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react" +import ReactDOM from "react-dom/client" +import "./index.css" +import "./components/TicTacToe/Square/styles.css" +import App from "./App" +import reportWebVitals from "./reportWebVitals" -const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement -); +const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement) root.render( - - - -); + + + +) // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); +reportWebVitals() diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts index 49a2a16..b69e5d2 100644 --- a/src/reportWebVitals.ts +++ b/src/reportWebVitals.ts @@ -1,15 +1,17 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from "web-vitals" const reportWebVitals = (onPerfEntry?: ReportHandler) => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; + if (onPerfEntry && onPerfEntry instanceof Function) { + import("web-vitals").then( + ({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry) + getFID(onPerfEntry) + getFCP(onPerfEntry) + getLCP(onPerfEntry) + getTTFB(onPerfEntry) + } + ) + } +} -export default reportWebVitals; +export default reportWebVitals diff --git a/src/setupTests.ts b/src/setupTests.ts index 8f2609b..6a0fd12 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import "@testing-library/jest-dom" diff --git a/tsconfig.json b/tsconfig.json index a273b0c..c0555cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,20 @@ { - "compilerOptions": { - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx" - }, - "include": [ - "src" - ] + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"] } diff --git a/yarn.lock b/yarn.lock index 5477777..d1c56d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7978,6 +7978,11 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== +prettier@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" From 3519b615cd207afa379ff74ee887c17789867b9b Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Thu, 26 Sep 2024 01:28:58 +0530 Subject: [PATCH 6/9] Chore: check for formatting using prettier in github action workflow --- .github/workflows/build.yml | 1 + src/App.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6e3ca2..2dbc5e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,4 +27,5 @@ jobs: cache: "yarn" - run: yarn install - run: yarn build + - run: yarn prettier -c . # - run: yarn test diff --git a/src/App.tsx b/src/App.tsx index 80547d7..3b8823a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,7 @@ import FilterableProductTable from "./components/FilterableProductTable" function App() { return ( -
    +
    Date: Thu, 26 Sep 2024 01:30:54 +0530 Subject: [PATCH 7/9] Chore: reformat styling --- src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 3b8823a..80547d7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,7 +4,7 @@ import FilterableProductTable from "./components/FilterableProductTable" function App() { return ( -
    +
    Date: Thu, 26 Sep 2024 04:11:16 +0530 Subject: [PATCH 8/9] Style: lint --- .github/workflows/build.yml | 2 +- eslint.config.mjs | 1 + package.json | 3 +- src/App.tsx | 5 +- .../ProductTable/ProductCategoryRow/index.tsx | 2 +- .../ProductTable/ProductRow/index.tsx | 6 +-- .../ProductTable/index.tsx | 52 +++++++++---------- .../SearchBar/index.tsx | 33 +++++++----- .../FilterableProductTable/index.tsx | 16 ++---- .../FilterableProductTable/model.ts | 6 +++ tsconfig.json | 3 +- 11 files changed, 68 insertions(+), 61 deletions(-) create mode 100644 src/components/FilterableProductTable/model.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2dbc5e9..6ac3547 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,5 +27,5 @@ jobs: cache: "yarn" - run: yarn install - run: yarn build - - run: yarn prettier -c . + - run: yarn reformat:check # - run: yarn test diff --git a/eslint.config.mjs b/eslint.config.mjs index 4d4fafe..38b8bb7 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -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", }, }, ]; diff --git a/package.json b/package.json index 4421291..c53f752 100644 --- a/package.json +++ b/package.json @@ -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": [ diff --git a/src/App.tsx b/src/App.tsx index c96e8b9..1e29a49 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,6 @@ -import "./App.css" -import { ConfigProvider, theme } from "antd" -import FilterableProductTable from "./components/FilterableProductTable" import "./App.css"; +import { ConfigProvider, theme } from "antd"; +import FilterableProductTable from "./components/FilterableProductTable"; function App() { return ( diff --git a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx index a1bc69c..ae39d00 100644 --- a/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/ProductCategoryRow/index.tsx @@ -25,5 +25,5 @@ export default function ProductCategoryRow({ category }: { category: string }) {
    - ) + ); } diff --git a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx index 9601234..b1ddf26 100644 --- a/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/ProductRow/index.tsx @@ -1,7 +1,7 @@ -import { IProduct } from "../.." +import { IProduct } from "../../model"; export default function ProductRow({ product }: { product: IProduct }) { - console.log(product) + console.log(product); return (
    - ) + ); } diff --git a/src/components/FilterableProductTable/ProductTable/index.tsx b/src/components/FilterableProductTable/ProductTable/index.tsx index 06bea4d..9bd55ed 100644 --- a/src/components/FilterableProductTable/ProductTable/index.tsx +++ b/src/components/FilterableProductTable/ProductTable/index.tsx @@ -1,51 +1,51 @@ -import { uniq } from "lodash-es" -import { IProduct } from ".." -import ProductCategoryRow from "./ProductCategoryRow" -import ProductRow from "./ProductRow" +import { uniq } from "lodash-es"; +import ProductCategoryRow from "./ProductCategoryRow"; +import ProductRow from "./ProductRow"; +import { IProduct } from "../model"; interface IProductCategoryRow { - categoryComponent: React.ReactElement - productComponents: React.ReactElement[] + categoryComponent: React.ReactElement; + productComponents: React.ReactElement[]; } export default function ProductTable({ ProductData, }: { - ProductData: IProduct[] + ProductData: IProduct[]; }) { - const categories: string[] = ProductData.map((product) => product.category) - const uniqCategories: string[] = uniq(categories) + const categories: string[] = ProductData.map((product) => product.category); + const uniqCategories: string[] = uniq(categories); - const productsByCategory = new Map() + const productsByCategory = new Map(); uniqCategories.forEach((category) => { productsByCategory.set( category, ProductData.filter((product) => product.category === category) - ) - }) + ); + }); - let productCaregoriesComponents: Map = new Map< - string, - IProductCategoryRow - >() + const productCaregoriesComponents: Map = + new Map(); - const tableRows: JSX.Element[] = [] + const tableRows: JSX.Element[] = []; productsByCategory.forEach((value, key) => { productCaregoriesComponents.set(key, { categoryComponent: , - productComponents: value.map((product) => ( - + productComponents: value.map((product, index) => ( + )), - }) - tableRows.push() + }); + tableRows.push(); tableRows.push( - ...value.map((product) => ) - ) - }) + ...value.map((product, index) => ( + + )) + ); + }); - console.log("hellooo", Object.fromEntries(productCaregoriesComponents)) + console.log("hellooo", Object.fromEntries(productCaregoriesComponents)); - return
    {tableRows}
    + return
    {tableRows}
    ; } diff --git a/src/components/FilterableProductTable/SearchBar/index.tsx b/src/components/FilterableProductTable/SearchBar/index.tsx index 3c6b6c7..22fa67b 100644 --- a/src/components/FilterableProductTable/SearchBar/index.tsx +++ b/src/components/FilterableProductTable/SearchBar/index.tsx @@ -1,24 +1,29 @@ -import { Button, Checkbox, Input } from "antd" -import { useState } from "react" -import type { ButtonProps, CheckboxProps, InputProps } from "antd" +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 [checked, setChecked] = useState(false); - const [searchVal, setSearchVal] = useState("") + const [searchVal, setSearchVal] = useState(""); const onChange: CheckboxProps["onChange"] = (e) => { - setChecked(e.target.checked) - } + setChecked(e.target.checked); + }; - const OnSearchClicked: ButtonProps["onClick"] = (e) => { - console.log(checked) - } + const OnSearchClicked: ButtonProps["onClick"] = () => { + console.log(checked); + }; + /** + * Handles the input event for the search bar. + * + * @param e - The input event object of type React.FormEvent. + */ const OnSearchInput: InputProps["onInput"] = (e: any) => { - console.log(e.target.value) - setSearchVal(e.target.value) - } + console.log(e.target.value); + setSearchVal(e.target.value); + }; return (
    - ) + ); } diff --git a/src/components/FilterableProductTable/index.tsx b/src/components/FilterableProductTable/index.tsx index f458ca5..0b211ec 100644 --- a/src/components/FilterableProductTable/index.tsx +++ b/src/components/FilterableProductTable/index.tsx @@ -1,12 +1,6 @@ -import ProductTable from "./ProductTable" -import SearchTable from "./SearchBar" - -export interface IProduct { - category: string - price: string - stocked: boolean - name: string -} +import { IProduct } from "./model"; +import ProductTable from "./ProductTable"; +import SearchTable from "./SearchBar"; const ProductData: IProduct[] = [ { category: "Fruits", price: "$1", stocked: true, name: "Apple" }, @@ -15,7 +9,7 @@ const ProductData: IProduct[] = [ { 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 ( @@ -27,5 +21,5 @@ export default function FilterableProductTable() {
    - ) + ); } diff --git a/src/components/FilterableProductTable/model.ts b/src/components/FilterableProductTable/model.ts new file mode 100644 index 0000000..0f72e08 --- /dev/null +++ b/src/components/FilterableProductTable/model.ts @@ -0,0 +1,6 @@ +export interface IProduct { + category: string; + price: string; + stocked: boolean; + name: string; +} diff --git a/tsconfig.json b/tsconfig.json index c0555cb..1696f33 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,8 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + "baseUrl": "./" }, "include": ["src"] } From 9d3ccb31f970af6b59e072997f18dff56c5a39ac Mon Sep 17 00:00:00 2001 From: Abhijeet Jain Date: Fri, 27 Sep 2024 03:37:43 +0530 Subject: [PATCH 9/9] clean up --- src/App.tsx | 4 ---- src/components/FilterableProductTable/SearchBar/index.tsx | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 1e29a49..2a3aa38 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,10 +11,6 @@ function App() { }} > - {/* - - - */}
    ); diff --git a/src/components/FilterableProductTable/SearchBar/index.tsx b/src/components/FilterableProductTable/SearchBar/index.tsx index 22fa67b..ed8fc88 100644 --- a/src/components/FilterableProductTable/SearchBar/index.tsx +++ b/src/components/FilterableProductTable/SearchBar/index.tsx @@ -15,11 +15,6 @@ export default function SearchTable() { console.log(checked); }; - /** - * Handles the input event for the search bar. - * - * @param e - The input event object of type React.FormEvent. - */ const OnSearchInput: InputProps["onInput"] = (e: any) => { console.log(e.target.value); setSearchVal(e.target.value);