<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="generator" content="Hostinger Horizons" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hostinger Horizons</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
{
"name": "web-app",
"type": "module",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite --host :: --port 3000",
"build": "node tools/generate-llms.js || true && vite build",
"preview": "vite preview --host :: --port 3000",
"lint": "eslint . --quiet",
"lint:warn": "eslint ."
},
"dependencies": {
"@emotion/is-prop-valid": "^1.4.0",
"@radix-ui/react-alert-dialog": "^1.1.4",
"@radix-ui/react-avatar": "^1.1.2",
"@radix-ui/react-checkbox": "^1.1.3",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-dropdown-menu": "^2.1.4",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-slider": "^1.2.2",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"framer-motion": "^11.15.0",
"lucide-react": "^0.469.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet": "^6.1.0",
"react-router-dom": "^6.16.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@babel/generator": "^7.26.3",
"@babel/parser": "^7.26.3",
"@babel/traverse": "^7.26.4",
"@babel/types": "^7.26.3",
"@types/node": "^20.17.10",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.1",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^5.1.0",
"globals": "^15.14.0",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
"terser": "^5.37.0",
"vite": "^4.4.5"
}
}
};
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ['class'],
content: [
'./pages/**/*.{js,jsx}',
'./components/**/*.{js,jsx}',
'./app/**/*.{js,jsx}',
'./src/**/*.{js,jsx}',
],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px',
},
},
extend: {
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
keyframes: {
'accordion-down': {
from: { height: 0 },
to: { height: 'var(--radix-accordion-content-height)' },
},
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 },
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out',
},
},
},
plugins: [require('tailwindcss-animate')],
};
export default App;
export default CallToAction;
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { Facebook, Instagram, Youtube, Mail, Phone, Video } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/use-toast';
const Footer = () => {
const [email, setEmail] = useState('');
const { toast } = useToast();
const handleSubscribe = (e) => {
e.preventDefault();
if (email) {
toast({
title: "Subscribed!",
description: "Thank you for subscribing to our newsletter.",
});
setEmail('');
}
};
return (
<footer className="bg-gray-50 border-t border-gray-200 mt-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{/* Brand Section */}
<div>
<span className="text-xl font-bold bg-gradient-to-r from-purple-600 to-purple-800 bg-clip-text text-transparent">
BinNaveed.Pk
</span>
<p className="mt-4 text-sm text-gray-600">
Celebrating tradition with contemporary elegance. Premium Pakistani Shalwar Kameez for men and women.
</p>
<div className="flex space-x-4 mt-6">
<a href="https://www.facebook.com/binnaveed.pk" target="_blank" rel="noopener noreferrer" className="bg-white p-2 rounded-full shadow-sm text-gray-500 hover:text-blue-600 hover:shadow-md transition-all">
<Facebook className="h-5 w-5" />
</a>
<a href="https://www.instagram.com/binnaveed.pk_" target="_blank" rel="noopener noreferrer" className="bg-white p-2 rounded-full shadow-sm text-gray-500 hover:text-pink-600 hover:shadow-md transition-all">
<Instagram className="h-5 w-5" />
</a>
<a href="https://www.tiktok.com/@binnaveed.pk" target="_blank" rel="noopener noreferrer" className="bg-white p-2 rounded-full shadow-sm text-gray-500 hover:text-black hover:shadow-md transition-all">
<Video className="h-5 w-5" />
</a>
<a href="https://www.youtube.com/@binnaveed.pk" target="_blank" rel="noopener noreferrer" className="bg-white p-2 rounded-full shadow-sm text-gray-500 hover:text-red-600 hover:shadow-md transition-all">
<Youtube className="h-5 w-5" />
</a>
</div>
</div>
{/* Quick Links */}
<div>
<span className="text-sm font-semibold text-gray-900 uppercase tracking-wider">
Quick Links
</span>
<ul className="mt-4 space-y-2">
<li>
<Link to="/" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Home
</Link>
</li>
<li>
<Link to="/men" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Men's Collection
</Link>
</li>
<li>
<Link to="/women" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Women's Collection
</Link>
</li>
<li>
<Link to="/about" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
About Us
</Link>
</li>
<li>
<Link to="/contact" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Contact
</Link>
</li>
</ul>
</div>
{/* Customer Service */}
<div>
<span className="text-sm font-semibold text-gray-900 uppercase tracking-wider">
Customer Service
</span>
<ul className="mt-4 space-y-2">
<li>
<Link to="/faq" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
FAQ
</Link>
</li>
<li>
<Link to="/shipping" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Shipping Info
</Link>
</li>
<li>
<Link to="/return-policy" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Return Policy
</Link>
</li>
<li>
<Link to="/privacy-policy" className="text-sm text-gray-600 hover:text-purple-600 transition-colors">
Privacy Policy
</Link>
</li>
</ul>
</div>
{/* Contact & Newsletter */}
<div>
<span className="text-sm font-semibold text-gray-900 uppercase tracking-wider">
Stay Connected
</span>
<div className="mt-4 space-y-3">
<a href="https://wa.me/923025327880" className="flex items-center text-sm text-gray-600 hover:text-purple-600 transition-colors">
<Phone className="h-4 w-4 mr-2" />
03025327880
</a>
<a href="mailto:binnaveed.pk@outlook.com" className="flex items-center text-sm text-gray-600 hover:text-purple-600 transition-colors">
<Mail className="h-4 w-4 mr-2" />
binnaveed.pk@outlook.com
</a>
</div>
<form onSubmit={handleSubscribe} className="mt-4">
<p className="text-sm text-gray-600 mb-2">Subscribe to our newsletter</p>
<div className="flex gap-2">
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Your email"
className="flex-1 px-3 py-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
required
/>
<Button type="submit" size="sm" className="bg-purple-600 hover:bg-purple-700">
Subscribe
</Button>
</div>
</form>
</div>
</div>
<div className="mt-8 pt-8 border-t border-gray-200">
<p className="text-center text-sm text-gray-600">
© {new Date().getFullYear()} BinNaveed.Pk. All rights reserved.
</p>
</div>
</div>
</footer>
);
};
export default Footer;
export default HeroImage;
import React, { useState, useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { ShoppingBag, Menu, X } from 'lucide-react';
import { useCart } from '@/contexts/CartContext';
import { Button } from '@/components/ui/button';
const Navigation = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const location = useLocation();
const { getCartCount } = useCart();
const cartCount = getCartCount();
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 20);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
useEffect(() => {
setIsMobileMenuOpen(false);
}, [location]);
const navLinks = [
{ name: 'Home', path: '/' },
{ name: "Men's", path: '/men' },
{ name: "Women's", path: '/women' },
{ name: 'About', path: '/about' },
{ name: 'Contact', path: '/contact' }
];
const supportLinks = [
{ name: 'FAQ', path: '/faq' },
{ name: 'Shipping', path: '/shipping' },
{ name: 'Returns', path: '/return-policy' },
{ name: 'Privacy', path: '/privacy-policy' }
];
return (
<nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
isScrolled ? 'bg-white shadow-md' : 'bg-white/95 backdrop-blur-sm'
}`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo */}
<Link to="/" className="flex items-center">
<span className="text-2xl font-bold bg-gradient-to-r from-purple-600 to-purple-800 bg-clip-text text-transparent">
BinNaveed.Pk
</span>
</Link>
{/* Desktop Navigation */}
<div className="hidden md:flex items-center space-x-8">
{navLinks.map((link) => (
<Link
key={link.path}
to={link.path}
className={`text-sm font-medium transition-colors duration-200 relative ${
location.pathname === link.path
? 'text-purple-600'
: 'text-gray-700 hover:text-purple-600'
}`}
>
{link.name}
{location.pathname === link.path && (
<motion.div
layoutId="activeLink"
className="absolute -bottom-1 left-0 right-0 h-0.5 bg-purple-600"
initial={false}
transition={{ type: 'spring', stiffness: 380, damping: 30 }}
/>
)}
</Link>
))}
</div>
{/* Cart Icon */}
<Link to="/cart" className="relative">
<Button variant="ghost" size="icon" className="relative">
<ShoppingBag className="h-5 w-5" />
{cartCount > 0 && (
<motion.span
initial={{ scale: 0 }}
animate={{ scale: 1 }}
className="absolute -top-1 -right-1 bg-purple-600 text-white text-xs font-bold rounded-full h-5 w-5 flex items-center justify-center"
>
{cartCount}
</motion.span>
)}
</Button>
</Link>
{/* Mobile Menu Button */}
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="md:hidden p-2 rounded-lg hover:bg-gray-100 transition-colors"
>
{isMobileMenuOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
</button>
</div>
</div>
{/* Mobile Menu */}
<AnimatePresence>
{isMobileMenuOpen && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.3 }}
className="md:hidden bg-white border-t border-gray-200 max-h-[80vh] overflow-y-auto"
>
<div className="px-4 py-4 space-y-3">
{navLinks.map((link) => (
<Link
key={link.path}
to={link.path}
className={`block px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
location.pathname === link.path
? 'bg-purple-50 text-purple-600'
: 'text-gray-700 hover:bg-gray-50'
}`}
>
{link.name}
</Link>
))}
{/* Support Links in Mobile Menu */}
<div className="pt-4 mt-4 border-t border-gray-100">
<p className="px-4 text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">Support</p>
{supportLinks.map((link) => (
<Link
key={link.path}
to={link.path}
className="block px-4 py-2 rounded-lg text-sm font-medium text-gray-600 hover:bg-gray-50 hover:text-purple-600"
>
{link.name}
</Link>
))}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</nav>
);
};
export default Navigation;
export default ProductCard;
export default WelcomeMessage;
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { CreditCard, Truck, Landmark, Wallet } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
const CheckoutForm = ({ onSubmit, isSubmitting }) => {
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
email: '',
phone: '',
address: '',
city: '',
province: '',
postalCode: '',
country: 'Pakistan',
paymentMethod: 'cod',
cardNumber: '',
cardExpiry: '',
cardCvc: ''
});
const [errors, setErrors] = useState({});
const validateForm = () => {
const newErrors = {};
if (!formData.firstName.trim()) newErrors.firstName = 'First name is required';
if (!formData.lastName.trim()) newErrors.lastName = 'Last name is required';
if (!formData.email.trim()) {
newErrors.email = 'Email is required';
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = 'Email is invalid';
}
if (!formData.phone.trim()) newErrors.phone = 'Phone number is required';
if (!formData.address.trim()) newErrors.address = 'Street address is required';
if (!formData.city.trim()) newErrors.city = 'City is required';
if (!formData.province.trim()) newErrors.province = 'Province/State is required';
if (!formData.postalCode.trim()) newErrors.postalCode = 'Postal code is required';
if (formData.paymentMethod === 'card') {
if (!formData.cardNumber.trim()) newErrors.cardNumber = 'Card number is required';
if (!formData.cardExpiry.trim()) newErrors.cardExpiry = 'Expiry date is required';
if (!formData.cardCvc.trim()) newErrors.cardCvc = 'CVC is required';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validateForm()) {
onSubmit(formData);
} else {
// Shake animation or scroll to error could be added here
const firstError = document.querySelector('.text-red-500');
if (firstError) {
firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
if (errors[name]) {
setErrors(prev => ({ ...prev, [name]: null }));
}
};
const paymentMethods = [
{ id: 'card', label: 'Credit/Debit Card', icon: CreditCard },
{ id: 'bank', label: 'Bank Transfer', icon: Landmark },
{ id: 'cod', label: 'Cash on Delivery', icon: Wallet },
];
return (
<form onSubmit={handleSubmit} className="space-y-8">
{/* Customer Info */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-gray-800 flex items-center gap-2">
<span className="flex items-center justify-center w-6 h-6 rounded-full bg-purple-100 text-purple-600 text-sm">1</span>
Customer Information
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
label="First Name" name="firstName" value={formData.firstName}
onChange={handleChange} error={errors.firstName} placeholder="John"
/>
<FormField
label="Last Name" name="lastName" value={formData.lastName}
onChange={handleChange} error={errors.lastName} placeholder="Doe"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
label="Email" name="email" type="email" value={formData.email}
onChange={handleChange} error={errors.email} placeholder="john@example.com"
/>
<FormField
label="Phone" name="phone" type="tel" value={formData.phone}
onChange={handleChange} error={errors.phone} placeholder="0300 1234567"
/>
</div>
</div>
{/* Shipping Address */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-gray-800 flex items-center gap-2">
<span className="flex items-center justify-center w-6 h-6 rounded-full bg-purple-100 text-purple-600 text-sm">2</span>
Shipping Address
</h3>
<FormField
label="Street Address" name="address" value={formData.address}
onChange={handleChange} error={errors.address} placeholder="123 Main St, Apt 4B"
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
label="City" name="city" value={formData.city}
onChange={handleChange} error={errors.city} placeholder="Lahore"
/>
<FormField
label="Province / State" name="province" value={formData.province}
onChange={handleChange} error={errors.province} placeholder="Punjab"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField
label="Postal Code" name="postalCode" value={formData.postalCode}
onChange={handleChange} error={errors.postalCode} placeholder="54000"
/>
<FormField
label="Country" name="country" value={formData.country}
onChange={handleChange} error={errors.country} disabled={true}
/>
</div>
</div>
{/* Payment Method */}
<div className="space-y-4">
<h3 className="text-lg font-semibold text-gray-800 flex items-center gap-2">
<span className="flex items-center justify-center w-6 h-6 rounded-full bg-purple-100 text-purple-600 text-sm">3</span>
Payment Method
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{paymentMethods.map((method) => (
<div
key={method.id}
onClick={() => setFormData(prev => ({ ...prev, paymentMethod: method.id }))}
className={cn(
"cursor-pointer border-2 rounded-lg p-4 flex flex-col items-center justify-center gap-2 transition-all duration-200 hover:border-purple-300",
formData.paymentMethod === method.id
? "border-purple-600 bg-purple-50 text-purple-700"
: "border-gray-200 text-gray-600"
)}
>
<method.icon className={cn("w-6 h-6", formData.paymentMethod === method.id ? "text-purple-600" : "text-gray-400")} />
<span className="text-sm font-medium">{method.label}</span>
</div>
))}
</div>
<AnimatePresence>
{formData.paymentMethod === 'card' && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
className="bg-gray-50 p-4 rounded-lg space-y-4 border border-gray-200"
>
<FormField
label="Card Number" name="cardNumber" value={formData.cardNumber}
onChange={handleChange} error={errors.cardNumber} placeholder="0000 0000 0000 0000"
/>
<div className="grid grid-cols-2 gap-4">
<FormField
label="Expiry Date" name="cardExpiry" value={formData.cardExpiry}
onChange={handleChange} error={errors.cardExpiry} placeholder="MM/YY"
/>
<FormField
label="CVC" name="cardCvc" value={formData.cardCvc}
onChange={handleChange} error={errors.cardCvc} placeholder="123"
/>
</div>
</motion.div>
)}
</AnimatePresence>
{formData.paymentMethod === 'bank' && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
className="bg-blue-50 p-4 rounded-lg text-sm text-blue-800 border border-blue-100"
>
<p className="font-semibold">Bank Transfer Instructions:</p>
<p>Bank: Meezan Bank</p>
<p>Account Title: BinNaveed.Pk</p>
<p>Account No: 0101-01010101-01</p>
<p className="mt-2 text-xs">Please use your Order ID as the payment reference.</p>
</motion.div>
)}
</div>
<div className="pt-4">
<Button
type="submit"
disabled={isSubmitting}
className="w-full h-12 text-lg bg-purple-600 hover:bg-purple-700 shadow-lg hover:shadow-xl transition-all"
>
{isSubmitting ? (
<div className="flex items-center gap-2">
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
Processing Order...
</div>
) : (
`Place Order`
)}
</Button>
<p className="text-xs text-center text-gray-500 mt-4">
By placing your order, you agree to our Terms of Service and Privacy Policy.
</p>
</div>
</form>
);
};
const FormField = ({ label, name, type = "text", value, onChange, error, placeholder, disabled = false }) => (
<div className="space-y-1">
<label htmlFor={name} className="block text-sm font-medium text-gray-700">
{label} {error && <span className="text-red-500">*</span>}
</label>
<input
type={type}
id={name}
name={name}
value={value}
onChange={onChange}
disabled={disabled}
placeholder={placeholder}
className={cn(
"w-full px-4 py-2.5 rounded-lg border focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none transition-all duration-200",
error ? "border-red-300 bg-red-50 focus:ring-red-200" : "border-gray-300 bg-white",
disabled && "bg-gray-100 text-gray-500 cursor-not-allowed"
)}
/>
{error && <p className="text-xs text-red-500 mt-1 animate-in slide-in-from-top-1 fade-in duration-200">{error}</p>}
</div>
);
export default CheckoutForm;
import React from 'react';
import { useCart } from '@/contexts/CartContext';
import { ShoppingBag } from 'lucide-react';
const OrderSummary = ({ cartItems }) => {
const { getCartTotal } = useCart();
const subtotal = getCartTotal();
const tax = subtotal * 0.10; // 10% Tax
const shipping = 500; // Fixed shipping rate PKR 500
const total = subtotal + tax + shipping;
return (
<div className="space-y-6">
<div className="space-y-4 max-h-[400px] overflow-y-auto pr-2 scrollbar-thin scrollbar-thumb-gray-200">
{cartItems.map((item) => (
<div key={`${item.id}-${item.color}`} className="flex gap-4 py-2">
<div className="w-16 h-20 rounded-md overflow-hidden bg-gray-100 flex-shrink-0 border border-gray-200">
<img
src={item.image}
alt={item.name}
className="w-full h-full object-cover"
/>
</div>
<div className="flex-1 min-w-0">
<h4 className="text-sm font-medium text-gray-900 truncate pr-2">{item.name}</h4>
<p className="text-xs text-gray-500 mt-1">
Color: {item.color}
</p>
<div className="flex justify-between items-center mt-2">
<span className="text-xs text-gray-500">Qty: {item.quantity}</span>
<span className="text-sm font-semibold text-gray-900">
PKR {(item.price * item.quantity).toLocaleString()}
</span>
</div>
</div>
</div>
))}
{cartItems.length === 0 && (
<div className="text-center py-8 text-gray-500">
<ShoppingBag className="w-12 h-12 mx-auto mb-2 opacity-20" />
<p>Your cart is empty</p>
</div>
)}
</div>
<div className="border-t border-gray-200 pt-4 space-y-3">
<div className="flex justify-between text-sm text-gray-600">
<span>Subtotal</span>
<span>PKR {subtotal.toLocaleString()}</span>
</div>
<div className="flex justify-between text-sm text-gray-600">
<span>Tax (10%)</span>
<span>PKR {tax.toLocaleString()}</span>
</div>
<div className="flex justify-between text-sm text-gray-600">
<span>Shipping</span>
<span>PKR {shipping.toLocaleString()}</span>
</div>
<div className="border-t border-gray-200 pt-3 mt-3">
<div className="flex justify-between items-center">
<span className="text-base font-bold text-gray-900">Total</span>
<span className="text-xl font-bold text-purple-600">
PKR {total.toLocaleString()}
</span>
</div>
<p className="text-xs text-gray-500 mt-1 text-right">
Including GST where applicable
</p>
</div>
</div>
</div>
);
};
export default OrderSummary;
import React from 'react';
import { Link } from 'react-router-dom';
import { motion } from 'framer-motion';
import { useProducts } from '@/contexts/ProductContext';
import ProductCard from '@/components/ProductCard';
import { Button } from '@/components/ui/button';
const FeaturedMenCollection = () => {
const { getProductsByCategory } = useProducts();
const menProducts = getProductsByCategory('men').slice(0, 3);
return (
<section className="py-16 px-4 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Men's Collection
</h2>
<p className="text-gray-600 max-w-2xl mx-auto">
Discover our premium collection of traditional shalwar kameez with contemporary elegance
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-8">
{menProducts.map((product, index) => (
<motion.div
key={product.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<ProductCard product={product} />
</motion.div>
))}
</div>
<div className="text-center">
<Link to="/men">
<Button size="lg" variant="outline" className="border-purple-600 text-purple-600 hover:bg-purple-50">
View All Men's Collection
</Button>
</Link>
</div>
</section>
);
};
export default FeaturedMenCollection;
import React from 'react';
import { Link } from 'react-router-dom';
import { motion } from 'framer-motion';
import { useProducts } from '@/contexts/ProductContext';
import ProductCard from '@/components/ProductCard';
import { Button } from '@/components/ui/button';
const FeaturedWomenCollection = () => {
const { getProductsByCategory } = useProducts();
const womenProducts = getProductsByCategory('women').slice(0, 3);
return (
<section className="py-16 px-4 max-w-7xl mx-auto bg-gray-50">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Women's Collection
</h2>
<p className="text-gray-600 max-w-2xl mx-auto">
Exquisite designs crafted with intricate detail and timeless beauty
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-8">
{womenProducts.map((product, index) => (
<motion.div
key={product.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<ProductCard product={product} />
</motion.div>
))}
</div>
<div className="text-center">
<Link to="/women">
<Button size="lg" variant="outline" className="border-purple-600 text-purple-600 hover:bg-purple-50">
View All Women's Collection
</Button>
</Link>
</div>
</section>
);
};
export default FeaturedWomenCollection;
import React from 'react';
import { motion } from 'framer-motion';
import { Link } from 'react-router-dom';
import { Button } from '@/components/ui/button';
const FinalCTA = () => {
return (
<section className="py-20 px-4 bg-gradient-to-br from-purple-600 to-purple-800">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="max-w-4xl mx-auto text-center"
>
<h2 className="text-3xl md:text-5xl font-bold text-white mb-6">
Ready to Celebrate Tradition?
</h2>
<p className="text-lg md:text-xl text-purple-100 mb-8 max-w-2xl mx-auto">
Explore our complete collections and find the perfect traditional wear for every occasion
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link to="/men">
<Button
size="lg"
className="bg-white text-purple-700 hover:bg-gray-100 px-8 py-6 text-lg"
>
Browse Men's Collection
</Button>
</Link>
<Link to="/women">
<Button
size="lg"
variant="outline"
className="border-2 border-white text-white hover:bg-white/10 px-8 py-6 text-lg"
>
Browse Women's Collection
</Button>
</Link>
</div>
</motion.div>
</section>
);
};
export default FinalCTA;
import React from 'react';
import { Link } from 'react-router-dom';
import { motion } from 'framer-motion';
import { Button } from '@/components/ui/button';
const HeroSection = () => {
return (
<section className="relative h-screen flex items-center justify-center overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<img
src="https://images.unsplash.com/photo-1656042744506-1d3c6e2b013e"
alt="Luxury boutique interior"
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-t from-gray-900 via-purple-900/50 to-transparent" />
</div>
{/* Content */}
<div className="relative z-10 text-center px-4 max-w-4xl mx-auto">
<motion.h1
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-6"
>
Premium Pakistani Shalwar Kameez
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4 }}
className="text-lg md:text-xl lg:text-2xl text-gray-100 mb-8"
>
Celebrate tradition with contemporary elegance
</motion.p>
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.6 }}
className="flex flex-col sm:flex-row gap-4 justify-center"
>
<Link to="/men">
<Button
size="lg"
className="bg-purple-600 hover:bg-purple-700 text-white px-8 py-6 text-lg w-full sm:w-auto"
>
Shop Men's
</Button>
</Link>
<Link to="/women">
<Button
size="lg"
className="bg-purple-600 hover:bg-purple-700 text-white px-8 py-6 text-lg w-full sm:w-auto"
>
Shop Women's
</Button>
</Link>
</motion.div>
</div>
</section>
);
};
export default HeroSection;
import React from 'react';
import { motion } from 'framer-motion';
import { Link } from 'react-router-dom';
import { Sparkles, Gift, TrendingUp } from 'lucide-react';
import { Button } from '@/components/ui/button';
const SpecialOffersSection = () => {
const offers = [
{
id: 1,
icon: Sparkles,
title: 'Summer Collection',
discount: '20% Off',
category: 'All Collections',
link: '/men',
gradient: 'from-purple-500 to-purple-700'
},
{
id: 2,
icon: Gift,
title: 'Bundle Deal',
discount: 'Buy 2 Get 15% Off',
category: 'Mix & Match',
link: '/women',
gradient: 'from-purple-600 to-purple-800'
},
{
id: 3,
icon: TrendingUp,
title: 'New Arrivals',
discount: 'Exclusive Preview',
category: 'Latest Designs',
link: '/men',
gradient: 'from-purple-500 to-purple-700'
}
];
return (
<section className="py-16 px-4 max-w-7xl mx-auto bg-gray-50">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Limited Time Offers
</h2>
<p className="text-gray-600 max-w-2xl mx-auto">
Don't miss out on these exclusive deals and special promotions
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{offers.map((offer, index) => (
<motion.div
key={offer.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
whileHover={{ scale: 1.05, y: -5 }}
className="relative overflow-hidden rounded-2xl shadow-lg group"
>
<div className={`bg-gradient-to-br ${offer.gradient} p-8 h-full flex flex-col justify-between`}>
<div>
<div className="w-12 h-12 bg-white/20 rounded-lg flex items-center justify-center mb-4">
<offer.icon className="w-6 h-6 text-white" />
</div>
<h3 className="text-2xl font-bold text-white mb-2">
{offer.title}
</h3>
<p className="text-3xl font-bold text-white mb-2">
{offer.discount}
</p>
<p className="text-purple-100 text-sm">
{offer.category}
</p>
</div>
<Link to={offer.link}>
<Button
variant="secondary"
className="w-full mt-6 bg-white text-purple-700 hover:bg-gray-100"
>
Shop Now
</Button>
</Link>
</div>
</motion.div>
))}
</div>
</section>
);
};
export default SpecialOffersSection;
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { ChevronLeft, ChevronRight, Star } from 'lucide-react';
import { Button } from '@/components/ui/button';
const TestimonialsSection = () => {
const [currentIndex, setCurrentIndex] = useState(0);
const testimonials = [
{
id: 1,
name: 'Ahmed Khan',
rating: 5,
text: 'Exceptional quality and craftsmanship! The fabric is premium and the fit is perfect. I received so many compliments at my cousin\'s wedding.',
image: 'AK'
},
{
id: 2,
name: 'Fatima Malik',
rating: 5,
text: 'Absolutely stunning! The embroidery work is exquisite and the colors are even more beautiful in person. BinNaveed.Pk never disappoints.',
image: 'FM'
},
{
id: 3,
name: 'Bilal Ahmed',
rating: 5,
text: 'The traditional design with modern touch is exactly what I was looking for. Great customer service and fast delivery too!',
image: 'BA'
},
{
id: 4,
name: 'Aisha Siddiqui',
rating: 5,
text: 'I\'ve ordered multiple times and each piece is more beautiful than the last. The quality is consistently outstanding. Highly recommend!',
image: 'AS'
},
{
id: 5,
name: 'Hassan Raza',
rating: 5,
text: 'Premium quality at reasonable prices. The attention to detail in every stitch is remarkable. This is now my go-to store for all occasions.',
image: 'HR'
}
];
const handlePrevious = () => {
setCurrentIndex((prev) => (prev === 0 ? testimonials.length - 1 : prev - 1));
};
const handleNext = () => {
setCurrentIndex((prev) => (prev === testimonials.length - 1 ? 0 : prev + 1));
};
return (
<section className="py-16 px-4 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
What Our Customers Say
</h2>
<p className="text-gray-600 max-w-2xl mx-auto">
Join thousands of satisfied customers celebrating tradition with style
</p>
</motion.div>
<div className="relative max-w-4xl mx-auto">
<AnimatePresence mode="wait">
<motion.div
key={currentIndex}
initial={{ opacity: 0, x: 100 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -100 }}
transition={{ duration: 0.3 }}
className="bg-white rounded-2xl shadow-lg p-8 md:p-12"
>
<div className="flex items-center justify-center mb-6">
<div className="w-16 h-16 bg-gradient-to-br from-purple-600 to-purple-800 rounded-full flex items-center justify-center text-white font-bold text-xl">
{testimonials[currentIndex].image}
</div>
</div>
<div className="flex justify-center mb-4">
{[...Array(testimonials[currentIndex].rating)].map((_, i) => (
<Star key={i} className="w-5 h-5 fill-yellow-400 text-yellow-400" />
))}
</div>
<p className="text-gray-700 text-lg text-center mb-6 italic">
"{testimonials[currentIndex].text}"
</p>
<p className="text-center font-semibold text-gray-900">
{testimonials[currentIndex].name}
</p>
</motion.div>
</AnimatePresence>
<div className="flex justify-center items-center gap-4 mt-8">
<Button
variant="outline"
size="icon"
onClick={handlePrevious}
className="rounded-full"
>
<ChevronLeft className="h-5 w-5" />
</Button>
<div className="flex gap-2">
{testimonials.map((_, index) => (
<button
key={index}
onClick={() => setCurrentIndex(index)}
className={`w-2 h-2 rounded-full transition-all ${
index === currentIndex ? 'bg-purple-600 w-8' : 'bg-gray-300'
}`}
/>
))}
</div>
<Button
variant="outline"
size="icon"
onClick={handleNext}
className="rounded-full"
>
<ChevronRight className="h-5 w-5" />
</Button>
</div>
</div>
</section>
);
};
export default TestimonialsSection;
import { cn } from '@/lib/utils';
import { Slot } from '@radix-ui/react-slot';
import { cva } from 'class-variance-authority';
import React from 'react';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline:
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
},
);
const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
});
Button.displayName = 'Button';
export { Button, buttonVariants };
import { cn } from '@/lib/utils';
import * as ToastPrimitives from '@radix-ui/react-toast';
import { cva } from 'class-variance-authority';
import { X } from 'lucide-react';
import React from 'react';
const ToastProvider = ToastPrimitives.Provider;
const ToastViewport = React.forwardRef(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
'fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]',
className,
)}
{...props}
/>
));
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
const toastVariants = cva(
'data-[swipe=move]:transition-none group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full data-[state=closed]:slide-out-to-right-full',
{
variants: {
variant: {
default: 'bg-background border',
destructive:
'group destructive border-destructive bg-destructive text-destructive-foreground',
},
},
defaultVariants: {
variant: 'default',
},
},
);
const Toast = React.forwardRef(({ className, variant, ...props }, ref) => {
return (
<ToastPrimitives.Root
ref={ref}
className={cn(toastVariants({ variant }), className)}
{...props}
/>
);
});
Toast.displayName = ToastPrimitives.Root.displayName;
const ToastAction = React.forwardRef(({ className, ...props }, ref) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
'inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-destructive/30 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive',
className,
)}
{...props}
/>
));
ToastAction.displayName = ToastPrimitives.Action.displayName;
const ToastClose = React.forwardRef(({ className, ...props }, ref) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
className,
)}
toast-close=""
{...props}
>
<X className="h-4 w-4" />
</ToastPrimitives.Close>
));
ToastClose.displayName = ToastPrimitives.Close.displayName;
const ToastTitle = React.forwardRef(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn('text-sm font-semibold', className)}
{...props}
/>
));
ToastTitle.displayName = ToastPrimitives.Title.displayName;
const ToastDescription = React.forwardRef(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn('text-sm opacity-90', className)}
{...props}
/>
));
ToastDescription.displayName = ToastPrimitives.Description.displayName;
export {
Toast,
ToastAction,
ToastClose,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
};
import {
Toast,
ToastClose,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
} from '@/components/ui/toast';
import { useToast } from '@/components/ui/use-toast';
import React from 'react';
export function Toaster() {
const { toasts } = useToast();
return (
<ToastProvider>
{toasts.map(({ id, title, description, action, ...props }) => {
return (
<Toast key={id} {...props}>
<div className="grid gap-1">
{title && <ToastTitle>{title}</ToastTitle>}
{description && (
<ToastDescription>{description}</ToastDescription>
)}
</div>
{action}
<ToastClose />
</Toast>
);
})}
<ToastViewport />
</ToastProvider>
);
}
import { useState, useEffect } from "react"
const TOAST_LIMIT = 1
let count = 0
function generateId() {
count = (count + 1) % Number.MAX_VALUE
return count.toString()
}
const toastStore = {
state: {
toasts: [],
},
listeners: [],
getState: () => toastStore.state,
setState: (nextState) => {
if (typeof nextState === 'function') {
toastStore.state = nextState(toastStore.state)
} else {
toastStore.state = { ...toastStore.state, ...nextState }
}
toastStore.listeners.forEach(listener => listener(toastStore.state))
},
subscribe: (listener) => {
toastStore.listeners.push(listener)
return () => {
toastStore.listeners = toastStore.listeners.filter(l => l !== listener)
}
}
}
export const toast = ({ ...props }) => {
const id = generateId()
const update = (props) =>
toastStore.setState((state) => ({
...state,
toasts: state.toasts.map((t) =>
t.id === id ? { ...t, ...props } : t
),
}))
const dismiss = () => toastStore.setState((state) => ({
...state,
toasts: state.toasts.filter((t) => t.id !== id),
}))
toastStore.setState((state) => ({
...state,
toasts: [
{ ...props, id, dismiss },
...state.toasts,
].slice(0, TOAST_LIMIT),
}))
return {
id,
dismiss,
update,
}
}
export function useToast() {
const [state, setState] = useState(toastStore.getState())
useEffect(() => {
const unsubscribe = toastStore.subscribe((state) => {
setState(state)
})
return unsubscribe
}, [])
useEffect(() => {
const timeouts = []
state.toasts.forEach((toast) => {
if (toast.duration === Infinity) {
return
}
const timeout = setTimeout(() => {
toast.dismiss()
}, toast.duration || 5000)
timeouts.push(timeout)
})
return () => {
timeouts.forEach((timeout) => clearTimeout(timeout))
}
}, [state.toasts])
return {
toast,
toasts: state.toasts,
}
}
import React, { createContext, useContext, useState, useEffect } from 'react';
import { useToast } from '@/components/ui/use-toast';
const CartContext = createContext();
export const useCart = () => {
const context = useContext(CartContext);
if (!context) {
throw new Error('useCart must be used within CartProvider');
}
return context;
};
export const CartProvider = ({ children }) => {
const [cartItems, setCartItems] = useState(() => {
const savedCart = localStorage.getItem('binnaveed-cart');
return savedCart ? JSON.parse(savedCart) : [];
});
const { toast } = useToast();
useEffect(() => {
localStorage.setItem('binnaveed-cart', JSON.stringify(cartItems));
}, [cartItems]);
const addToCart = (product, selectedColor, quantity = 1) => {
const existingItemIndex = cartItems.findIndex(
item => item.id === product.id && item.color === selectedColor
);
if (existingItemIndex > -1) {
const updatedCart = [...cartItems];
updatedCart[existingItemIndex].quantity += quantity;
setCartItems(updatedCart);
toast({
title: "Updated cart",
description: `${product.name} quantity updated`,
});
} else {
const newItem = {
id: product.id,
name: product.name,
price: product.price,
image: product.image,
color: selectedColor,
quantity: quantity
};
setCartItems([...cartItems, newItem]);
toast({
title: "Added to cart",
description: `${product.name} has been added to your cart`,
});
}
};
// Adapter for backward compatibility with hidden CartPage
const removeFromCart = (itemId, arg2, arg3) => {
let color;
// Check if called with (itemId, size, color) [Legacy] or (itemId, color) [New]
if (arg3 !== undefined) {
// Legacy: arg2 is size (ignored), arg3 is color
color = arg3;
} else {
// New: arg2 is color
color = arg2;
}
setCartItems(cartItems.filter(
item => !(item.id === itemId && item.color === color)
));
toast({
title: "Removed from cart",
description: "Item has been removed from your cart",
});
};
// Adapter for backward compatibility with hidden CartPage
const updateQuantity = (itemId, arg2, arg3, arg4) => {
let color, newQuantity;
// Check if called with (itemId, size, color, quantity) [Legacy] or (itemId, color, quantity) [New]
if (arg4 !== undefined) {
// Legacy
color = arg3;
newQuantity = arg4;
} else {
// New
color = arg2;
newQuantity = arg3;
}
if (newQuantity < 1) return;
const updatedCart = cartItems.map(item =>
item.id === itemId && item.color === color
? { ...item, quantity: newQuantity }
: item
);
setCartItems(updatedCart);
};
const clearCart = () => {
setCartItems([]);
toast({
title: "Cart cleared",
description: "All items have been removed from your cart",
});
};
const getCartTotal = () => {
return cartItems.reduce((total, item) => total + (item.price * item.quantity), 0);
};
const getCartCount = () => {
return cartItems.reduce((count, item) => count + item.quantity, 0);
};
return (
<CartContext.Provider value={{
cartItems,
addToCart,
removeFromCart,
updateQuantity,
clearCart,
getCartTotal,
getCartCount
}}>
{children}
</CartContext.Provider>
);
};
import React, { createContext, useContext } from 'react';
const ProductContext = createContext();
export const useProducts = () => {
const context = useContext(ProductContext);
if (!context) {
throw new Error('useProducts must be used within ProductProvider');
}
return context;
};
export const ProductProvider = ({ children }) => {
const products = [
// Men's Collection
{
id: 'men-1',
name: 'Royal Blue Formal Shalwar Kameez',
category: 'men',
price: 8999,
sizes: ['S', 'M', 'L', 'XL', 'XXL'],
colors: ['Royal Blue', 'Navy Blue', 'Black'],
description: 'Exquisite formal shalwar kameez crafted from premium fabric with intricate embroidery. Perfect for weddings and special occasions.',
image: 'https://images.unsplash.com/photo-1682240306508-2ae6178a1a94',
rating: 4.8,
reviews: 156
},
{
id: 'men-2',
name: 'Emerald Green Casual Set',
category: 'men',
price: 5999,
sizes: ['S', 'M', 'L', 'XL', 'XXL'],
colors: ['Emerald Green', 'Forest Green', 'Olive'],
description: 'Comfortable casual wear with traditional elegance. Made from breathable cotton blend for everyday comfort.',
image: 'https://images.unsplash.com/photo-1620386875077-e322fb810928',
rating: 4.6,
reviews: 98
},
{
id: 'men-3',
name: 'Classic White Kurta',
category: 'men',
price: 4999,
sizes: ['S', 'M', 'L', 'XL', 'XXL'],
colors: ['White', 'Cream', 'Ivory'],
description: 'Timeless white kurta shalwar, perfect for religious occasions and casual gatherings. Premium cotton fabric.',
image: 'https://images.unsplash.com/photo-1649059131203-07704210ef6b',
rating: 4.9,
reviews: 203
},
{
id: 'men-4',
name: 'Charcoal Grey Premium Set',
category: 'men',
price: 7499,
sizes: ['S', 'M', 'L', 'XL', 'XXL'],
colors: ['Charcoal Grey', 'Slate Grey', 'Ash'],
description: 'Contemporary grey shalwar kameez with modern cut and traditional craftsmanship. Ideal for formal events.',
image: 'https://images.unsplash.com/photo-1682240306508-2ae6178a1a94',
rating: 4.7,
reviews: 124
},
{
id: 'men-5',
name: 'Maroon Festive Wear',
category: 'men',
price: 9999,
sizes: ['S', 'M', 'L', 'XL', 'XXL'],
colors: ['Maroon', 'Burgundy', 'Wine'],
description: 'Luxurious festive wear with golden embroidery. Premium silk blend for special celebrations.',
image: 'https://images.unsplash.com/photo-1620386875077-e322fb810928',
rating: 4.9,
reviews: 187
},
{
id: 'men-6',
name: 'Black Embroidered Kurta',
category: 'men',
price: 6999,
sizes: ['S', 'M', 'L', 'XL', 'XXL'],
colors: ['Black', 'Charcoal', 'Midnight Blue'],
description: 'Elegant black kurta with subtle embroidery. Versatile piece for various occasions.',
image: 'https://images.unsplash.com/photo-1649059131203-07704210ef6b',
rating: 4.5,
reviews: 145
},
// Women's Collection
{
id: 'women-1',
name: 'Crimson Silk Shalwar Kameez',
category: 'women',
price: 12999,
sizes: ['XS', 'S', 'M', 'L', 'XL'],
colors: ['Crimson', 'Ruby Red', 'Deep Rose'],
description: 'Stunning crimson silk shalwar kameez with intricate handwork. Perfect for weddings and grand celebrations.',
image: 'https://images.unsplash.com/photo-1693987646306-10e4670fea01',
rating: 5.0,
reviews: 234
},
{
id: 'women-2',
name: 'Sage Green Embroidered Set',
category: 'women',
price: 8999,
sizes: ['XS', 'S', 'M', 'L', 'XL'],
colors: ['Sage Green', 'Mint', 'Seafoam'],
description: 'Elegant embroidered set in soothing sage green. Contemporary design with traditional elements.',
image: 'https://images.unsplash.com/photo-1693987644111-491262bffa47',
rating: 4.8,
reviews: 176
},
{
id: 'women-3',
name: 'Pearl White Formal Suit',
category: 'women',
price: 14999,
sizes: ['XS', 'S', 'M', 'L', 'XL'],
colors: ['Pearl White', 'Ivory', 'Off-White'],
description: 'Luxurious pearl white formal suit with delicate embellishments. Premium quality for special occasions.',
image: 'https://images.unsplash.com/photo-1693988107976-3d051e639ea6',
rating: 4.9,
reviews: 198
},
{
id: 'women-4',
name: 'Royal Blue Bridal Collection',
category: 'women',
price: 24999,
sizes: ['XS', 'S', 'M', 'L', 'XL'],
colors: ['Royal Blue', 'Sapphire', 'Cobalt'],
description: 'Exquisite bridal collection in royal blue with heavy embroidery and stone work. A statement piece.',
image: 'https://images.unsplash.com/photo-1693987646306-10e4670fea01',
rating: 5.0,
reviews: 289
},
{
id: 'women-5',
name: 'Peach Casual Wear',
category: 'women',
price: 6999,
sizes: ['XS', 'S', 'M', 'L', 'XL'],
colors: ['Peach', 'Coral', 'Blush'],
description: 'Comfortable casual wear in soft peach tones. Perfect for everyday elegance.',
image: 'https://images.unsplash.com/photo-1693987644111-491262bffa47',
rating: 4.7,
reviews: 142
},
{
id: 'women-6',
name: 'Emerald Green Party Wear',
category: 'women',
price: 16999,
sizes: ['XS', 'S', 'M', 'L', 'XL'],
colors: ['Emerald Green', 'Jade', 'Forest Green'],
description: 'Glamorous party wear in emerald green with sequin work. Stand out at every celebration.',
image: 'https://images.unsplash.com/photo-1693988107976-3d051e639ea6',
rating: 4.9,
reviews: 221
}
];
const getProductById = (id) => {
return products.find(product => product.id === id);
};
const getProductsByCategory = (category) => {
return products.filter(product => product.category === category);
};
const getRelatedProducts = (productId, category, limit = 4) => {
return products
.filter(product => product.category === category && product.id !== productId)
.slice(0, limit);
};
return (
<ProductContext.Provider value={{
products,
getProductById,
getProductsByCategory,
getRelatedProducts
}}>
{children}
</ProductContext.Provider>
);
};
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 262.1 83.3% 57.8%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 262.1 83.3% 57.8%;
--radius: 0.5rem;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #7c3aed;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #6d28d9;
}
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from '@/App';
import '@/index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<App />
);
import React from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { Link } from 'react-router-dom';
import { Award, Heart, Sparkles, Users } from 'lucide-react';
import { Button } from '@/components/ui/button';
const AboutPage = () => {
const values = [
{
icon: Award,
title: 'Tradition',
description: 'Honoring centuries-old Pakistani textile heritage with authentic craftsmanship'
},
{
icon: Sparkles,
title: 'Quality',
description: 'Premium fabrics and meticulous attention to detail in every stitch'
},
{
icon: Heart,
title: 'Innovation',
description: 'Blending traditional designs with contemporary fashion sensibilities'
},
{
icon: Users,
title: 'Customer-First',
description: 'Dedicated to delivering exceptional service and satisfaction'
}
];
return (
<>
<Helmet>
<title>About Us - Our Story & Values | BinNaveed.Pk</title>
<meta name="description" content="Learn about BinNaveed.Pk - celebrating Pakistani tradition with contemporary elegance. Premium quality, authentic designs, exceptional service." />
</Helmet>
<div className="pt-24 pb-16">
{/* Hero Section */}
<section className="px-4 max-w-7xl mx-auto mb-16">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center max-w-3xl mx-auto"
>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-6">
Celebrating Tradition with Contemporary Elegance
</h1>
<p className="text-lg text-gray-600">
At BinNaveed.Pk, we're passionate about preserving the rich heritage of Pakistani traditional wear while embracing modern design sensibilities.
</p>
</motion.div>
</section>
{/* Our Heritage */}
<section className="px-4 max-w-7xl mx-auto mb-16">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<motion.div
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
Our Heritage
</h2>
<p className="text-gray-600 mb-4 leading-relaxed">
The Pakistani Shalwar Kameez is more than just clothing—it's a symbol of cultural identity, grace, and timeless elegance. For generations, this traditional attire has been worn with pride across Pakistan, representing our rich heritage and artistic craftsmanship.
</p>
<p className="text-gray-600 leading-relaxed">
At BinNaveed.Pk, we honor this legacy by sourcing the finest fabrics and working with skilled artisans who bring decades of expertise to every piece. Each garment tells a story of tradition, quality, and meticulous attention to detail.
</p>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="aspect-[4/3] rounded-2xl overflow-hidden shadow-xl"
>
<img
src="https://images.unsplash.com/photo-1682240306508-2ae6178a1a94"
alt="Traditional craftsmanship"
className="w-full h-full object-cover"
/>
</motion.div>
</div>
</section>
{/* Our Commitment */}
<section className="px-4 max-w-7xl mx-auto mb-16 bg-gray-50 py-16 rounded-2xl">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<motion.div
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="aspect-[4/3] rounded-2xl overflow-hidden shadow-xl order-2 lg:order-1"
>
<img
src="https://images.unsplash.com/photo-1693987646306-10e4670fea01"
alt="Quality craftsmanship"
className="w-full h-full object-cover"
/>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="order-1 lg:order-2"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-6">
Our Commitment
</h2>
<p className="text-gray-600 mb-4 leading-relaxed">
We are committed to delivering premium quality traditional wear that exceeds expectations. Every piece in our collection undergoes rigorous quality checks to ensure superior craftsmanship, perfect fit, and lasting durability.
</p>
<p className="text-gray-600 leading-relaxed">
Our dedication extends beyond products to exceptional customer service. We believe in building lasting relationships with our customers, ensuring every shopping experience is memorable and satisfying.
</p>
</motion.div>
</div>
</section>
{/* Why Choose Us */}
<section className="px-4 max-w-7xl mx-auto mb-16">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Why Choose BinNaveed.Pk
</h2>
<p className="text-gray-600 max-w-2xl mx-auto">
Discover what makes us the preferred choice for traditional Pakistani wear
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: 0.1 }}
className="text-center"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Award className="w-8 h-8 text-purple-600" />
</div>
<h3 className="text-xl font-bold text-gray-900 mb-2">Premium Quality</h3>
<p className="text-gray-600">
Only the finest fabrics and materials, ensuring comfort and durability
</p>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-center"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Sparkles className="w-8 h-8 text-purple-600" />
</div>
<h3 className="text-xl font-bold text-gray-900 mb-2">Diverse Variety</h3>
<p className="text-gray-600">
Extensive collections for every occasion, from casual to formal wear
</p>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: 0.3 }}
className="text-center"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Heart className="w-8 h-8 text-purple-600" />
</div>
<h3 className="text-xl font-bold text-gray-900 mb-2">Customer Service</h3>
<p className="text-gray-600">
Dedicated support team ensuring your complete satisfaction
</p>
</motion.div>
</div>
</section>
{/* Our Values */}
<section className="px-4 max-w-7xl mx-auto mb-16">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
Our Values
</h2>
<p className="text-gray-600 max-w-2xl mx-auto">
The principles that guide everything we do
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{values.map((value, index) => (
<motion.div
key={value.title}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="bg-white rounded-xl p-6 shadow-md hover:shadow-xl transition-shadow"
>
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center mb-4">
<value.icon className="w-6 h-6 text-purple-600" />
</div>
<h3 className="text-lg font-bold text-gray-900 mb-2">
{value.title}
</h3>
<p className="text-gray-600 text-sm">
{value.description}
</p>
</motion.div>
))}
</div>
</section>
{/* CTA */}
<section className="px-4 max-w-4xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="bg-gradient-to-br from-purple-600 to-purple-800 rounded-2xl p-8 md:p-12 text-center"
>
<h2 className="text-3xl md:text-4xl font-bold text-white mb-4">
Explore Our Collections
</h2>
<p className="text-purple-100 mb-8 max-w-2xl mx-auto">
Discover premium traditional wear that celebrates your heritage with contemporary style
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link to="/men">
<Button size="lg" className="bg-white text-purple-700 hover:bg-gray-100">
Men's Collection
</Button>
</Link>
<Link to="/women">
<Button size="lg" variant="outline" className="border-2 border-white text-white hover:bg-white/10">
Women's Collection
</Button>
</Link>
</div>
</motion.div>
</section>
</div>
</>
);
};
export default AboutPage;
import React from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { useCart } from '@/contexts/CartContext';
import { Trash2, Plus, Minus, ShoppingBag, ArrowRight } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/use-toast';
const CartPage = () => {
const { cartItems, removeFromCart, updateQuantity, getCartTotal } = useCart();
const { toast } = useToast();
const navigate = useNavigate();
const subtotal = getCartTotal();
const taxEstimate = subtotal * 0.10; // 10% tax
const shippingEstimate = 500; // Fixed shipping
const total = subtotal + taxEstimate + shippingEstimate;
const handleCheckout = () => {
if (cartItems.length === 0) {
toast({
title: "Cart is empty",
description: "Please add items to your cart before checking out.",
variant: "destructive"
});
return;
}
navigate('/checkout');
};
if (cartItems.length === 0) {
return (
<>
<Helmet>
<title>Shopping Cart | BinNaveed.Pk</title>
<meta name="description" content="Your shopping cart" />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<div className="text-center py-16">
<ShoppingBag className="w-24 h-24 mx-auto text-gray-300 mb-4" />
<h2 className="text-2xl font-bold text-gray-900 mb-4">Your cart is empty</h2>
<p className="text-gray-600 mb-8">Start shopping to add items to your cart</p>
<Link to="/">
<Button size="lg" className="bg-purple-600 hover:bg-purple-700">
Shop Now
</Button>
</Link>
</div>
</div>
</>
);
}
return (
<>
<Helmet>
<title>Shopping Cart | BinNaveed.Pk</title>
<meta name="description" content="Review your shopping cart and checkout" />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-3xl md:text-4xl font-bold text-gray-900 mb-8"
>
Shopping Cart ({cartItems.length} {cartItems.length === 1 ? 'item' : 'items'})
</motion.h1>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Cart Items */}
<div className="lg:col-span-2 space-y-4">
{cartItems.map((item, index) => (
<motion.div
key={`${item.id}-${item.size}-${item.color}`}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
className="bg-white rounded-xl shadow-md p-4 md:p-6"
>
<div className="flex gap-4">
<div className="w-24 h-32 md:w-32 md:h-40 rounded-lg overflow-hidden flex-shrink-0">
<img
src={item.image}
alt={item.name}
className="w-full h-full object-cover"
/>
</div>
<div className="flex-grow">
<div className="flex justify-between items-start mb-2">
<h3 className="font-semibold text-lg text-gray-900">
{item.name}
</h3>
<button
onClick={() => removeFromCart(item.id, item.size, item.color)}
className="text-red-500 hover:text-red-700 transition-colors"
>
<Trash2 className="w-5 h-5" />
</button>
</div>
<div className="space-y-2 mb-4">
<p className="text-sm text-gray-600">Size: {item.size}</p>
<p className="text-sm text-gray-600">Color: {item.color}</p>
<p className="text-xl font-bold text-purple-600">
PKR {item.price.toLocaleString()}
</p>
</div>
<div className="flex items-center gap-3">
<Button
variant="outline"
size="icon"
onClick={() => updateQuantity(item.id, item.size, item.color, item.quantity - 1)}
>
<Minus className="h-4 w-4" />
</Button>
<span className="text-lg font-semibold text-gray-900 w-8 text-center">
{item.quantity}
</span>
<Button
variant="outline"
size="icon"
onClick={() => updateQuantity(item.id, item.size, item.color, item.quantity + 1)}
>
<Plus className="h-4 w-4" />
</Button>
</div>
</div>
</div>
</motion.div>
))}
</div>
{/* Order Summary */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="lg:col-span-1"
>
<div className="bg-gray-50 rounded-xl p-6 sticky top-24">
<h2 className="text-xl font-bold text-gray-900 mb-6">Order Summary</h2>
<div className="space-y-3 mb-6">
<div className="flex justify-between text-gray-600">
<span>Subtotal</span>
<span>PKR {subtotal.toLocaleString()}</span>
</div>
<div className="flex justify-between text-gray-600">
<span>Tax Estimate (10%)</span>
<span>PKR {taxEstimate.toLocaleString()}</span>
</div>
<div className="flex justify-between text-gray-600">
<span>Shipping Estimate</span>
<span>PKR {shippingEstimate.toLocaleString()}</span>
</div>
<div className="border-t border-gray-300 pt-3">
<div className="flex justify-between text-lg font-bold text-gray-900">
<span>Total</span>
<span>PKR {total.toLocaleString()}</span>
</div>
</div>
</div>
<div className="space-y-3">
<Button
onClick={handleCheckout}
size="lg"
className="w-full bg-purple-600 hover:bg-purple-700 group"
>
Proceed to Checkout
<ArrowRight className="w-4 h-4 ml-2 group-hover:translate-x-1 transition-transform" />
</Button>
<Link to="/">
<Button variant="outline" size="lg" className="w-full">
Continue Shopping
</Button>
</Link>
</div>
</div>
</motion.div>
</div>
</div>
</>
);
};
export default CartPage;
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { useCart } from '@/contexts/CartContext';
import CheckoutForm from '@/components/checkout/CheckoutForm';
import OrderSummary from '@/components/checkout/OrderSummary';
import { useToast } from '@/components/ui/use-toast';
const CheckoutPage = () => {
const { cartItems, getCartTotal, clearCart } = useCart();
const navigate = useNavigate();
const { toast } = useToast();
const [isSubmitting, setIsSubmitting] = useState(false);
// Redirect if cart is empty
React.useEffect(() => {
if (cartItems.length === 0) {
navigate('/cart');
}
}, [cartItems, navigate]);
const handleCheckoutSubmit = async (formData) => {
setIsSubmitting(true);
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
// Calculate totals
const subtotal = getCartTotal();
const tax = subtotal * 0.10;
const shipping = 500; // PKR 500 roughly equivalent to $5 requested, adjusted for PKR context
const total = subtotal + tax + shipping;
const orderData = {
id: `ORD-${Date.now()}`,
date: new Date().toISOString(),
customer: {
firstName: formData.firstName,
lastName: formData.lastName,
email: formData.email,
phone: formData.phone,
},
shipping: {
address: formData.address,
city: formData.city,
province: formData.province,
postalCode: formData.postalCode,
country: formData.country,
},
paymentMethod: formData.paymentMethod,
items: cartItems,
totals: {
subtotal,
tax,
shipping,
total
}
};
// Store in localStorage
const existingOrders = JSON.parse(localStorage.getItem('binnaveed-orders') || '[]');
localStorage.setItem('binnaveed-orders', JSON.stringify([...existingOrders, orderData]));
// Store current order for confirmation page
localStorage.setItem('binnaveed-current-order', JSON.stringify(orderData));
clearCart();
setIsSubmitting(false);
toast({
title: "Order Placed Successfully! 🎉",
description: `Order #${orderData.id} has been confirmed.`,
});
navigate('/order-confirmation');
};
return (
<>
<Helmet>
<title>Checkout - BinNaveed.Pk</title>
<meta name="description" content="Secure checkout for your premium Pakistani Shalwar Kameez order." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto bg-gray-50 min-h-screen">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-3xl md:text-4xl font-bold text-gray-900 mb-8 text-center"
>
Secure Checkout
</motion.h1>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.1 }}
className="lg:col-span-2"
>
<div className="bg-white rounded-xl shadow-md p-6 md:p-8">
<h2 className="text-xl font-bold text-gray-900 mb-6 pb-2 border-b">
Shipping & Payment Details
</h2>
<CheckoutForm onSubmit={handleCheckoutSubmit} isSubmitting={isSubmitting} />
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.2 }}
className="lg:col-span-1"
>
<div className="bg-white rounded-xl shadow-md p-6 sticky top-24">
<h2 className="text-xl font-bold text-gray-900 mb-6 pb-2 border-b">
Order Summary
</h2>
<OrderSummary cartItems={cartItems} />
</div>
</motion.div>
</div>
</div>
</>
);
};
export default CheckoutPage;
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { Mail, Phone, Clock, Send } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/use-toast';
const ContactPage = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
phone: '',
subject: '',
message: ''
});
const [isSubmitting, setIsSubmitting] = useState(false);
const { toast } = useToast();
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
// Simulate form submission
setTimeout(() => {
console.log('Form submitted:', formData);
toast({
title: "Message sent!",
description: "Thank you for contacting us. We'll get back to you soon.",
});
setFormData({
name: '',
email: '',
phone: '',
subject: '',
message: ''
});
setIsSubmitting(false);
}, 1500);
};
return (
<>
<Helmet>
<title>Contact Us - Get in Touch | BinNaveed.Pk</title>
<meta name="description" content="Contact BinNaveed.Pk for inquiries about our premium Pakistani Shalwar Kameez collections. We're here to help!" />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
Get in Touch
</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
Have a question or need assistance? We're here to help you find the perfect traditional wear.
</p>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
{/* Contact Information */}
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
className="space-y-8"
>
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-6">
Contact Information
</h2>
<div className="space-y-4">
<a
href="https://wa.me/923025327880"
className="flex items-start gap-4 p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors group"
>
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center flex-shrink-0 group-hover:bg-purple-200 transition-colors">
<Phone className="w-6 h-6 text-purple-600" />
</div>
<div>
<p className="font-semibold text-gray-900 mb-1">WhatsApp</p>
<p className="text-purple-600">03025327880</p>
<p className="text-sm text-gray-600 mt-1">
Click to chat with us on WhatsApp
</p>
</div>
</a>
<a
href="mailto:binnaveed.pk@outlook.com"
className="flex items-start gap-4 p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors group"
>
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center flex-shrink-0 group-hover:bg-purple-200 transition-colors">
<Mail className="w-6 h-6 text-purple-600" />
</div>
<div>
<p className="font-semibold text-gray-900 mb-1">Email</p>
<p className="text-purple-600">binnaveed.pk@outlook.com</p>
<p className="text-sm text-gray-600 mt-1">
Send us an email anytime
</p>
</div>
</a>
<div className="flex items-start gap-4 p-4 bg-gray-50 rounded-lg">
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center flex-shrink-0">
<Clock className="w-6 h-6 text-purple-600" />
</div>
<div>
<p className="font-semibold text-gray-900 mb-1">Business Hours</p>
<p className="text-gray-600">Monday - Saturday: 9:00 AM - 8:00 PM</p>
<p className="text-gray-600">Sunday: 10:00 AM - 6:00 PM</p>
</div>
</div>
</div>
</div>
<div className="bg-gradient-to-br from-purple-600 to-purple-800 rounded-2xl p-8 text-white">
<h3 className="text-xl font-bold mb-4">Why Contact Us?</h3>
<ul className="space-y-3">
<li className="flex items-start gap-2">
<span className="text-purple-200">•</span>
<span>Product inquiries and recommendations</span>
</li>
<li className="flex items-start gap-2">
<span className="text-purple-200">•</span>
<span>Size and fit guidance</span>
</li>
<li className="flex items-start gap-2">
<span className="text-purple-200">•</span>
<span>Custom orders and bulk purchases</span>
</li>
<li className="flex items-start gap-2">
<span className="text-purple-200">•</span>
<span>Order tracking and support</span>
</li>
</ul>
</div>
</motion.div>
{/* Contact Form */}
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, delay: 0.4 }}
>
<div className="bg-white rounded-2xl shadow-lg p-8">
<h2 className="text-2xl font-bold text-gray-900 mb-6">
Send us a Message
</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="name" className="block text-sm font-semibold text-gray-900 mb-2">
Name *
</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
required
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
placeholder="Your full name"
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-semibold text-gray-900 mb-2">
Email *
</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
placeholder="your.email@example.com"
/>
</div>
<div>
<label htmlFor="phone" className="block text-sm font-semibold text-gray-900 mb-2">
Phone
</label>
<input
type="tel"
id="phone"
name="phone"
value={formData.phone}
onChange={handleChange}
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
placeholder="03XX-XXXXXXX"
/>
</div>
<div>
<label htmlFor="subject" className="block text-sm font-semibold text-gray-900 mb-2">
Subject *
</label>
<input
type="text"
id="subject"
name="subject"
value={formData.subject}
onChange={handleChange}
required
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
placeholder="How can we help you?"
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-semibold text-gray-900 mb-2">
Message *
</label>
<textarea
id="message"
name="message"
value={formData.message}
onChange={handleChange}
required
rows={5}
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 resize-none text-gray-900"
placeholder="Tell us more about your inquiry..."
/>
</div>
<Button
type="submit"
size="lg"
disabled={isSubmitting}
className="w-full bg-purple-600 hover:bg-purple-700"
>
{isSubmitting ? (
'Sending...'
) : (
<>
<Send className="w-5 h-5 mr-2" />
Send Message
</>
)}
</Button>
</form>
</div>
</motion.div>
</div>
</div>
</>
);
};
export default ContactPage;
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import { motion, AnimatePresence } from 'framer-motion';
import { Plus, Minus, HelpCircle } from 'lucide-react';
const FAQPage = () => {
const [openIndex, setOpenIndex] = useState(0);
const faqs = [
{
category: "Products & Sizing",
questions: [
{
q: "How do I find my size?",
a: "We provide detailed size charts on every product page. We recommend measuring a well-fitting shalwar kameez you already own and comparing it to our chart. If you're between sizes, we suggest sizing up for a more traditional comfortable fit."
},
{
q: "What fabrics do you use?",
a: "We use premium quality fabrics including pure cotton, wash-and-wear blends, boski, karandi, and linen. Specific fabric details are listed on each product page description."
},
{
q: "Are the colors accurate to the photos?",
a: "We make every effort to display product colors as accurately as possible. However, please note that colors may vary slightly due to professional studio lighting and different screen calibrations."
}
]
},
{
category: "Ordering & Payment",
questions: [
{
q: "What payment methods do you accept?",
a: "We accept Credit/Debit Cards (Visa, MasterCard), Bank Transfers, and Cash on Delivery (COD) for orders within Pakistan."
},
{
q: "Can I modify my order after placing it?",
a: "Orders can be modified within 12 hours of placement. Please contact our support team on WhatsApp at 03025327880 immediately for assistance."
}
]
},
{
category: "Shipping & Returns",
questions: [
{
q: "How long does shipping take?",
a: "Standard delivery time is 3-5 working days for major cities in Pakistan. For remote areas, it may take 5-7 working days. International shipping times vary by location."
},
{
q: "What is your return policy?",
a: "We offer a 15-day return policy for unworn items with original tags attached. Please visit our Return Policy page for full details and instructions."
}
]
}
];
const toggleAccordion = (index) => {
setOpenIndex(openIndex === index ? -1 : index);
};
return (
<>
<Helmet>
<title>Frequently Asked Questions | BinNaveed.Pk</title>
<meta name="description" content="Find answers to common questions about BinNaveed.Pk products, shipping, returns, and ordering process." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-4xl mx-auto min-h-screen">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-6">
<HelpCircle className="w-8 h-8 text-purple-600" />
</div>
<h1 className="text-4xl font-bold text-gray-900 mb-4">
Frequently Asked Questions
</h1>
<p className="text-lg text-gray-600">
Everything you need to know about shopping with us
</p>
</motion.div>
<div className="space-y-8">
{faqs.map((section, sectionIndex) => (
<div key={sectionIndex} className="bg-white rounded-xl shadow-md p-6">
<h2 className="text-xl font-bold text-purple-700 mb-6 pb-2 border-b border-gray-100">
{section.category}
</h2>
<div className="space-y-4">
{section.questions.map((item, i) => {
const globalIndex = `${sectionIndex}-${i}`;
const isOpen = openIndex === globalIndex;
return (
<div
key={i}
className="border border-gray-200 rounded-lg overflow-hidden transition-all duration-200 hover:border-purple-200"
>
<button
onClick={() => toggleAccordion(globalIndex)}
className="w-full flex justify-between items-center p-4 text-left bg-gray-50 hover:bg-gray-100 transition-colors"
>
<span className="font-semibold text-gray-900">{item.q}</span>
{isOpen ? (
<Minus className="w-5 h-5 text-purple-600 flex-shrink-0" />
) : (
<Plus className="w-5 h-5 text-gray-400 flex-shrink-0" />
)}
</button>
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3 }}
>
<div className="p-4 bg-white text-gray-600 leading-relaxed border-t border-gray-100">
{item.a}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
);
})}
</div>
</div>
))}
</div>
</div>
</>
);
};
export default FAQPage;
import React from 'react';
import { Helmet } from 'react-helmet';
import HeroSection from '@/components/home/HeroSection';
import FeaturedMenCollection from '@/components/home/FeaturedMenCollection';
import FeaturedWomenCollection from '@/components/home/FeaturedWomenCollection';
import TestimonialsSection from '@/components/home/TestimonialsSection';
import SpecialOffersSection from '@/components/home/SpecialOffersSection';
import FinalCTA from '@/components/home/FinalCTA';
const HomePage = () => {
return (
<>
<Helmet>
<title>BinNaveed.Pk - Premium Pakistani Shalwar Kameez | Men's & Women's Collections</title>
<meta name="description" content="Shop premium Pakistani Shalwar Kameez for men and women. Celebrate tradition with contemporary elegance. Quality craftsmanship, authentic designs." />
</Helmet>
<div className="pt-16">
<HeroSection />
<FeaturedMenCollection />
<FeaturedWomenCollection />
<TestimonialsSection />
<SpecialOffersSection />
<FinalCTA />
</div>
</>
);
};
export default HomePage;
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { useProducts } from '@/contexts/ProductContext';
import ProductCard from '@/components/ProductCard';
const MenCollectionPage = () => {
const { getProductsByCategory } = useProducts();
const menProducts = getProductsByCategory('men');
const [sortBy, setSortBy] = useState('default');
const sortedProducts = [...menProducts].sort((a, b) => {
if (sortBy === 'price-low') return a.price - b.price;
if (sortBy === 'price-high') return b.price - a.price;
if (sortBy === 'rating') return b.rating - a.rating;
return 0;
});
return (
<>
<Helmet>
<title>Men's Collection - Premium Shalwar Kameez | BinNaveed.Pk</title>
<meta name="description" content="Browse our premium men's shalwar kameez collection. Traditional craftsmanship meets contemporary elegance." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
Men's Collection
</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
Discover our premium collection of traditional shalwar kameez designed for the modern gentleman
</p>
</motion.div>
{/* Sort Options */}
<div className="flex justify-between items-center mb-8">
<p className="text-gray-600">
Showing {sortedProducts.length} products
</p>
<select
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
className="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
>
<option value="default">Sort by: Default</option>
<option value="price-low">Price: Low to High</option>
<option value="price-high">Price: High to Low</option>
<option value="rating">Rating: High to Low</option>
</select>
</div>
{/* Products Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{sortedProducts.map((product, index) => (
<motion.div
key={product.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<ProductCard product={product} />
</motion.div>
))}
</div>
</div>
</>
);
};
export default MenCollectionPage;
import React, { useEffect, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { motion } from 'framer-motion';
import { CheckCircle, Home, ShoppingBag, MapPin, CreditCard, Mail } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Helmet } from 'react-helmet';
const OrderConfirmationPage = () => {
const [order, setOrder] = useState(null);
const navigate = useNavigate();
useEffect(() => {
const savedOrder = localStorage.getItem('binnaveed-current-order');
if (!savedOrder) {
navigate('/');
return;
}
setOrder(JSON.parse(savedOrder));
}, [navigate]);
if (!order) return null;
return (
<>
<Helmet>
<title>Order Confirmed - BinNaveed.Pk</title>
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-4xl mx-auto bg-gray-50 min-h-screen">
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
className="bg-white rounded-2xl shadow-lg overflow-hidden"
>
{/* Header */}
<div className="bg-purple-600 p-8 text-center text-white">
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ delay: 0.3, type: 'spring', stiffness: 200 }}
className="w-20 h-20 bg-white rounded-full flex items-center justify-center mx-auto mb-6"
>
<CheckCircle className="w-12 h-12 text-purple-600" />
</motion.div>
<h1 className="text-3xl font-bold mb-2">Order Confirmed!</h1>
<p className="text-purple-100 text-lg">
Thank you for shopping with BinNaveed.Pk
</p>
<p className="text-purple-200 mt-4 text-sm font-mono bg-purple-700/50 inline-block px-4 py-1 rounded-full">
Order #{order.id}
</p>
</div>
<div className="p-6 md:p-8 space-y-8">
{/* Customer & Shipping Details */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="space-y-4">
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2 flex items-center gap-2">
<MapPin className="w-5 h-5 text-purple-600" /> Shipping Details
</h3>
<div className="text-gray-600 text-sm space-y-1">
<p className="font-medium text-gray-900">
{order.customer.firstName} {order.customer.lastName}
</p>
<p>{order.shipping.address}</p>
<p>{order.shipping.city}, {order.shipping.province}</p>
<p>{order.shipping.postalCode}, {order.shipping.country}</p>
</div>
</div>
<div className="space-y-4">
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2 flex items-center gap-2">
<Mail className="w-5 h-5 text-purple-600" /> Contact & Payment
</h3>
<div className="text-gray-600 text-sm space-y-1">
<p><span className="font-medium text-gray-900">Email:</span> {order.customer.email}</p>
<p><span className="font-medium text-gray-900">Phone:</span> {order.customer.phone}</p>
<p className="capitalize"><span className="font-medium text-gray-900">Payment:</span> {order.paymentMethod.replace('cod', 'Cash on Delivery')}</p>
<p><span className="font-medium text-gray-900">Date:</span> {new Date(order.date).toLocaleDateString()}</p>
</div>
</div>
</div>
{/* Order Items */}
<div>
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2 mb-4 flex items-center gap-2">
<ShoppingBag className="w-5 h-5 text-purple-600" /> Order Summary
</h3>
<div className="bg-gray-50 rounded-lg p-4 space-y-4">
{order.items.map((item, index) => (
<div key={index} className="flex justify-between items-center text-sm">
<div className="flex items-center gap-3">
<span className="w-6 h-6 bg-purple-100 text-purple-600 rounded-full flex items-center justify-center text-xs font-bold">
{item.quantity}x
</span>
<span className="text-gray-800">{item.name}</span>
</div>
<span className="font-medium text-gray-900">
PKR {(item.price * item.quantity).toLocaleString()}
</span>
</div>
))}
<div className="border-t border-gray-200 pt-4 mt-4 space-y-2">
<div className="flex justify-between text-sm text-gray-600">
<span>Subtotal</span>
<span>PKR {order.totals.subtotal.toLocaleString()}</span>
</div>
<div className="flex justify-between text-sm text-gray-600">
<span>Shipping</span>
<span>PKR {order.totals.shipping.toLocaleString()}</span>
</div>
<div className="flex justify-between text-sm text-gray-600">
<span>Tax</span>
<span>PKR {order.totals.tax.toLocaleString()}</span>
</div>
<div className="flex justify-between text-lg font-bold text-gray-900 pt-2 border-t border-gray-200">
<span>Total Paid</span>
<span className="text-purple-600">PKR {order.totals.total.toLocaleString()}</span>
</div>
</div>
</div>
</div>
{/* Actions */}
<div className="flex flex-col sm:flex-row gap-4 justify-center pt-4">
<Link to="/">
<Button size="lg" className="w-full sm:w-auto bg-purple-600 hover:bg-purple-700">
<Home className="w-4 h-4 mr-2" />
Continue Shopping
</Button>
</Link>
</div>
</div>
</motion.div>
</div>
</>
);
};
export default OrderConfirmationPage;
import React from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { Shield, Lock, Eye, FileText } from 'lucide-react';
const PrivacyPolicyPage = () => {
return (
<>
<Helmet>
<title>Privacy Policy | BinNaveed.Pk</title>
<meta name="description" content="BinNaveed.Pk Privacy Policy. How we collect, use, and protect your personal information." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-4xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-6">
<Shield className="w-8 h-8 text-purple-600" />
</div>
<h1 className="text-4xl font-bold text-gray-900 mb-4">
Privacy Policy
</h1>
<p className="text-lg text-gray-600">
Your privacy and data security are our top priorities.
</p>
</motion.div>
<div className="space-y-8 text-gray-600 leading-relaxed">
<section className="bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<h2 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-2">
<FileText className="w-5 h-5 text-purple-600" />
Information We Collect
</h2>
<p className="mb-4">
When you visit BinNaveed.Pk, we collect certain information about your device, including your web browser, IP address, time zone, and some of the cookies that are installed on your device. Additionally, as you browse the Site, we collect information about the individual web pages or products that you view.
</p>
<p>
When you make a purchase, we collect certain information from you, including your name, billing address, shipping address, payment information, email address, and phone number.
</p>
</section>
<section className="bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<h2 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-2">
<Eye className="w-5 h-5 text-purple-600" />
How We Use Your Information
</h2>
<ul className="list-disc pl-5 space-y-2">
<li>To fulfill any orders placed through the Site (including processing your payment information, arranging for shipping, and providing you with invoices and/or order confirmations).</li>
<li>To communicate with you regarding your order or inquiries.</li>
<li>To screen our orders for potential risk or fraud.</li>
<li>To provide you with information or advertising relating to our products or services.</li>
</ul>
</section>
<section className="bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<h2 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-2">
<Lock className="w-5 h-5 text-purple-600" />
Data Security
</h2>
<p className="mb-4">
We implement a variety of security measures to maintain the safety of your personal information. Your personal information is contained behind secured networks and is only accessible by a limited number of persons who have special access rights to such systems.
</p>
<p>
We do not sell, trade, or otherwise transfer to outside parties your Personally Identifiable Information unless we provide users with advance notice. This does not include website hosting partners and other parties who assist us in operating our website, conducting our business, or serving our users.
</p>
</section>
<section className="bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<h2 className="text-xl font-bold text-gray-900 mb-4">Cookies</h2>
<p>
Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow) that enables the site's or service provider's systems to recognize your browser and capture and remember certain information. We use cookies to help us remember and process the items in your shopping cart and understand your preferences based on previous or current site activity.
</p>
</section>
<div className="text-center pt-8 border-t border-gray-200">
<p className="text-sm">
Last Updated: {new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}
</p>
</div>
</div>
</div>
</>
);
};
export default PrivacyPolicyPage;
import React, { useState } from 'react';
import { useParams, Link } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { useProducts } from '@/contexts/ProductContext';
import { useCart } from '@/contexts/CartContext';
import { Star, Heart, Minus, Plus, ShoppingBag } from 'lucide-react';
import { Button } from '@/components/ui/button';
import ProductCard from '@/components/ProductCard';
import { useToast } from '@/components/ui/use-toast';
const ProductDetailPage = () => {
const { id } = useParams();
const { getProductById, getRelatedProducts } = useProducts();
const { addToCart } = useCart();
const { toast } = useToast();
const product = getProductById(id);
const [selectedColor, setSelectedColor] = useState('');
const [quantity, setQuantity] = useState(1);
if (!product) {
return (
<div className="pt-24 pb-16 px-4 text-center">
<h1 className="text-2xl font-bold text-gray-900">Product not found</h1>
<Link to="/" className="text-purple-600 hover:underline mt-4 inline-block">
Return to Home
</Link>
</div>
);
}
const relatedProducts = getRelatedProducts(product.id, product.category);
const handleAddToCart = () => {
if (!selectedColor) {
toast({
title: "Selection Required",
description: "Please select color before adding to cart",
variant: "destructive"
});
return;
}
// Updated: Removed size argument
addToCart(product, selectedColor, quantity);
};
const handleAddToWishlist = () => {
toast({
title: "🚧 This feature isn't implemented yet—but don't worry! You can request it in your next prompt! 🚀"
});
};
return (
<>
<Helmet>
<title>{product.name} | BinNaveed.Pk</title>
<meta name="description" content={product.description} />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 mb-16">
{/* Product Image */}
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6 }}
className="space-y-4"
>
<div className="aspect-[3/4] rounded-2xl overflow-hidden shadow-xl">
<img
src={product.image}
alt={product.name}
className="w-full h-full object-cover"
/>
</div>
</motion.div>
{/* Product Details */}
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6 }}
className="space-y-6"
>
<div>
<h1 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
{product.name}
</h1>
<div className="flex items-center gap-4 mb-4">
<div className="flex items-center gap-1">
{[...Array(5)].map((_, i) => (
<Star
key={i}
className={`w-5 h-5 ${
i < Math.floor(product.rating)
? 'fill-yellow-400 text-yellow-400'
: 'text-gray-300'
}`}
/>
))}
</div>
<span className="text-sm text-gray-600">
{product.rating} ({product.reviews} reviews)
</span>
</div>
<p className="text-3xl font-bold text-purple-600 mb-6">
PKR {product.price.toLocaleString()}
</p>
</div>
<div className="border-t border-b border-gray-200 py-6 space-y-6">
<p className="text-gray-700 leading-relaxed">
{product.description}
</p>
{/* Size Selection Removed */}
{/* Color Selection */}
<div>
<label className="block text-sm font-semibold text-gray-900 mb-3">
Select Color
</label>
<div className="flex flex-wrap gap-2">
{product.colors.map((color) => (
<button
key={color}
onClick={() => setSelectedColor(color)}
className={`px-6 py-2 border-2 rounded-lg font-medium transition-all ${
selectedColor === color
? 'border-purple-600 bg-purple-50 text-purple-600'
: 'border-gray-300 text-gray-700 hover:border-purple-300'
}`}
>
{color}
</button>
))}
</div>
</div>
{/* Quantity Selection */}
<div>
<label className="block text-sm font-semibold text-gray-900 mb-3">
Quantity
</label>
<div className="flex items-center gap-3">
<Button
variant="outline"
size="icon"
onClick={() => setQuantity(Math.max(1, quantity - 1))}
>
<Minus className="h-4 w-4" />
</Button>
<span className="text-xl font-semibold text-gray-900 w-12 text-center">
{quantity}
</span>
<Button
variant="outline"
size="icon"
onClick={() => setQuantity(quantity + 1)}
>
<Plus className="h-4 w-4" />
</Button>
</div>
</div>
</div>
{/* Action Buttons */}
<div className="space-y-3">
<Button
onClick={handleAddToCart}
size="lg"
className="w-full bg-purple-600 hover:bg-purple-700 text-white"
>
<ShoppingBag className="w-5 h-5 mr-2" />
Add to Cart
</Button>
<Button
onClick={handleAddToWishlist}
size="lg"
variant="outline"
className="w-full border-purple-600 text-purple-600 hover:bg-purple-50"
>
<Heart className="w-5 h-5 mr-2" />
Add to Wishlist
</Button>
</div>
</motion.div>
</div>
{/* Related Products */}
{relatedProducts.length > 0 && (
<div>
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-8">
You May Also Like
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{relatedProducts.map((relatedProduct, index) => (
<motion.div
key={relatedProduct.id}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<ProductCard product={relatedProduct} />
</motion.div>
))}
</div>
</div>
)}
</div>
</>
);
};
export default ProductDetailPage;
import React from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { RefreshCcw, CheckCircle, XCircle, AlertCircle } from 'lucide-react';
const ReturnPolicyPage = () => {
return (
<>
<Helmet>
<title>Return Policy | BinNaveed.Pk</title>
<meta name="description" content="Read our 15-day return policy. Information on refunds, exchanges, and return conditions at BinNaveed.Pk." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-4xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-6">
<RefreshCcw className="w-8 h-8 text-purple-600" />
</div>
<h1 className="text-4xl font-bold text-gray-900 mb-4">
Return & Exchange Policy
</h1>
<p className="text-lg text-gray-600">
We want you to be completely satisfied with your purchase.
</p>
</motion.div>
<div className="space-y-8">
{/* Overview */}
<section className="bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<h2 className="text-xl font-bold text-gray-900 mb-4 flex items-center gap-2">
<AlertCircle className="w-5 h-5 text-purple-600" />
15-Day Return Window
</h2>
<p className="text-gray-600 leading-relaxed">
You can return or exchange any item within <strong>15 days</strong> of delivery. The item must be unused, unwashed, and in its original packaging with all tags intact.
</p>
</section>
{/* Conditions */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<motion.div
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
className="bg-green-50 rounded-xl p-6 border border-green-100"
>
<h3 className="text-lg font-bold text-green-800 mb-4 flex items-center gap-2">
<CheckCircle className="w-5 h-5" />
Returnable Items
</h3>
<ul className="space-y-2 text-green-700">
<li>• Items with manufacturing defects</li>
<li>• Wrong size or color delivered</li>
<li>• Unworn items with original tags</li>
<li>• Items in original packaging</li>
</ul>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 20 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
className="bg-red-50 rounded-xl p-6 border border-red-100"
>
<h3 className="text-lg font-bold text-red-800 mb-4 flex items-center gap-2">
<XCircle className="w-5 h-5" />
Non-Returnable Items
</h3>
<ul className="space-y-2 text-red-700">
<li>• Washed or worn items</li>
<li>• Items without tags</li>
<li>• Sale or clearance items</li>
<li>• Custom or altered orders</li>
</ul>
</motion.div>
</div>
{/* Process */}
<section className="bg-white rounded-xl shadow-sm border border-gray-100 p-8">
<h2 className="text-xl font-bold text-gray-900 mb-6">How to Initiate a Return</h2>
<div className="space-y-6">
<div className="flex gap-4">
<div className="w-8 h-8 bg-purple-600 text-white rounded-full flex items-center justify-center font-bold flex-shrink-0">1</div>
<div>
<h4 className="font-bold text-gray-900">Contact Us</h4>
<p className="text-gray-600 mt-1">
WhatsApp us at <strong>03025327880</strong> or email <strong>binnaveed.pk@outlook.com</strong> with your Order ID and reason for return.
</p>
</div>
</div>
<div className="flex gap-4">
<div className="w-8 h-8 bg-purple-600 text-white rounded-full flex items-center justify-center font-bold flex-shrink-0">2</div>
<div>
<h4 className="font-bold text-gray-900">Pack Your Item</h4>
<p className="text-gray-600 mt-1">
Securely pack the item in its original packaging including all accessories and invoice.
</p>
</div>
</div>
<div className="flex gap-4">
<div className="w-8 h-8 bg-purple-600 text-white rounded-full flex items-center justify-center font-bold flex-shrink-0">3</div>
<div>
<h4 className="font-bold text-gray-900">Ship Back</h4>
<p className="text-gray-600 mt-1">
Send the package to our return address provided by our support team.
</p>
</div>
</div>
<div className="flex gap-4">
<div className="w-8 h-8 bg-purple-600 text-white rounded-full flex items-center justify-center font-bold flex-shrink-0">4</div>
<div>
<h4 className="font-bold text-gray-900">Refund/Exchange</h4>
<p className="text-gray-600 mt-1">
Once received and inspected, we will process your refund or ship the exchange item within 3 working days.
</p>
</div>
</div>
</div>
</section>
</div>
</div>
</>
);
};
export default ReturnPolicyPage;
import React from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { Truck, Globe, Clock, Package } from 'lucide-react';
const ShippingPage = () => {
return (
<>
<Helmet>
<title>Shipping Information | BinNaveed.Pk</title>
<meta name="description" content="Learn about BinNaveed.Pk shipping methods, delivery times, and costs for Pakistan and international orders." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center mx-auto mb-6">
<Truck className="w-8 h-8 text-purple-600" />
</div>
<h1 className="text-4xl font-bold text-gray-900 mb-4">
Shipping Information
</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
We are committed to delivering your order quickly, safely, and efficiently.
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-12">
{/* Domestic Shipping */}
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.2 }}
className="bg-white rounded-xl shadow-lg p-8 border-t-4 border-purple-600"
>
<div className="flex items-center gap-4 mb-6">
<div className="bg-purple-100 p-3 rounded-lg">
<Truck className="w-6 h-6 text-purple-600" />
</div>
<h2 className="text-2xl font-bold text-gray-900">Domestic Shipping</h2>
</div>
<ul className="space-y-4 text-gray-600">
<li className="flex gap-3">
<Clock className="w-5 h-5 text-purple-600 flex-shrink-0" />
<span><strong>Delivery Time:</strong> 3-5 working days for major cities (Lahore, Karachi, Islamabad). 5-7 days for other regions.</span>
</li>
<li className="flex gap-3">
<Package className="w-5 h-5 text-purple-600 flex-shrink-0" />
<span><strong>Shipping Cost:</strong> Flat rate of PKR 200. Free shipping on orders over PKR 5,000.</span>
</li>
<li className="flex gap-3">
<Globe className="w-5 h-5 text-purple-600 flex-shrink-0" />
<span><strong>Coverage:</strong> We deliver to all cities and towns across Pakistan via TCS, Leopard, and M&P.</span>
</li>
</ul>
</motion.div>
{/* International Shipping */}
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ delay: 0.3 }}
className="bg-white rounded-xl shadow-lg p-8 border-t-4 border-gray-800"
>
<div className="flex items-center gap-4 mb-6">
<div className="bg-gray-100 p-3 rounded-lg">
<Globe className="w-6 h-6 text-gray-800" />
</div>
<h2 className="text-2xl font-bold text-gray-900">International Shipping</h2>
</div>
<ul className="space-y-4 text-gray-600">
<li className="flex gap-3">
<Clock className="w-5 h-5 text-gray-800 flex-shrink-0" />
<span><strong>Delivery Time:</strong> 7-14 working days depending on destination country and customs clearance.</span>
</li>
<li className="flex gap-3">
<Package className="w-5 h-5 text-gray-800 flex-shrink-0" />
<span><strong>Shipping Cost:</strong> Calculated at checkout based on weight and destination.</span>
</li>
<li className="flex gap-3">
<Globe className="w-5 h-5 text-gray-800 flex-shrink-0" />
<span><strong>Partners:</strong> We use reliable services like DHL and FedEx for international shipments.</span>
</li>
</ul>
</motion.div>
</div>
{/* Tracking Info */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
className="bg-purple-50 rounded-xl p-8 text-center"
>
<h2 className="text-2xl font-bold text-gray-900 mb-4">Order Tracking</h2>
<p className="text-gray-600 max-w-2xl mx-auto mb-6">
Once your order is dispatched, you will receive a tracking number via email and SMS. You can use this number to track your parcel on our courier partner's website.
</p>
<div className="flex justify-center gap-4">
<div className="text-sm font-semibold text-purple-700 bg-purple-100 px-4 py-2 rounded-full">
Email Notifications
</div>
<div className="text-sm font-semibold text-purple-700 bg-purple-100 px-4 py-2 rounded-full">
SMS Updates
</div>
</div>
</motion.div>
</div>
</>
);
};
export default ShippingPage;
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import { motion } from 'framer-motion';
import { useProducts } from '@/contexts/ProductContext';
import ProductCard from '@/components/ProductCard';
const WomenCollectionPage = () => {
const { getProductsByCategory } = useProducts();
const womenProducts = getProductsByCategory('women');
const [sortBy, setSortBy] = useState('default');
const sortedProducts = [...womenProducts].sort((a, b) => {
if (sortBy === 'price-low') return a.price - b.price;
if (sortBy === 'price-high') return b.price - a.price;
if (sortBy === 'rating') return b.rating - a.rating;
return 0;
});
return (
<>
<Helmet>
<title>Women's Collection - Premium Shalwar Kameez | BinNaveed.Pk</title>
<meta name="description" content="Explore our exquisite women's shalwar kameez collection. Elegant designs with intricate craftsmanship." />
</Helmet>
<div className="pt-24 pb-16 px-4 max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-center mb-12"
>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
Women's Collection
</h1>
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
Exquisite designs crafted with intricate detail and timeless beauty for every occasion
</p>
</motion.div>
{/* Sort Options */}
<div className="flex justify-between items-center mb-8">
<p className="text-gray-600">
Showing {sortedProducts.length} products
</p>
<select
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
className="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 text-gray-900"
>
<option value="default">Sort by: Default</option>
<option value="price-low">Price: Low to High</option>
<option value="price-high">Price: High to Low</option>
<option value="rating">Rating: High to Low</option>
</select>
</div>
{/* Products Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{sortedProducts.map((product, index) => (
<motion.div
key={product.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
>
<ProductCard product={product} />
</motion.div>
))}
</div>
</div>
</>
);
};
export default WomenCollectionPage;
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ['class'],
content: [
'./pages/**/*.{js,jsx}',
'./components/**/*.{js,jsx}',
'./app/**/*.{js,jsx}',
'./src/**/*.{js,jsx}',
],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px',
},
},
extend: {
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
keyframes: {
'accordion-down': {
from: { height: 0 },
to: { height: 'var(--radix-accordion-content-height)' },
},
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 },
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out',
},
},
},
plugins: [require('tailwindcss-animate')],
};