first commit

This commit is contained in:
2026-01-17 14:17:42 +05:30
commit 0f194eb9e7
328 changed files with 73544 additions and 0 deletions

View File

@@ -0,0 +1,366 @@
'use client'
import Link from 'next/link'
import Image from 'next/image'
import { useState, useEffect } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { ChevronDown, Menu, X, Wheat, Leaf, Package, Building2, Settings, ShoppingBag, LogOut, LucideIcon } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
import { useSession, signOut } from 'next-auth/react'
import CartSidebar from '@/components/shop/CartSidebar'
import MegaMenu from '@/components/layout/MegaMenu'
import { isFeatureEnabled } from '@/lib/business-config'
interface MenuItem {
name: string
href: string
description: string
}
interface MenuCategory {
name: string
icon: LucideIcon
items: MenuItem[]
}
interface MegaMenuConfig {
title: string
type: 'categories'
categories: MenuCategory[]
}
export function Header() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [activeDropdown, setActiveDropdown] = useState<string | null>(null)
const [isScrolled, setIsScrolled] = useState(false)
const navItems = [
// { name: 'Home', href: '/' },
{ name: 'Recipes', href: '/recipes' },
// { name: 'About', href: '/about' },
{ name: 'Contact', href: '/contact' },
]
const megaMenus: Record<string, MegaMenuConfig> = {
products: {
title: 'Products',
type: 'categories' as const,
categories: [] // Will be populated dynamically by MegaMenu component
},
company: {
title: 'Company',
type: 'categories' as const,
categories: [
{
name: 'About Us',
icon: Building2,
items: [
{ name: 'Our Story', href: '/about', description: 'Company history and mission' },
{ name: 'Our Founder', href: '/about/founder', description: 'Meet our visionary leader' },
{ name: 'Certifications', href: '/about/certifications', description: 'Industry recognition' },
]
},
{
name: 'Business',
icon: Settings,
items: [
{ name: 'Partnership', href: '/partnership', description: 'Join our network' },
{ name: 'Wholesaler', href: '/wholesaler', description: 'Wholesaler program' },
{ name: 'Sustainability', href: '/sustainability', description: 'Environmental commitment' },
]
},
]
}
}
const { data: session } = useSession()
const adminNavigation = [
{ name: 'Admin Dashboard', href: '/admin', icon: Settings },
{ name: 'Manage Products', href: '/admin/products', icon: Package },
{ name: 'Manage Orders', href: '/admin/orders', icon: ShoppingBag },
]
const memberNavigation = [
{ name: 'Dashboard', href: '/dashboard', icon: Settings },
{ name: 'My Orders', href: '/dashboard/orders', icon: ShoppingBag },
{ name: 'Profile', href: '/dashboard/profile', icon: Settings },
]
// Scroll detection for sticky header
useEffect(() => {
const handleScroll = () => {
const scrollTop = window.scrollY
const scrolled = scrollTop > 0
setIsScrolled(scrolled)
// Add/remove class to body for content padding
if (scrolled) {
document.body.classList.add('header-sticky')
} else {
document.body.classList.remove('header-sticky')
}
}
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
document.body.classList.remove('header-sticky')
}
}, [])
useEffect(() => {
if (mobileMenuOpen) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = 'unset'
}
return () => {
document.body.style.overflow = 'unset'
}
}, [mobileMenuOpen])
const handleMouseEnter = (dropdown: string) => {
setActiveDropdown(dropdown)
}
const handleMouseLeave = () => {
setActiveDropdown(null)
}
const handleMobileMenuClick = () => {
setMobileMenuOpen(!mobileMenuOpen)
}
const handleMobileLinkClick = () => {
setMobileMenuOpen(false)
}
return (
<nav className={`transition-all duration-300 ${
isScrolled
? 'fixed top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-b border-slate-200 shadow-lg'
: 'relative bg-white border-b border-slate-200'
}`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className={`flex justify-between items-center transition-all duration-300 ${
isScrolled ? 'h-20' : 'h-24'
}`}>
{/* Logo */}
<Link href="/" className="flex-shrink-0 flex items-center z-10">
<div className="flex items-center space-x-3">
<Image
src="/kashmina-logo.png"
alt="PADMAAJA RASOOI PVT. LTD."
width={150}
height={150}
className="object-contain"
/>
{/* <div className="flex flex-col">
<span className="text-lg font-bold text-slate-800 transition-colors duration-300 leading-tight">
KASHMINA RICE
</span>
<span className="text-xs uppercase text-slate-600 transition-colors duration-300 leading-tight">
&quot;Premium Rice&quot;
</span>
</div> */}
</div>
</Link>
{/* Desktop Navigation */}
<div className="hidden lg:flex items-center space-x-8">
{/* Regular Nav Items */}
{navItems.map(item => (
<Link
key={item.name}
href={item.href}
className="text-base font-medium text-slate-700 hover:text-emerald-600 transition-colors duration-200"
>
{item.name}
</Link>
))}
{/* Mega Menu Items */}
{Object.entries(megaMenus).map(([key, menu]) => (
<div
key={key}
className="relative"
onMouseEnter={() => handleMouseEnter(key)}
onMouseLeave={handleMouseLeave}
>
<button
className={`flex items-center space-x-1 text-base font-medium text-slate-700 hover:text-emerald-600 transition-colors duration-200 ${
activeDropdown === key ? 'text-emerald-600' : ''
}`}
>
<span>{menu.title}</span>
<ChevronDown className={`w-4 h-4 transition-transform duration-200 ${
activeDropdown === key ? 'rotate-180' : ''
}`} />
</button>
{/* Mega Menu Dropdown */}
<MegaMenu
menuKey={key}
menu={menu}
isActive={activeDropdown === key}
onClose={() => setActiveDropdown(null)}
/>
</div>
))}
<div className="flex items-center space-x-4">
{/* B2C Feature - Cart Sidebar (Disabled for B2B mode) */}
{isFeatureEnabled('cart') && <CartSidebar />}
{session ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-10 w-10 rounded-full">
<Avatar className="h-10 w-10">
<AvatarImage src={session.user.image || ''} alt={session.user.name || ''} />
<AvatarFallback>
{session.user.name?.[0] || session.user.email?.[0] || 'U'}
</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="end" forceMount>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">{session.user.name}</p>
<p className="text-xs leading-none text-muted-foreground">
{session.user.email}
</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
{session.user.role === 'ADMIN' && adminNavigation.map((item) => (
<DropdownMenuItem key={item.name} asChild>
<Link href={item.href} className="flex items-center">
<item.icon className="mr-2 h-4 w-4" />
{item.name}
</Link>
</DropdownMenuItem>
))}
{(session.user.role === 'MEMBER' || session.user.role === 'ADMIN') &&
memberNavigation.map((item) => (
<DropdownMenuItem key={item.name} asChild>
<Link href={item.href} className="flex items-center">
<item.icon className="mr-2 h-4 w-4" />
{item.name}
</Link>
</DropdownMenuItem>
))}
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => signOut()}>
<LogOut className="mr-2 h-4 w-4" />
Log out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
) : (
<div className="flex items-center space-x-2">
<Button variant="ghost" className="h-10 px-4 py-2 text-base font-medium" asChild>
<Link href="/auth/signin">Sign In</Link>
</Button>
<Button className="h-10 px-4 py-2 text-base font-medium" asChild>
<Link href="/auth/signup">Sign Up</Link>
</Button>
</div>
)}
</div>
</div>
{/* Mobile Menu Button */}
<div className="lg:hidden">
<button
onClick={handleMobileMenuClick}
className="p-4 rounded-lg text-slate-700 hover:bg-slate-100 transition-colors duration-200 touch-manipulation min-w-[48px] min-h-[48px] flex items-center justify-center"
aria-label="Toggle mobile menu"
>
{mobileMenuOpen ? <X className="w-7 h-7" /> : <Menu className="w-7 h-7" />}
</button>
</div>
</div>
</div>
{/* Mobile Menu */}
<AnimatePresence>
{mobileMenuOpen && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.3 }}
className="lg:hidden border-t bg-white border-slate-200 shadow-lg relative z-50"
>
<div className="px-4 py-6 space-y-6 max-h-[80vh] overflow-y-auto">
{/* Regular Nav Items */}
{navItems.map(item => (
<Link
key={item.name}
href={item.href}
className="mobile-nav-item block text-lg font-medium text-slate-700 hover:text-emerald-600 transition-colors duration-200 py-3 px-2 rounded-lg hover:bg-slate-50 touch-manipulation"
onClick={handleMobileLinkClick}
>
{item.name}
</Link>
))}
{/* Mobile Mega Menu Items */}
{Object.entries(megaMenus).map(([key, menu]) => (
<div key={key} className="space-y-3">
<h3 className="font-semibold text-slate-800 text-lg sm:text-xl">{menu.title}</h3>
{menu.type === 'categories' ? (
// Products with Categories - Mobile Responsive
<div className="space-y-4">
{menu.categories?.map((category: MenuCategory, idx: number) => {
const IconComponent = category.icon
return (
<div key={idx} className="space-y-2">
<div className="flex items-center space-x-2 text-emerald-600 font-medium text-base sm:text-lg">
<IconComponent className="w-4 h-4 flex-shrink-0" />
<span>{category.name}</span>
</div>
<div className="pl-6 space-y-1">
{category.items.map((item: MenuItem, itemIdx: number) => (
<Link
key={itemIdx}
href={item.href}
className="mobile-nav-item block text-base text-slate-600 hover:text-emerald-600 hover:bg-slate-50 transition-colors duration-200 py-2 px-2 rounded-md touch-manipulation"
onClick={handleMobileLinkClick}
>
<div className="font-medium">{item.name}</div>
<div className="text-xs text-slate-500 mt-0.5">{item.description}</div>
</Link>
))}
</div>
</div>
)
})}
</div>
) : null}
</div>
))}
{/* Mobile CTA */}
<Link href="/contact#quote" onClick={handleMobileLinkClick}>
<Button className="w-full bg-emerald-600 text-white hover:bg-emerald-700 rounded-xl px-6 py-4 mt-6 font-medium text-lg touch-manipulation">
Get a Quote
</Button>
</Link>
</div>
</motion.div>
)}
</AnimatePresence>
</nav>
)
}