Custom Checkout Progress

This commit is contained in:
Bel Curcio
2021-05-27 14:23:55 -03:00
parent 8fb6c7b206
commit 7c1344a19e
60 changed files with 869 additions and 252 deletions

View File

@@ -1,6 +1,31 @@
.root {
@apply flex flex-col py-4;
}
.root:first-child {
padding-top: 0;
}
.actions {
@apply flex p-1 border-accent-3 border items-center justify-center w-12 text-accent-7;
transition-property: border-color, background, color, transform, box-shadow;
transition-duration: 0.15s;
transition-timing-function: ease;
}
.actions:hover {
@apply bg-accent-1 border-accent-4 text-accent-9;
transition: border-color;
z-index: 10;
}
.actions:focus {
@apply bg-accent-2 outline-none;
}
.quantity {
appearance: textfield;
@apply w-8 border-accents-2 border mx-3 rounded text-center text-sm text-black;
@apply w-8 border-accent-2 border mx-3 rounded text-center text-sm text-black;
}
.quantity::-webkit-outer-spin-button,

View File

@@ -3,7 +3,7 @@ import cn from 'classnames'
import Image from 'next/image'
import Link from 'next/link'
import s from './CartItem.module.css'
import { Trash, Plus, Minus } from '@components/icons'
import { Trash, Plus, Minus, Cross } from '@components/icons'
import { useUI } from '@components/ui/context'
import type { LineItem } from '@framework/types'
import usePrice from '@framework/product/use-price'
@@ -20,8 +20,10 @@ type ItemOption = {
const CartItem = ({
item,
currencyCode,
noEdit = false,
...rest
}: {
noEdit?: boolean
item: LineItem
currencyCode: string
}) => {
@@ -49,6 +51,7 @@ const CartItem = ({
setQuantity(Number(e.target.value))
}
}
const handleBlur = () => {
const val = Number(quantity)
@@ -56,6 +59,7 @@ const CartItem = ({
updateQuantity(val)
}
}
const increaseQuantity = (n = 1) => {
const val = Number(quantity) + n
@@ -64,6 +68,7 @@ const CartItem = ({
updateQuantity(val)
}
}
const handleRemove = async () => {
setRemoving(true)
@@ -87,75 +92,100 @@ const CartItem = ({
return (
<li
className={cn('flex flex-row space-x-8 py-8', {
'opacity-75 pointer-events-none': removing,
className={cn(s.root, {
'opacity-50 pointer-events-none': removing,
})}
{...rest}
>
<div className="w-16 h-16 bg-violet relative overflow-hidden cursor-pointer">
<Link href={`/product/${item.path}`}>
<Image
onClick={() => closeSidebarIfPresent()}
className={s.productImage}
width={150}
height={150}
src={item.variant.image!.url}
alt={item.variant.image!.altText}
unoptimized
/>
</Link>
<div className="flex flex-row space-x-4 py-4">
<div className="w-16 h-16 bg-violet relative overflow-hidden cursor-pointer">
<Link href={`/product/${item.path}`}>
<Image
onClick={() => closeSidebarIfPresent()}
className={s.productImage}
width={150}
height={150}
src={item.variant.image!.url}
alt={item.variant.image!.altText}
unoptimized
/>
</Link>
</div>
<div className="flex-1 flex flex-col text-base">
<Link href={`/product/${item.path}`}>
<span
className="font-medium cursor-pointer leading-6"
onClick={() => closeSidebarIfPresent()}
>
{item.name}
</span>
</Link>
{options && options.length > 0 ? (
<div className="">
{options.map((option: ItemOption, i: number) => (
<div
key={`${item.id}-${option.name}`}
className="text-sm font-semibold text-accent-7 inline-flex items-center justify-center"
>
{option.name}
{option.name === 'Color' ? (
<span
className="mx-2 rounded-full bg-transparent border w-5 h-5 p-1 text-accent-9 inline-flex items-center justify-center overflow-hidden"
style={{
backgroundColor: `${option.value}`,
}}
></span>
) : (
<span className="mx-2 rounded-full bg-transparent border h-5 p-1 text-accent-9 inline-flex items-center justify-center overflow-hidden">
{option.value}
</span>
)}
{i === options.length - 1 ? '' : <span className="mr-3" />}
</div>
))}
</div>
) : null}
</div>
<div className="flex flex-col justify-between space-y-2 text-sm">
<span>{price}</span>
</div>
</div>
<div className="flex-1 flex flex-col text-base">
<Link href={`/product/${item.path}`}>
<span
className="font-bold text-lg cursor-pointer leading-6"
onClick={() => closeSidebarIfPresent()}
>
{item.name}
</span>
</Link>
{options && options.length > 0 ? (
<div className="">
{options.map((option: ItemOption, i: number) => (
<span
key={`${item.id}-${option.name}`}
className="text-sm font-semibold text-accents-7"
>
{option.value}
{i === options.length - 1 ? '' : ', '}
</span>
))}
</div>
) : null}
<div className="flex items-center mt-3">
<button type="button" onClick={() => increaseQuantity(-1)}>
<Minus width={18} height={18} />
{!noEdit ? (
<div className="flex flex-row h-9">
<button className={s.actions} onClick={handleRemove}>
<Cross width={20} height={20} />
</button>
<label>
<label className="w-full border-accent-3 border ml-2">
<input
type="number"
max={99}
min={0}
className={s.quantity}
className="bg-transparent px-4 w-full h-full focus:outline-none"
value={quantity}
onChange={handleQuantity}
onBlur={handleBlur}
/>
</label>
<button type="button" onClick={() => increaseQuantity(1)}>
<button
type="button"
onClick={() => increaseQuantity(-1)}
className={s.actions}
style={{ marginLeft: '-1px' }}
>
<Minus width={18} height={18} />
</button>
<button
type="button"
onClick={() => increaseQuantity(1)}
className={cn(s.actions)}
style={{ marginLeft: '-1px' }}
>
<Plus width={18} height={18} />
</button>
</div>
</div>
<div className="flex flex-col justify-between space-y-2 text-base">
<span>{price}</span>
<button
className="flex justify-end outline-none"
onClick={handleRemove}
>
<Trash />
</button>
</div>
) : (
<div>x{quantity}</div>
)}
</li>
)
}

View File

@@ -1,5 +1,5 @@
.root {
@apply h-full flex flex-col;
@apply h-full flex flex-col relative w-full relative;
}
.root.empty {

View File

@@ -1,8 +1,8 @@
import { FC } from 'react'
import cn from 'classnames'
import Link from 'next/link'
import CartItem from '../CartItem'
import { FC } from 'react'
import s from './CartSidebarView.module.css'
import CartItem from '../CartItem'
import { Button } from '@components/ui'
import { UserNav } from '@components/common'
import { useUI } from '@components/ui/context'
@@ -11,7 +11,7 @@ import useCart from '@framework/cart/use-cart'
import usePrice from '@framework/product/use-price'
const CartSidebarView: FC = () => {
const { closeSidebar } = useUI()
const { closeSidebar, setSidebarView } = useUI()
const { data, isLoading, isEmpty } = useCart()
const { price: subTotal } = usePrice(
@@ -27,6 +27,7 @@ const CartSidebarView: FC = () => {
}
)
const handleClose = () => closeSidebar()
const goToCheckout = () => setSidebarView('CHECKOUT_VIEW')
const error = null
const success = null
@@ -43,9 +44,12 @@ const CartSidebarView: FC = () => {
<button
onClick={handleClose}
aria-label="Close panel"
className="hover:text-gray-500 transition ease-in-out duration-150"
className="hover:text-gray-500 transition ease-in-out duration-150 flex items-center focus:outline-none"
>
<Cross className="h-6 w-6" />
<span className="ml-2 text-accent-7 text-xs hover:text-gray-500">
Close
</span>
</button>
</div>
<div className="space-y-1">
@@ -62,7 +66,7 @@ const CartSidebarView: FC = () => {
<h2 className="pt-6 text-2xl font-bold tracking-wide text-center">
Your cart is empty
</h2>
<p className="text-accents-3 px-10 text-center pt-2">
<p className="text-accent-3 px-10 text-center pt-2">
Biscuit oat cake wafer icing ice cream tiramisu pudding cupcake.
</p>
</div>
@@ -90,13 +94,13 @@ const CartSidebarView: FC = () => {
<div className="px-4 sm:px-6 flex-1">
<Link href="/cart">
<h2
className="pt-1 pb-4 text-2xl leading-7 font-bold text-base tracking-wide cursor-pointer inline-block"
className="pt-1 pb-8 text-2xl font-semibold tracking-wide cursor-pointer inline-block"
onClick={handleClose}
>
My Cart
</h2>
</Link>
<ul className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accents-3 border-t border-accents-3">
<ul className="py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-3 border-accent-3">
{data!.lineItems.map((item: any) => (
<CartItem
key={item.id}
@@ -107,30 +111,41 @@ const CartSidebarView: FC = () => {
</ul>
</div>
<div className="flex-shrink-0 px-4 py-5 sm:px-6">
<div className="border-t border-accents-3">
<ul className="py-3">
<li className="flex justify-between py-1">
<span>Subtotal</span>
<span>{subTotal}</span>
</li>
<li className="flex justify-between py-1">
<span>Taxes</span>
<span>Calculated at checkout</span>
</li>
<li className="flex justify-between py-1">
<span>Estimated Shipping</span>
<span className="font-bold tracking-wide">FREE</span>
</li>
</ul>
<div className="flex justify-between border-t border-accents-3 py-3 font-bold mb-10">
<span>Total</span>
<span>{total}</span>
</div>
<div className="flex-shrink-0 px-6 py-6 sm:px-6 sticky z-20 bottom-0 w-full right-0 left-0 bg-accent-0 shadow-outline-normal text-sm">
<ul className="pb-2">
<li className="flex justify-between py-1">
<span>Subtotal</span>
<span>{subTotal}</span>
</li>
<li className="flex justify-between py-1">
<span>Taxes</span>
<span>Calculated at checkout</span>
</li>
<li className="flex justify-between py-1">
<span>Shipping</span>
<span className="font-bold tracking-wide">FREE</span>
</li>
</ul>
<div className="flex justify-between border-t border-accent-3 py-3 font-bold mb-2">
<span>Total</span>
<span>{total}</span>
</div>
<div>
{process.env.COMMERCE_CHECKOUT_ENABLED ? (
<Button
Component="a"
width="100%"
variant="ghost"
onClick={goToCheckout}
>
Continue to Checkout
</Button>
) : (
<Button href="/checkout" Component="a" width="100%">
Proceed to Checkout
</Button>
)}
</div>
<Button href="/checkout" Component="a" width="100%">
Proceed to Checkout
</Button>
</div>
</>
)}