Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions app/account/cart/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use server";

/* Components */
import Breadcrumbs, {BreadcrumbItem} from "@/components/ui/breadcrumbs";
import CartPageClient from "@/components/pages/account/cart/cartPageClient";
import Nav from "@/components/layout/nav";

/* Lib */
import getCartItems from "@/lib/api/cartItems";

export default async function CartPage() {
const cartItems = await getCartItems("12344321");

const breadcrumbsItems: BreadcrumbItem[] = [
{ label: "Scent", href: "/" },
{ label: "Cart", href: "/account/cart" },
];

return (
<>
<div className="mt-2 mb-14">
<Nav />
</div>
<main className="container mx-auto px-8 mb-40">
{/* Header */}
<div className="flex flex-row justify-between items-center mb-[100px]">
<h1 className="text-[40px] font-semibold leading-12">
Cart
</h1>
<Breadcrumbs items={breadcrumbsItems} />
</div>

{/* Interactive Client Part */}
{/* Cart items list & total*/}
<CartPageClient cartItems={cartItems} />
</main>
</>
);
}
6 changes: 4 additions & 2 deletions app/demo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export default function Page() {
<DemoSection title="Cart Items (Main)">
<div className="flex flex-col gap-6">
<CartItem
title="Versace Eros Flame"
name="Versace Eros Flame"
productId="cart-001"
productCode="01203213"
quantityInStock={11}
Expand All @@ -189,9 +189,10 @@ export default function Page() {
pricePerItem={4999}
quantity={1}
onDelete={() => console.log("Deleted")}
onQuantityChange={() => console.log("QuantityChange")}
/>
<CartItem
title="Expensive Limited Edition"
name="Expensive Limited Edition"
productId="cart-002"
productCode="01203213"
quantityInStock={0}
Expand All @@ -200,6 +201,7 @@ export default function Page() {
pricePerItem={11999}
quantity={1}
onDelete={() => console.log("Deleted")}
onQuantityChange={() => console.log("QuantityChange")}
/>
</div>
</DemoSection>
Expand Down
186 changes: 90 additions & 96 deletions components/cartItem.tsx
Original file line number Diff line number Diff line change
@@ -1,126 +1,120 @@
"use client";

import { AvailabilityType } from "@/lib/types";
import {AvailabilityType} from "@/lib/types";
import {
getAvailability,
getAvailabilityClass,
getEuro,
getAvailability,
getAvailabilityClass,
getEuro,
} from "@/lib/utils";
import { Trash2 } from "lucide-react";
import {Trash2} from "lucide-react";
import Image from "next/image";
import { useState } from "react";
import Stepper from "./stepper/stepper";
import Link from "next/link";

export interface CartItemProps {
imageUrl: string;
title: string;
volume: number;
productId: string;
productCode: string;
quantity: number;
quantityInStock: number;
pricePerItem: number; // cents
onDelete: () => void;
imageUrl: string;
name: string;
volume: number;
productId: string;
productCode: string;
quantity: number;
quantityInStock: number;
pricePerItem: number; // cents
onDelete: (id: string) => void;
onQuantityChange: (id: string, newValue: number) => void;
}

export default function CartItem({
imageUrl,
title,
volume,
productId,
productCode,
quantity,
quantityInStock,
pricePerItem,
onDelete,
}: CartItemProps) {
const [isDeleted, setIsDeleted] = useState<boolean>(false);
const [availability] = useState<AvailabilityType>(
getAvailability(quantityInStock)
);
const availabilityClass: string = getAvailabilityClass(availability);
const productLink: string = `/shop/product/${productId}`;
imageUrl,
name,
volume,
productId,
productCode,
quantity,
quantityInStock,
pricePerItem,
onDelete,
onQuantityChange,
}: CartItemProps) {
const availability: AvailabilityType = getAvailability(quantityInStock);
const availabilityClass: string = getAvailabilityClass(availability);
const productLink: string = `/shop/product/${productId}`;

const [newQuantity, setNewQuantity] = useState<number>(quantity);
const [totalPrice, setTotalPrice] = useState<number>(
pricePerItem * quantity
);
const totalPrice = pricePerItem * quantity;

const handleQuantity = (e: number) => {
setNewQuantity(e);
setTotalPrice(e * pricePerItem);
};
const handleQuantityChange = (delta: number) => {
console.log("Changed value by:", delta);
onQuantityChange(productId, delta);
};

const handleDelete = () => {
setIsDeleted(true);
onDelete();
};
const handleDelete = () => {
onDelete(productId);
};

return (
<>
{!isDeleted && (
<div className="grid grid-cols-[3fr_1fr_1fr] gap-x-4 items-center w-full bg-white text-main border-gray-200 border-2 p-10 rounded-[8px]">
<Link href={productLink} className="flex gap-x-10">
<div className="relative overflow-hidden size-[100px] aspect-square flex shrink-0 justify-center items-center">
<Image
src={imageUrl}
alt={`${title} ${volume} ml`}
fill
className="object-contain"
loading="eager"
priority={false}
></Image>
</div>
<div className="flex flex-col justify-between min-w-[240px]">
<div className="">
<h3 className="text-2xl font-semibold mb-3 leading-8">
{title}
</h3>
<div className="flex justify-between font-semibold leading-3">
return (
<>
<div
className="grid grid-cols-[3fr_1fr_1fr] gap-x-4 items-center w-full bg-white text-main border-gray-200 border-2 p-10 rounded-[8px]">
<Link href={productLink} className="flex gap-x-10">
<div
className="relative overflow-hidden size-[100px] aspect-square flex shrink-0 justify-center items-center">
<Image
src={imageUrl}
alt={`${name} ${volume} ml`}
fill
className="object-contain"
loading="eager"
priority={false}
></Image>
</div>
<div className="flex flex-col justify-between min-w-[240px]">
<div className="">
<h3 className="text-2xl font-semibold mb-3 leading-8">
{name}
</h3>
<div className="flex justify-between font-semibold leading-3">
<span className="text-gray-500">
{volume} ml
</span>
<span className="text-gray-500">
<span className="text-gray-500">
Product Code&nbsp;-&nbsp;
<span className="text-main">
<span className="text-main">
{productCode}
</span>
</span>
</div>
</div>
</div>
</div>

<span
className={`text-xl font-semibold capitalize leading-7 ${availabilityClass}`}
>
<span
className={`text-xl font-semibold capitalize leading-7 ${availabilityClass}`}
>
{availability}
</span>
</div>
</Link>
<Stepper
value={newQuantity}
onChange={(e) => handleQuantity(e)}
min={1}
max={quantityInStock}
disabled={quantityInStock == 0}
></Stepper>
<div className="flex gap-x-[calc(24px+5vw)] items-center">
</div>
</Link>
<Stepper
value={quantity}
onChange={(delta) => handleQuantityChange(delta)}
min={1}
max={quantityInStock}
disabled={quantityInStock == 0}
></Stepper>
<div className="flex gap-x-[calc(24px+5vw)] items-center">
<span className="my-text-h4">
{getEuro(totalPrice)}
</span>
<button
title="Remove from cart"
aria-label="Remove from cart"
onClick={handleDelete}
>
<Trash2
strokeWidth={1.5}
className="hover:stroke-red-600 transition-colors"
></Trash2>
</button>
</div>
</div>
)}
</>
);
<button
title="Remove from cart"
aria-label="Remove from cart"
onClick={handleDelete}
>
<Trash2
strokeWidth={1.5}
className="hover:stroke-red-600 transition-colors"
></Trash2>
</button>
</div>
</div>
</>
);
}
2 changes: 1 addition & 1 deletion components/layout/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ function SearchDropdown({ isOpen, query }: { isOpen: boolean; query: string }) {
function CartLink({ items = 0 }: { items?: number }) {
return (
<Link
href={"/cart"}
href={"/account/cart"}
aria-label="Go to cart"
className="relative button-icon flex items-center justify-center"
>
Expand Down
Loading
Loading