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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
!.yarn/plugins
!.yarn/releases
!.yarn/versions
pnpm-lock.yaml

# testing
/coverage
Expand Down
7 changes: 6 additions & 1 deletion app/demo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Suspense, useState } from "react";

// Components
import CartDrawerItem from "@/components/cartDrawerItem/cartDrawerItem";
import CartDrawerItem from "@/components/cartDrawer/item/cartDrawerItem";
import CartItem from "@/components/cartItem";
import CommentCard from "@/components/commentCard/commentCard";
import ProductCard from "@/components/productCard";
Expand All @@ -20,6 +20,7 @@ import Footer from "@/components/layout/footer";
import Nav from "@/components/layout/nav";
import { SortingType } from "@/lib/types";
import Sorting from "@/components/pages/shop/sorting";
import CartDrawer from "@/components/cartDrawer/cartDrawer";

// --- Helper Component for Layout ---
const DemoSection = ({
Expand Down Expand Up @@ -361,6 +362,10 @@ export default function Page() {
</Suspense>
</div>
</DemoSection>

<DemoSection title={"Cart drawer"}>
<CartDrawer></CartDrawer>
</DemoSection>
</div>
<Footer />
</div>
Expand Down
3 changes: 2 additions & 1 deletion app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.129 0.042 264.695);
/*--foreground: oklch(0.129 0.042 264.695);*/
--foreground: #121729;
--card: oklch(1 0 0);
--card-foreground: oklch(0.129 0.042 264.695);
--popover: oklch(1 0 0);
Expand Down
176 changes: 176 additions & 0 deletions components/cartDrawer/cartDrawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
"use client";

// import {useRef, useState} from "react";
import {Check, ShoppingCart, X, Lock, Search} from "lucide-react";
import {Dialog} from "radix-ui";
import "./styles.css";
import {Button} from "@/components/ui/button";
import CartDrawerItem, {CartDrawerItemProps} from "@/components/cartDrawer/item/cartDrawerItem";
import Link from "next/link";

export default function CartDrawer() {
// const [isOpen, setIsOpen] = useState<boolean>(false);
// const quantityRef = useRef(null);
// const openCart = () => setIsOpen(true);
// const closeCart = () => setIsOpen(false);

const recentlyAddedItem: CartDrawerItemProps = {
title: "Versace Eros Flame",
productId: "drawer-001",
productCode: "01203213",
quantityInStock: 11,
imageUrl: "https://i.makeup.it/1/1x/1xkz6atfgthd.jpg",
volume: 30,
pricePerItem: 4999,
quantity: 1,
onDelete: () => console.log("Deleted"),
};
const items: CartDrawerItemProps[] = [
recentlyAddedItem,
...Array.from({length: 4}, () => ({
title: "Versace Eros Flame",
productId: "drawer-001",
productCode: "01203213",
quantityInStock: 11,
imageUrl: "https://i.makeup.it/1/1x/1xkz6atfgthd.jpg",
volume: 30,
pricePerItem: 4999,
quantity: 1,
onDelete: () => console.log("Deleted"),
}))
];

return (
<>
<Dialog.Root>
<Dialog.Trigger asChild>
<Button>Trigger cart drawer</Button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="dialog__overlay"/>
<Dialog.Content className="dialog__content">
{/* Description: hidden */}
<Dialog.Description className="hidden">
Manage your cart articles here.
</Dialog.Description>
{/* Header */}
<div className="flex items-center justify-between">
<div className="flex gap-10 items-center">
<Dialog.Title className="dialog__title">Shopping Cart</Dialog.Title>
{/* Quantity */}
<span className="p-2 bg-slate-600 rounded-[8px] text-base text-white leading-3">
{items.length}
</span>
</div>

{/* Close button */}
<Dialog.Close asChild>
<button
className="size-10 flex justify-center items-center rounded-[8px] hover:bg-gray-100"
>
<X className="size-8" strokeWidth={1.5}/>
</button>

</Dialog.Close>
</div>

{/* Conditional Rendering */}
{/* Handle empty and full cart states */}
{items.length === 0 ? (
<div className={"dialog__banner h-12 justify-center items-center gap-x-3 bg-gray-100! text-slate-500!"}>
<Search strokeWidth={2}></Search>
<span>
Shopping cart is empty for now.
</span>
</div>
) : (
<>
{/* Scrollable content */}
<div className="dialog__scrollable-container">

{/* Added item */}
<div className="flex flex-col gap-y-6">
<div className="dialog__banner">
<Check className={"class-6"} strokeWidth={1.5}></Check>
1 product added to cart
</div>

<CartDrawerItem
title={recentlyAddedItem.title}
productId={recentlyAddedItem.productId}
productCode={recentlyAddedItem.productCode}
quantityInStock={recentlyAddedItem.quantityInStock}
imageUrl={recentlyAddedItem.imageUrl}
volume={recentlyAddedItem.volume}
pricePerItem={recentlyAddedItem.pricePerItem}
quantity={recentlyAddedItem.quantity}
onDelete={recentlyAddedItem.onDelete}
/>
</div>

{/* All cart items */}
<div className="flex flex-col gap-y-6">
<h3 className={"text-xl leading-7 font-semibold"}>
All products ({items.length})
</h3>
<div className="flex flex-col gap-y-2">
{items.map((item, index) => (
<CartDrawerItem
key={item.productCode + index}
title={item.title}
productId={item.productId}
productCode={item.productCode}
quantityInStock={item.quantityInStock}
imageUrl={item.imageUrl}
volume={item.volume}
pricePerItem={item.pricePerItem}
quantity={item.quantity}
onDelete={item.onDelete}
/>
))}
</div>
</div>
</div>
</>
)}

{/* Total */}
<div className="dialog__total">
<div className="w-full flex flex-col gap-y-4">
<div className="total__row">
<span className={"font-semibold"}>Total:</span>
<span className={"text-xl font-semibold"}>€8256.99</span>
</div>
<div className="grid grid-cols-2 gap-2">
<Button
size="lg"
variant="outline"
className="h-[44px] w-full text-base"
asChild
>
<Link href={"/account/cart"}>
<ShoppingCart size={16} strokeWidth={2}></ShoppingCart>
{" "}
<span>View Cart</span>
</Link>
</Button>
<Button
size={"lg"}
className={"w-full h-[44px] text-base bg-main"}
asChild
>
<Link href={"/account/checkout"}>
<Lock size={16} strokeWidth={2}></Lock>
{" "}
<span>Checkout</span>
</Link>
</Button>
</div>
</div>
</div>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@reference "../../app/globals.css";
@reference "../../../app/globals.css";

.not-available {
@apply border-none hover:bg-[#f7f7f7];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { Trash2 } from "lucide-react";
import Image from "next/image";
import { useState } from "react";
import Stepper from "../stepper/stepper";
import Stepper from "../../stepper/stepper";
import "./cartDrawerItem.css";
import Link from "next/link";

Expand Down Expand Up @@ -71,24 +71,24 @@ export default function CartDrawerItem({
src={imageUrl}
alt={`${title} ${volume} ml`}
fill
sizes={"72px"}
className="object-contain"
loading="eager"
priority={false}
></Image>
</Link>

<div className="w-full flex flex-col gap-5">
<div className="w-full overflow-hidden flex flex-col gap-5">
<div className="flex justify-between items-baseline">
<Link
href={productLink}
className="item__text flex flex-col gap-y-2.5"
className="overflow-hidden item__text flex flex-col gap-y-2.5"
>
<h4 className="font-semibold leading-3">
<h4 className="font-semibold leading-3 overflow-hidden truncate">
{title}
</h4>
<div className="flex gap-4 text-xs font-semibold">
<span className="text-gray-600">
Product code -&nbsp;
<span className="text-black">
{productCode}
</span>
Expand Down
46 changes: 46 additions & 0 deletions components/cartDrawer/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@reference "../../app/globals.css";

.dialog__overlay {
@apply fixed bg-black/30 backdrop-blur-md inset-0;
}
.dialog__overlay[data-state="open"] {
@apply animate-in fade-in duration-300;
}
.dialog__overlay[data-state="closed"] {
@apply animate-out fade-out duration-300;
}

.dialog__content {
@apply fixed h-full w-full max-w-[440px] flex flex-col gap-y-6 top-0 right-0;
@apply bg-white px-8 pt-10 pb-[168px];
@apply focus:outline-none
}
.dialog__content[data-state="open"] {
@apply animate-in slide-in-from-right duration-300;
}
.dialog__content[data-state="closed"] {
@apply animate-out slide-out-to-right duration-300;
}

.dialog__scrollable-container {
@apply overflow-x-hidden overflow-y-auto;
@apply flex flex-col gap-y-6 py-4;
}

.dialog__title {
@apply text-2xl font-semibold;
}

.dialog__banner {
@apply w-full py-2.5 px-5 flex gap-6 rounded-md bg-accent-light text-sm text-accent font-medium leading-6;
}

.dialog__total {
@apply absolute bottom-0 left-0 w-full h-[168px] p-10;
@apply flex justify-center items-center;
@apply bg-white shadow-[0px_-2px_4px_0px_rgba(0,0,0,0.12)];
}

.total__row {
@apply flex py-1 justify-between;
}
1 change: 1 addition & 0 deletions components/cartItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default function CartItem({
src={imageUrl}
alt={`${name} ${volume} ml`}
fill
sizes={"100px"}
className="object-contain"
loading="eager"
priority={false}
Expand Down
4 changes: 0 additions & 4 deletions components/filterDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,6 @@ interface RangeSliderProps {
function RangeSlider({ min, max, value, onChange }: RangeSliderProps) {
const [localValue, setLocalValue] = useState(value);

useEffect(() => {
setLocalValue(value);
}, [value]);

const handleInputChange = (index: 0 | 1, newValue: string) => {
const num = parseInt(newValue);
if (isNaN(num)) return;
Expand Down
1 change: 1 addition & 0 deletions components/productCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default function ProductCard({
src={imageUrl}
alt={`${name} ${volume} ml`}
fill
sizes={"200px"}
className="object-contain"
priority={false}
/>
Expand Down
1 change: 1 addition & 0 deletions components/searchResultItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default function SearchResultItem({
src={imageUrl}
alt={`${title} ${volume} ml`}
fill
sizes={"100px"}
className="object-contain"
loading="eager"
priority={false}
Expand Down
2 changes: 1 addition & 1 deletion components/stepper/stepper.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
@apply h-10 w-[70px] my-text-h5;
}
.stepper_sm .stepper__display {
@apply h-[18px] w-[60px] text-xs font-semibold;
@apply h-[18px] w-[40px] text-xs font-semibold;
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"@prisma/client": "^6.19.0",
"@prisma/extension-accelerate": "^2.0.2",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-slot": "^1.2.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
Expand Down
Loading
Loading