diff --git a/src/App.css b/src/App.css index 74b5e05..57fcfc3 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,58 @@ +/* Global reset */ +* { + box-sizing: border-box; +} + +/* App container */ .App { + max-width: 700px; + margin: 40px auto; + padding: 20px; + font-family: Arial, Helvetica, sans-serif; + background-color: #f9f9f9; +} + +/* Title */ +h1 { text-align: center; + margin-bottom: 20px; +} + +/* Search bar */ +input[type="text"] { + width: 100%; + padding: 8px; + margin-bottom: 10px; + font-size: 14px; } -.App-logo { - height: 40vmin; - pointer-events: none; +/* Checkbox area */ +label { + font-size: 14px; } -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } +/* Table */ +table { + width: 100%; + border-collapse: collapse; + margin-top: 20px; + background-color: white; } -.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; +/* Table header */ +th { + text-align: left; + padding: 8px; + border-bottom: 2px solid #ddd; } -.App-link { - color: #61dafb; +/* Table rows */ +td { + padding: 8px; + border-bottom: 1px solid #eee; } -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +/* Row hover effect */ +tbody tr:hover { + background-color: #f1f1f1; } diff --git a/src/App.js b/src/App.js index 3784575..7d47767 100644 --- a/src/App.js +++ b/src/App.js @@ -1,25 +1,17 @@ -import logo from './logo.svg'; -import './App.css'; + +// src/App.js + +import "./App.css"; + +import ProductsPage from './components/ProductsPage'; function App() { + return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
+
+
); } -export default App; +export default App; diff --git a/src/components/ProductRow.js b/src/components/ProductRow.js new file mode 100644 index 0000000..14f27fe --- /dev/null +++ b/src/components/ProductRow.js @@ -0,0 +1,14 @@ +function ProductRow({ product }) { + const textStyle = { + color: product.inStock ? "black" : "red", + }; + + return ( + + {product.name} + {product.price} + + ); +} + +export default ProductRow; diff --git a/src/components/ProductTable.js b/src/components/ProductTable.js new file mode 100644 index 0000000..5edbb16 --- /dev/null +++ b/src/components/ProductTable.js @@ -0,0 +1,22 @@ +import ProductRow from "./ProductRow"; + +function ProductTable({ products }) { + return ( + + + + + + + + + + {products.map((product) => ( + + ))} + +
NamePrice
+ ); +} + +export default ProductTable; diff --git a/src/components/ProductsPage.js b/src/components/ProductsPage.js new file mode 100644 index 0000000..ccdcaa2 --- /dev/null +++ b/src/components/ProductsPage.js @@ -0,0 +1,38 @@ +import { useState } from "react"; +import jsonData from "../data.json"; + +import SearchBar from "./SearchBar"; +import ProductTable from "./ProductTable"; + +function ProductsPage() { + const [products] = useState(jsonData); + const [searchText, setSearchText] = useState(""); + const [inStockOnly, setInStockOnly] = useState(false); + + const filteredProducts = products.filter((product) => { + const matchesSearch = product.name + .toLowerCase() + .includes(searchText.toLowerCase()); + + const matchesStock = inStockOnly ? product.inStock : true; + + return matchesSearch && matchesStock; + }); + + return ( +
+

Root Store

+ + + + +
+ ); +} + +export default ProductsPage; diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js new file mode 100644 index 0000000..f12ffa2 --- /dev/null +++ b/src/components/SearchBar.js @@ -0,0 +1,28 @@ +function SearchBar({ + searchText, + onSearchChange, + inStockOnly, + onInStockChange, +}) { + return ( +
+ onSearchChange(e.target.value)} + /> + + +
+ ); +} + +export default SearchBar;