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
32 changes: 21 additions & 11 deletions src/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getActiveProducts, salesAPI } from '@/services/api.service';
import type { Product } from '@/types/index';
import { PolarProduct } from '@/types/polar';
import { useAuth } from '@/context/auth-store';
import { ShoppingCart } from 'lucide-react';

interface HomePageProps {
tab?: string;
Expand Down Expand Up @@ -154,7 +155,6 @@ const HomePage: React.FC<HomePageProps> = ({
const handleProductClick = (productUntyped: Product | PolarProduct) => {
const product = productUntyped as Product;
setSelectedProduct(product);
setIsDrawerOpen(true);
setCartItems((prevCart) => {
const pid = String(product.id); // stable local id for UI/cart identity
const polarProductId = (product as any).polar_id || String(product.id); // original Polar ID for API calls
Expand Down Expand Up @@ -263,6 +263,8 @@ const HomePage: React.FC<HomePageProps> = ({
setCartItems([]);
};

const totalItems = cartItems.length;

// Function to reload products
const reloadProducts = async () => {
try {
Expand Down Expand Up @@ -346,22 +348,16 @@ const HomePage: React.FC<HomePageProps> = ({
loading={loading}
/>

<div
className={`pt-6 px-4 transition-all duration-300 ${
isDrawerOpen && !isPaymentOpen && !isSuccessOpen
? 'md:mr-[40%] lg:mr-[33.333333%]'
: ''
}`}
>
<div className='mx-auto max-w-7xl sm:px-6 lg:px-8'>
<div className='mb-6'>
<div className="pt-6 px-4 transition-all duration-300">
<div className="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div className="mb-6">
<HomeStats
count={filteredProducts.length}
searchTerm={activeSearchTerm}
/>
</div>

<div className='p-6 bg-white border rounded-lg border-gray-300 animate-scale-in'>
<div className="p-6 bg-white border rounded-lg border-gray-300 animate-scale-in">
<ProductGrid
products={filteredProducts}
onProductClick={handleProductClick}
Expand All @@ -370,6 +366,20 @@ const HomePage: React.FC<HomePageProps> = ({
</div>
</div>

<button
onClick={() => setIsDrawerOpen(true)}
className="fixed bottom-4 right-4 bg-[#F88612] text-white p-3 rounded-full shadow-lg hover:bg-[#d17110] transition-colors"
>
<div className="relative">
<ShoppingCart size={24} />
{totalItems > 0 && (
<span className="absolute -top-2 -right-2 bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center">
{totalItems}
</span>
)}
</div>
</button>

<SalesDrawer
isOpen={isDrawerOpen}
onClose={handleCloseDrawer}
Expand Down
229 changes: 112 additions & 117 deletions src/components/SalesDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,143 +47,138 @@ const SalesDrawer: React.FC<SalesDrawerProps> = ({

return (
<>
<div
className={`fixed inset-0 bg-black/40 backdrop-blur-sm transition-opacity duration-300 z-40 ${
isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'
}`}
onClick={onClose}
/>

<aside
className={`fixed top-0 right-0 h-full w-full sm:w-96 bg-white border-l border-[#CBD5E1] transform transition-transform duration-300 ease-in-out z-50 flex flex-col ${
isOpen ? 'translate-x-0' : 'translate-x-full'
}`}
>
<div className="flex items-center justify-between p-4 border-b border-[#CBD5E1] bg-[#F9FAFB]">
<h2 className="text-lg font-semibold text-black animate-slide-in-left">
Shopping Cart
</h2>
<button
onClick={onClose}
className="p-2 transition-all duration-300 rounded-full hover:bg-gray-50 hover:scale-110 icon-bounce"
>
<X size={20} className="text-black" />
</button>
</div>

{/* Content */}
<div className="flex-1 p-4 overflow-y-auto">
{cartItems.length > 0 ? (
<div className="space-y-4 animate-stagger">
{cartItems.map((item, index) => (
<div
key={`cart-item-${index}-${item.id || 'unknown'}`}
className="p-4 bg-white border rounded-lg shadow-sm border-[#CBD5E1] hover-lift"
>
<div className="flex items-center justify-between mb-2">
<div>
<h3 className="font-medium text-black text-glow">
{item.name}
</h3>
{item.recurring_interval && (
<span className="text-xs text-blue-600 bg-blue-100 px-2 py-1 rounded-full">
{item.recurring_interval}ly
</span>
)}
</div>
<button
onClick={() => removeCartItem(item.id)}
className="transition-colors duration-300 text-error hover:text-error-600 icon-bounce"
>
<Trash2 size={16} color="red" />
</button>
</div>
<div className="flex items-center justify-between p-4 border-b border-[#CBD5E1] bg-[#F9FAFB]">
<h2 className="text-lg font-semibold text-black animate-slide-in-left">
Shopping Cart
</h2>
<button
onClick={onClose}
className="p-2 transition-all duration-300 rounded-full hover:bg-gray-50 hover:scale-110 icon-bounce"
>
<X size={20} className="text-black" />
</button>
</div>

<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<button
onClick={() => updateCartItemQuantity(item.id, -1)}
disabled={item.quantity <= 1}
className="flex items-center justify-center w-8 h-8 transition-all duration-300 bg-gray-100 rounded-full hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed hover:scale-110"
>
<Minus size={14} />
</button>
<span className="w-8 font-medium text-center text-black">
{item.quantity}
</span>
{/* Content */}
<div className="flex-1 p-4 overflow-y-auto">
{cartItems.length > 0 ? (
<div className="space-y-4 animate-stagger">
{cartItems.map((item, index) => (
<div
key={`cart-item-${index}-${item.id || 'unknown'}`}
className="p-4 bg-white border rounded-lg shadow-sm border-[#CBD5E1] hover-lift"
>
<div className="flex items-center justify-between mb-2">
<div>
<h3 className="font-medium text-black text-glow">
{item.name}
</h3>
{item.recurring_interval && (
<span className="text-xs text-blue-600 bg-blue-100 px-2 py-1 rounded-full">
{item.recurring_interval}ly
</span>
)}
</div>
<button
onClick={() => updateCartItemQuantity(item.id, 1)}
disabled={
item.quantity >=
(item.productData?.metadata?.quantity || item.stock)
}
className="flex items-center justify-center w-8 h-8 transition-all duration-300 bg-gray-100 rounded-full hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed hover:scale-110"
onClick={() => removeCartItem(item.id)}
className="transition-colors duration-300 text-error hover:text-error-600 icon-bounce"
>
<Plus size={14} />
<Trash2 size={16} color="red" />
</button>
</div>
<div className="text-right">
<div className="font-medium text-black">
${(item.price * item.quantity).toFixed(2)}
</div>
<div className="text-sm text-gray-500">
${item.price.toFixed(2)} each

<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<button
onClick={() => updateCartItemQuantity(item.id, -1)}
disabled={item.quantity <= 1}
className="flex items-center justify-center w-8 h-8 transition-all duration-300 bg-gray-100 rounded-full hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed hover:scale-110"
>
<Minus size={14} />
</button>
<span className="w-8 font-medium text-center text-black">
{item.quantity}
</span>
<button
onClick={() => updateCartItemQuantity(item.id, 1)}
disabled={
item.quantity >=
(item.productData?.metadata?.quantity || item.stock)
}
className="flex items-center justify-center w-8 h-8 transition-all duration-300 bg-gray-100 rounded-full hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed hover:scale-110"
>
<Plus size={14} />
</button>
</div>
<div className="text-xs text-gray-400">
Stock:{' '}
{item.productData?.metadata?.quantity || item.stock}
<div className="text-right">
<div className="font-medium text-black">
${(item.price * item.quantity).toFixed(2)}
</div>
<div className="text-sm text-gray-500">
${item.price.toFixed(2)} each
</div>
<div className="text-xs text-gray-400">
Stock:{' '}
{item.productData?.metadata?.quantity || item.stock}
</div>
</div>
</div>
</div>
</div>
))}
</div>
) : (
<div className="py-12 text-center animate-fade-in">
<ShoppingCart size={48} className="mx-auto mb-4 text-gray-300" />
<h3 className="mb-2 text-lg font-medium text-black">
Your cart is empty
</h3>
<p className="text-gray-500">Add some products to get started</p>
</div>
)}
))}
</div>
) : (
<div className="py-12 text-center animate-fade-in">
<ShoppingCart size={48} className="mx-auto mb-4 text-gray-300" />
<h3 className="mb-2 text-lg font-medium text-black">
Your cart is empty
</h3>
<p className="text-gray-500">Add some products to get started</p>
</div>
)}

{/* Summary */}
{cartItems.length > 0 && (
<div className="mt-6 space-y-4 animate-fade-in">
{/* Subtotal */}
<div className="p-4 border rounded-lg bg-gray-50 border-[#CBD5E1]">
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span className="text-[#CBD5E1]">Subtotal:</span>
<span className="text-black">${subtotal.toFixed(2)}</span>
</div>
{/* Summary */}
{cartItems.length > 0 && (
<div className="mt-6 space-y-4 animate-fade-in">
{/* Subtotal */}
<div className="p-4 border rounded-lg bg-gray-50 border-[#CBD5E1]">
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span className="text-[#CBD5E1]">Subtotal:</span>
<span className="text-black">${subtotal.toFixed(2)}</span>
</div>

<div className="flex justify-between pt-2 text-lg font-bold border-t border-[#CBD5E1]">
<span className="text-black">Total:</span>
<span className="text-success">${cartAmount.toFixed(2)}</span>
<div className="flex justify-between pt-2 text-lg font-bold border-t border-[#CBD5E1]">
<span className="text-black">Total:</span>
<span className="text-success">
${cartAmount.toFixed(2)}
</span>
</div>
</div>
</div>
</div>

{/* Payment Button */}
<button
onClick={handlePaymentClick}
className="w-full py-4 font-medium text-white transition-all duration-300 bg-[#F88612] hover:bg-[#d17110] rounded-lg"
>
Proceed to Payment
</button>
{/* Payment Button */}
<button
onClick={handlePaymentClick}
className="w-full py-4 font-medium text-white transition-all duration-300 bg-[#F88612] hover:bg-[#d17110] rounded-lg"
>
Proceed to Payment
</button>

{/* Clear Cart */}
<button
onClick={clearCart}
className="w-full py-3 font-medium transition-all duration-300 bg-gray-100 rounded-lg hover:bg-gray-200 text-black"
>
Clear Cart
</button>
</div>
)}
</div>
{/* Clear Cart */}
<button
onClick={clearCart}
className="w-full py-3 font-medium transition-all duration-300 bg-gray-100 rounded-lg hover:bg-gray-200 text-black"
>
Clear Cart
</button>
</div>
)}
</div>
</aside>
</>
);
Expand Down