import React, { createContext, useContext, useState, useEffect } from 'react'; import { CONFIG, apiFetch } from '../config'; type Page = 'home' | 'about' | 'contact' | 'login' | 'signup' | 'how-it-works' | 'pricing' | 'grow-business' | 'profile-completion' | 'confirmation' | 'dashboard' | 'forgot-password' | 'login-otp' | 'welcome-tour' | 'application-submitted'; type DashboardTab = 'overview' | 'products' | 'orders' | 'returns' | 'wallet' | 'settings' | 'barcode-generator' | 'analytics'; type DateFilter = 'year' | 'week' | 'day' | 'custom'; interface Product { id: string; title: string; category: string; price: number; stock: number; sku: string; image: string; } interface Order { id: string; date: string; item: string; quantity: number; customer: string; total: number; status: 'Ready to Ship test' | 'Ready to Ship' | 'Shipped' | 'Delivered' | 'Cancelled' | 'Pending Acceptance' | 'Rejected'; carrier: string; tracking: string; eta: string; } interface ReturnRequest { id: string; orderId: string; customer: string; item: string; reason: string; status: 'Pending Approval' | 'Approved' | 'Rejected' | 'In Transit'; image: string; returningTracking: string; } export const SellerContext = createContext(null); export const useSeller = () => useContext(SellerContext); export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children }) => { const [currentPage, setCurrentPage] = useState('home') const [isSidebarOpen, setIsSidebarOpen] = useState(false) const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) const [activeTab, setActiveTab] = useState<'login' | 'register'>('login') // Onboarding Status const [isProfileComplete, setIsProfileComplete] = useState(false) // Registration / Onboarding Form States const [email, setEmail] = useState('') const [phone, setPhone] = useState('') const [password, setPassword] = useState('') // Step 1: Verification const [phoneVerified, setPhoneVerified] = useState(false) const [emailVerified, setEmailVerified] = useState(false) const [phoneOtpSent, setPhoneOtpSent] = useState(false) const [emailOtpSent, setEmailOtpSent] = useState(false) const [enteredPhoneOtp, setEnteredPhoneOtp] = useState('') const [enteredEmailOtp, setEnteredEmailOtp] = useState('') // Step 2: Business details (moved GSTIN here) const [gstin, setGstin] = useState('29AAAAA1111A1Z1') const [isGstinVerified, setIsGstinVerified] = useState(false) const [aadharFile, setAadharFile] = useState(null) const [panFile, setPanFile] = useState(null) const [aadharS3Key, setAadharS3Key] = useState(null) const [aadharUrl, setAadharUrl] = useState(null) // New const [panS3Key, setPanS3Key] = useState(null) const [panUrl, setPanUrl] = useState(null) // New // New onboarding customization states const [businessType, setBusinessType] = useState<'registered_company' | 'self_help_group' | 'individual_maker'>('registered_company') const [storeSlug, setStoreSlug] = useState('') const [supportEmail, setSupportEmail] = useState('') const [supportPhone, setSupportPhone] = useState('') const [selectedCategories, setSelectedCategories] = useState([]) // 7-step onboarding state const [onboardingStep, setOnboardingStep] = useState(1) const [applicationId, setApplicationId] = useState('TRD-' + Math.floor(100000 + Math.random() * 900000)) const [bankDetails, setBankDetails] = useState({ accountHolderName: '', accountNumber: '', confirmAccountNumber: '', ifscCode: '', bankName: '', branchName: '', accountType: 'Current' }) const [pickupAddress, setPickupAddress] = useState({ buildingName: '', street: '123 Handloom Lane', landmark: '', city: 'Textile Town', state: 'Karnataka', pincode: '560001', contactPerson: '', contactPhone: '' }) const [initialProduct, setInitialProduct] = useState({ title: '', category: 'Handloom & Textiles', price: '', stock: '', description: '', sku: '', materials: '', image: '' }) // Store and Location details const [storeName, setStoreName] = useState('My Artisan Handloom') const [storeLogo, setStoreLogo] = useState(null) const [logoS3Key, setLogoS3Key] = useState(null) const [businessBio, setBusinessBio] = useState('Traditional weaving and local sustainable designs.') const [address, setAddress] = useState({ street: '123 Handloom Lane', city: 'Textile Town', state: 'Karnataka', pincode: '560001' }) const [mapCoordinates, setMapCoordinates] = useState({ lat: 12.9716, lng: 77.5946 }) // --- Password visibility, confirm password and policy states --- const [showLoginPass, setShowLoginPass] = useState(false) const [showSignupPass, setShowSignupPass] = useState(false) const [showSignupConfirmPass, setShowSignupConfirmPass] = useState(false) const [confirmPassword, setConfirmPassword] = useState('') const [policyAccepted, setPolicyAccepted] = useState(false) // --- Password Reset Page States --- const [resetEmail, setResetEmail] = useState('') const [resetOtpSent, setResetOtpSent] = useState(false) const [resetOtp, setResetOtp] = useState('') const [resetPassword, setResetPassword] = useState('') // --- OTP Login States --- const [otpLoginPhone, setOtpLoginPhone] = useState('') const [otpLoginSent, setOtpLoginSent] = useState(false) const [otpLoginCode, setOtpLoginCode] = useState('') // --- Barcode Generator States --- const [barcodeProductSku, setBarcodeProductSku] = useState('') const [barcodeGenerated, setBarcodeGenerated] = useState(false) // --- Active Dashboard States --- const [dashTab, setDashTab] = useState('overview') const [dateFilter, setDateFilter] = useState('year') const [customDates, setCustomDates] = useState({ start: '2026-06-01', end: '2026-06-15' }) // Lists const [products, setProducts] = useState([]) const [orders, setOrders] = useState([]) const [returns, setReturns] = useState([]) // Forms & Editing const [productForm, setProductForm] = useState({ id: '', title: '', category: 'Apparel', price: 0, stock: 0, sku: '', image: 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=100' }) const [isEditingProduct, setIsEditingProduct] = useState(false) // New Heritage UI wizard states const [productWizardStep, setProductWizardStep] = useState(0) // 0: Catalog list, 1-5: Product upload wizard steps const [productFormDetails, setProductFormDetails] = useState({ id: '', name: '', category: 'Textiles & Apparel', description: '', isGiTagged: false, primaryImage: 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=300', additionalViews: [] as string[], videoUrl: '', view360Url: '', basePrice: '', compareAtPrice: '', trackInventory: true, sku: '', initialStock: '', shippingProfile: 'Standard Fragile', processingDays: 3, packageWeight: 1.0 }) const [selectedOrderDetail, setSelectedOrderDetail] = useState(null) const [orderNotes, setOrderNotes] = useState('') // Payout outstanding states const [wallet, setWallet] = useState({ outstanding: 850.00, withdrawn: 1250.00, history: [ { id: 'TX-9031', date: '2026-08-01', amount: 500.00, status: 'Transferred' }, { id: 'TX-9022', date: '2026-07-15', amount: 750.00, status: 'Transferred' } ] }) const [withdrawAmount, setWithdrawAmount] = useState('') // Load data from backend on mount or when profile is complete / logged in useEffect(() => { const token = localStorage.getItem('access_token'); if (token) { apiFetch(`${CONFIG.apiBaseUrl}/api/profile/`) .then(res => { if (res.ok) return res.json(); throw new Error('Session expired'); }) .then(user => { if (user && user.profile) { const profile = user.profile; setPhone(profile.phone || ''); setPhoneVerified(profile.phone_verified || false); setEmail(user.email || ''); setEmailVerified(profile.email_verified || false); setGstin(profile.gstin || '29AAAAA1111A1Z1'); setIsGstinVerified(profile.is_gstin_verified || false); setAadharFile(profile.aadhar_file || null); setPanFile(profile.pan_file || null); setAadharS3Key(profile.aadhar_s3_key || null); setPanS3Key(profile.pan_s3_key || null); setAadharUrl(profile.aadhar_url || null); // New setPanUrl(profile.pan_url || null); // New setBusinessType(profile.business_type || 'registered_company'); setStoreSlug(profile.store_slug || ''); setSupportEmail(profile.support_email || ''); setSupportPhone(profile.support_phone || ''); setSelectedCategories(profile.categories || []); setStoreName(profile.store_name || 'My Artisan Handloom'); setStoreLogo(profile.store_logo || null); setLogoS3Key(profile.logo_s3_key || null); setBusinessBio(profile.business_bio || 'Traditional weaving and local sustainable designs.'); setAddress({ street: profile.street || '123 Handloom Lane', city: profile.city || 'Textile Town', state: profile.state || 'Karnataka', pincode: profile.pincode || '560001' }); if (profile.latitude && profile.longitude) { setMapCoordinates({ lat: Number(profile.latitude), lng: Number(profile.longitude) }); } const step = profile.onboarding_step; // The onboarding flow is now just 1 step, so anything >= 2 (or 4 if we keep old backend state) means complete if (step >= 4 || profile.is_profile_complete) { setIsProfileComplete(true); setCurrentPage('dashboard'); } else { setIsProfileComplete(false); setCurrentPage('profile-completion'); } } }) .catch(err => { console.error('Session restore failed:', err); localStorage.removeItem('access_token') localStorage.removeItem('refresh_token'); }); } }, []); useEffect(() => { if (isProfileComplete || currentPage === 'dashboard') { // Fetch Products apiFetch(`${CONFIG.apiBaseUrl}/api/products/`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) setProducts(data); else if (data && Array.isArray(data.results)) setProducts(data.results); }) .catch(err => console.error('Error fetching products:', err)); // Fetch Orders apiFetch(`${CONFIG.apiBaseUrl}/api/orders/`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) setOrders(data); else if (data && Array.isArray(data.results)) setOrders(data.results); }) .catch(err => console.error('Error fetching orders:', err)); // Fetch Returns apiFetch(`${CONFIG.apiBaseUrl}/api/returns/`) .then(res => res.json()) .then(data => { if (Array.isArray(data)) setReturns(data); else if (data && Array.isArray(data.results)) setReturns(data.results); }) .catch(err => console.error('Error fetching returns:', err)); // Fetch Wallet apiFetch(`${CONFIG.apiBaseUrl}/api/wallet/`) .then(res => res.json()) .then(data => { if (data) setWallet(data); }) .catch(err => console.error('Error fetching wallet:', err)); } }, [isProfileComplete, currentPage]); const uploadDocument = async (file: File, fileType: string) => { try { const response = await apiFetch(`${CONFIG.apiBaseUrl}/api/profile/presigned-url/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ file_type: fileType, content_type: file.type }) }); if (!response.ok) throw new Error('Failed to get presigned URL'); const data = await response.json(); // Simulate file upload PUT to mock presigned_url await fetch(data.presigned_url, { method: 'PUT', body: file, headers: { 'Content-Type': file.type } }).catch(err => console.log('Mock S3 upload:', err)); return data.s3_key; } catch (err) { console.error(err); return `suppliers/default/${fileType}.jpg`; } }; const handleAcceptOrder = (id: string) => { apiFetch(`${CONFIG.apiBaseUrl}/api/orders/${id}/accept/`, { method: 'POST' }) .then(res => res.json()) .then(updatedOrder => { setOrders(orders.map(o => o.id === updatedOrder.id ? updatedOrder : o)) alert(`Order accepted successfully!`) }) .catch(err => console.error(err)) } const handleRejectOrder = (id: string) => { apiFetch(`${CONFIG.apiBaseUrl}/api/orders/${id}/reject/`, { method: 'POST' }) .then(res => res.json()) .then(updatedOrder => { setOrders(orders.map(o => o.id === updatedOrder.id ? updatedOrder : o)) alert(`Order rejected.`) }) .catch(err => console.error(err)) } // Bulk Upload const [bulkLog, setBulkLog] = useState([]) const [isParsingBulk, setIsParsingBulk] = useState(false) const [bulkCsvFile, setBulkCsvFile] = useState(null) const [bulkZipFile, setBulkZipFile] = useState(null) // GSTIN verification simulator const handleVerifyGstin = () => { if (!gstin.trim() || gstin.length !== 15) { alert('Invalid GSTIN length. Must be 15 chars.'); return; } apiFetch(`${CONFIG.apiBaseUrl}/api/profile/submit-gstin/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ gstin }) }) .then(res => { if (!res.ok) throw new Error('Failed to verify GSTIN.'); return res.json(); }) .then(data => { if (data.verified) { setIsGstinVerified(true); } }) .catch(err => { alert(err.message); }); } // Handle Logo Upload simulation const handleLogoChange = async (e: React.ChangeEvent) => { const file = e.target.files?.[0] if (file) { const reader = new FileReader() reader.onloadend = () => { setStoreLogo(reader.result as string) } reader.readAsDataURL(file) const s3Key = await uploadDocument(file, 'logo'); setLogoS3Key(s3Key); } } // Route/Navigation Guard: If profile is not complete, redirect to profile-completion const navigateTo = (page: Page, forceComplete: boolean = false) => { const publicPages: Page[] = ['home', 'about', 'contact', 'login', 'signup', 'forgot-password', 'login-otp'] const complete = isProfileComplete || forceComplete if (!complete && !publicPages.includes(page) && page !== 'profile-completion') { alert('Access Denied: Please complete your supplier profile first!') setCurrentPage('profile-completion') } else { setCurrentPage(page) } window.scrollTo({ top: 0, behavior: 'smooth' }) } const handleLogout = () => { apiFetch(`${CONFIG.apiBaseUrl}/api/auth/logout/`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }) .catch(err => console.error('Error logging out:', err)) .finally(() => { localStorage.removeItem('access_token') localStorage.removeItem('refresh_token') // Reset all onboarding & profile states to their defaults setIsProfileComplete(false) setEmail('') setPhone('') setPassword('') setConfirmPassword('') setPolicyAccepted(false) setPhoneVerified(false) setEmailVerified(false) setPhoneOtpSent(false) setEmailOtpSent(false) setEnteredPhoneOtp('') setEnteredEmailOtp('') setGstin('29AAAAA1111A1Z1') setIsGstinVerified(false) setAadharFile(null) setPanFile(null) setAadharS3Key(null) setAadharUrl(null) setPanS3Key(null) setPanUrl(null) setBusinessType('registered_company') setStoreSlug('') setSupportEmail('') setSupportPhone('') setSelectedCategories([]) setStoreName('My Artisan Handloom') setStoreLogo(null) setLogoS3Key(null) setBusinessBio('Traditional weaving and local sustainable designs.') setAddress({ street: '123 Handloom Lane', city: 'Textile Town', state: 'Karnataka', pincode: '560001' }) setMapCoordinates({ lat: 12.9716, lng: 77.5946 }) navigateTo('home', true) }) } const handleRegisterSubmit = (e: React.FormEvent) => { e.preventDefault() // Email Validation const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { alert('Please enter a valid email address.'); return; } // Phone Validation const phoneRegex = /^[6-9]\d{9}$/; if (!phoneRegex.test(phone)) { alert('Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.'); return; } // Password Validation if (password.length < 8) { alert('Password must be at least 8 characters long.'); return; } if (password !== confirmPassword) { alert('Passwords do not match.'); return; } // Policy Validation if (!policyAccepted) { alert('You must accept the Terms of Service and Privacy Policy.'); return; } apiFetch(`${CONFIG.apiBaseUrl}/api/auth/register/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: email, email: email, phone: phone, password: password, confirm_password: confirmPassword, policy_accepted: policyAccepted }) }) .then(res => { if (!res.ok) throw new Error('Registration failed. Username/email might already be taken.'); return res.json(); }) .then(() => { // Auto login after signup apiFetch(`${CONFIG.apiBaseUrl}/api/auth/login/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: email, password: password }) }) .then(res => { if (!res.ok) throw new Error('Auto-login failed.'); return res.json(); }) .then(data => { localStorage.setItem('access_token', data.access_token); if (data.refresh_token) localStorage.setItem('refresh_token', data.refresh_token); navigateTo('profile-completion') }) }) .catch(err => { alert(err.message); }); } const handleLoginSubmit = (e: React.FormEvent) => { e.preventDefault() if (!email.trim()) { alert('Please enter your email or phone number.'); return; } apiFetch(`${CONFIG.apiBaseUrl}/api/auth/login/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: email, password: password }) }) .then(res => { if (!res.ok) throw new Error('Invalid credentials.'); return res.json(); }) .then(data => { localStorage.setItem('access_token', data.access_token); if (data.refresh_token) localStorage.setItem('refresh_token', data.refresh_token); if (data.user && data.user.profile) { const profile = data.user.profile; setPhone(profile.phone || ''); setPhoneVerified(profile.phone_verified || false); setEmail(data.user.email || ''); setEmailVerified(profile.email_verified || false); setGstin(profile.gstin || '29AAAAA1111A1Z1'); setIsGstinVerified(profile.is_gstin_verified || false); setAadharFile(profile.aadhar_file || null); setPanFile(profile.pan_file || null); setAadharS3Key(profile.aadhar_s3_key || null); setPanS3Key(profile.pan_s3_key || null); setAadharUrl(profile.aadhar_url || null); setPanUrl(profile.pan_url || null); setBusinessType(profile.business_type || 'registered_company'); setStoreSlug(profile.store_slug || ''); setSupportEmail(profile.support_email || ''); setSupportPhone(profile.support_phone || ''); setSelectedCategories(profile.categories || []); setStoreName(profile.store_name || 'My Artisan Handloom'); setStoreLogo(profile.store_logo || null); setLogoS3Key(profile.logo_s3_key || null); setBusinessBio(profile.business_bio || 'Traditional weaving and local sustainable designs.'); setAddress({ street: profile.street || '123 Handloom Lane', city: profile.city || 'Textile Town', state: profile.state || 'Karnataka', pincode: profile.pincode || '560001' }); if (profile.latitude && profile.longitude) { setMapCoordinates({ lat: Number(profile.latitude), lng: Number(profile.longitude) }); } const step = profile.onboarding_step; if (step >= 4 || profile.is_profile_complete) { setIsProfileComplete(true); navigateTo('dashboard', true); } else { setIsProfileComplete(false); navigateTo('profile-completion'); } } else { setIsProfileComplete(false); navigateTo('profile-completion'); } }) .catch(err => { alert(err.message); }); } const saveProfileBackend = (isComplete: boolean) => { return apiFetch(`${CONFIG.apiBaseUrl}/api/profile/`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone: phone, phone_verified: phoneVerified, email_verified: emailVerified, gstin: gstin, is_gstin_verified: isGstinVerified, business_type: businessType, store_slug: storeSlug, support_email: supportEmail, support_phone: supportPhone, categories: selectedCategories, aadhar_file: aadharFile, pan_file: panFile, aadhar_s3_key: aadharS3Key || null, pan_s3_key: panS3Key || null, store_name: storeName, store_logo: storeLogo || 'https://images.unsplash.com/photo-1513519245088-0e12902e5a38?auto=format&fit=crop&q=80&w=800', logo_s3_key: logoS3Key || null, business_bio: businessBio, street: address.street, city: address.city, state: address.state, pincode: address.pincode, latitude: mapCoordinates.lat, longitude: mapCoordinates.lng, is_profile_complete: isComplete }) }) .then(res => { if (!res.ok) throw new Error('Failed to update profile.'); return res.json(); }); }; const handleProfileSubmit = (e?: React.FormEvent) => { if (e && typeof e.preventDefault === 'function') { e.preventDefault(); } return saveProfileBackend(true) .catch(err => { alert(err.message); }) }; // --- Dashboard Logic Actions --- // Product creation/modification const handleSaveProduct = (e: React.FormEvent) => { e.preventDefault() const url = isEditingProduct ? `${CONFIG.apiBaseUrl}/api/products/${productForm.id}/` : `${CONFIG.apiBaseUrl}/api/products/` const method = isEditingProduct ? 'PUT' : 'POST' apiFetch(url, { method: method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: productForm.title, category: productForm.category, price: String(productForm.price), stock: Number(productForm.stock), sku: productForm.sku || `PROD-${Date.now().toString().slice(-6)}`, image: productForm.image }) }) .then(res => res.json()) .then(() => { // Refresh products from backend apiFetch(`${CONFIG.apiBaseUrl}/api/products/`) .then(r => r.json()) .then(prods => { if (Array.isArray(prods)) setProducts(prods); else if (prods && Array.isArray(prods.results)) setProducts(prods.results); }) setIsEditingProduct(false) alert(isEditingProduct ? 'Product modified successfully!' : 'Product uploaded successfully!') }) .catch(err => console.error(err)) // reset form setProductForm({ id: '', title: '', category: 'Apparel', price: 0, stock: 0, sku: '', image: 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=100' }) } const handleEditClick = (p: Product) => { setProductForm(p) setIsEditingProduct(true) } const handleDeleteProduct = (id: string) => { if (confirm('Are you sure you want to delete this listing?')) { apiFetch(`${CONFIG.apiBaseUrl}/api/products/${id}/`, { method: 'DELETE' }) .then(() => { setProducts(products.filter(p => p.id !== id)) }) .catch(err => console.error(err)) } } const handleBulkUploadSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!bulkCsvFile) { alert("Please select a CSV file to upload."); return; } setIsParsingBulk(true); setBulkLog(['Uploading files to server...', 'Parsing CSV data and extracting ZIP images...']); const formData = new FormData(); formData.append('csv_file', bulkCsvFile); if (bulkZipFile) { formData.append('zip_file', bulkZipFile); } try { const token = localStorage.getItem('access_token'); const response = await fetch(`${CONFIG.apiBaseUrl}/api/products/bulk-upload/`, { method: 'POST', headers: { ...(token ? { 'Authorization': `Bearer ${token}` } : {}) }, body: formData }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to complete bulk upload.'); } setBulkLog([ 'CSV file parsed successfully.', `Extracted and matched images for SKUs from ZIP file.`, `Successfully added ${data.products?.length || 0} product listings!`, ]); // Refresh product list const prodRes = await apiFetch(`${CONFIG.apiBaseUrl}/api/products/`); const prods = await prodRes.json(); if (Array.isArray(prods)) { setProducts(prods); } else if (prods && Array.isArray(prods.results)) { setProducts(prods.results); } setBulkCsvFile(null); setBulkZipFile(null); } catch (err: any) { setBulkLog(prev => [...prev, `Error: ${err.message}`]); } finally { setIsParsingBulk(false); } }; // Wallet outstanding requests const handleWithdrawRequest = (e: React.FormEvent) => { e.preventDefault() const amount = Number(withdrawAmount) if (isNaN(amount) || amount <= 0) { alert('Please enter a valid amount') return } apiFetch(`${CONFIG.apiBaseUrl}/api/wallet/withdraw/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: String(amount) }) }) .then(res => { if (!res.ok) throw new Error('Insufficient funds or invalid request'); return res.json(); }) .then(updatedWallet => { setWallet(updatedWallet) setWithdrawAmount('') alert(`Payout of $${amount} successfully transferred!`) }) .catch(err => { alert(err.message) }) } // Returns actions const handleReturnAction = (id: string, action: 'Approved' | 'Rejected') => { apiFetch(`${CONFIG.apiBaseUrl}/api/returns/${id}/action/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: action }) }) .then(res => res.json()) .then(updatedReturn => { setReturns(returns.map(ret => ret.id === id ? updatedReturn : ret)) alert(`Return request ${action.toLowerCase()}!`) }) .catch(err => console.error(err)) } // Compute realtime metrics based on state loaded from backend const computeRealtimeMetrics = () => { const totalSales = orders .filter(o => o.status !== 'Cancelled' && o.status !== 'Rejected') .reduce((sum, o) => sum + Number(o.total), 0) const totalEarned = Number(wallet.outstanding) + Number(wallet.withdrawn) const totalStock = products.reduce((sum, p) => sum + Number(p.stock), 0) const totalReturns = returns.length const isLoggedIn = currentPage === 'dashboard' || currentPage === 'profile-completion' || currentPage === 'welcome-tour' || isProfileComplete if (isLoggedIn) { return { totalSales, totalEarned, stockDetails: totalStock, returnedItems: totalReturns, chartValues: orders.length > 0 ? orders.map(o => Number(o.total)) : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] } } return { totalSales: 45280.00, totalEarned: 38488.00, stockDetails: 342, returnedItems: 12, chartValues: CONFIG.dashboardData.filters[dateFilter]?.chartValues || [30, 45, 35, 60, 50, 75, 65, 80, 70, 95, 90, 110] } } const selectedMetrics = computeRealtimeMetrics() const contextValue = { setBusinessBio, email, resetPassword, setLogoS3Key, setStoreName, setShowLoginPass, storeName, otpLoginSent, setOtpLoginSent, aadharS3Key, logoS3Key, customDates, setProductFormDetails, handleBulkUploadSubmit, setMapCoordinates, setAadharFile, gstin, mapCoordinates, setIsGstinVerified, enteredPhoneOtp, address, setEmailVerified, dashTab, selectedOrderDetail, setShowSignupConfirmPass, handleRegisterSubmit, setBulkCsvFile, confirmPassword, navigateTo, setResetPassword, orderNotes, setOrders, handleRejectOrder, barcodeProductSku, setEnteredEmailOtp, setIsEditingProduct, setBulkLog, isMobileMenuOpen, resetOtp, productWizardStep, setCustomDates, setConfirmPassword, isGstinVerified, bulkCsvFile, setAddress, storeLogo, handleProfileSubmit, setPhoneOtpSent, setOrderNotes, handleDeleteProduct, setWallet, policyAccepted, emailOtpSent, setResetOtpSent, setGstin, phoneOtpSent, showLoginPass, showSignupConfirmPass, setPhoneVerified, aadharFile, setDateFilter, activeTab, computeRealtimeMetrics, setIsParsingBulk, handleLogout, panS3Key, setCurrentPage, selectedCategories, setEmailOtpSent, showSignupPass, resetEmail, handleLogoChange, dateFilter, setShowSignupPass, businessBio, setWithdrawAmount, phoneVerified, currentPage, setResetOtp, enteredEmailOtp, setEnteredPhoneOtp, setPanFile, setIsSidebarOpen, setSelectedOrderDetail, handleAcceptOrder, saveProfileBackend, supportPhone, handleEditClick, setStoreLogo, setEmail, password, setOtpLoginPhone, bulkLog, businessType, setPanS3Key, setProducts, setSupportEmail, setOtpLoginCode, withdrawAmount, handleSaveProduct, setStoreSlug, setBarcodeProductSku, setProductForm, setBulkZipFile, productFormDetails, setIsProfileComplete, otpLoginPhone, orders, setActiveTab, bulkZipFile, isSidebarOpen, setBarcodeGenerated, setBusinessType, handleReturnAction, setSupportPhone, barcodeGenerated, products, productForm, setProductWizardStep, resetOtpSent, emailVerified, panFile, isParsingBulk, setDashTab, setReturns, setPassword, handleWithdrawRequest, uploadDocument, setPolicyAccepted, isEditingProduct, setIsMobileMenuOpen, isProfileComplete, setSelectedCategories, storeSlug, phone, setPhone, setAadharS3Key, handleVerifyGstin, returns, handleLoginSubmit, setResetEmail, wallet, otpLoginCode, supportEmail, aadharUrl, setAadharUrl, panUrl, setPanUrl, onboardingStep, setOnboardingStep, applicationId, setApplicationId, bankDetails, setBankDetails, pickupAddress, setPickupAddress, initialProduct, setInitialProduct }; return ( {children} ); };