Skip to content
Open
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
197 changes: 197 additions & 0 deletions RestroHub-FrontEnd/src/components/customer/CartDrawer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { useCart } from '@context/CartContext';

const formatPrice = (price) => {
const num = parseFloat(price);
return isNaN(num) ? '0.00' : num.toFixed(2);
};

const CartDrawer = ({ isOpen, onClose }) => {
const { items, removeItem, updateQuantity, clearCart, itemCount, totalAmount } = useCart();

if (!isOpen) return null;

return (
<>
<div
style={{
position: 'fixed', inset: 0, zIndex: 1100,
background: 'rgba(0,0,0,0.4)', backdropFilter: 'blur(4px)',
}}
onClick={onClose}
/>

<div
style={{
position: 'fixed', top: 0, right: 0, bottom: 0, zIndex: 1101,
width: '100%', maxWidth: '420px',
background: '#fff', display: 'flex', flexDirection: 'column',
boxShadow: '-8px 0 30px rgba(0,0,0,0.15)',
animation: 'cartSlideIn 0.3s ease-out',
}}
>
<style>{`
@keyframes cartSlideIn {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
`}</style>

<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '16px 20px', borderBottom: '1px solid #e5e7eb',
}}>
<h2 style={{ fontSize: '18px', fontWeight: 700, margin: 0, color: '#111827' }}>
Your Cart ({itemCount})
</h2>
<button
onClick={onClose}
style={{
width: '36px', height: '36px', borderRadius: '50%',
border: 'none', background: '#f3f4f6', cursor: 'pointer',
fontSize: '18px', display: 'flex', alignItems: 'center',
justifyContent: 'center', color: '#6b7280',
}}
>
</button>
</div>

{items.length === 0 ? (
<div style={{
flex: 1, display: 'flex', flexDirection: 'column',
alignItems: 'center', justifyContent: 'center',
padding: '40px 20px', color: '#9ca3af', textAlign: 'center',
}}>
<span style={{ fontSize: '48px', marginBottom: '16px' }}>🛒</span>
<p style={{ fontSize: '16px', fontWeight: 600, margin: '0 0 8px', color: '#374151' }}>
Your cart is empty
</p>
<p style={{ fontSize: '14px', margin: 0 }}>
Add items from the menu to get started
</p>
</div>
) : (
<>
<div style={{ flex: 1, overflowY: 'auto', padding: '12px 20px' }}>
{items.map((item) => (
<div
key={item.foodId}
style={{
display: 'flex', gap: '12px', padding: '12px 0',
borderBottom: '1px solid #f3f4f6',
}}
>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<span style={{
display: 'inline-block', width: '10px', height: '10px',
borderRadius: '50%', flexShrink: 0,
background: item.isVeg ? '#22c55e' : '#ef4444',
}} />
<p style={{
margin: 0, fontWeight: 600, fontSize: '14px', color: '#111827',
}}>
{item.name}
</p>
</div>
<p style={{
margin: '4px 0 0', fontSize: '14px', fontWeight: 700, color: '#f59e0b',
}}>
₹{formatPrice(item.price)}
</p>
</div>

<div style={{
display: 'flex', alignItems: 'center', gap: '8px', flexShrink: 0,
}}>
<div style={{
display: 'flex', alignItems: 'center', gap: '4px',
border: '1px solid #e5e7eb', borderRadius: '8px', overflow: 'hidden',
}}>
<button
onClick={() => updateQuantity(item.foodId, item.quantity - 1)}
style={{
border: 'none', background: '#f9fafb', cursor: 'pointer',
padding: '6px 10px', fontSize: '16px', fontWeight: 600,
color: '#374151', lineHeight: 1,
}}
>
</button>
<span style={{
minWidth: '28px', textAlign: 'center', fontSize: '14px',
fontWeight: 600, color: '#111827',
}}>
{item.quantity}
</span>
<button
onClick={() => updateQuantity(item.foodId, item.quantity + 1)}
style={{
border: 'none', background: '#f9fafb', cursor: 'pointer',
padding: '6px 10px', fontSize: '16px', fontWeight: 600,
color: '#374151', lineHeight: 1,
}}
>
+
</button>
</div>
<button
onClick={() => removeItem(item.foodId)}
style={{
border: 'none', background: 'none', cursor: 'pointer',
padding: '4px', fontSize: '16px', color: '#9ca3af', lineHeight: 1,
}}
title="Remove item"
>
🗑️
</button>
</div>
</div>
))}
</div>

<div style={{
borderTop: '1px solid #e5e7eb', padding: '16px 20px',
}}>
<div style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
marginBottom: '12px',
}}>
<span style={{ fontSize: '16px', fontWeight: 600, color: '#111827' }}>
Total
</span>
<span style={{ fontSize: '20px', fontWeight: 700, color: '#f59e0b' }}>
₹{formatPrice(totalAmount)}
</span>
</div>
<div style={{ display: 'flex', gap: '8px' }}>
<button
onClick={clearCart}
style={{
flex: 1, padding: '10px', borderRadius: '10px',
border: '1px solid #e5e7eb', background: '#fff',
cursor: 'pointer', fontWeight: 600, fontSize: '14px',
color: '#6b7280',
}}
>
Clear
</button>
<button
style={{
flex: 2, padding: '10px', borderRadius: '10px',
border: 'none', background: 'linear-gradient(135deg, #f59e0b, #d97706)',
color: '#fff', cursor: 'pointer', fontWeight: 700, fontSize: '14px',
}}
>
Place Order
</button>
</div>
</div>
</>
)}
</div>
</>
);
};

