-
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.
Added dark theme
- Loading branch information
Showing
20 changed files
with
435 additions
and
116 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
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
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
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
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 |
---|---|---|
@@ -1,15 +1,75 @@ | ||
'use client'; | ||
|
||
import classNames from 'classnames'; | ||
import { Fragment, useMemo } from 'react'; | ||
import { Popover, Transition } from '@headlessui/react'; | ||
import { useCart } from '@/store'; | ||
import { Cart as CartLogo } from '@/components/Icons'; | ||
import CartItem from '@/components/CartItem'; | ||
import CountDot from '@/components/CountDot'; | ||
import Button from '../Button'; | ||
|
||
export default function CartPopover() { | ||
const { total, cart } = useCart(); | ||
const itemsCount = useMemo( | ||
() => cart.reduce((acc, item) => acc + item.count, 0), | ||
[cart] | ||
); | ||
|
||
export default function Cart() { | ||
const { total } = useCart(); | ||
return ( | ||
<div className="w-full lg:w-[300px] lg:h-[400px] p-4 rounded-md border bg-white flex justify-between"> | ||
<p className="text-lg font-medium">Cart Total:</p> | ||
<p className="text-2xl font-medium"> | ||
£<span data-testid="cart-total">{total.toFixed(2)}</span> | ||
</p> | ||
</div> | ||
<Popover className="relative"> | ||
{({ open }) => ( | ||
<> | ||
<Popover.Button | ||
as={Button} | ||
size="large" | ||
// className={` | ||
// ${open ? 'text-black' : 'text-black/90'} | ||
// text-gray-900 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-md text-sm p-1 w-8 h-8 inline-flex items-center justify-center relative`} | ||
> | ||
<CartLogo className="w-6 h-6 dark:text-gray-200 text-gray-900" /> | ||
|
||
{itemsCount > 0 && ( | ||
<CountDot count={itemsCount} className="absolute -top-2 left-6" /> | ||
)} | ||
</Popover.Button> | ||
<Transition | ||
as={Fragment} | ||
enter="transition ease-out duration-200" | ||
enterFrom="opacity-0 translate-y-1" | ||
enterTo="opacity-100 translate-y-0" | ||
leave="transition ease-in duration-150" | ||
leaveFrom="opacity-100 translate-y-0" | ||
leaveTo="opacity-0 translate-y-1" | ||
> | ||
<Popover.Panel className="absolute left-1/2 z-10 mt-3 sm:mt-2 w-[400px] max-w-xs sm:max-w-sm -translate-x-full ml-8 transform px-4 sm:px-0"> | ||
<div className="w-full p-4 rounded-md border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900 flex flex-col justify-between gap-2 shadow-[0_8px_30px_rgb(0,0,0,0.12)]"> | ||
<div className="flex flex-col gap-2"> | ||
{cart.map((item) => ( | ||
<CartItem key={item.id} product={item} /> | ||
))} | ||
{cart.length === 0 && <p className="text-center">No Items</p>} | ||
</div> | ||
|
||
<div | ||
className={classNames( | ||
'flex justify-between pt-2 px-1 border-t', | ||
{ | ||
'mt-3 ': cart.length > 0, | ||
} | ||
)} | ||
> | ||
<p className="text-lg font-medium">Cart Total:</p> | ||
<p className="text-2xl font-medium font-mono"> | ||
£ | ||
<span data-testid="cart-total">{total.toFixed(2)}</span> | ||
</p> | ||
</div> | ||
</div> | ||
</Popover.Panel> | ||
</Transition> | ||
</> | ||
)} | ||
</Popover> | ||
); | ||
} |
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,109 @@ | ||
'use client'; | ||
import classNames from 'classnames'; | ||
import Image from 'next/image'; | ||
import { useCallback, useMemo } from 'react'; | ||
import Button from '@/components/Button'; | ||
import Color from '@/components/Color'; | ||
import { Add, Minus } from '@/components/Icons'; | ||
import { useCart } from '@/store'; | ||
import { Product } from '../ProductItem'; | ||
|
||
type Props = { | ||
product: Product; | ||
className?: string; | ||
}; | ||
|
||
export default function CartItem({ product, className }: Props) { | ||
const { addItem, removeItem, clearItem, cart } = useCart(); | ||
const count = useMemo( | ||
() => cart.find((item) => item.id === product.id)?.count || 0, | ||
[cart, product] | ||
); | ||
const handleAddItem = useCallback(() => addItem(product), [addItem, product]); | ||
const handleRemoveItem = useCallback( | ||
() => removeItem(product), | ||
[removeItem, product] | ||
); | ||
const handleClearItem = useCallback( | ||
() => clearItem(product), | ||
[clearItem, product] | ||
); | ||
const disabled = useMemo(() => count === 0, [count]); | ||
return ( | ||
<div | ||
className={classNames(className, 'flex flex-col')} | ||
data-testid={`product-${product.id}`} | ||
> | ||
<div className="flex-1 flex rounded-md overflow-hidden bg-white dark:bg-gray-900 shadow-[rgba(17,_17,_26,_0.1)_0px_0px_16px] border border-gray-200 dark:border-gray-800"> | ||
<Image | ||
priority | ||
src={product.img} | ||
alt="Product Image" | ||
className="rounded-l-md" | ||
width={50} | ||
height={80} | ||
data-testid={`product-${product.id}-img`} | ||
style={{ objectFit: 'cover', objectPosition: '50% 20%' }} | ||
/> | ||
<div className="info flex-1 px-2 py-1 flex flex-col"> | ||
<h2 | ||
className="text-sm font-semibold mb-1 line-clamp-1" | ||
title={product.name} | ||
aria-label={product.name} | ||
> | ||
{product.name} | ||
</h2> | ||
|
||
<div className="flex justify-between items-center gap-3 mb-1"> | ||
<div className="flex items-center gap-3"> | ||
<Color | ||
color={product.colour} | ||
data-testid={`product-${product.id}-color`} | ||
size="small" | ||
/> | ||
<p className="text-sm text-gray-500 font-medium font-mono"> | ||
£ | ||
<span data-testid={`product-${product.id}-price`}> | ||
{product.price.toFixed(2)} | ||
</span> | ||
</p> | ||
</div> | ||
<button | ||
className="px-1 text-sm text-gray-600 disabled:text-gray-400 disabled:cursor-not-allowed disabled:hover:no-underline hover:underline focus:underline underline-offset-4 decoration-2" | ||
onClick={handleClearItem} | ||
disabled={disabled} | ||
data-testid={`product-${product.id}-clear`} | ||
> | ||
<span>Remove</span> | ||
</button> | ||
</div> | ||
<div className="w-full border border-gray-200 dark:border-gray-800 px-2 rounded-md sm:max-w-xs flex justify-around items-center"> | ||
<Button | ||
onClick={handleRemoveItem} | ||
disabled={disabled} | ||
aria-label="Remove One Item" | ||
data-testid={`product-${product.id}-remove`} | ||
size="small" | ||
> | ||
<Minus className="w-4 h-4" /> | ||
</Button> | ||
<span | ||
data-testid={`product-${product.id}-count`} | ||
className="text-md text-gray-500 px-5 min-w-16 rounded-md text-center" | ||
> | ||
{count} | ||
</span> | ||
<Button | ||
onClick={handleAddItem} | ||
aria-label="Add One Item" | ||
data-testid={`product-${product.id}-add`} | ||
size="small" | ||
> | ||
<Add className="w-4 h-4" /> | ||
</Button> | ||
</div> | ||
</div> | ||
</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
Oops, something went wrong.