-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a8839e5
commit 9a37c1f
Showing
37 changed files
with
2,195 additions
and
359 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
API_URL=https://5d6da1df777f670014036125.mockapi.io/api/v1/product |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import React ,{ReactNode}from 'react' | ||
import Navbar from '../Navbar' | ||
|
||
interface LayoutProps { | ||
children: ReactNode | ||
} | ||
|
||
export default function Layout({children}:LayoutProps) { | ||
return ( | ||
<> | ||
<Navbar/> | ||
<main className="flex w-full min-h-screen px-5 md:px-20 font-montserrat py-20 pb-24 bg-gray-200"> | ||
{children} | ||
</main> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import React, { useEffect } from 'react'; | ||
import Link from 'next/link'; | ||
import { useRouter } from 'next/router'; | ||
import {BsCart3} from 'react-icons/bs'; | ||
import {useCart} from '../../hooks/useCart'; | ||
export default function Navbar() { | ||
|
||
const {cart} = useCart(); | ||
|
||
const [productCounter, setProductCounter] = React.useState(0); | ||
|
||
useEffect( | ||
() => { | ||
const numberOfProducts = cart.length; | ||
setProductCounter(numberOfProducts); | ||
},[cart] | ||
); | ||
|
||
|
||
const router = useRouter(); | ||
//set the active class on the navbar | ||
const activeClass = (path: string) => { | ||
if (router.pathname === path) { | ||
return 'decoration-blue-300 hover:decoration-gray-300 underline underline-offset-2'; | ||
} | ||
return ''; | ||
}; | ||
|
||
return ( | ||
<nav className="flex justify-between content-center align-middle p-3 bg-white drop-shadow-md z-50 fixed top-0 w-full bg-opacity-80 backdrop-blur"> | ||
|
||
<Link href="/home"> | ||
<a className={`${activeClass('/home')} text-black-500 hover:text-black-400`}> | ||
Home | ||
</a> | ||
</Link> | ||
|
||
<Link href="/cart"> | ||
<a className={`${activeClass('/cart')} hover:text-gray-400 content-center justify-center pt-1 pr-6 relative`}> | ||
<BsCart3 className="w-5 h-5" /> | ||
<div className="text-gray-700 text-sm absolute -top-2 -right-1 text-gray-100 rounded-full flex justify-center items-center bg-slate-700 w-5 h-6 px-3"> | ||
<span className="text-xs">{productCounter}</span> | ||
</div> | ||
</a> | ||
</Link> | ||
|
||
</nav> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { productInterface } from '../../../interfaces'; | ||
import { useCart } from '../../../hooks/useCart'; | ||
import { HiPlus, HiMinus } from 'react-icons/hi'; | ||
interface AmountControlProps { | ||
product: productInterface; | ||
min?: number; | ||
} | ||
|
||
export function AmountControl({ product,min }: AmountControlProps) { | ||
const { updateProductAmount, cart } = useCart(); | ||
|
||
const [ formatedProduct, setFormatedProduct ] = useState({ | ||
...product, | ||
total: (product.amount * product.price).toFixed(2) | ||
}); | ||
|
||
useEffect( | ||
() => { | ||
//find product in cart with the id of product | ||
const productInCart = cart.find((item) => item.productId === product.id); | ||
if (productInCart) { | ||
setFormatedProduct({ | ||
...product, | ||
total: (product.amount * product.price).toFixed(2), | ||
amount: productInCart.amount | ||
}); | ||
} else { | ||
setFormatedProduct({ ...product, total: (product.amount * product.price).toFixed(2) }); | ||
} | ||
}, | ||
[ product, cart ] | ||
); | ||
|
||
const handleIncreaseAmount = (product: productInterface) => { | ||
const updatedProduct = { productId: product.id, amount: product.amount + 1 }; | ||
|
||
updateProductAmount(updatedProduct); | ||
}; | ||
|
||
const handleDecreaseAmount = (product: productInterface) => { | ||
if(product.amount > min){ | ||
const updatedProduct = { productId: product.id, amount: product.amount - 1 }; | ||
updateProductAmount(updatedProduct); | ||
} | ||
}; | ||
return ( | ||
<div className="flex flex-row ml-1 py-3 items-center"> | ||
|
||
{formatedProduct.amount === undefined ? ( | ||
<button className="h-5 w-5 text-gray-400"> | ||
<HiMinus /> | ||
</button> | ||
) : ( | ||
|
||
<button className="h-5 w-5 text-gray-700" onClick={() => handleDecreaseAmount(formatedProduct)}> | ||
<HiMinus /> | ||
</button> | ||
)} | ||
|
||
<p className="w-fit px-3 bg-gray-100 rounded mr-1 text-gray-700"> | ||
x{formatedProduct.amount ? formatedProduct.amount : 0} | ||
</p> | ||
<button className="text-xl text-gray-700" onClick={() => handleIncreaseAmount(formatedProduct)}> | ||
<HiPlus /> | ||
</button> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import React, { useEffect } from 'react' | ||
import Link from 'next/link' | ||
import { useRouter } from 'next/router' | ||
interface BuyContainerProps { | ||
total: number, | ||
text:string | ||
} | ||
|
||
import { formatedPrice } from '../../../utils' | ||
|
||
export function BuyContainer({total,text}:BuyContainerProps) { | ||
const router= useRouter() | ||
|
||
return ( | ||
<div className="fixed bottom-0 left-0 right-0 bg-white w-full p-1 h-fit flex flex-row items-center justify-around"> | ||
<div className='self-start'> | ||
<span className="text-xl text-gray-800">total: </span> | ||
<span className="text-sm text-gray-600">R$ {formatedPrice(total)??'0.00'}</span> | ||
</div> | ||
<div className={`w-1/3 bottom-2 left-2 right-4 ${total==0?" bg-gray-400 ":"bg-gray-900 "} p-2 rounded-md text-gray-400 text-center`}> | ||
{ | ||
|
||
total>0?( | ||
|
||
router.pathname.includes('/product/') ? | ||
( | ||
<Link href="/cart"> | ||
<a className='cursor-pointer'> | ||
<span className="text-xl text-gray-200">{text}</span> | ||
</a> | ||
</Link> | ||
): | ||
( | ||
<Link href={`/payment`}> | ||
<a> | ||
<span className="text-xl text-gray-200">{text}</span> | ||
</a> | ||
</Link> | ||
|
||
) | ||
) | ||
: | ||
<span className="text-xl text-gray-300">{text}</span> | ||
} | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import {useState,useEffect} from 'react'; | ||
import { productProp } from '../../../interfaces'; | ||
import {useCart} from '../../../hooks/useCart'; | ||
import {RiShoppingCart2Fill,RiShoppingCart2Line} from 'react-icons/ri'; | ||
|
||
export const OnCart=({product}:productProp)=>{ | ||
|
||
const { cart, removeProduct, addProduct } = useCart(); | ||
const [ liked, setLiked ] = useState(false); | ||
|
||
|
||
useEffect( | ||
() => { | ||
const isSaved = cart.find((cart_product) => cart_product.productId == product.id); | ||
|
||
if (isSaved) { | ||
setLiked(true); | ||
} | ||
}, | ||
[ cart, product.id ] | ||
); | ||
|
||
const handleToogleLike = () => { | ||
|
||
if (liked) { | ||
removeProduct(product.id); | ||
setLiked(false); | ||
} else { | ||
addProduct(product.id); | ||
setLiked(true); | ||
} | ||
}; | ||
|
||
return ( | ||
<div | ||
onClick={handleToogleLike} | ||
className=" right-0 m-2 w-8 h-8 flex justify-center items-center self-end" | ||
> | ||
{liked ? ( | ||
<RiShoppingCart2Fill className=" text-gray-500 w-5 h-5" /> | ||
) : ( | ||
<RiShoppingCart2Line className="text-gray-400 w-5 h-5 focus:pointer-events-auto" /> | ||
)} | ||
</div> | ||
) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import Link from 'next/link'; | ||
import { handleDelete } from '../../../utils'; | ||
import { IoMdClose } from 'react-icons/io'; | ||
import { AmountControl } from '../AmountControl'; | ||
import { useCart } from '../../../hooks/useCart'; | ||
import { productProp } from '../../../interfaces'; | ||
import { formatImageURL } from '../../../utils'; | ||
import { ProductImage } from '../ProductImage'; | ||
|
||
export function ProductCardCart({ product }: productProp) { | ||
const { removeProduct } = useCart(); | ||
const [ formatedProduct, setFormatedProduct ] = useState({ | ||
...product, | ||
image: formatImageURL(product.image), | ||
total: (product.amount * product.price).toFixed(2) | ||
}); | ||
|
||
useEffect( | ||
() => { | ||
setFormatedProduct({ | ||
...product, | ||
image: formatImageURL(product.image), | ||
total: (product.amount * product.price).toFixed(2) | ||
}); | ||
}, | ||
[ product ] | ||
); | ||
|
||
return ( | ||
<div className="flex flex-row justify-start w-full mb-3 relative h-32 rounded-md"> | ||
<Link href="/product/[id]" as={`/product/${product.id}`}> | ||
<div className="max-h-64 max-w-64 bg-gray-300 h-32 w-48"> | ||
{/* passing cart as classname couse the style wanted is on ../../../styles/Cart.modules.css */} | ||
<ProductImage product={product} styles={'rounded-l-md h-full'}/> | ||
</div> | ||
</Link> | ||
<div className="flex flex-col w-full bg-white pl-3 rounded-r-md pt-2"> | ||
<div className="flex flex-row justify-between"> | ||
<Link href="/product/[id]" as={`/product/${product.id}`}> | ||
<a> | ||
<p className="w-full text-gray-600 text-sm line-clamp-1 hover:text-gray-400 transition-colors duration-300">{product.name}</p> | ||
</a> | ||
</Link> | ||
</div> | ||
<p className="text-lg">R$ {product.price}</p> | ||
|
||
<div className="flex"> | ||
<AmountControl product={product} min={1} /> | ||
</div> | ||
<p className="absolute bottom-2 bottom-2 text-gray-700 text-xs"> | ||
<span className="text-gray-600 mr-1">Total:</span> R$ {formatedProduct.total} | ||
</p> | ||
<button className="absolute top-2 right-2" onClick={() => handleDelete({handler:()=>removeProduct(formatedProduct.id),message:"Product has been deleted!"})}> | ||
<IoMdClose className="w-4 h-4 text-gray-600" /> | ||
</button> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import Link from 'next/link'; | ||
import { productProp } from '../../../interfaces'; | ||
import { Product } from '../index'; | ||
import { OnCart } from '../OnCart'; | ||
import {Share} from '../Share'; | ||
import { ProductImage } from '../ProductImage'; | ||
|
||
export function ProductCard({ product }: productProp) { | ||
|
||
return ( | ||
<div className="flex flex-col rounded-sm bg-gray-100 justify-between hover:drop-shadow-2xl transition-all ease-out duration-1000 cursor-pointer relative"> | ||
<div className=" h-72 w-80 z-10"> | ||
{/* rounded-t-md is a custom css classname found at styles/Lazy.module.css */} | ||
<ProductImage product={product} styles='h-full rounded-t-md'/> | ||
<div className='flex flex-row items-center w-full justify-end'> | ||
<Share product={product}/> | ||
<OnCart product={product} /> | ||
</div> | ||
</div> | ||
|
||
<Product product={product} /> | ||
<Link href={`/product/${product.id}`}> | ||
<a> | ||
<div className="m-1 p-2 bg-gray-700 text-gray-200 rounded-md text-center">See more</div> | ||
</a> | ||
</Link> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import React from 'react'; | ||
import { productInterface } from '../../../interfaces'; | ||
import { LazyLoadImage } from 'react-lazy-load-image-component'; | ||
import 'react-lazy-load-image-component/src/effects/blur.css'; | ||
|
||
interface ProductImageProps { | ||
styles?: string; | ||
product: productInterface; | ||
} | ||
|
||
export function ProductImage({ product, styles }: ProductImageProps) { | ||
return ( | ||
<div className={`${styles} relative`}> | ||
<LazyLoadImage src={product.image} alt={product.name} effect='blur' placeholderSrc="/default-image.jpg"/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React from 'react'; | ||
import {FaTelegramPlane} from 'react-icons/fa'; | ||
import Swal from 'sweetalert2'; | ||
export function Share({product}) { | ||
|
||
const handleClick = (product) => { | ||
//copy to clipboard | ||
const text = `${product.name} - R$ ${product.price}`; | ||
const el = document.createElement('textarea'); | ||
el.value = text; | ||
document.body.appendChild(el); | ||
el.select(); | ||
document.execCommand('copy'); | ||
document.body.removeChild(el); | ||
|
||
if (navigator.share) { | ||
navigator | ||
.share({ | ||
title: product.name, | ||
text: `${product.name} - R$ ${product.price}`, | ||
url: `${process.env.NEXT_PUBLIC_URL}/product/${product.id}`, | ||
}) | ||
.then(() => { | ||
console.log("Successfully shared!"); | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
} | ||
else | ||
Swal.fire | ||
({ | ||
title: 'Oops...🙄!', | ||
text: 'It seems you are not using a browser that supports sharing', | ||
}) | ||
}; | ||
|
||
return <> | ||
<FaTelegramPlane className='text-gray-500 w-5 h-5 m-3' onClick={()=>handleClick(product)}/> | ||
</>; | ||
} |
Oops, something went wrong.