diff --git a/src/App.css b/src/App.css index 74b5e05..fad85da 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,20 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .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; +body { + font-family: Arial, sans-serif; + background-color: #f8f9fa; + margin: 0; + padding: 0; } -.App-link { - color: #61dafb; +.App { + max-width: 800px; + margin: 20px auto; + padding: 20px; + background-color: #fff; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + border-radius: 5px; } -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +h1 { + color: #343a40; + text-align: center; } diff --git a/src/App.js b/src/App.js index 3784575..677d95c 100644 --- a/src/App.js +++ b/src/App.js @@ -1,23 +1,10 @@ -import logo from './logo.svg'; +import ProductPage from './components/ProductPage'; import './App.css'; function App() { return (
-
- logo -

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

- - Learn React - -
+
); } diff --git a/src/components/ProductPage.js b/src/components/ProductPage.js new file mode 100644 index 0000000..88b527b --- /dev/null +++ b/src/components/ProductPage.js @@ -0,0 +1,26 @@ +import { useState } from "react"; +import ProductTable from "./ProductTable"; +import SearchBar from "./SearchBar"; +import jsonData from '../data.json'; +import './ProductsPage.css' + +export default function ProductPage() { + const [products] = useState(jsonData); + const [searchTerm, setSearchTerm] = useState(''); + const [inStockOnly, setInStockOnly] = useState(false); + + const handleSearch = (term) => { + setSearchTerm(term); + }; + + const handleInStockChange = (inStock) => { + setInStockOnly(inStock); + } + return ( +
+

Root Store

+ + +
+ ) +} \ No newline at end of file diff --git a/src/components/ProductRow.css b/src/components/ProductRow.css new file mode 100644 index 0000000..68c8c9b --- /dev/null +++ b/src/components/ProductRow.css @@ -0,0 +1,4 @@ +.ProductRow td { + padding: 10px; + } + \ No newline at end of file diff --git a/src/components/ProductRow.js b/src/components/ProductRow.js new file mode 100644 index 0000000..2c084f6 --- /dev/null +++ b/src/components/ProductRow.js @@ -0,0 +1,9 @@ +import './ProductRow.css' +export default function ProductRow({ product }) { + return ( + + {product.name} + {product.price} + + ) +} \ No newline at end of file diff --git a/src/components/ProductTable.css b/src/components/ProductTable.css new file mode 100644 index 0000000..f64fc97 --- /dev/null +++ b/src/components/ProductTable.css @@ -0,0 +1,19 @@ +.ProductTable { + width: 100%; + border-collapse: collapse; + } + + .ProductTable th, .ProductTable td { + padding: 10px; + border: 1px solid #dee2e6; + text-align: left; + } + + .ProductTable th { + background-color: #f1f1f1; + } + + .ProductTable tr:nth-child(even) { + background-color: #f8f9fa; + } + \ No newline at end of file diff --git a/src/components/ProductTable.js b/src/components/ProductTable.js new file mode 100644 index 0000000..851bd30 --- /dev/null +++ b/src/components/ProductTable.js @@ -0,0 +1,25 @@ +import ProductRow from "./ProductRow"; +import './ProductTable.css'; + +export default function ProductTable({ products, searchTerm, inStockOnly }) { + const filteredProducts = products.filter((product) => { + const matchesSearchTerm = product.name.toLowerCase().includes(searchTerm.toLowerCase()); + const matchesInStock = inStockOnly ? product.inStock : true; + return matchesSearchTerm && matchesInStock; + }) + return ( + + + + + + + + + {filteredProducts.map((product) => ( + + ))} + +
NamePrice
+ ) +} \ No newline at end of file diff --git a/src/components/ProductsPage.css b/src/components/ProductsPage.css new file mode 100644 index 0000000..eed37dc --- /dev/null +++ b/src/components/ProductsPage.css @@ -0,0 +1,5 @@ +.ProductsPage { + padding: 20px; + background-color: #fff; + } + \ No newline at end of file diff --git a/src/components/SearchBar.css b/src/components/SearchBar.css new file mode 100644 index 0000000..fc5fe42 --- /dev/null +++ b/src/components/SearchBar.css @@ -0,0 +1,22 @@ +.SearchBar { + display: flex; + justify-content: space-between; + margin-bottom: 20px; + } + + .SearchBar input[type="text"] { + width: 70%; + padding: 8px; + border: 1px solid #ced4da; + border-radius: 4px; + } + + .SearchBar label { + display: flex; + align-items: center; + } + + .SearchBar input[type="checkbox"] { + margin-right: 5px; + } + \ No newline at end of file diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js new file mode 100644 index 0000000..c9ea06f --- /dev/null +++ b/src/components/SearchBar.js @@ -0,0 +1,19 @@ +import './SearchBar.css'; +export default function SearchBar({ onSearch, onInStockChange }) { + const handleSearch = (event) => { + onSearch(event.target.value); + }; + + const handleInStockChange = (event) => { + onInStockChange(event.target.checked); + }; + return ( +
+ + +
+ ); +}