export default CartDrawer;
32 changes: 32 additions & 0 deletions RestroHub-FrontEnd/src/components/customer/MenuSection.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { useSiteData } from '@context/SiteContext.jsx';
import { useCart } from '@context/CartContext';

// ============================================
// MENU SECTION COMPONENT
Expand All @@ -8,6 +9,7 @@ import { useSiteData } from '@context/SiteContext.jsx';

const MenuSection = () => {
const { siteData } = useSiteData();
const { addItem } = useCart();
const [activeCategory, setActiveCategory] = useState('starters');

if (!siteData) return null;
Expand Down Expand Up @@ -54,6 +56,18 @@ const MenuSection = () => {
))}
</div>
)}
<button
onClick={() => addItem({
foodId: item.foodId || item.id || index,
name: item.name,
price: item.price === 'varies' ? 0 : parseFloat(item.price) || 0,
imageUrl: item.imageUrl || '',
isVeg: item.isVeg ?? true,
})}
className="menu-add-btn"
>
Add to Cart
</button>
</div>
<p className="menu-item-price font-heading">
{item.price === 'varies' ? item.price : `$${item.price}`}
Expand Down Expand Up @@ -204,6 +218,24 @@ const MenuSection = () => {
color: var(--color-primary);
white-space: nowrap;
}
.menu-add-btn {
margin-top: var(--spacing-sm, 8px);
padding: 6px 16px;
font-size: var(--text-xs, 12px);
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
border: 1px solid var(--color-primary, #f59e0b);
background: transparent;
color: var(--color-primary, #f59e0b);
border-radius: var(--radius-sm, 4px);
cursor: pointer;
transition: all var(--transition-normal, 0.3s);
}
.menu-add-btn:hover {
background: var(--color-primary, #f59e0b);
color: #fff;
}

@media (min-width: 768px) {
.menu-item-price {
Expand Down
39 changes: 38 additions & 1 deletion RestroHub-FrontEnd/src/components/customer/Navigation.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { useSiteData } from '@context/SiteContext.jsx';
import { useCart } from '@context/CartContext';

const Navigation = () => {
const Navigation = ({ onCartClick }) => {
const { siteData } = useSiteData();
const { itemCount } = useCart();
const navigate = useNavigate();
const [scrolled, setScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
Expand Down Expand Up @@ -45,6 +47,23 @@ const Navigation = () => {
))}
</div>

<button
onClick={onCartClick}
className="nav-cart-btn"
aria-label={`Cart with ${itemCount} items`}
>
<svg width="22" height="22" viewBox="0 0 24 24" fill="none"
stroke="currentColor" strokeWidth="2" strokeLinecap="round"
strokeLinejoin="round">
<circle cx="9" cy="21" r="1"/>
<circle cx="20" cy="21" r="1"/>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/>
</svg>
{itemCount > 0 && (
<span className="nav-cart-badge">{itemCount}</span>
)}
</button>

<button
className="nav-mobile-btn"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
Expand Down Expand Up @@ -113,8 +132,26 @@ const Navigation = () => {
align-items: center;
gap: var(--spacing-xl, 20px);
}
.nav-cart-btn {
position: relative; display: none; align-items: center; justify-content: center;
background: none; border: 1px solid var(--color-border-primary, #d1d5db);
border-radius: 50%; width: 40px; height: 40px; cursor: pointer;
color: var(--color-text-primary, #333); transition: all 0.2s;
}
.nav-cart-btn:hover {
border-color: var(--color-primary, #f59e0b);
color: var(--color-primary, #f59e0b);
}
.nav-cart-badge {
position: absolute; top: -4px; right: -4px;
background: var(--color-primary, #f59e0b); color: #fff;
font-size: 11px; font-weight: 700; min-width: 18px; height: 18px;
border-radius: 9px; display: flex; align-items: center;
justify-content: center; line-height: 1;
}
@media (min-width: 768px) {
.nav-links { display: flex; }
.nav-cart-btn { display: flex; }
}
.nav-link {
color: var(--color-text-primary, #333);
Expand Down
Loading