diff --git a/src/App.js b/src/App.js index 7ad559c..ebca7d0 100644 --- a/src/App.js +++ b/src/App.js @@ -8,33 +8,26 @@ import Homepage from './Components/Homepage/Homepage'; import MyCart from './Components/CartPage/MyCart'; import SignIn from './Components/SignIn/SignIn'; import ProductList from './Components/ProductList/ProductList'; +import SingleProduct from './Components/SingleProduct/SingleProduct'; function App() { const setQuery = useStore(state => state.setQuery); useEffect(() => { setQuery(''); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( - - - - - - - - - - - - - - - + + + + + + diff --git a/src/Components/ProductList/ProductItem.jsx b/src/Components/ProductList/ProductItem.jsx index 983ab50..5ba8bd1 100644 --- a/src/Components/ProductList/ProductItem.jsx +++ b/src/Components/ProductList/ProductItem.jsx @@ -1,15 +1,7 @@ import { Link } from 'react-router-dom'; -import { numberWithCommas } from '../../utils'; +import { formatDate, numberWithCommas } from '../../utils'; import Rating from './Rating'; -function formatDate(dt) { - return dt.toLocaleString('en-CA', { - month: 'long', - day: 'numeric', - year: 'numeric', - }); -} - function ProductItem({ product }) { const priceWithoutDiscount = parseInt( (product.price * 100) / (100 - product.discount), @@ -66,8 +58,7 @@ function ProductItem({ product }) {
{/* need to get prime image here */} - - {product.fullfilled && } Get it by + {product.fullfilled && } Get it by {formatDate(deliveryDate)}
diff --git a/src/Components/SingleProduct/ProductCart.jsx b/src/Components/SingleProduct/ProductCart.jsx new file mode 100644 index 0000000..6b91e80 --- /dev/null +++ b/src/Components/SingleProduct/ProductCart.jsx @@ -0,0 +1,33 @@ +import useStore from '../../store'; + +function ProductCart({ product }) { + const user_location = useStore(state => state.user_location); + return ( +
+

+ + +

+
+ + +
+
+ +

Secure transaction

+
+
+ +

Deliver to {user_location}

+
+
+ ); +} + +export default ProductCart; diff --git a/src/Components/SingleProduct/SingleProduct.jsx b/src/Components/SingleProduct/SingleProduct.jsx new file mode 100644 index 0000000..b699470 --- /dev/null +++ b/src/Components/SingleProduct/SingleProduct.jsx @@ -0,0 +1,166 @@ +import { Link, useParams } from 'react-router-dom'; +import { getProductById } from '../../Data/products/index'; +import { capitalizeFirst, formatDate, numberWithCommas } from '../../utils'; +import Rating from '../ProductList/Rating'; +import ProductCart from './ProductCart'; + +function DeliveryFeature() { + const items = [ + { + id: '8zeyta-kx8gfg-fjk4h3-8sto0p', + dataId: 'RETURNS_POLICY', + name: '7 Days Replacement', + image: + 'https://images-na.ssl-images-amazon.com/images/G/31/A2I-Convert/mobile/IconFarm/icon-returns._CB484059092_.png', + }, + { + id: 'ibgdh0-jdltm8-4exan-3k9cpe', + dataId: 'AMAZON_DELIVERED', + name: 'Amazon Delivered', + image: + 'https://images-na.ssl-images-amazon.com/images/G/31/A2I-Convert/mobile/IconFarm/icon-amazon-delivered._CB485933725_.png', + }, + { + id: '6h83sn-2ix3xj-piu7hy-gldgb6', + dataId: 'WARRANTY', + name: '1 Year Warranty', + image: + 'https://images-na.ssl-images-amazon.com/images/G/31/A2I-Convert/mobile/IconFarm/icon-warranty._CB485935626_.png', + }, + { + id: 'ka0dd9-f9ibnx-cv0w2n-b0lldt', + dataId: 'NO_CONTACT_DELIVERY', + name: 'No-Contact Delivery', + image: + 'https://images-na.ssl-images-amazon.com/images/G/31/A2I-Convert/mobile/IconFarm/No_contact_delivery_final._CB432269791_.png', + }, + ]; + + return ( +
+ {items.map(i => ( +
+
+ {i.name} +
+
+ + {i.name}{' '} + +
+
+ ))} +
+ ); +} + +function SingleProduct() { + const { productId } = useParams(); + const product = getProductById(productId); + const priceWithoutDiscount = parseInt( + (product.price * 100) / (100 - product.discount), + ); + let deliveryDate = new Date(); + deliveryDate.setDate(deliveryDate.getDate() + product.deliveryDays); + + return ( +
+
+ {product.name} +
+
+

{product.name}

+

+ Category:{' '} + + {capitalizeFirst(product.category)} + +

+
+ + + + {numberWithCommas(product.numReviews)} ratings + +
+ {product.fullfilled && ( +

+ fullfilled +

+ )} +
+ + + + + + + + + + + + + + + + + +
M.R.P.: + ₹{numberWithCommas(priceWithoutDiscount)} +
Deal Price:₹{numberWithCommas(product.price)}
You Save: + ₹{numberWithCommas(priceWithoutDiscount - product.price)} ( + {product.discount}%) +
Inclusive of all taxes
+
+

+ + {product.price > 500 ? 'FREE Delivery' : 'Delivery at'}: + + {formatDate(deliveryDate)} + Details +

+ + In Stock. +

+ Sold by Random Seller + {product.fullfilled && ( + + {' '} + and Fulfilled by Amazon + + )} +

+

+ {product.description} Lorem ipsum dolor, sit amet consectetur + adipisicing elit. Nobis corporis dolore eos veritatis deserunt non? + Consequuntur possimus placeat iste earum at quos facere facilis + dolores voluptate, libero officiis itaque nesciunt.{' '} +

+
+ +
+ ); +} + +export default SingleProduct; diff --git a/src/Data/products/index.js b/src/Data/products/index.js index f35a490..c0fc3df 100644 --- a/src/Data/products/index.js +++ b/src/Data/products/index.js @@ -39,4 +39,8 @@ function shuffle(array) { const products = shuffle([...mobiles, ...laptops]); +export function getProductById(id) { + return products.find(p => p.id === id); +} + export default products; diff --git a/src/Data/products.json b/src/Data/productsData.json similarity index 100% rename from src/Data/products.json rename to src/Data/productsData.json diff --git a/src/Styles/_resuable.scss b/src/Styles/_resuable.scss index 9099254..da2f397 100644 --- a/src/Styles/_resuable.scss +++ b/src/Styles/_resuable.scss @@ -1,25 +1,40 @@ .sign_in_btn { - background-color: #ffd814; - padding: 8px 5px; - display: block; - border: none; - border-radius: 8px; - width: 100%; - text-align: center; - font-size: 13px; - margin: 10px 0; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.061); - cursor: pointer; - &:hover { - background-color: #f6d115; - } - &:active { - background-color: #ceac06; - } + background-color: #ffd814; + padding: 8px 5px; + display: block; + border: none; + border-radius: 8px; + width: 100%; + text-align: center; + font-size: 13px; + margin: 10px 0; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.061); + cursor: pointer; + &:hover { + background-color: #f6d115; + } + &:active { + background-color: #ceac06; + } } .bold { - font-weight: 600; + font-weight: 600; +} + +.amz-link { + text-decoration: none; + color: #007185; + + &:hover { + text-decoration: underline; + cursor: pointer; + color: #c7511f; + } + + &.no-underline:hover { + text-decoration: none; + } } // Max-width: 1450px or 1500px diff --git a/src/Styles/_single_pdt.scss b/src/Styles/_single_pdt.scss new file mode 100644 index 0000000..842ec28 --- /dev/null +++ b/src/Styles/_single_pdt.scss @@ -0,0 +1,171 @@ +.singleProduct { + display: grid; + grid-template-columns: 40% auto 244px; + gap: 1.4rem; + max-width: 1500px; + margin: 0 auto; + padding: 3rem 1rem; + background-color: #fff; + + .product-image { + display: grid; + justify-content: center; + padding: 1rem 2rem; + img { + max-width: 500px; + min-width: 250px; + object-fit: contain; + } + } + + .product-details { + font-size: 15px; + h1 { + font-size: 1.3rem; + font-weight: 400; + line-height: 32px; + margin-bottom: 1rem; + } + + .ratings { + margin-top: 5px; + display: flex; + align-items: center; + gap: 3px; + color: rgb(0, 105, 175); + cursor: pointer; + filter: drop-shadow(0 0 3px rgba (0, 0, 0, 0.473)); + + .reviews { + color: #007185; + font-size: 14px; + margin-left: 0.6rem; + &:hover { + color: #c7511f; + text-decoration: underline; + } + } + } + + .fullfilled-image { + height: 20px; + margin: 0.3rem 0; + object-fit: contain; + } + + .price-details { + margin: 0.3rem 0; + border-top: 1px solid lightgray; + padding-top: 0.8rem; + table { + border-spacing: 0.5rem 0.2rem; + th { + text-align: right; + color: #595959; + font-weight: normal; + font-size: 14px; + line-height: 20px; + } + + tr { + font-size: 14px; + line-height: 20px; + } + + .strike { + text-decoration: line-through; + color: #595959; + } + + .price { + color: #b12704; + font-size: 18px; + line-height: 24px; + } + .save { + color: #b12704; + } + } + } + .delivery-info { + display: flex; + align-items: center; + font-size: 14px; + .free-delivery { + margin-right: 0.4rem; + } + strong { + margin-right: 0.4rem; + } + } + .icon-farm-wrapper { + display: flex; + font-size: 12px; + text-align: center; + margin: 0.8rem 0; + padding-bottom: 0.3rem; + width: max-content; + border-bottom: 1px solid lightgray; + .icon-content { + width: 80%; + margin: 0 auto; + .amz-link:hover { + text-decoration: none; + } + } + } + .stock { + display: inline-block; + color: green; + font-size: 1rem; + margin: 0.3rem 0 0.7rem; + } + } + + .product-cart { + padding: 1.4rem; + border-radius: 5px; + border: 1px solid lightgray; + + height: max-content; + + select { + margin-right: 0.4rem; + outline: none; + padding: 0.3rem; + border-radius: 0.3rem; + cursor: pointer; + background-color: #f5f5f5; + } + .sign_in_btn { + border-radius: 999px; + } + .buy_now_btn { + background: #ffa41c; + border-color: #ff8f00; + &:hover { + background: #fa8900; + border-color: #e3931e; + } + } + + .delivery-details { + font-size: small; + display: flex; + align-items: center; + p { + margin-left: 0.3rem; + } + } + .secure-transaction { + font-size: 14px; + margin: 0.5rem 0; + display: flex; + align-items: center; + color: gray; + p { + margin-left: 0.3rem; + } + } + } +} diff --git a/src/Styles/style.scss b/src/Styles/style.scss index 1d10c05..680774d 100644 --- a/src/Styles/style.scss +++ b/src/Styles/style.scss @@ -19,4 +19,5 @@ body { @import 'sign-in'; @import 'cart'; @import 'footer'; -@import 'products'; \ No newline at end of file +@import 'products'; +@import 'single_pdt'; diff --git a/src/utils.js b/src/utils.js index b764983..3dcad3a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,15 @@ export function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); + return x.toLocaleString('en-IN'); +} + +export function capitalizeFirst(str) { + return str[0].toUpperCase() + str.slice(1, str.length); +} + +export function formatDate(dt) { + return dt.toLocaleString('en-CA', { + month: 'long', + day: 'numeric', + year: 'numeric', + }); }