supplier_central_frontend/src/App.tsx

2114 lines
98 KiB
TypeScript
Raw Normal View History

import { useState } from 'react'
import { CONFIG } from './config'
2026-08-09 05:29:03 +00:00
type Page = 'home' | 'about' | 'contact' | 'login' | 'signup' | 'profile-completion' | 'confirmation' | 'dashboard' | 'forgot-password' | 'login-otp' | 'welcome-tour'
type DashboardTab = 'overview' | 'products' | 'orders' | 'returns' | 'wallet' | 'settings' | 'barcode-generator'
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
2026-08-09 05:29:03 +00:00
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 default function App() {
const [currentPage, setCurrentPage] = useState<Page>('home')
const [activeTab, setActiveTab] = useState<'login' | 'register'>('login')
2026-08-09 01:53:57 +00:00
2026-08-09 05:29:03 +00:00
// Onboarding Status
const [isProfileComplete, setIsProfileComplete] = useState(false)
const [profileStep, setProfileStep] = useState(1)
// Registration / Onboarding Form States
const [email, setEmail] = useState('')
const [phone, setPhone] = useState('')
const [password, setPassword] = useState('')
2026-08-09 05:29:03 +00:00
// 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')
2026-08-09 05:29:03 +00:00
const [isGstinVerified, setIsGstinVerified] = useState(false)
const [aadharFile, setAadharFile] = useState<string | null>(null)
const [panFile, setPanFile] = useState<string | null>(null)
2026-08-09 01:53:57 +00:00
2026-08-09 05:29:03 +00:00
// Step 3: Store and Location details
const [storeName, setStoreName] = useState('My Artisan Handloom')
const [storeLogo, setStoreLogo] = useState<string | null>(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'
})
2026-08-09 05:29:03 +00:00
const [mapCoordinates, setMapCoordinates] = useState({ lat: 12.9716, lng: 77.5946 })
// --- 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 [barcodeFormat, setBarcodeFormat] = useState('CODE128')
const [barcodeValue, setBarcodeValue] = useState('')
const [barcodeGenerated, setBarcodeGenerated] = useState(false)
// --- Active Dashboard States ---
const [dashTab, setDashTab] = useState<DashboardTab>('overview')
const [dateFilter, setDateFilter] = useState<DateFilter>('year')
const [customDates, setCustomDates] = useState({ start: '2026-06-01', end: '2026-06-15' })
2026-08-09 01:53:57 +00:00
// Lists
const [products, setProducts] = useState<Product[]>(CONFIG.dashboardData.initialProducts)
2026-08-09 05:29:03 +00:00
const [orders, setOrders] = useState<Order[]>([
...CONFIG.dashboardData.initialOrders as Order[],
{ id: 'ORD-8501', date: '2026-08-08', item: 'Brass Elephant Figurine', quantity: 1, customer: 'Bruce Wayne', total: 120.00, status: 'Pending Acceptance', carrier: 'Pending', tracking: 'Pending', eta: 'N/A' },
{ id: 'ORD-8502', date: '2026-08-08', item: 'Handwoven Indigo Shawl', quantity: 2, customer: 'Clark Kent', total: 170.00, status: 'Pending Acceptance', carrier: 'Pending', tracking: 'Pending', eta: 'N/A' }
])
const [returns, setReturns] = useState<ReturnRequest[]>(CONFIG.dashboardData.initialReturns as ReturnRequest[])
2026-08-09 01:53:57 +00:00
// 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)
2026-08-09 01:53:57 +00:00
// 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('')
// Bulk Upload simulations
const [bulkLog, setBulkLog] = useState<string[]>([])
const [isParsingBulk, setIsParsingBulk] = useState(false)
// GSTIN verification simulator
const handleVerifyGstin = () => {
if (!gstin.trim()) return
2026-08-09 05:29:03 +00:00
setIsGstinVerified(true)
}
// Handle Logo Upload simulation
const handleLogoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]
if (file) {
const reader = new FileReader()
reader.onloadend = () => {
setStoreLogo(reader.result as string)
}
reader.readAsDataURL(file)
}
}
2026-08-09 05:29:03 +00:00
// 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 handleRegisterSubmit = (e: React.FormEvent) => {
e.preventDefault()
navigateTo('profile-completion')
}
const handleLoginSubmit = (e: React.FormEvent) => {
e.preventDefault()
2026-08-09 05:29:03 +00:00
setIsProfileComplete(true)
navigateTo('dashboard', true)
}
const handleProfileSubmit = (e: React.FormEvent) => {
e.preventDefault()
2026-08-09 05:29:03 +00:00
if (profileStep < 3) {
setProfileStep(prev => prev + 1)
} else {
setIsProfileComplete(true)
navigateTo('welcome-tour', true)
}
}
// --- Dashboard Logic Actions ---
2026-08-09 01:53:57 +00:00
// Product creation/modification
const handleSaveProduct = (e: React.FormEvent) => {
e.preventDefault()
if (isEditingProduct) {
setProducts(products.map(p => p.id === productForm.id ? { ...productForm, price: Number(productForm.price), stock: Number(productForm.stock) } : p))
setIsEditingProduct(false)
alert('Product modified successfully!')
} else {
const newProd: Product = {
...productForm,
id: String(products.length + 1),
price: Number(productForm.price),
stock: Number(productForm.stock),
sku: productForm.sku || `PROD-${Date.now().toString().slice(-6)}`
}
setProducts([...products, newProd])
alert('Product uploaded successfully!')
}
// 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?')) {
setProducts(products.filter(p => p.id !== id))
}
}
// Bulk parser simulation
const handleBulkUploadSimulate = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files?.length) return
setIsParsingBulk(true)
setBulkLog(['Parsing CSV file template...', 'Validating rows against inventory Schema...'])
2026-08-09 01:53:57 +00:00
setTimeout(() => {
const parsedProducts: Product[] = [
{ id: String(products.length + 1), title: 'Hand-Carved Walnut Bowl', category: 'Kitchenware', price: 65.00, stock: 15, sku: 'BOWL-WAL-12', image: 'https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&q=80&w=100' },
{ id: String(products.length + 2), title: 'Organic Cotton Tablecloth', category: 'Linens', price: 48.00, stock: 30, sku: 'LINE-COT-15', image: 'https://images.unsplash.com/photo-1603006905003-be475563bc59?auto=format&fit=crop&q=80&w=100' }
]
setProducts(prev => [...prev, ...parsedProducts])
setBulkLog(prev => [
...prev,
'Row 1: Verified SKU BOWL-WAL-12 - Added',
'Row 2: Verified SKU LINE-COT-15 - Added',
'Successfully added 2 new listings bulk!'
])
setIsParsingBulk(false)
}, 1500)
}
// 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
}
if (amount > wallet.outstanding) {
alert('Amount exceeds outstanding ready payout balance')
return
}
const txId = `TX-${Math.floor(1000 + Math.random() * 9000)}`
const newTx = {
id: txId,
date: new Date().toISOString().split('T')[0],
amount: amount,
status: 'Transferred'
}
setWallet({
outstanding: wallet.outstanding - amount,
withdrawn: wallet.withdrawn + amount,
history: [newTx, ...wallet.history]
})
setWithdrawAmount('')
alert(`Payout of $${amount} successfully transferred!`)
}
// Returns actions
const handleReturnAction = (id: string, action: 'Approved' | 'Rejected') => {
setReturns(returns.map(ret => {
if (ret.id === id) {
return {
...ret,
status: action === 'Approved' ? 'In Transit' : 'Rejected'
}
}
return ret
}))
alert(`Return request ${action.toLowerCase()}!`)
}
const selectedMetrics = CONFIG.dashboardData.filters[dateFilter]
return (
<>
{/* Dynamic Header */}
<header className="app-header">
<div className="logo-container" onClick={() => navigateTo('home')}>
<div className="logo-icon">{CONFIG.logoLetter}</div>
<span className="logo-text">{CONFIG.companyName}</span>
</div>
<nav className="nav-links">
2026-08-09 01:53:57 +00:00
<button
className={`nav-link ${currentPage === 'home' ? 'active' : ''}`}
onClick={() => navigateTo('home')}
>
Platform
</button>
2026-08-09 01:53:57 +00:00
<button
className="nav-link"
onClick={() => navigateTo('home')}
>
Pricing
</button>
2026-08-09 01:53:57 +00:00
<button
className={`nav-link ${currentPage === 'about' ? 'active' : ''}`}
onClick={() => navigateTo('about')}
>
Success Stories
</button>
2026-08-09 01:53:57 +00:00
<button
className={`nav-link ${currentPage === 'contact' ? 'active' : ''}`}
onClick={() => navigateTo('contact')}
>
Support
</button>
</nav>
<div className="nav-buttons">
{currentPage === 'dashboard' ? (
<button className="btn btn-secondary" onClick={() => navigateTo('home')}>
Logout
</button>
) : (
<>
<button className="btn btn-secondary" onClick={() => { setActiveTab('login'); navigateTo('login'); }}>
Login
</button>
<button className="btn btn-primary" onClick={() => { setActiveTab('register'); navigateTo('signup'); }}>
Get Started
</button>
</>
)}
</div>
</header>
{/* Main Content Area */}
{currentPage !== 'dashboard' ? (
<main className={`main-content ${currentPage === 'home' ? 'full-width' : ''}`}>
2026-08-09 01:53:57 +00:00
{/* HOMEPAGE VIEW */}
{currentPage === 'home' && (
<div>
<section className="hero-section">
<div className="hero-content">
<h1>
{CONFIG.hero.title.split('. ')[0]}.<br />
{CONFIG.hero.title.split('. ')[1]}
</h1>
<p>
{CONFIG.hero.subtitle}
</p>
<div style={{ display: 'flex', gap: '1rem' }}>
<button className="btn btn-dark" onClick={() => { setActiveTab('register'); navigateTo('signup'); }}>
Get Started Today
</button>
<button className="btn btn-outline-dark" onClick={() => navigateTo('about')}>
Learn More
</button>
</div>
</div>
<div className="hero-image-wrapper">
2026-08-09 01:53:57 +00:00
<img
src={CONFIG.hero.image}
alt="Artisans Crafting"
className="hero-img"
/>
</div>
</section>
<section className="features-section">
<div className="features-grid">
{CONFIG.features.map((feature, i) => (
<div className="feature-card" key={i}>
<div className="feature-icon-wrapper">{feature.icon}</div>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</div>
))}
</div>
</section>
<section className="featured-artisan-section">
<div className="artisan-card">
2026-08-09 01:53:57 +00:00
<img
src={CONFIG.featuredArtisan.avatar}
alt="Featured Artisan"
className="artisan-avatar"
/>
<div className="artisan-info">
<h4>Featured Artisan</h4>
<p className="artisan-quote">
{CONFIG.featuredArtisan.quote}
</p>
<p style={{ fontWeight: 'bold' }}>- {CONFIG.featuredArtisan.name} ({CONFIG.featuredArtisan.role})</p>
</div>
</div>
</section>
</div>
)}
{/* ABOUT US VIEW */}
{currentPage === 'about' && (
<div>
<div className="about-mission">
<h2>{CONFIG.about.missionTitle}</h2>
<p>
{CONFIG.about.missionDescription}
</p>
</div>
2026-08-09 01:53:57 +00:00
<div className="team-section">
<h3>Meet Our Leaders</h3>
<div className="team-grid">
{CONFIG.about.team.map((member, i) => (
<div className="team-card" key={i}>
<img src={member.avatar} alt={member.name} className="team-avatar" />
<h4>{member.name}</h4>
<p>{member.role}</p>
</div>
))}
</div>
</div>
</div>
)}
{/* CONTACT US VIEW */}
{currentPage === 'contact' && (
<div className="contact-layout">
<div className="form-card" style={{ margin: 0, maxWidth: '100%' }}>
<h2 className="form-card-title" style={{ textAlign: 'left' }}>Get in Touch</h2>
<form onSubmit={(e) => { e.preventDefault(); alert('Thank you for contacting us! We will get back to you shortly.'); navigateTo('home'); }}>
<div className="form-group">
<label htmlFor="contact-name">Full Name *</label>
<input id="contact-name" type="text" className="form-control" placeholder="Enter your full name" required />
</div>
<div className="form-group">
<label htmlFor="contact-business">Business Name</label>
<input id="contact-business" type="text" className="form-control" placeholder="Enter your business name" />
</div>
<div className="form-group">
<label htmlFor="contact-email">Email Address *</label>
<input id="contact-email" type="email" className="form-control" placeholder="name@example.com" required />
</div>
<div className="form-group">
<label htmlFor="contact-msg">Message *</label>
<textarea id="contact-msg" className="form-control" rows={4} placeholder="How can we help you?" required></textarea>
</div>
<button type="submit" className="btn btn-dark" style={{ width: '100%', marginTop: '1rem' }}>
Submit Inquiry
</button>
</form>
</div>
2026-08-09 01:53:57 +00:00
<div className="contact-info-panel">
<div className="info-item">
<h4>Address</h4>
<p dangerouslySetInnerHTML={{ __html: CONFIG.address.replace(', ', ',<br />') }}></p>
</div>
<div className="info-item">
<h4>Support Email</h4>
<p>{CONFIG.supportEmail}</p>
</div>
<div className="info-item">
<h4>Partner Hotline</h4>
<p>{CONFIG.supportPhone}</p>
</div>
2026-08-09 01:53:57 +00:00
<div className="map-placeholder">
📍 Interactive Map Preview
</div>
</div>
</div>
)}
{/* AUTHENTICATION VIEW (LOGIN & SIGNUP) */}
{(currentPage === 'login' || currentPage === 'signup') && (
<div className="form-card">
<div className="tab-container">
2026-08-09 01:53:57 +00:00
<button
className={`tab-btn ${activeTab === 'login' ? 'active' : ''}`}
onClick={() => { setActiveTab('login'); navigateTo('login'); }}
>
Login
</button>
2026-08-09 01:53:57 +00:00
<button
className={`tab-btn ${activeTab === 'register' ? 'active' : ''}`}
onClick={() => { setActiveTab('register'); navigateTo('signup'); }}
>
Register
</button>
</div>
{activeTab === 'login' ? (
<form onSubmit={handleLoginSubmit}>
<h2 className="form-card-title">Supplier Portal Access</h2>
<div className="form-group">
<label htmlFor="login-email">Business Email</label>
2026-08-09 01:53:57 +00:00
<input
id="login-email"
2026-08-09 01:53:57 +00:00
type="email"
className="form-control"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<div className="form-group">
<label htmlFor="login-password">Password</label>
2026-08-09 01:53:57 +00:00
<input
id="login-password"
2026-08-09 01:53:57 +00:00
type="password"
className="form-control"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<div style={{ textAlign: 'right', marginBottom: '1.5rem' }}>
2026-08-09 05:29:03 +00:00
<button type="button" className="nav-link" style={{ color: 'var(--text-muted)', fontSize: '0.85rem', textDecoration: 'none', background: 'none', border: 'none', cursor: 'pointer' }} onClick={(e) => { e.preventDefault(); navigateTo('forgot-password'); }}>Forgot Password?</button>
</div>
<button type="submit" className="btn btn-primary" style={{ width: '100%', padding: '0.75rem' }}>
Secure Login
</button>
<div style={{ textAlign: 'center', marginTop: '1.5rem', fontSize: '0.9rem' }}>
2026-08-09 05:29:03 +00:00
<button type="button" className="nav-link" style={{ color: 'var(--primary)', fontWeight: 'bold', background: 'none', border: 'none', cursor: 'pointer' }} onClick={() => navigateTo('login-otp')}>Login with OTP</button>
</div>
</form>
) : (
<form onSubmit={handleRegisterSubmit}>
<h2 className="form-card-title">Create Your Supplier Account</h2>
<div className="form-group">
<label htmlFor="reg-email">Business Email *</label>
2026-08-09 01:53:57 +00:00
<input
id="reg-email"
2026-08-09 01:53:57 +00:00
type="email"
className="form-control"
placeholder="Enter email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<div className="form-group">
<label htmlFor="reg-phone">Mobile Number *</label>
2026-08-09 01:53:57 +00:00
<input
id="reg-phone"
2026-08-09 01:53:57 +00:00
type="tel"
className="form-control"
placeholder="Enter 10-digit number"
value={phone}
onChange={(e) => setPhone(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<div className="form-group">
<label htmlFor="reg-pass">Create Password *</label>
2026-08-09 01:53:57 +00:00
<input
id="reg-pass"
2026-08-09 01:53:57 +00:00
type="password"
className="form-control"
placeholder="Minimum 8 characters"
value={password}
onChange={(e) => setPassword(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<button type="submit" className="btn btn-primary" style={{ width: '100%', padding: '0.75rem', marginTop: '1rem' }}>
Register Business
</button>
</form>
)}
</div>
)}
2026-08-09 05:29:03 +00:00
{/* FORGOT PASSWORD PAGE */}
{currentPage === 'forgot-password' && (
<div className="form-card" style={{ maxWidth: '480px' }}>
<h2 className="form-card-title">Reset Your Password</h2>
<p style={{ color: 'var(--text-muted)', marginBottom: '1.5rem', fontSize: '0.9rem' }}>
Enter your registered business email or mobile number to receive a secure password reset link / OTP.
</p>
{!resetOtpSent ? (
<form onSubmit={(e) => { e.preventDefault(); if (resetEmail.trim()) { setResetOtpSent(true); alert('Simulated Reset Code (123456) sent successfully!'); } }}>
<div className="form-group">
<label htmlFor="reset-email">Email or Phone Number *</label>
2026-08-09 01:53:57 +00:00
<input
2026-08-09 05:29:03 +00:00
id="reset-email"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
2026-08-09 05:29:03 +00:00
placeholder="name@example.com or 10-digit number"
value={resetEmail}
onChange={(e) => setResetEmail(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
2026-08-09 05:29:03 +00:00
</div>
<button type="submit" className="btn btn-primary" style={{ width: '100%', padding: '0.75rem' }}>
Send Verification Code
</button>
<div style={{ textAlign: 'center', marginTop: '1.5rem' }}>
<button type="button" className="nav-link" style={{ color: 'var(--primary)', background: 'none', border: 'none', cursor: 'pointer' }} onClick={() => navigateTo('login')}>Back to Login</button>
</div>
</form>
) : (
<form onSubmit={(e) => { e.preventDefault(); if (resetOtp === '123456') { setPassword(resetPassword); alert('Password updated successfully! Please login with your new password.'); setResetOtpSent(false); setResetEmail(''); setResetOtp(''); setResetPassword(''); navigateTo('login'); } else { alert('Invalid OTP. Please enter 123456'); } }}>
<div className="form-group">
<label htmlFor="reset-otp">Enter 6-Digit OTP *</label>
2026-08-09 01:53:57 +00:00
<input
2026-08-09 05:29:03 +00:00
id="reset-otp"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
2026-08-09 05:29:03 +00:00
placeholder="Enter 123456"
value={resetOtp}
onChange={(e) => setResetOtp(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
2026-08-09 05:29:03 +00:00
<div className="form-group">
<label htmlFor="reset-new-pass">Create New Password *</label>
2026-08-09 01:53:57 +00:00
<input
2026-08-09 05:29:03 +00:00
id="reset-new-pass"
type="password"
2026-08-09 01:53:57 +00:00
className="form-control"
2026-08-09 05:29:03 +00:00
placeholder="Minimum 8 characters"
value={resetPassword}
onChange={(e) => setResetPassword(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
2026-08-09 05:29:03 +00:00
</div>
<button type="submit" className="btn btn-primary" style={{ width: '100%', padding: '0.75rem' }}>
Update Password & Login
</button>
</form>
)}
</div>
)}
{/* LOGIN WITH OTP PAGE */}
{currentPage === 'login-otp' && (
<div className="form-card" style={{ maxWidth: '480px' }}>
<h2 className="form-card-title">Login with OTP</h2>
<p style={{ color: 'var(--text-muted)', marginBottom: '1.5rem', fontSize: '0.9rem' }}>
Access your seller portal using a temporary verification code sent to your mobile.
</p>
{!otpLoginSent ? (
<form onSubmit={(e) => { e.preventDefault(); if (otpLoginPhone.trim()) { setOtpLoginSent(true); alert('Simulated Login Code (123456) sent to mobile!'); } }}>
<div className="form-group">
<label htmlFor="otp-login-phone">Registered Mobile Number *</label>
2026-08-09 01:53:57 +00:00
<input
2026-08-09 05:29:03 +00:00
id="otp-login-phone"
type="tel"
2026-08-09 01:53:57 +00:00
className="form-control"
2026-08-09 05:29:03 +00:00
placeholder="Enter 10-digit number"
value={otpLoginPhone}
onChange={(e) => setOtpLoginPhone(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
2026-08-09 05:29:03 +00:00
<button type="submit" className="btn btn-primary" style={{ width: '100%', padding: '0.75rem' }}>
Send Login OTP
</button>
<div style={{ textAlign: 'center', marginTop: '1.5rem' }}>
<button type="button" className="nav-link" style={{ color: 'var(--primary)', background: 'none', border: 'none', cursor: 'pointer' }} onClick={() => navigateTo('login')}>Back to Password Login</button>
</div>
</form>
) : (
<form onSubmit={(e) => { e.preventDefault(); if (otpLoginCode === '123456') { setOtpLoginSent(false); setOtpLoginPhone(''); setOtpLoginCode(''); if (!isProfileComplete) { navigateTo('profile-completion'); } else { navigateTo('dashboard'); } } else { alert('Invalid OTP. Please enter 123456'); } }}>
<div className="form-group">
<label htmlFor="otp-login-code">Enter 6-Digit OTP *</label>
2026-08-09 01:53:57 +00:00
<input
2026-08-09 05:29:03 +00:00
id="otp-login-code"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
2026-08-09 05:29:03 +00:00
placeholder="Enter 123456"
value={otpLoginCode}
onChange={(e) => setOtpLoginCode(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
2026-08-09 05:29:03 +00:00
</div>
<button type="submit" className="btn btn-primary" style={{ width: '100%', padding: '0.75rem' }}>
Verify & Login
</button>
</form>
)}
</div>
)}
{currentPage === 'profile-completion' && (
<div className="form-card" style={{ maxWidth: '640px' }}>
<div className="step-progress-wrapper">
<span className="step-label">Step {profileStep} of 3: {
profileStep === 1 ? 'Contact Verification' :
profileStep === 2 ? 'Tax & Identity Verification' :
'Store & Pickup Location'
}</span>
<div className="step-bar-container">
<div className="step-bar-fill" style={{ width: `${(profileStep / 3) * 100}%` }}></div>
</div>
</div>
<h2 className="form-card-title" style={{ marginBottom: '1.5rem' }}>Complete Your Supplier Profile</h2>
<form onSubmit={handleProfileSubmit}>
{profileStep === 1 && (
<div>
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 1: Verify Contacts</h3>
{/* Phone/WhatsApp Verification */}
<div className="form-group" style={{ padding: '1rem', backgroundColor: 'rgba(233, 196, 110, 0.08)', borderRadius: '8px', border: '1px solid var(--border)', marginBottom: '1rem' }}>
<label htmlFor="verify-phone">Mobile / WhatsApp Number *</label>
<div style={{ display: 'flex', gap: '0.75rem', marginBottom: '0.75rem' }}>
<input
id="verify-phone"
type="tel"
className="form-control"
placeholder="e.g. 9876543210"
value={phone}
onChange={(e) => setPhone(e.target.value)}
disabled={phoneVerified}
/>
<button
type="button"
className="btn btn-primary"
onClick={() => { setPhoneOtpSent(true); alert('WhatsApp OTP Code is 123456'); }}
disabled={phoneVerified || !phone}
style={{ minWidth: '130px' }}
>
{phoneOtpSent ? 'Resend OTP' : 'Send WhatsApp OTP'}
</button>
</div>
{phoneOtpSent && !phoneVerified && (
<div style={{ display: 'flex', gap: '0.75rem', alignItems: 'center' }}>
<input
type="text"
className="form-control"
placeholder="Enter 123456"
value={enteredPhoneOtp}
onChange={(e) => setEnteredPhoneOtp(e.target.value)}
style={{ maxWidth: '150px' }}
/>
<button
type="button"
className="btn btn-dark"
onClick={() => {
if (enteredPhoneOtp === '123456') {
setPhoneVerified(true);
alert('Phone verified successfully!');
} else {
alert('Incorrect code. Enter 123456');
}
}}
>
Verify Code
</button>
</div>
)}
{phoneVerified && (
<div style={{ color: 'var(--success)', fontWeight: 600, fontSize: '0.9rem' }}>
Mobile & WhatsApp Verified
</div>
)}
</div>
{/* Email Verification */}
<div className="form-group" style={{ padding: '1rem', backgroundColor: 'rgba(42, 157, 143, 0.08)', borderRadius: '8px', border: '1px solid var(--border)', marginBottom: '1.5rem' }}>
<label htmlFor="verify-email">Business Email Address *</label>
<div style={{ display: 'flex', gap: '0.75rem', marginBottom: '0.75rem' }}>
<input
id="verify-email"
type="email"
className="form-control"
placeholder="name@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
disabled={emailVerified}
/>
<button
type="button"
className="btn btn-primary"
onClick={() => { setEmailOtpSent(true); alert('Email OTP Code is 123456'); }}
disabled={emailVerified || !email}
style={{ minWidth: '130px' }}
>
{emailOtpSent ? 'Resend OTP' : 'Send Email OTP'}
</button>
</div>
{emailOtpSent && !emailVerified && (
<div style={{ display: 'flex', gap: '0.75rem', alignItems: 'center' }}>
<input
type="text"
className="form-control"
placeholder="Enter 123456"
value={enteredEmailOtp}
onChange={(e) => setEnteredEmailOtp(e.target.value)}
style={{ maxWidth: '150px' }}
/>
<button
type="button"
className="btn btn-dark"
onClick={() => {
if (enteredEmailOtp === '123456') {
setEmailVerified(true);
alert('Email verified successfully!');
} else {
alert('Incorrect code. Enter 123456');
}
}}
>
Verify Code
</button>
</div>
)}
{emailVerified && (
<div style={{ color: 'var(--success)', fontWeight: 600, fontSize: '0.9rem' }}>
Email Verified
</div>
)}
</div>
2026-08-09 01:53:57 +00:00
<button
2026-08-09 05:29:03 +00:00
type="submit"
className="btn btn-primary"
style={{ width: '100%', padding: '0.8rem', backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
disabled={!phoneVerified || !emailVerified}
>
2026-08-09 05:29:03 +00:00
Next Step: Identity Verification
</button>
</div>
2026-08-09 05:29:03 +00:00
)}
2026-08-09 05:29:03 +00:00
{profileStep === 2 && (
<div>
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 2: GSTIN, PAN & Aadhaar</h3>
{/* GSTIN verification */}
<div className="form-group">
<label htmlFor="verify-gst">GSTIN Number *</label>
<div style={{ display: 'flex', gap: '0.75rem' }}>
<input
id="verify-gst"
type="text"
className="form-control"
placeholder="Enter 15-digit GSTIN"
value={gstin}
onChange={(e) => setGstin(e.target.value)}
required
/>
<button
type="button"
className={`btn ${isGstinVerified ? 'btn-secondary' : 'btn-primary'}`}
onClick={handleVerifyGstin}
2026-08-09 05:30:46 +00:00
disabled={isGstinVerified}
2026-08-09 05:29:03 +00:00
style={{ minWidth: '120px' }}
>
2026-08-09 05:30:46 +00:00
{isGstinVerified ? 'Verified ✓' : 'Verify GSTIN'}
2026-08-09 05:29:03 +00:00
</button>
</div>
{isGstinVerified && (
<p style={{ color: 'var(--success)', fontSize: '0.85rem', marginTop: '0.5rem', fontWeight: 600 }}>
GSTIN successfully verified with government registry.
</p>
)}
</div>
{/* Aadhaar Upload */}
<div className="form-group" style={{ marginBottom: '1.25rem' }}>
<label htmlFor="aadhar-upload">Aadhaar Card Upload *</label>
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<input
id="aadhar-upload"
type="file"
accept=".pdf,image/*"
onChange={(e) => {
if (e.target.files?.[0]) {
setAadharFile(e.target.files[0].name);
alert(`Aadhaar card uploaded: ${e.target.files[0].name}`);
}
}}
style={{ display: 'none' }}
/>
<button
type="button"
className="btn btn-outline-dark"
onClick={() => document.getElementById('aadhar-upload')?.click()}
>
📁 Select Aadhaar File
</button>
<span style={{ fontSize: '0.9rem', color: 'var(--text-muted)' }}>
{aadharFile ? `Selected: ${aadharFile}` : 'No file uploaded yet'}
</span>
</div>
</div>
{/* PAN Upload */}
<div className="form-group" style={{ marginBottom: '2rem' }}>
<label htmlFor="pan-upload">PAN Card Upload *</label>
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<input
id="pan-upload"
type="file"
accept=".pdf,image/*"
onChange={(e) => {
if (e.target.files?.[0]) {
setPanFile(e.target.files[0].name);
alert(`PAN card uploaded: ${e.target.files[0].name}`);
}
}}
style={{ display: 'none' }}
/>
<button
type="button"
className="btn btn-outline-dark"
onClick={() => document.getElementById('pan-upload')?.click()}
>
📁 Select PAN File
</button>
<span style={{ fontSize: '0.9rem', color: 'var(--text-muted)' }}>
{panFile ? `Selected: ${panFile}` : 'No file uploaded yet'}
</span>
</div>
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(1)}>
Back
</button>
<button
type="submit"
className="btn btn-primary"
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
disabled={!isGstinVerified || !aadharFile || !panFile}
>
Next Step: Store & Location
</button>
</div>
</div>
)}
{profileStep === 3 && (
<div>
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 3: Store Details & Location Map</h3>
<div className="form-group">
<label htmlFor="store-name">Store Display Name *</label>
<input
id="store-name"
type="text"
className="form-control"
placeholder="Enter store name"
value={storeName}
onChange={(e) => setStoreName(e.target.value)}
required
/>
</div>
<div className="form-group">
<label htmlFor="store-bio">About Your Craft / Business *</label>
<textarea
id="store-bio"
className="form-control"
rows={2}
placeholder="Describe your craft, materials, and history..."
value={businessBio}
onChange={(e) => setBusinessBio(e.target.value)}
required
></textarea>
</div>
{/* Interactive Location Map Picker */}
<div className="form-group">
<label>Store Location on Map *</label>
<div
style={{
height: '180px',
backgroundColor: '#cbd5e1',
borderRadius: '8px',
position: 'relative',
overflow: 'hidden',
border: '2px solid var(--border)',
cursor: 'crosshair',
backgroundImage: 'radial-gradient(circle, #94a3b8 1px, transparent 1px)',
backgroundSize: '16px 16px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
onClick={(e) => {
const rect = e.currentTarget.getBoundingClientRect();
const x = Math.round(e.clientX - rect.left);
const y = Math.round(e.clientY - rect.top);
setMapCoordinates({ lat: Number((12.9 + y * 0.001).toFixed(4)), lng: Number((77.5 + x * 0.001).toFixed(4)) });
setAddress(prev => ({
...prev,
street: `Plot ${x}, Sector ${Math.round(y/10)}, Handicraft Park`
}));
alert(`Location Pinned: Lat: ${(12.9 + y * 0.001).toFixed(4)}, Lng: ${(77.5 + x * 0.001).toFixed(4)}`);
}}
>
{/* Map Marker Pin */}
<div
style={{
position: 'absolute',
left: `${(mapCoordinates.lng - 77.5) * 1000}px`,
top: `${(mapCoordinates.lat - 12.9) * 1000}px`,
transform: 'translate(-50%, -100%)',
fontSize: '2rem',
color: 'var(--error)',
pointerEvents: 'none',
textShadow: '0 2px 4px rgba(0,0,0,0.3)'
}}
>
📍
</div>
<div style={{
position: 'absolute',
bottom: '8px',
left: '8px',
backgroundColor: 'rgba(26, 43, 69, 0.85)',
color: 'white',
padding: '0.3rem 0.6rem',
borderRadius: '4px',
fontSize: '0.75rem',
pointerEvents: 'none'
}}>
Coordinates: Lat {mapCoordinates.lat}, Lng {mapCoordinates.lng} (Click map to change pin)
</div>
<span style={{ fontSize: '0.85rem', color: '#475569', pointerEvents: 'none', fontWeight: 600 }}>Click anywhere on the map grid to pin location</span>
</div>
</div>
<div className="form-group">
<label htmlFor="location-text">Location in Text (Address) *</label>
<input
id="location-text"
type="text"
className="form-control"
placeholder="Street, Landmark, District"
value={address.street}
onChange={(e) => setAddress({ ...address, street: e.target.value })}
required
/>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }} className="form-group">
<div>
<label htmlFor="loc-city">City *</label>
<input
id="loc-city"
type="text"
className="form-control"
value={address.city}
onChange={(e) => setAddress({ ...address, city: e.target.value })}
required
/>
</div>
<div>
<label htmlFor="loc-pincode">Pincode *</label>
<input
id="loc-pincode"
type="text"
className="form-control"
placeholder="6-digit Pincode"
value={address.pincode}
onChange={(e) => setAddress({ ...address, pincode: e.target.value })}
required
/>
</div>
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', marginTop: '2rem' }}>
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(2)}>
Back
</button>
<button
type="submit"
className="btn btn-primary"
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
>
Submit Supplier Profile
</button>
</div>
</div>
)}
</form>
</div>
)}
{/* ONBOARDING CONFIRMATION / REVIEW STATUS VIEW (Step 3 of 3) */}
{currentPage === 'confirmation' && (
<div className="form-card" style={{ maxWidth: '640px', textAlign: 'center' }}>
<div className="step-progress-wrapper">
<span className="step-label">Step 3 of 3: Verification</span>
<div className="step-bar-container">
<div className="step-bar-fill" style={{ width: '100%' }}></div>
</div>
</div>
<div style={{ fontSize: '4rem', marginBottom: '1.5rem' }}>🎉</div>
<h2 className="form-card-title">Welcome to {CONFIG.companyName}!</h2>
2026-08-09 01:53:57 +00:00
<p style={{ color: 'var(--text-muted)', marginBottom: '2rem', fontSize: '1.05rem' }}>
Your registration is under review. We will verify your GSTIN credentials and activate your dashboard access within 24-48 hours.
</p>
<div className="conf-dashboard-preview">
<div className="mock-dash-header">
<div className="mock-dash-dot"></div>
<div className="mock-dash-dot"></div>
<div className="mock-dash-dot"></div>
</div>
<div className="mock-dash-body">
<div className="mock-dash-card">
<div className="mock-dash-card-title">Total Sales</div>
<div className="mock-dash-card-val">$0.00</div>
</div>
<div className="mock-dash-card">
<div className="mock-dash-card-title">Active Orders</div>
<div className="mock-dash-card-val">0</div>
</div>
<div className="mock-dash-card">
<div className="mock-dash-card-title">Balance</div>
<div className="mock-dash-card-val">$0.00</div>
</div>
<div className="mock-dash-chart">
<div className="mock-chart-bar" style={{ height: '40px' }}></div>
<div className="mock-chart-bar" style={{ height: '60px' }}></div>
<div className="mock-chart-bar" style={{ height: '50px' }}></div>
<div className="mock-chart-bar active" style={{ height: '80px' }}></div>
<div className="mock-chart-bar" style={{ height: '30px' }}></div>
</div>
</div>
</div>
2026-08-09 01:53:57 +00:00
<button
className="btn btn-dark"
style={{ marginTop: '2.5rem', width: '100%', padding: '0.8rem' }}
onClick={() => navigateTo('dashboard')}
>
Go to Dashboard (Preview Only)
</button>
</div>
)}
2026-08-09 05:29:03 +00:00
{/* WELCOME PAGE & SETUP TOUR FOR NEW SELLERS */}
{currentPage === 'welcome-tour' && (
<WelcomeTourWizard onComplete={() => navigateTo('dashboard')} storeName={storeName} />
)}
</main>
) : (
/* --- FULL SERVICE SUPPLIER ACTIVE DASHBOARD PAGE --- */
<div className="dashboard-container">
2026-08-09 01:53:57 +00:00
{/* Sidebar */}
<aside className="dashboard-sidebar">
<div style={{ marginBottom: '2rem', paddingLeft: '1rem' }}>
<div style={{ fontSize: '0.8rem', opacity: 0.6 }}>SELLER PANEL</div>
<h4 style={{ color: 'var(--accent)', fontWeight: 700 }}>{storeName || 'Artisan Shop'}</h4>
</div>
<ul className="sidebar-menu">
<li>
2026-08-09 01:53:57 +00:00
<button
className={`sidebar-item-btn ${dashTab === 'overview' ? 'active' : ''}`}
onClick={() => setDashTab('overview')}
>
📊 Overview & Analytics
</button>
</li>
<li>
2026-08-09 01:53:57 +00:00
<button
className={`sidebar-item-btn ${dashTab === 'products' ? 'active' : ''}`}
onClick={() => setDashTab('products')}
>
📦 Manage Products
</button>
</li>
<li>
2026-08-09 01:53:57 +00:00
<button
className={`sidebar-item-btn ${dashTab === 'orders' ? 'active' : ''}`}
onClick={() => setDashTab('orders')}
>
🚚 Orders & Transit
</button>
</li>
<li>
2026-08-09 01:53:57 +00:00
<button
className={`sidebar-item-btn ${dashTab === 'returns' ? 'active' : ''}`}
onClick={() => setDashTab('returns')}
>
🔄 Returns Management
</button>
</li>
<li>
2026-08-09 01:53:57 +00:00
<button
className={`sidebar-item-btn ${dashTab === 'wallet' ? 'active' : ''}`}
onClick={() => setDashTab('wallet')}
>
💼 Wallet & Payouts
</button>
2026-08-09 05:29:03 +00:00
</li>
<li>
<button
className={`sidebar-item-btn ${dashTab === 'barcode-generator' ? 'active' : ''}`}
onClick={() => setDashTab('barcode-generator')}
>
🏷 Barcode Generator
</button>
</li>
<li>
2026-08-09 01:53:57 +00:00
<button
className={`sidebar-item-btn ${dashTab === 'settings' ? 'active' : ''}`}
onClick={() => setDashTab('settings')}
>
Store Settings
</button>
</li>
</ul>
</aside>
{/* Main Dashboard Space */}
<section className="dashboard-main">
2026-08-09 01:53:57 +00:00
{/* OVERVIEW PANEL */}
{dashTab === 'overview' && (
<div>
<div className="dashboard-header-bar">
<h2 className="dashboard-title">Performance Analytics</h2>
<div className="time-filter-bar">
<button className={`time-filter-btn ${dateFilter === 'year' ? 'active' : ''}`} onClick={() => setDateFilter('year')}>Year</button>
<button className={`time-filter-btn ${dateFilter === 'week' ? 'active' : ''}`} onClick={() => setDateFilter('week')}>Week</button>
<button className={`time-filter-btn ${dateFilter === 'day' ? 'active' : ''}`} onClick={() => setDateFilter('day')}>Day</button>
<button className={`time-filter-btn ${dateFilter === 'custom' ? 'active' : ''}`} onClick={() => setDateFilter('custom')}>Custom Date</button>
</div>
</div>
{dateFilter === 'custom' && (
<div className="custom-date-panel">
<div className="form-group" style={{ margin: 0 }}>
<label style={{ fontSize: '0.75rem' }}>Start Date</label>
2026-08-09 01:53:57 +00:00
<input type="date" className="form-control" value={customDates.start} onChange={e => setCustomDates({ ...customDates, start: e.target.value })} />
</div>
<div className="form-group" style={{ margin: 0 }}>
<label style={{ fontSize: '0.75rem' }}>End Date</label>
2026-08-09 01:53:57 +00:00
<input type="date" className="form-control" value={customDates.end} onChange={e => setCustomDates({ ...customDates, end: e.target.value })} />
</div>
</div>
)}
<div className="metrics-row">
<div className="metric-data-card">
<div className="metric-title">Total Sales Volume</div>
<div className="metric-value">${selectedMetrics.totalSales.toFixed(2)}</div>
</div>
<div className="metric-data-card">
<div className="metric-title">Total Net Earned</div>
<div className="metric-value" style={{ color: 'var(--success)' }}>${selectedMetrics.totalEarned.toFixed(2)}</div>
</div>
<div className="metric-data-card">
<div className="metric-title">Available Stock</div>
<div className="metric-value">{selectedMetrics.stockDetails} units</div>
</div>
<div className="metric-data-card">
<div className="metric-title">Returned Items</div>
<div className="metric-value" style={{ color: 'var(--error)' }}>{selectedMetrics.returnedItems} requests</div>
</div>
</div>
<div className="chart-card">
<div className="chart-header">
<h3 className="chart-title">Revenue Trajectory</h3>
<span style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>Filtered by {dateFilter} metrics</span>
</div>
<div className="main-bar-chart">
{selectedMetrics.chartValues.map((val, idx) => (
2026-08-09 01:53:57 +00:00
<div
key={idx}
className={`chart-bar-col ${idx === selectedMetrics.chartValues.length - 1 ? 'highlighted' : ''}`}
style={{ height: `${val}%` }}
title={`Point ${idx + 1}: ${val}%`}
></div>
))}
</div>
</div>
</div>
)}
{/* PRODUCTS TAB */}
{dashTab === 'products' && (
<div>
<h2 className="dashboard-title" style={{ marginBottom: '2rem' }}>Product Listings & Upload</h2>
2026-08-09 01:53:57 +00:00
<div className="tool-split-layout">
2026-08-09 01:53:57 +00:00
{/* Products Grid list */}
<div>
<h3 style={{ marginBottom: '1rem', color: 'var(--primary)' }}>Active Inventory ({products.length})</h3>
<div className="dashboard-table-wrapper">
<table className="dashboard-table">
<thead>
<tr>
<th>Product</th>
<th>SKU</th>
<th>Category</th>
<th>Price</th>
<th>Stock</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{products.map(p => (
<tr key={p.id}>
<td style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
<img src={p.image} alt={p.title} className="product-thumb" />
<span style={{ fontWeight: 600 }}>{p.title}</span>
</td>
<td>{p.sku}</td>
<td>{p.category}</td>
<td>${p.price.toFixed(2)}</td>
<td style={{ fontWeight: 600, color: p.stock < 15 ? 'var(--error)' : 'inherit' }}>
{p.stock} pcs
</td>
<td>
<button className="btn btn-outline-dark" style={{ padding: '0.3rem 0.6rem', fontSize: '0.8rem', marginRight: '0.5rem' }} onClick={() => handleEditClick(p)}>Edit</button>
<button className="btn btn-outline-dark" style={{ padding: '0.3rem 0.6rem', fontSize: '0.8rem', borderColor: 'var(--error)', color: 'var(--error)' }} onClick={() => handleDeleteProduct(p.id)}>Delete</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
{/* Bulk tools */}
<div className="chart-card" style={{ marginTop: '2rem' }}>
<h3 style={{ marginBottom: '1rem', color: 'var(--primary)' }}>Bulk Operations</h3>
2026-08-09 05:29:03 +00:00
<p style={{ color: 'var(--text-muted)', fontSize: '0.9rem', marginBottom: '1.5rem' }}>
To upload products in bulk, use our standard Excel/CSV template. Review the sample format below, download the template, populate your inventory rows, and upload.
</p>
{/* Sample Template Table */}
<div style={{ overflowX: 'auto', marginBottom: '1.5rem', borderRadius: '8px', border: '1px solid var(--border)' }}>
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.8rem', textAlign: 'left' }}>
<thead>
<tr style={{ backgroundColor: 'var(--primary)', color: 'white' }}>
<th style={{ padding: '0.5rem' }}>Title *</th>
<th style={{ padding: '0.5rem' }}>SKU *</th>
<th style={{ padding: '0.5rem' }}>Category *</th>
<th style={{ padding: '0.5rem' }}>Price ($) *</th>
<th style={{ padding: '0.5rem' }}>Stock *</th>
<th style={{ padding: '0.5rem' }}>Description</th>
</tr>
</thead>
<tbody>
<tr style={{ borderBottom: '1px solid var(--border)', backgroundColor: '#faf9f6' }}>
<td style={{ padding: '0.5rem' }}>Silk Banarasi Saree</td>
<td style={{ padding: '0.5rem' }}>SAR-BAN-101</td>
<td style={{ padding: '0.5rem' }}>Apparel</td>
<td style={{ padding: '0.5rem' }}>120.00</td>
<td style={{ padding: '0.5rem' }}>15</td>
<td style={{ padding: '0.5rem' }}>Pure handloom zardozi border</td>
</tr>
<tr style={{ backgroundColor: '#ffffff' }}>
<td style={{ padding: '0.5rem' }}>Wooden Carved Ganesha</td>
<td style={{ padding: '0.5rem' }}>-GAN-302</td>
<td style={{ padding: '0.5rem' }}>Home Decor</td>
<td style={{ padding: '0.5rem' }}>85.00</td>
<td style={{ padding: '0.5rem' }}>5</td>
<td style={{ padding: '0.5rem' }}>Premium teak wood hand carved</td>
</tr>
</tbody>
</table>
</div>
<div style={{ display: 'flex', gap: '1rem', marginBottom: '1.5rem' }}>
<button
type="button"
className="btn btn-outline-dark"
style={{ flex: 1, padding: '0.6rem', fontSize: '0.85rem' }}
onClick={() => {
// Simulate download of CSV file
const csvContent = "data:text/csv;charset=utf-8,Title,SKU,Category,Price,Stock,Description\nSilk Banarasi Saree,SAR-BAN-101,Apparel,120.00,15,Pure handloom zardozi border\nWooden Carved Ganesha,GAN-302,Home Decor,85.00,5,Premium teak wood hand carved";
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "seller_product_template.csv");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
alert('Sample template downloaded successfully!');
}}
>
📥 Download Sample Excel Template
</button>
</div>
<div className="bulk-drop-zone" onClick={() => document.getElementById('bulk-file-pick')?.click()}>
2026-08-09 05:29:03 +00:00
<span>{isParsingBulk ? 'Processing bulk data...' : '📂 Click or drop your populated template file here to import'}</span>
<input id="bulk-file-pick" type="file" accept=".csv" onChange={handleBulkUploadSimulate} style={{ display: 'none' }} />
</div>
2026-08-09 01:53:57 +00:00
{bulkLog.length > 0 && (
2026-08-09 05:29:03 +00:00
<div style={{ backgroundColor: '#f1f5f9', padding: '1rem', borderRadius: '8px', fontFamily: 'monospace', fontSize: '0.85rem', marginTop: '1rem' }}>
<h4 style={{ marginBottom: '0.5rem' }}>Import log:</h4>
{bulkLog.map((log, i) => <div key={i}>{log}</div>)}
</div>
)}
</div>
</div>
{/* Add/Edit Form */}
<div className="form-card" style={{ margin: 0, maxWidth: '100%' }}>
<h3 style={{ marginBottom: '1.5rem', color: 'var(--primary)' }}>
{isEditingProduct ? 'Modify Product Listing' : 'Upload New Product'}
</h3>
<form onSubmit={handleSaveProduct}>
<div className="form-group">
<label htmlFor="prod-title">Product Title *</label>
2026-08-09 01:53:57 +00:00
<input
id="prod-title"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
value={productForm.title}
onChange={e => setProductForm({ ...productForm, title: e.target.value })}
required
/>
</div>
<div className="form-group">
<label htmlFor="prod-sku">SKU Code (Auto-generates if empty)</label>
2026-08-09 01:53:57 +00:00
<input
id="prod-sku"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
placeholder="e.g. SHAWL-IND-01"
value={productForm.sku}
onChange={e => setProductForm({ ...productForm, sku: e.target.value })}
/>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }} className="form-group">
<div>
<label htmlFor="prod-price">Price ($) *</label>
2026-08-09 01:53:57 +00:00
<input
id="prod-price"
2026-08-09 01:53:57 +00:00
type="number"
className="form-control"
value={productForm.price || ''}
onChange={e => setProductForm({ ...productForm, price: Number(e.target.value) })}
required
/>
</div>
<div>
<label htmlFor="prod-stock">Initial Stock *</label>
2026-08-09 01:53:57 +00:00
<input
id="prod-stock"
2026-08-09 01:53:57 +00:00
type="number"
className="form-control"
value={productForm.stock || ''}
onChange={e => setProductForm({ ...productForm, stock: Number(e.target.value) })}
required
/>
</div>
</div>
<div className="form-group">
<label htmlFor="prod-category">Category</label>
2026-08-09 01:53:57 +00:00
<select
id="prod-category"
2026-08-09 01:53:57 +00:00
className="form-control"
value={productForm.category}
onChange={e => setProductForm({ ...productForm, category: e.target.value })}
>
<option value="Apparel">Apparel</option>
<option value="Home Decor">Home Decor</option>
<option value="Sculptures">Sculptures</option>
<option value="Kitchenware">Kitchenware</option>
<option value="Linens">Linens</option>
</select>
</div>
2026-08-09 01:53:57 +00:00
<div style={{ display: 'flex', gap: '1rem', marginTop: '2rem' }}>
{isEditingProduct && (
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => {
setIsEditingProduct(false)
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' })
}}>Cancel</button>
)}
<button type="submit" className="btn btn-dark" style={{ flex: 1 }}>
{isEditingProduct ? 'Save Modifications' : 'Upload Product'}
</button>
</div>
</form>
</div>
</div>
</div>
)}
{/* ORDERS & TRACKING TAB */}
{dashTab === 'orders' && (
<div>
<h2 className="dashboard-title" style={{ marginBottom: '2rem' }}>Active Orders & Payout status</h2>
2026-08-09 01:53:57 +00:00
<div className="dashboard-table-wrapper">
<table className="dashboard-table">
<thead>
<tr>
<th>Order ID</th>
<th>Order Date</th>
<th>Item Details</th>
<th>Qty</th>
<th>Customer</th>
<th>Total</th>
<th>Status</th>
2026-08-09 05:29:03 +00:00
<th>Logistics & Carrier Details / Actions</th>
</tr>
</thead>
<tbody>
{orders.map(o => (
<tr key={o.id}>
<td><span style={{ fontWeight: 'bold' }}>{o.id}</span></td>
<td>{o.date}</td>
<td>{o.item}</td>
<td>{o.quantity}</td>
<td>{o.customer}</td>
<td style={{ fontWeight: 600 }}>${o.total.toFixed(2)}</td>
<td>
2026-08-09 05:29:03 +00:00
<span className={`badge ${
o.status === 'Delivered' ? 'badge-success' :
o.status === 'Shipped' ? 'badge-info' :
o.status === 'Pending Acceptance' ? 'badge-warning' :
o.status === 'Rejected' || o.status === 'Cancelled' ? 'badge-danger' : 'badge-warning'
}`}>
{o.status}
</span>
</td>
<td>
2026-08-09 05:29:03 +00:00
{o.status === 'Pending Acceptance' ? (
<div style={{ display: 'flex', gap: '0.5rem' }}>
<button
className="btn btn-primary"
style={{ backgroundColor: 'var(--success)', color: 'white', border: 'none', padding: '0.35rem 0.75rem', fontSize: '0.8rem', cursor: 'pointer' }}
onClick={() => {
setOrders(orders.map(item => item.id === o.id ? {
...item,
status: 'Ready to Ship',
carrier: 'DHL Express',
tracking: `DHL-${Math.floor(100000 + Math.random() * 900000)}`,
eta: '3 Days'
} : item));
alert(`Order ${o.id} accepted successfully!`);
}}
>
Accept
</button>
<button
className="btn btn-primary"
style={{ backgroundColor: 'var(--error)', color: 'white', border: 'none', padding: '0.35rem 0.75rem', fontSize: '0.8rem', cursor: 'pointer' }}
onClick={() => {
setOrders(orders.map(item => item.id === o.id ? {
...item,
status: 'Rejected',
carrier: 'N/A',
tracking: 'N/A',
eta: 'N/A'
} : item));
alert(`Order ${o.id} rejected.`);
}}
>
Reject
</button>
</div>
) : (
<div style={{ fontSize: '0.85rem' }}>
<div><strong>Carrier</strong>: {o.carrier}</div>
<div><strong>Tracking</strong>: {o.tracking}</div>
<div><strong>ETA / Delivery</strong>: {o.eta}</div>
</div>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
2026-08-09 05:29:03 +00:00
{dashTab === 'barcode-generator' && (
<div>
<h2 className="dashboard-title" style={{ marginBottom: '2rem' }}>Product Barcode Generator</h2>
<p style={{ color: 'var(--text-muted)', marginBottom: '2rem' }}>
Generate and print industry-standard barcodes for your product inventory to track shipments, sales, and warehouse stock.
</p>
<div className="tool-split-layout">
<div className="form-card" style={{ margin: 0, maxWidth: '100%' }}>
<h3 style={{ marginBottom: '1.5rem', color: 'var(--primary)' }}>Barcode Configuration</h3>
<div className="form-group">
<label htmlFor="barcode-product">Select Product *</label>
<select
id="barcode-product"
className="form-control"
value={barcodeProductSku}
onChange={(e) => {
const sku = e.target.value;
setBarcodeProductSku(sku);
setBarcodeValue(sku);
setBarcodeGenerated(true);
}}
>
<option value="">-- Choose an active listing --</option>
{products.map(p => (
<option key={p.id} value={p.sku}>{p.title} ({p.sku})</option>
))}
</select>
</div>
<div className="form-group">
<label htmlFor="barcode-fmt">Symbology / Format *</label>
<select
id="barcode-fmt"
className="form-control"
value={barcodeFormat}
onChange={(e) => setBarcodeFormat(e.target.value)}
>
<option value="CODE128">Code 128 (Alpha-Numeric, Recommended)</option>
<option value="EAN13">EAN-13 (Standard Retail Product ID)</option>
<option value="UPCA">UPC-A (Standard Retail Product ID)</option>
</select>
</div>
<div className="form-group">
<label htmlFor="barcode-val">Barcode Value / SKU *</label>
<input
id="barcode-val"
type="text"
className="form-control"
value={barcodeValue}
onChange={(e) => { setBarcodeValue(e.target.value); setBarcodeGenerated(false); }}
placeholder="Enter alphanumeric identifier"
/>
</div>
<button
type="button"
className="btn btn-dark"
style={{ width: '100%', marginTop: '1rem' }}
onClick={() => {
if (!barcodeValue.trim()) {
alert('Please enter a barcode value');
return;
}
setBarcodeGenerated(true);
}}
>
Generate Barcode Graphic
</button>
</div>
<div className="chart-card" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', minHeight: '300px' }}>
{barcodeGenerated && barcodeValue ? (
<div>
<h4 style={{ marginBottom: '1.5rem', color: 'var(--primary)' }}>Generated Barcode Preview</h4>
{/* Beautiful CSS Mock Barcode */}
<div style={{
backgroundColor: 'white',
padding: '1.5rem',
borderRadius: '8px',
border: '1px solid var(--border)',
display: 'inline-block',
boxShadow: '0 4px 12px rgba(0,0,0,0.05)',
marginBottom: '1.5rem'
}}>
<div style={{ fontSize: '0.8rem', fontWeight: 'bold', color: 'var(--primary)', marginBottom: '0.5rem', textAlign: 'center' }}>
{products.find(p => p.sku === barcodeProductSku)?.title || 'Custom Identifier'}
</div>
{/* Barcode lines */}
<div style={{
display: 'flex',
alignItems: 'stretch',
height: '70px',
width: '240px',
margin: '0 auto',
backgroundColor: 'white'
}}>
{/* Simple pseudorandom pattern generator based on barcodeValue string */}
{Array.from({ length: 48 }).map((_, idx) => {
const hash = barcodeValue.split('').reduce((acc, char) => acc + char.charCodeAt(0), idx);
const isBlack = (hash * (idx + 7)) % 3 !== 0;
const width = (idx % 5 === 0) ? '5px' : (idx % 3 === 0) ? '3px' : '1px';
return (
<div
key={idx}
style={{
width: width,
backgroundColor: isBlack ? 'black' : 'white',
flexGrow: 1
}}
/>
);
})}
</div>
<div style={{ marginTop: '0.5rem', letterSpacing: '4px', fontSize: '0.9rem', fontWeight: 600, color: 'black' }}>
{barcodeValue.toUpperCase()}
</div>
</div>
<div style={{ display: 'flex', gap: '0.5rem', justifyContent: 'center' }}>
<button
type="button"
className="btn btn-outline-dark"
onClick={() => alert(`Printing barcode sheet for ${barcodeValue}...`)}
>
🖨 Print Label
</button>
<button
type="button"
className="btn btn-outline-dark"
onClick={() => alert(`Downloading SVG barcode graphic file...`)}
>
💾 Download SVG
</button>
</div>
</div>
) : (
<div style={{ color: 'var(--text-muted)' }}>
<span style={{ fontSize: '3rem' }}>🏷</span>
<p style={{ marginTop: '1rem' }}>Enter configuration details and click generate to render visual barcode label.</p>
</div>
)}
</div>
</div>
</div>
)}
{/* RETURNS MANAGEMENT TAB */}
{dashTab === 'returns' && (
<div>
<h2 className="dashboard-title" style={{ marginBottom: '2rem' }}>Returns & Quality Assurance Center</h2>
2026-08-09 01:53:57 +00:00
<h3 style={{ marginBottom: '1rem', color: 'var(--primary)' }}>Items Requested for Return</h3>
<div className="dashboard-table-wrapper" style={{ marginBottom: '3rem' }}>
<table className="dashboard-table">
<thead>
<tr>
<th>Return ID</th>
<th>Original Order ID</th>
<th>Item Info</th>
<th>Customer</th>
<th>Reason Given</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{returns.filter(r => r.status === 'Pending Approval').map(r => (
<tr key={r.id}>
<td><strong>{r.id}</strong></td>
<td>{r.orderId}</td>
<td style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
<img src={r.image} alt={r.item} className="product-thumb" />
<span>{r.item}</span>
</td>
<td>{r.customer}</td>
<td style={{ fontStyle: 'italic' }}>"{r.reason}"</td>
<td>
<span className="badge badge-warning">{r.status}</span>
</td>
<td>
<button className="btn btn-primary" style={{ padding: '0.3rem 0.6rem', fontSize: '0.8rem', marginRight: '0.5rem', backgroundColor: 'var(--success)', border: 'none', color: 'white' }} onClick={() => handleReturnAction(r.id, 'Approved')}>Approve</button>
<button className="btn btn-primary" style={{ padding: '0.3rem 0.6rem', fontSize: '0.8rem', backgroundColor: 'var(--error)', border: 'none', color: 'white' }} onClick={() => handleReturnAction(r.id, 'Rejected')}>Reject</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
<h3 style={{ marginBottom: '1rem', color: 'var(--primary)' }}>In-Transit Return Tracking</h3>
<div className="dashboard-table-wrapper">
<table className="dashboard-table">
<thead>
<tr>
<th>Return ID</th>
<th>Item</th>
<th>Customer</th>
<th>Return Tracking Number</th>
<th>Progress Status</th>
</tr>
</thead>
<tbody>
{returns.filter(r => r.status !== 'Pending Approval').map(r => (
<tr key={r.id}>
<td><strong>{r.id}</strong></td>
<td>{r.item}</td>
<td>{r.customer}</td>
<td>{r.returningTracking}</td>
<td>
<span className={`badge ${r.status === 'Rejected' ? 'badge-danger' : 'badge-info'}`}>
{r.status}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{/* WALLET & PAYOUTS TAB */}
{dashTab === 'wallet' && (
<div>
<h2 className="dashboard-title" style={{ marginBottom: '2rem' }}>Wallet & Payout Portal</h2>
2026-08-09 01:53:57 +00:00
<div className="metrics-row">
<div className="metric-data-card">
<div className="metric-title">Outstanding Ready Balance</div>
<div className="metric-value" style={{ color: 'var(--success)' }}>${wallet.outstanding.toFixed(2)}</div>
</div>
<div className="metric-data-card">
<div className="metric-title">Total Payouts Withdrawn</div>
<div className="metric-value">${wallet.withdrawn.toFixed(2)}</div>
</div>
</div>
<div className="tool-split-layout">
{/* Withdrawal form */}
<div className="form-card" style={{ margin: 0, maxWidth: '100%' }}>
<h3 style={{ marginBottom: '1.5rem', color: 'var(--primary)' }}>Withdraw Payout Funds</h3>
<form onSubmit={handleWithdrawRequest}>
<div className="form-group">
<label htmlFor="payout-val">Withdrawal Amount ($) *</label>
2026-08-09 01:53:57 +00:00
<input
id="payout-val"
2026-08-09 01:53:57 +00:00
type="number"
className="form-control"
placeholder="e.g. 200"
value={withdrawAmount}
onChange={e => setWithdrawAmount(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<button type="submit" className="btn btn-dark" style={{ width: '100%', marginTop: '1.5rem' }}>
Process Payout Withdrawal
</button>
</form>
</div>
{/* Payout History */}
<div className="chart-card">
<h3 style={{ marginBottom: '1.5rem', color: 'var(--primary)' }}>Transaction Payout Logs</h3>
<div className="dashboard-table-wrapper" style={{ border: 'none', boxShadow: 'none' }}>
<table className="dashboard-table">
<thead>
<tr>
<th>Transaction ID</th>
<th>Transfer Date</th>
<th>Amount</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{wallet.history.map(tx => (
<tr key={tx.id}>
<td>{tx.id}</td>
<td>{tx.date}</td>
<td style={{ fontWeight: 600 }}>${tx.amount.toFixed(2)}</td>
<td><span className="badge badge-success">{tx.status}</span></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
)}
{/* SETTINGS TAB */}
{dashTab === 'settings' && (
<div className="form-card" style={{ margin: 0, maxWidth: '640px' }}>
<h2 className="form-card-title" style={{ textAlign: 'left', marginBottom: '2rem' }}>Store Configurations</h2>
2026-08-09 01:53:57 +00:00
<form onSubmit={e => { e.preventDefault(); alert('Store configurations updated successfully!'); }}>
<div className="form-group">
<label htmlFor="set-store">Store Display Name *</label>
2026-08-09 01:53:57 +00:00
<input
id="set-store"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
value={storeName}
onChange={e => setStoreName(e.target.value)}
required
/>
</div>
<div className="form-group">
<label htmlFor="set-logo">Store Logo</label>
<div className="upload-btn-wrapper">
<div className="upload-preview-box">
{storeLogo ? (
<img src={storeLogo} alt="Logo" />
) : (
<span style={{ fontSize: '1.5rem', color: 'var(--text-muted)' }}>🖼</span>
)}
</div>
2026-08-09 01:53:57 +00:00
<input
id="set-logo"
2026-08-09 01:53:57 +00:00
type="file"
accept="image/*"
onChange={handleLogoChange}
/>
</div>
</div>
<div className="form-group">
<label htmlFor="set-bio">About Your Craft / Business</label>
2026-08-09 01:53:57 +00:00
<textarea
id="set-bio"
2026-08-09 01:53:57 +00:00
className="form-control"
rows={3}
value={businessBio}
onChange={e => setBusinessBio(e.target.value)}
></textarea>
</div>
<div className="form-group">
<label>Pickup Location Address *</label>
<div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '0.75rem', marginBottom: '0.75rem' }}>
2026-08-09 01:53:57 +00:00
<input
type="text"
className="form-control"
placeholder="Street Address"
value={address.street}
onChange={e => setAddress({ ...address, street: e.target.value })}
required
/>
2026-08-09 01:53:57 +00:00
<input
type="text"
className="form-control"
placeholder="City"
value={address.city}
onChange={e => setAddress({ ...address, city: e.target.value })}
required
/>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }}>
2026-08-09 01:53:57 +00:00
<input
type="text"
className="form-control"
placeholder="State"
value={address.state}
onChange={e => setAddress({ ...address, state: e.target.value })}
required
/>
2026-08-09 01:53:57 +00:00
<input
type="text"
className="form-control"
placeholder="Pincode"
value={address.pincode}
onChange={e => setAddress({ ...address, pincode: e.target.value })}
required
/>
</div>
</div>
<div className="form-group">
<label htmlFor="set-gstin">GSTIN Number</label>
2026-08-09 01:53:57 +00:00
<input
id="set-gstin"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
value={gstin}
onChange={e => setGstin(e.target.value)}
disabled
/>
<p style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginTop: '0.25rem' }}>GSTIN cannot be modified after verification.</p>
</div>
<button type="submit" className="btn btn-dark" style={{ width: '100%', marginTop: '2rem' }}>
Save Store Configurations
</button>
</form>
</div>
)}
</section>
</div>
)}
{/* Footer Section */}
<footer className="app-footer">
<div className="footer-content">
<div className="footer-logo-text">{CONFIG.companyName}</div>
<div className="footer-links">
<a href="#about" className="footer-link" onClick={(e) => { e.preventDefault(); navigateTo('about'); }}>About Us</a>
<a href="#careers" className="footer-link" onClick={(e) => { e.preventDefault(); alert('Careers section coming soon.'); }}>Careers</a>
<a href="#press" className="footer-link" onClick={(e) => { e.preventDefault(); alert('Press details coming soon.'); }}>Press</a>
<a href="#terms" className="footer-link" onClick={(e) => { e.preventDefault(); alert('Terms of Service.'); }}>Terms</a>
<a href="#privacy" className="footer-link" onClick={(e) => { e.preventDefault(); alert('Privacy Policy.'); }}>Privacy</a>
</div>
</div>
<div className="footer-copyright">
© {new Date().getFullYear()} {CONFIG.companyName}. All rights reserved.
</div>
</footer>
</>
)
}
2026-08-09 05:29:03 +00:00
function WelcomeTourWizard({ onComplete, storeName }: { onComplete: () => void; storeName: string }) {
const [tourStep, setTourStep] = useState(1)
const steps = [
{
title: "Welcome to Global Artisans Hub! 🎉",
description: `Congratulations ${storeName}! Your supplier profile is verified and complete. Let's take a 1-minute tour to get you familiar with your active workspace so you can begin selling immediately.`,
icon: "🎉",
action: "Start Tour"
},
{
title: "📦 Products & Inventory Management",
description: "Under the 'Manage Products' tab, you can add new product listings, edit stock values, and perform bulk uploads using our structured Excel template.",
icon: "📦",
action: "Next: Order Management"
},
{
title: "🚚 Order Acceptance Control",
description: "When customers place orders, they arrive in your queue. You must review and Accept or Reject each order from the 'Orders & Transit' tab before shipping them.",
icon: "🚚",
action: "Next: Barcode Generation"
},
{
title: "🏷️ Barcode Identification & Tracking",
description: "Track your sales in real-time. Use the 'Barcode Generator' tab to create unique visual barcodes for each product SKU. You can download and print them easily.",
icon: "🏷️",
action: "Next: Earnings & Wallet"
},
{
title: "💼 Wallet & Payout Withdrawals",
description: "Monitor outstanding payouts and withdraw your earnings directly to your bank account anytime. Keep track of transaction receipts directly inside the Wallet tab.",
icon: "💼",
action: "Launch Dashboard 🚀"
}
]
const current = steps[tourStep - 1]
return (
<div className="form-card" style={{ maxWidth: '640px', margin: '2rem auto', textAlign: 'center', padding: '2.5rem' }}>
<div style={{ fontSize: '4rem', marginBottom: '1rem' }}>{current.icon}</div>
<h2 className="form-card-title">{current.title}</h2>
<p style={{ color: 'var(--text-muted)', fontSize: '1.05rem', margin: '1.5rem 0 2rem' }}>
{current.description}
</p>
<div style={{ display: 'flex', justifyContent: 'center', gap: '0.5rem', marginBottom: '2rem' }}>
{steps.map((_, idx) => (
<div
key={idx}
style={{
width: '12px',
height: '12px',
borderRadius: '50%',
backgroundColor: tourStep === idx + 1 ? 'var(--primary)' : 'var(--border)',
transition: 'background-color 0.2s'
}}
/>
))}
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
{tourStep > 1 ? (
<button type="button" className="btn btn-outline-dark" onClick={() => setTourStep(prev => prev - 1)}>
Back
</button>
) : (
<div />
)}
<button
type="button"
className="btn btn-primary"
style={{ backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
onClick={() => {
if (tourStep < steps.length) {
setTourStep(prev => prev + 1)
} else {
onComplete()
}
}}
>
{current.action}
</button>
</div>
</div>
)
}