supplier_central_frontend/src/App.tsx

1354 lines
58 KiB
TypeScript
Raw Normal View History

import { useState } from 'react'
import { CONFIG } from './config'
type Page = 'home' | 'about' | 'contact' | 'login' | 'signup' | 'profile-completion' | 'confirmation' | 'dashboard'
type DashboardTab = 'overview' | 'products' | 'orders' | 'returns' | 'wallet' | 'settings'
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 01:53:57 +00:00
status: 'Ready to Ship test' | 'Shipped' | 'Delivered' | 'Cancelled'
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
// Registration / Onboarding Form States
const [email, setEmail] = useState('')
const [phone, setPhone] = useState('')
const [password, setPassword] = useState('')
const [gstin, setGstin] = useState('29AAAAA1111A1Z1')
const [isGstinVerified, setIsGstinVerified] = useState(true)
const [isVerifyingGstin, setIsVerifyingGstin] = useState(false)
2026-08-09 01:53:57 +00:00
// Profile Completion States
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'
})
// --- 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)
const [orders] = useState<Order[]>(CONFIG.dashboardData.initialOrders as Order[])
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
setIsVerifyingGstin(true)
setTimeout(() => {
setIsVerifyingGstin(false)
setIsGstinVerified(true)
}, 1200)
}
// 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)
}
}
const navigateTo = (page: Page) => {
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()
navigateTo('dashboard')
}
const handleProfileSubmit = (e: React.FormEvent) => {
e.preventDefault()
navigateTo('dashboard')
}
// --- 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' }}>
<a href="#forgot" style={{ color: 'var(--text-muted)', fontSize: '0.85rem', textDecoration: 'none' }} onClick={(e) => { e.preventDefault(); alert('Password reset flow initiated.'); }}>Forgot Password?</a>
</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' }}>
<button type="button" className="nav-link" style={{ color: 'var(--primary)', fontWeight: 'bold' }} onClick={() => alert('OTP login code sent to registered number.')}>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>
<div className="form-group">
<label htmlFor="reg-gst">GSTIN / Tax ID *</label>
2026-08-09 01:53:57 +00:00
<input
id="reg-gst"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
placeholder="Enter GSTIN format"
value={gstin}
onChange={(e) => setGstin(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>
)}
{/* PROFILE COMPLETION VIEW (Step 2 of 3) */}
{currentPage === 'profile-completion' && (
<div className="form-card" style={{ maxWidth: '640px' }}>
<div className="step-progress-wrapper">
<span className="step-label">Step 2 of 3: Business Details</span>
<div className="step-bar-container">
<div className="step-bar-fill" style={{ width: '66%' }}></div>
</div>
</div>
<h2 className="form-card-title">Complete Your Supplier Profile</h2>
2026-08-09 01:53:57 +00:00
<form onSubmit={handleProfileSubmit}>
<div className="form-group">
<label htmlFor="store-name">Store Display Name *</label>
2026-08-09 01:53:57 +00:00
<input
id="store-name"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
placeholder="Enter store name"
value={storeName}
onChange={(e) => setStoreName(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
</div>
<div className="form-group">
<label htmlFor="store-logo">Upload Store Logo *</label>
<div className="upload-btn-wrapper">
<div className="upload-preview-box">
{storeLogo ? (
<img src={storeLogo} alt="Logo preview" />
) : (
<span style={{ fontSize: '1.5rem', color: 'var(--text-muted)' }}>🖼</span>
)}
</div>
2026-08-09 01:53:57 +00:00
<input
id="store-logo"
2026-08-09 01:53:57 +00:00
type="file"
accept="image/*"
onChange={handleLogoChange}
style={{ fontSize: '0.9rem' }}
/>
</div>
</div>
<div className="form-group">
<label htmlFor="store-bio">About Your Craft / Business *</label>
2026-08-09 01:53:57 +00:00
<textarea
id="store-bio"
2026-08-09 01:53:57 +00:00
className="form-control"
rows={3}
placeholder="Describe your craft, materials, and artisan history..."
value={businessBio}
onChange={(e) => setBusinessBio(e.target.value)}
required
></textarea>
</div>
<div className="form-group">
<label>Business Address for Pickup *</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}
2026-08-09 01:53:57 +00:00
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}
2026-08-09 01:53:57 +00:00
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}
2026-08-09 01:53:57 +00:00
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}
2026-08-09 01:53:57 +00:00
onChange={(e) => setAddress({ ...address, pincode: e.target.value })}
required
/>
</div>
</div>
<div className="form-group">
<label htmlFor="verify-gst">GSTIN *</label>
<div style={{ display: 'flex', gap: '0.75rem' }}>
2026-08-09 01:53:57 +00:00
<input
id="verify-gst"
2026-08-09 01:53:57 +00:00
type="text"
className="form-control"
placeholder="Verify GSTIN"
value={gstin}
onChange={(e) => setGstin(e.target.value)}
2026-08-09 01:53:57 +00:00
required
/>
2026-08-09 01:53:57 +00:00
<button
type="button"
className={`btn ${isGstinVerified ? 'btn-secondary' : 'btn-primary'}`}
onClick={handleVerifyGstin}
disabled={isVerifyingGstin || isGstinVerified}
style={{ minWidth: '120px' }}
>
{isVerifyingGstin ? 'Verifying...' : isGstinVerified ? 'Verified ✓' : 'Verify GSTIN'}
</button>
</div>
{isGstinVerified && (
<p style={{ color: 'var(--success)', fontSize: '0.85rem', marginTop: '0.5rem', fontWeight: 600 }}>
GSTIN successfully verified with government registry.
</p>
)}
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '2.5rem', alignItems: 'center' }}>
<button type="button" className="btn btn-outline-dark" onClick={() => navigateTo('signup')}>
Back
</button>
2026-08-09 01:53:57 +00:00
<button
type="submit"
className="btn btn-primary"
style={{ backgroundColor: 'var(--accent)', color: 'var(--primary)' }}
>
Save & Continue
</button>
</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>
)}
</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>
</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>
<div className="bulk-drop-zone" onClick={() => document.getElementById('bulk-file-pick')?.click()}>
<span>{isParsingBulk ? 'Processing bulk data...' : '📥 Click to select CSV Template file for bulk upload'}</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 && (
<div style={{ backgroundColor: '#f1f5f9', padding: '1rem', borderRadius: '8px', fontFamily: 'monospace', fontSize: '0.85rem' }}>
<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>
<th>Logistics & Carrier Details</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 01:53:57 +00:00
<span className={`badge ${o.status === 'Delivered' ? 'badge-success' :
o.status === 'Shipped' ? 'badge-info' : 'badge-warning'
}`}>
{o.status}
</span>
</td>
<td>
<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>
)}
{/* 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>
</>
)
}