diff --git a/components/commerce/cart-drawer.tsx b/components/commerce/cart-drawer.tsx index a2cb2e5..ae79f05 100644 --- a/components/commerce/cart-drawer.tsx +++ b/components/commerce/cart-drawer.tsx @@ -4,17 +4,39 @@ import React from 'react'; import { useShopifyCart, redirectToCheckout } from '@/hooks/use-shopify-cart'; import { Button } from '@/components/ui/button'; import { Spinner } from '@/components/ui/spinner'; +import { Loader } from '@/components/ui/loader'; +import { + RiCloseLine, + RiImageLine, + RiSubtractLine, + RiAddLine, +} from '@remixicon/react'; +import { + Empty, + EmptyHeader, + EmptyTitle, + EmptyDescription, + EmptyContent, +} from '@/components/ui/empty'; import { Sheet, SheetContent, SheetHeader, SheetTitle, - SheetBody, - SheetFooter, } from '@/components/ui/sheet'; const CartDrawer: React.FC = () => { - const { isOpen, closeCart, items, itemCount, totalAmount, checkoutUrl, loading, removeItem, updateItemQuantity } = useShopifyCart(); + const { + isOpen, + closeCart, + items, + itemCount, + totalAmount, + checkoutUrl, + loading, + removeItem, + updateItemQuantity, + } = useShopifyCart(); const handleCheckout = () => { if (checkoutUrl) { @@ -22,42 +44,57 @@ const CartDrawer: React.FC = () => { } }; - const getItemImage = (item: typeof items[0]) => { + const getItemImage = (item: (typeof items)[0]) => { return item.merchandise.image?.url; }; - const getSelectedOptions = (item: typeof items[0]) => { + const getSelectedOptions = (item: (typeof items)[0]) => { return item.merchandise.selectedOptions ?? []; }; return ( - !open && closeCart()} side="right"> - + !open && closeCart()}> + {/* Header */} - - - Shopping Cart ({itemCount}) - + +
+ + Shopping Cart ({itemCount}) + + +
{/* Cart Items */} - +
{loading && items.length === 0 ? (
) : items.length === 0 ? ( -
- -

Your cart is empty

-

Add some products to get started!

- -
+ + + + Your cart is empty + + Add some products to get started! + + + + + ) : (
{items.map((item) => { @@ -65,7 +102,10 @@ const CartDrawer: React.FC = () => { const selectedOptions = getSelectedOptions(item); return ( -
+
{/* Product Image */}
{image ? ( @@ -76,7 +116,7 @@ const CartDrawer: React.FC = () => { /> ) : (
- +
)}
@@ -93,7 +133,9 @@ const CartDrawer: React.FC = () => { {selectedOptions.map((option, index) => ( {option.value} - {index < selectedOptions.length - 1 ? ' / ' : ''} + {index < selectedOptions.length - 1 + ? ' / ' + : ''} ))}
@@ -103,25 +145,29 @@ const CartDrawer: React.FC = () => {
{item.quantity}
@@ -141,9 +187,9 @@ const CartDrawer: React.FC = () => { variant="ghost" size="icon-sm" disabled={loading} - className="text-gray-400 hover:text-red-500" + className="text-gray-400 hover:text-gray-700" > - +
@@ -151,11 +197,11 @@ const CartDrawer: React.FC = () => { })}
)} -
+ {/* Footer - Checkout Section */} {items.length > 0 && ( - +
{/* Subtotal */}
Subtotal @@ -178,7 +224,7 @@ const CartDrawer: React.FC = () => { > {loading ? ( - + Processing... ) : ( @@ -186,15 +232,11 @@ const CartDrawer: React.FC = () => { )} -
- +
)}
diff --git a/components/ui/sheet.tsx b/components/ui/sheet.tsx index 7c84c8f..7bf2857 100644 --- a/components/ui/sheet.tsx +++ b/components/ui/sheet.tsx @@ -1,303 +1,134 @@ -"use client"; +"use client" -import React, { useState, useCallback, useContext, createContext } from 'react'; -import { createPortal } from 'react-dom'; -import { motion, AnimatePresence } from 'framer-motion'; -import { cn } from '@/lib/utils'; +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { XIcon } from "lucide-react" -interface SheetContextType { - open: boolean; - setOpen: (open: boolean) => void; - side: 'top' | 'right' | 'bottom' | 'left'; +import { cn } from "@/lib/utils" + +function Sheet({ ...props }: React.ComponentProps) { + return } -const SheetContext = createContext(undefined); - -function useSheet() { - const context = useContext(SheetContext); - if (!context) { - throw new Error('Sheet components must be used within a Sheet'); - } - return context; +function SheetTrigger({ + ...props +}: React.ComponentProps) { + return } -interface SheetProps { - open?: boolean; - onOpenChange?: (open: boolean) => void; - children: React.ReactNode; - side?: 'top' | 'right' | 'bottom' | 'left'; +function SheetClose({ + ...props +}: React.ComponentProps) { + return } -function Sheet({ - open: controlledOpen, - onOpenChange, - children, - side = 'right', -}: SheetProps) { - const [internalOpen, setInternalOpen] = useState(false); - const isControlled = controlledOpen !== undefined; - const open = isControlled ? controlledOpen : internalOpen; - - const setOpen = useCallback( - (newOpen: boolean) => { - if (!isControlled) { - setInternalOpen(newOpen); - } - onOpenChange?.(newOpen); - }, - [isControlled, onOpenChange] - ); - - return ( - - {children} - - ); -} - -function SheetTrigger( - props: React.ButtonHTMLAttributes & { asChild?: boolean } -) { - const { setOpen } = useSheet(); - const { children, asChild, ...rest } = props; - - if (asChild && React.isValidElement(children)) { - return React.cloneElement(children as React.ReactElement, { - ...rest, - onClick: (e: React.MouseEvent) => { - setOpen(true); - children.props.onClick?.(e); - }, - }); - } - - return ( - - ); -} - -function SheetPortal({ children }: { children: React.ReactNode }) { - if (typeof document === 'undefined') return null; - return createPortal(children, document.body); +function SheetPortal({ + ...props +}: React.ComponentProps) { + return } function SheetOverlay({ className, - onClick, ...props -}: React.HTMLAttributes) { - const { setOpen } = useSheet(); - +}: React.ComponentProps) { return ( - { - setOpen(false); - onClick?.(e); - }} + className={cn( + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", + className + )} {...props} /> - ); -} - -interface SheetContentProps extends React.HTMLAttributes { - showCloseButton?: boolean; + ) } function SheetContent({ className, children, + side = "right", showCloseButton = true, ...props -}: SheetContentProps) { - const { open, setOpen, side } = useSheet(); - - const sideClasses = { - right: 'inset-y-0 right-0 h-full w-3/4 sm:max-w-sm border-l', - left: 'inset-y-0 left-0 h-full w-3/4 sm:max-w-sm border-r', - top: 'inset-x-0 top-0 h-auto border-b', - bottom: 'inset-x-0 bottom-0 h-auto border-t', - }; - - const slideVariants = { - right: { - initial: { x: 400, opacity: 0 }, - animate: { x: 0, opacity: 1 }, - exit: { x: 400, opacity: 0 }, - }, - left: { - initial: { x: -400, opacity: 0 }, - animate: { x: 0, opacity: 1 }, - exit: { x: -400, opacity: 0 }, - }, - top: { - initial: { y: -400, opacity: 0 }, - animate: { y: 0, opacity: 1 }, - exit: { y: -400, opacity: 0 }, - }, - bottom: { - initial: { y: 400, opacity: 0 }, - animate: { y: 0, opacity: 1 }, - exit: { y: 400, opacity: 0 }, - }, - }; - +}: React.ComponentProps & { + side?: "top" | "right" | "bottom" | "left" + showCloseButton?: boolean +}) { return ( - - {open ? ( - <> - - - {children} - {showCloseButton && ( - - )} - - - ) : null} - + + + {children} + {showCloseButton && ( + + + Close + + )} + - ); + ) } -function SheetClose( - props: React.ButtonHTMLAttributes & { asChild?: boolean } -) { - const { setOpen } = useSheet(); - const { children, asChild, ...rest } = props; - - if (asChild && React.isValidElement(children)) { - return React.cloneElement(children as React.ReactElement, { - ...rest, - onClick: (e: React.MouseEvent) => { - setOpen(false); - children.props.onClick?.(e); - }, - }); - } - - return ( - - ); -} - -function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) { +function SheetHeader({ className, ...props }: React.ComponentProps<"div">) { return (
- ); + ) } -function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) { +function SheetFooter({ className, ...props }: React.ComponentProps<"div">) { return (
- ); + ) } -function SheetTitle({ className, ...props }: React.ComponentProps<'h2'>) { +function SheetTitle({ + className, + ...props +}: React.ComponentProps) { return ( -

- ); + ) } -function SheetDescription({ className, ...props }: React.ComponentProps<'p'>) { +function SheetDescription({ + className, + ...props +}: React.ComponentProps) { return ( -

- ); -} - -interface SheetBodyProps extends React.HTMLAttributes { - children: React.ReactNode; -} - -function SheetBody({ className, children, ...props }: SheetBodyProps) { - return ( -

- {children} -
- ); + ) } export { @@ -309,8 +140,4 @@ export { SheetFooter, SheetTitle, SheetDescription, - SheetBody, - SheetPortal, - SheetOverlay, - AnimatePresence, -}; +}