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 (
+
+
+ Quantity:
+
+ {new Array(9).fill(1).map((_, i) => (
+
+ {i} {i === 0 && '(Delete)'}
+
+ ))}
+
+
+
+ Add to Cart
+ Buy Now
+
+
+
+
+
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}{' '}
+
+
+
+ ))}
+
+ );
+}
+
+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}
+
+ Category:{' '}
+
+ {capitalizeFirst(product.category)}
+
+
+
+
+
+
+ {numberWithCommas(product.numReviews)} ratings
+
+
+ {product.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',
+ });
}