diff --git a/client/src/features/home/FeaturedItems.jsx b/client/src/features/home/FeaturedItems.jsx
index 35cf0b2..9bbdd2f 100644
--- a/client/src/features/home/FeaturedItems.jsx
+++ b/client/src/features/home/FeaturedItems.jsx
@@ -2,12 +2,14 @@ import React, { useEffect, useMemo, useState } from 'react';
import MenuCard from '../../components/ui/MenuCard';
import api from '../../lib/axios';
-const FeaturedItems = ({ outletId, showAll = false }) => {
+const FeaturedItems = ({ outletId, showAll = false, searchQuery = '', categoryFilter = 'all', dietFilter = 'all' }) => {
const [items, setItems] = useState([]);
- const [searchTerm, setSearchTerm] = useState('');
- const [category, setCategory] = useState('all');
- const [diet, setDiet] = useState('all'); // 'all' | 'veg' | 'non-veg'
- const [tag, setTag] = useState('all');
+ const [tag] = useState('all');
+
+ // Use external filters if provided
+ const activeSearch = searchQuery;
+ const activeCategory = categoryFilter;
+ const activeDiet = dietFilter;
useEffect(() => {
const fetchMenu = async () => {
@@ -34,31 +36,16 @@ const FeaturedItems = ({ outletId, showAll = false }) => {
const filteredItems = useMemo(() => {
if (!outletId) return [];
- const term = searchTerm.trim().toLowerCase();
+ const term = activeSearch.trim().toLowerCase();
return items.filter((item) => {
- const matchesCategory = category === 'all' || item.category === category;
- const matchesDiet = diet === 'all' || (diet === 'veg' ? item.isVeg === true : item.isVeg === false);
+ const matchesCategory = activeCategory === 'all' || item.category === activeCategory;
+ const matchesDiet = activeDiet === 'all' || (activeDiet === 'veg' ? item.isVeg === true : item.isVeg === false);
const matchesTag = tag === 'all' || (Array.isArray(item.tags) && item.tags.includes(tag));
const matchesSearch =
!term || item.name.toLowerCase().includes(term) || (item.description || '').toLowerCase().includes(term);
return matchesCategory && matchesDiet && matchesTag && matchesSearch;
});
- }, [items, searchTerm, category, diet, tag, outletId]);
-
- const categories = useMemo(() => {
- const unique = Array.from(new Set(items.map((item) => item.category).filter(Boolean)));
- return ['all', ...unique];
- }, [items]);
-
- const tags = useMemo(() => {
- const unique = new Set();
- items.forEach((item) => {
- if (Array.isArray(item.tags)) {
- item.tags.forEach((t) => t && unique.add(t));
- }
- });
- return ['all', ...Array.from(unique)];
- }, [items]);
+ }, [items, activeSearch, activeCategory, activeDiet, tag, outletId]);
const displayItems = showAll ? filteredItems : filteredItems.slice(0, 8);
@@ -66,53 +53,6 @@ const FeaturedItems = ({ outletId, showAll = false }) => {
return (
-
-
-
setSearchTerm(e.target.value)}
- placeholder="Search dishes..."
- className="w-full sm:w-1/2 bg-zinc-800 text-white text-sm rounded-lg px-3 py-2 border border-white/10 focus:border-amber-500 focus:outline-none"
- />
-
-
-
-
-
-
-
-
-
-
{displayItems.map((item) => (
diff --git a/client/src/features/home/TrendingItems.jsx b/client/src/features/home/TrendingItems.jsx
index eef7377..36cade3 100644
--- a/client/src/features/home/TrendingItems.jsx
+++ b/client/src/features/home/TrendingItems.jsx
@@ -4,7 +4,7 @@ import api from '../../lib/axios';
import { Flame } from 'lucide-react';
import MenuCard from '../../components/ui/MenuCard';
-const TrendingItems = ({ outletId }) => {
+const TrendingItems = ({ outletId, searchQuery = '', categoryFilter = 'all', dietFilter = 'all' }) => {
const { addToCart } = useCart();
const [trendingItems, setTrendingItems] = useState([]);
@@ -26,8 +26,19 @@ const TrendingItems = ({ outletId }) => {
fetchTrendingItems();
}, [outletId]);
- // Don't show section if no trending items found
- if (trendingItems.length === 0) {
+ // Filter trending items based on search and filters
+ const filteredTrendingItems = trendingItems.filter((item) => {
+ const matchesSearch =
+ !searchQuery ||
+ item.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ (item.description || '').toLowerCase().includes(searchQuery.toLowerCase());
+ const matchesCategory = categoryFilter === 'all' || item.category === categoryFilter;
+ const matchesDiet = dietFilter === 'all' || (dietFilter === 'veg' ? item.isVeg === true : item.isVeg === false);
+ return matchesSearch && matchesCategory && matchesDiet;
+ });
+
+ // Don't show section if no trending items found after filtering
+ if (filteredTrendingItems.length === 0) {
return null;
}
@@ -40,7 +51,7 @@ const TrendingItems = ({ outletId }) => {
- {trendingItems.map((item) => (
+ {filteredTrendingItems.map((item) => (
{
+ const timer = setTimeout(() => {
+ setDebouncedValue(value);
+ }, delay);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [value, delay]);
+
+ return debouncedValue;
+}
diff --git a/client/src/pages/Order/OrderSession.jsx b/client/src/pages/Order/OrderSession.jsx
index 1328d76..ea267a8 100644
--- a/client/src/pages/Order/OrderSession.jsx
+++ b/client/src/pages/Order/OrderSession.jsx
@@ -3,6 +3,8 @@ import { useParams, useNavigate } from 'react-router-dom';
import ClassicLoader from '@/components/ui/loader';
import { useOutlet } from '../../context/OutletContextValues';
import { useCart } from '../../context/CartContextValues';
+import { useTheme } from '../../context/useTheme';
+import { useDebounce } from '../../hooks/useDebounce';
import api from '../../lib/axios';
import toast from 'react-hot-toast';
import { AnimatePresence, motion } from 'framer-motion'; // eslint-disable-line no-unused-vars
@@ -14,9 +16,11 @@ import {
ChevronDown,
Search,
Menu as MenuIcon,
- X,
+ Sun,
+ Moon,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import CartDrawer from '../../components/cart/CartDrawer';
import FeaturedItems from '../../features/home/FeaturedItems';
@@ -28,6 +32,7 @@ const OrderSession = () => {
const navigate = useNavigate();
const { setOutlet, selectedOutlet } = useOutlet();
const { setTableInfo, tableInfo, setIsCartOpen, cartItems } = useCart();
+ const { isDarkMode, toggleTheme } = useTheme();
const initializationRef = useRef(false);
const [activeTab, setActiveTab] = useState('menu'); // 'menu' | 'orders' | 'bill'
@@ -36,6 +41,15 @@ const OrderSession = () => {
const [orders, setOrders] = useState([]);
const [isOrdersLoading, setIsOrdersLoading] = useState(false);
const [expandedOrders, setExpandedOrders] = useState([]);
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+ // Search and filter states
+ const [searchQuery, setSearchQuery] = useState('');
+ const [categoryFilter, setCategoryFilter] = useState('all');
+ const [dietFilter, setDietFilter] = useState('all');
+
+ // Debounced search query
+ const debouncedSearch = useDebounce(searchQuery, 500);
// --- 1. Session Initialization ---
useEffect(() => {
@@ -134,37 +148,86 @@ const OrderSession = () => {
{/* 1. Header (Sticky) */}
-