2026-08-09 07:45:57 +00:00
import { useState , useEffect } from 'react'
2026-08-09 08:13:18 +00:00
import { CONFIG , apiFetch } from './config'
2026-08-07 07:42:14 +00:00
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'
2026-08-18 06:52:31 +00:00
type DashboardTab = 'overview' | 'products' | 'orders' | 'returns' | 'wallet' | 'settings' | 'barcode-generator' | 'analytics'
2026-08-08 07:46:17 +00:00
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'
2026-08-08 07:46:17 +00:00
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 )
2026-08-08 07:46:17 +00:00
// 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)
2026-08-08 07:46:17 +00:00
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-12 12:48:47 +00:00
const [ aadharS3Key , setAadharS3Key ] = useState < string | null > ( null )
const [ panS3Key , setPanS3Key ] = useState < string | null > ( null )
2026-08-09 01:53:57 +00:00
2026-08-18 06:00:45 +00:00
// New onboarding customization states
const [ businessType , setBusinessType ] = useState < 'registered_company' | 'self_help_group' | 'individual_maker' > ( 'registered_company' )
const [ storeSlug , setStoreSlug ] = useState ( '' )
const [ supportEmail , setSupportEmail ] = useState ( '' )
const [ supportPhone , setSupportPhone ] = useState ( '' )
const [ selectedCategories , setSelectedCategories ] = useState < string [ ] > ( [ ] )
2026-08-09 05:29:03 +00:00
// Step 3: Store and Location details
2026-08-08 07:46:17 +00:00
const [ storeName , setStoreName ] = useState ( 'My Artisan Handloom' )
const [ storeLogo , setStoreLogo ] = useState < string | null > ( null )
2026-08-12 12:48:47 +00:00
const [ logoS3Key , setLogoS3Key ] = useState < string | null > ( null )
2026-08-08 07:46:17 +00:00
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 } )
2026-08-09 07:35:45 +00:00
// --- Password visibility, confirm password and policy states ---
const [ showLoginPass , setShowLoginPass ] = useState ( false )
const [ showSignupPass , setShowSignupPass ] = useState ( false )
const [ showSignupConfirmPass , setShowSignupConfirmPass ] = useState ( false )
const [ confirmPassword , setConfirmPassword ] = useState ( '' )
const [ policyAccepted , setPolicyAccepted ] = useState ( false )
2026-08-09 05:29:03 +00:00
// --- Password Reset Page States ---
const [ resetEmail , setResetEmail ] = useState ( '' )
const [ resetOtpSent , setResetOtpSent ] = useState ( false )
const [ resetOtp , setResetOtp ] = useState ( '' )
const [ resetPassword , setResetPassword ] = useState ( '' )
// --- OTP Login States ---
const [ otpLoginPhone , setOtpLoginPhone ] = useState ( '' )
const [ otpLoginSent , setOtpLoginSent ] = useState ( false )
const [ otpLoginCode , setOtpLoginCode ] = useState ( '' )
// --- Barcode Generator States ---
const [ barcodeProductSku , setBarcodeProductSku ] = useState ( '' )
const [ barcodeGenerated , setBarcodeGenerated ] = useState ( false )
2026-08-08 07:46:17 +00:00
// --- 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
2026-08-08 07:46:17 +00:00
// Lists
2026-08-12 14:52:09 +00:00
const [ products , setProducts ] = useState < Product [ ] > ( [ ] )
const [ orders , setOrders ] = useState < Order [ ] > ( [ ] )
const [ returns , setReturns ] = useState < ReturnRequest [ ] > ( [ ] )
2026-08-09 01:53:57 +00:00
2026-08-08 07:46:17 +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
2026-08-18 06:52:31 +00:00
// New Heritage UI wizard states
const [ productWizardStep , setProductWizardStep ] = useState < number > ( 0 ) // 0: Catalog list, 1-5: Product upload wizard steps
const [ productFormDetails , setProductFormDetails ] = useState ( {
id : '' ,
name : '' ,
category : 'Textiles & Apparel' ,
description : '' ,
isGiTagged : false ,
primaryImage : 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=300' ,
additionalViews : [ ] as string [ ] ,
videoUrl : '' ,
view360Url : '' ,
basePrice : '' ,
compareAtPrice : '' ,
trackInventory : true ,
sku : '' ,
initialStock : '' ,
shippingProfile : 'Standard Fragile' ,
processingDays : 3 ,
packageWeight : 1.0
} )
const [ selectedOrderDetail , setSelectedOrderDetail ] = useState < any | null > ( null )
const [ orderNotes , setOrderNotes ] = useState < string > ( '' )
2026-08-08 07:46:17 +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 ( '' )
2026-08-09 07:45:57 +00:00
// Load data from backend on mount or when profile is complete / logged in
2026-08-12 12:48:47 +00:00
useEffect ( ( ) = > {
const token = localStorage . getItem ( 'access_token' ) ;
if ( token ) {
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/profile/ ` )
. then ( res = > {
if ( res . ok ) return res . json ( ) ;
throw new Error ( 'Session expired' ) ;
} )
. then ( user = > {
if ( user && user . profile ) {
const profile = user . profile ;
setPhone ( profile . phone || '' ) ;
setPhoneVerified ( profile . phone_verified || false ) ;
setEmail ( user . email || '' ) ;
setEmailVerified ( profile . email_verified || false ) ;
setGstin ( profile . gstin || '29AAAAA1111A1Z1' ) ;
setIsGstinVerified ( profile . is_gstin_verified || false ) ;
setAadharFile ( profile . aadhar_file || null ) ;
setPanFile ( profile . pan_file || null ) ;
setAadharS3Key ( profile . aadhar_s3_key || null ) ;
setPanS3Key ( profile . pan_s3_key || null ) ;
2026-08-18 06:00:45 +00:00
setBusinessType ( profile . business_type || 'registered_company' ) ;
setStoreSlug ( profile . store_slug || '' ) ;
setSupportEmail ( profile . support_email || '' ) ;
setSupportPhone ( profile . support_phone || '' ) ;
setSelectedCategories ( profile . categories || [ ] ) ;
2026-08-12 12:48:47 +00:00
setStoreName ( profile . store_name || 'My Artisan Handloom' ) ;
setStoreLogo ( profile . store_logo || null ) ;
setLogoS3Key ( profile . logo_s3_key || null ) ;
setBusinessBio ( profile . business_bio || 'Traditional weaving and local sustainable designs.' ) ;
setAddress ( {
street : profile.street || '123 Handloom Lane' ,
city : profile.city || 'Textile Town' ,
state : profile.state || 'Karnataka' ,
pincode : profile.pincode || '560001'
} ) ;
if ( profile . latitude && profile . longitude ) {
setMapCoordinates ( { lat : Number ( profile . latitude ) , lng : Number ( profile . longitude ) } ) ;
}
const step = profile . onboarding_step ;
2026-08-18 06:00:45 +00:00
if ( step >= 7 ) {
2026-08-12 12:48:47 +00:00
setIsProfileComplete ( true ) ;
setCurrentPage ( 'dashboard' ) ;
} else {
setProfileStep ( step ) ;
setIsProfileComplete ( false ) ;
setCurrentPage ( 'profile-completion' ) ;
}
}
} )
. catch ( err = > {
console . error ( 'Session restore failed:' , err ) ;
localStorage . removeItem ( 'access_token' ) ;
} ) ;
}
} , [ ] ) ;
2026-08-09 07:45:57 +00:00
useEffect ( ( ) = > {
if ( isProfileComplete || currentPage === 'dashboard' ) {
// Fetch Products
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/products/ ` )
2026-08-09 07:45:57 +00:00
. then ( res = > res . json ( ) )
. then ( data = > {
if ( Array . isArray ( data ) ) setProducts ( data ) ;
2026-08-12 15:26:59 +00:00
else if ( data && Array . isArray ( data . results ) ) setProducts ( data . results ) ;
2026-08-09 07:45:57 +00:00
} )
. catch ( err = > console . error ( 'Error fetching products:' , err ) ) ;
// Fetch Orders
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/orders/ ` )
2026-08-09 07:45:57 +00:00
. then ( res = > res . json ( ) )
. then ( data = > {
if ( Array . isArray ( data ) ) setOrders ( data ) ;
2026-08-12 15:26:59 +00:00
else if ( data && Array . isArray ( data . results ) ) setOrders ( data . results ) ;
2026-08-09 07:45:57 +00:00
} )
. catch ( err = > console . error ( 'Error fetching orders:' , err ) ) ;
// Fetch Returns
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/returns/ ` )
2026-08-09 07:45:57 +00:00
. then ( res = > res . json ( ) )
. then ( data = > {
if ( Array . isArray ( data ) ) setReturns ( data ) ;
2026-08-12 15:26:59 +00:00
else if ( data && Array . isArray ( data . results ) ) setReturns ( data . results ) ;
2026-08-09 07:45:57 +00:00
} )
. catch ( err = > console . error ( 'Error fetching returns:' , err ) ) ;
// Fetch Wallet
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/wallet/ ` )
2026-08-09 07:45:57 +00:00
. then ( res = > res . json ( ) )
. then ( data = > {
if ( data ) setWallet ( data ) ;
} )
. catch ( err = > console . error ( 'Error fetching wallet:' , err ) ) ;
}
} , [ isProfileComplete , currentPage ] ) ;
2026-08-12 12:48:47 +00:00
const uploadDocument = async ( file : File , fileType : string ) = > {
try {
const response = await apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/profile/presigned-url/ ` , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { file_type : fileType , content_type : file.type } )
} ) ;
if ( ! response . ok ) throw new Error ( 'Failed to get presigned URL' ) ;
const data = await response . json ( ) ;
// Simulate file upload PUT to mock presigned_url
await fetch ( data . presigned_url , {
method : 'PUT' ,
body : file ,
headers : { 'Content-Type' : file . type }
} ) . catch ( err = > console . log ( 'Mock S3 upload:' , err ) ) ;
return data . s3_key ;
} catch ( err ) {
console . error ( err ) ;
return ` suppliers/default/ ${ fileType } .jpg ` ;
}
} ;
2026-08-09 07:45:57 +00:00
const handleAcceptOrder = ( id : string ) = > {
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/orders/ ${ id } /accept/ ` , {
2026-08-09 07:45:57 +00:00
method : 'POST'
} )
. then ( res = > res . json ( ) )
. then ( updatedOrder = > {
setOrders ( orders . map ( o = > o . id === updatedOrder . id ? updatedOrder : o ) )
alert ( ` Order accepted successfully! ` )
} )
. catch ( err = > console . error ( err ) )
}
const handleRejectOrder = ( id : string ) = > {
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/orders/ ${ id } /reject/ ` , {
2026-08-09 07:45:57 +00:00
method : 'POST'
} )
. then ( res = > res . json ( ) )
. then ( updatedOrder = > {
setOrders ( orders . map ( o = > o . id === updatedOrder . id ? updatedOrder : o ) )
alert ( ` Order rejected. ` )
} )
. catch ( err = > console . error ( err ) )
}
2026-08-12 15:00:52 +00:00
// Bulk Upload
2026-08-08 07:46:17 +00:00
const [ bulkLog , setBulkLog ] = useState < string [ ] > ( [ ] )
const [ isParsingBulk , setIsParsingBulk ] = useState ( false )
2026-08-12 15:00:52 +00:00
const [ bulkCsvFile , setBulkCsvFile ] = useState < File | null > ( null )
const [ bulkZipFile , setBulkZipFile ] = useState < File | null > ( null )
2026-08-08 07:46:17 +00:00
// GSTIN verification simulator
const handleVerifyGstin = ( ) = > {
2026-08-12 12:48:47 +00:00
if ( ! gstin . trim ( ) || gstin . length !== 15 ) {
alert ( 'Invalid GSTIN length. Must be 15 chars.' ) ;
return ;
}
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/profile/submit-gstin/ ` , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { gstin } )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Failed to verify GSTIN.' ) ;
return res . json ( ) ;
} )
. then ( data = > {
if ( data . verified ) {
setIsGstinVerified ( true ) ;
}
} )
. catch ( err = > {
alert ( err . message ) ;
} ) ;
2026-08-08 07:46:17 +00:00
}
// Handle Logo Upload simulation
2026-08-12 12:48:47 +00:00
const handleLogoChange = async ( e : React.ChangeEvent < HTMLInputElement > ) = > {
2026-08-08 07:46:17 +00:00
const file = e . target . files ? . [ 0 ]
if ( file ) {
const reader = new FileReader ( )
reader . onloadend = ( ) = > {
setStoreLogo ( reader . result as string )
}
reader . readAsDataURL ( file )
2026-08-12 12:48:47 +00:00
const s3Key = await uploadDocument ( file , 'logo' ) ;
setLogoS3Key ( s3Key ) ;
2026-08-08 07:46:17 +00:00
}
}
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 )
}
2026-08-08 07:46:17 +00:00
window . scrollTo ( { top : 0 , behavior : 'smooth' } )
}
2026-08-10 12:32:20 +00:00
const handleLogout = ( ) = > {
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/auth/logout/ ` , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' }
} )
. catch ( err = > console . error ( 'Error logging out:' , err ) )
. finally ( ( ) = > {
2026-08-12 12:48:47 +00:00
localStorage . removeItem ( 'access_token' )
2026-08-10 12:32:20 +00:00
// Reset all onboarding & profile states to their defaults
setIsProfileComplete ( false )
setProfileStep ( 1 )
setEmail ( '' )
setPhone ( '' )
setPassword ( '' )
setConfirmPassword ( '' )
setPolicyAccepted ( false )
setPhoneVerified ( false )
setEmailVerified ( false )
setPhoneOtpSent ( false )
setEmailOtpSent ( false )
setEnteredPhoneOtp ( '' )
setEnteredEmailOtp ( '' )
setGstin ( '29AAAAA1111A1Z1' )
setIsGstinVerified ( false )
setAadharFile ( null )
setPanFile ( null )
2026-08-12 12:48:47 +00:00
setAadharS3Key ( null )
setPanS3Key ( null )
2026-08-10 12:32:20 +00:00
setStoreName ( 'My Artisan Handloom' )
setStoreLogo ( null )
2026-08-12 12:48:47 +00:00
setLogoS3Key ( null )
2026-08-10 12:32:20 +00:00
setBusinessBio ( 'Traditional weaving and local sustainable designs.' )
setAddress ( {
street : '123 Handloom Lane' ,
city : 'Textile Town' ,
state : 'Karnataka' ,
pincode : '560001'
} )
setMapCoordinates ( { lat : 12.9716 , lng : 77.5946 } )
navigateTo ( 'home' , true )
} )
}
2026-08-08 07:46:17 +00:00
const handleRegisterSubmit = ( e : React.FormEvent ) = > {
e . preventDefault ( )
2026-08-09 07:35:45 +00:00
// Email Validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ ;
if ( ! emailRegex . test ( email ) ) {
alert ( 'Please enter a valid email address.' ) ;
return ;
}
// Phone Validation
const phoneRegex = /^[6-9]\d{9}$/ ;
if ( ! phoneRegex . test ( phone ) ) {
alert ( 'Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.' ) ;
return ;
}
// Password Validation
if ( password . length < 8 ) {
alert ( 'Password must be at least 8 characters long.' ) ;
return ;
}
if ( password !== confirmPassword ) {
alert ( 'Passwords do not match.' ) ;
return ;
}
// Policy Validation
if ( ! policyAccepted ) {
alert ( 'You must accept the Terms of Service and Privacy Policy.' ) ;
return ;
}
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/auth/register/ ` , {
2026-08-09 07:52:49 +00:00
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( {
username : email ,
email : email ,
phone : phone ,
2026-08-12 12:48:47 +00:00
password : password ,
confirm_password : confirmPassword ,
policy_accepted : policyAccepted
2026-08-09 07:52:49 +00:00
} )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Registration failed. Username/email might already be taken.' ) ;
return res . json ( ) ;
} )
. then ( ( ) = > {
// Auto login after signup
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/auth/login/ ` , {
2026-08-09 07:52:49 +00:00
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { username : email , password : password } )
} )
2026-08-12 12:48:47 +00:00
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Auto-login failed.' ) ;
return res . json ( ) ;
} )
. then ( data = > {
localStorage . setItem ( 'access_token' , data . access_token ) ;
2026-08-09 07:52:49 +00:00
navigateTo ( 'profile-completion' )
} )
} )
. catch ( err = > {
alert ( err . message ) ;
} ) ;
2026-08-08 07:46:17 +00:00
}
const handleLoginSubmit = ( e : React.FormEvent ) = > {
e . preventDefault ( )
2026-08-09 07:35:45 +00:00
2026-08-13 04:44:56 +00:00
if ( ! email . trim ( ) ) {
alert ( 'Please enter your email or phone number.' ) ;
2026-08-09 07:35:45 +00:00
return ;
}
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/auth/login/ ` , {
2026-08-09 07:52:49 +00:00
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { username : email , password : password } )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Invalid credentials.' ) ;
return res . json ( ) ;
} )
2026-08-12 12:48:47 +00:00
. then ( data = > {
localStorage . setItem ( 'access_token' , data . access_token ) ;
if ( data . user && data . user . profile ) {
const profile = data . user . profile ;
setPhone ( profile . phone || '' ) ;
setPhoneVerified ( profile . phone_verified || false ) ;
setEmail ( data . user . email || '' ) ;
setEmailVerified ( profile . email_verified || false ) ;
setGstin ( profile . gstin || '29AAAAA1111A1Z1' ) ;
setIsGstinVerified ( profile . is_gstin_verified || false ) ;
setAadharFile ( profile . aadhar_file || null ) ;
setPanFile ( profile . pan_file || null ) ;
setAadharS3Key ( profile . aadhar_s3_key || null ) ;
setPanS3Key ( profile . pan_s3_key || null ) ;
setStoreName ( profile . store_name || 'My Artisan Handloom' ) ;
setStoreLogo ( profile . store_logo || null ) ;
setLogoS3Key ( profile . logo_s3_key || null ) ;
setBusinessBio ( profile . business_bio || 'Traditional weaving and local sustainable designs.' ) ;
setAddress ( {
street : profile.street || '123 Handloom Lane' ,
city : profile.city || 'Textile Town' ,
state : profile.state || 'Karnataka' ,
pincode : profile.pincode || '560001'
} ) ;
if ( profile . latitude && profile . longitude ) {
setMapCoordinates ( { lat : Number ( profile . latitude ) , lng : Number ( profile . longitude ) } ) ;
}
const step = profile . onboarding_step ;
if ( step >= 4 ) {
setIsProfileComplete ( true ) ;
navigateTo ( 'dashboard' , true ) ;
} else {
setProfileStep ( step ) ;
setIsProfileComplete ( false ) ;
navigateTo ( 'profile-completion' ) ;
}
} else {
setIsProfileComplete ( false ) ;
navigateTo ( 'profile-completion' ) ;
}
2026-08-09 07:52:49 +00:00
} )
. catch ( err = > {
alert ( err . message ) ;
} ) ;
2026-08-08 07:46:17 +00:00
}
2026-08-12 12:48:47 +00:00
const saveProfileBackend = ( isComplete : boolean ) = > {
return apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/profile/ ` , {
method : 'PUT' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( {
phone : phone ,
phone_verified : phoneVerified ,
email_verified : emailVerified ,
gstin : gstin ,
is_gstin_verified : isGstinVerified ,
2026-08-18 06:00:45 +00:00
business_type : businessType ,
store_slug : storeSlug ,
support_email : supportEmail ,
support_phone : supportPhone ,
categories : selectedCategories ,
2026-08-12 12:48:47 +00:00
aadhar_file : aadharFile ,
pan_file : panFile ,
aadhar_s3_key : aadharS3Key || 'suppliers/default/aadhar.pdf' ,
pan_s3_key : panS3Key || 'suppliers/default/pan.pdf' ,
store_name : storeName ,
store_logo : storeLogo || 'https://images.unsplash.com/photo-1513519245088-0e12902e5a38?auto=format&fit=crop&q=80&w=800' ,
logo_s3_key : logoS3Key || 'suppliers/default/logo.jpg' ,
business_bio : businessBio ,
street : address.street ,
city : address.city ,
state : address.state ,
pincode : address.pincode ,
latitude : mapCoordinates.lat ,
longitude : mapCoordinates.lng ,
is_profile_complete : isComplete
} )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Failed to update profile.' ) ;
return res . json ( ) ;
} ) ;
} ;
2026-08-08 07:46:17 +00:00
const handleProfileSubmit = ( e : React.FormEvent ) = > {
e . preventDefault ( )
2026-08-09 08:00:32 +00:00
if ( profileStep === 2 ) {
setIsGstinVerified ( true )
}
2026-08-18 06:00:45 +00:00
const isLastStep = profileStep === 6 ;
2026-08-12 12:48:47 +00:00
saveProfileBackend ( isLastStep )
. then ( ( ) = > {
if ( ! isLastStep ) {
setProfileStep ( prev = > prev + 1 )
} else {
2026-08-18 06:00:45 +00:00
setProfileStep ( 7 ) ;
2026-08-12 12:48:47 +00:00
}
} )
. catch ( err = > {
alert ( err . message ) ;
} ) ;
2026-08-08 07:46:17 +00:00
}
// --- Dashboard Logic Actions ---
2026-08-09 01:53:57 +00:00
2026-08-08 07:46:17 +00:00
// Product creation/modification
const handleSaveProduct = ( e : React.FormEvent ) = > {
e . preventDefault ( )
2026-08-09 07:45:57 +00:00
const url = isEditingProduct
? ` ${ CONFIG . apiBaseUrl } /api/products/ ${ productForm . id } / `
: ` ${ CONFIG . apiBaseUrl } /api/products/ `
const method = isEditingProduct ? 'PUT' : 'POST'
2026-08-09 08:13:18 +00:00
apiFetch ( url , {
2026-08-09 07:45:57 +00:00
method : method ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( {
title : productForm.title ,
category : productForm.category ,
price : String ( productForm . price ) ,
2026-08-08 07:46:17 +00:00
stock : Number ( productForm . stock ) ,
2026-08-09 07:45:57 +00:00
sku : productForm.sku || ` PROD- ${ Date . now ( ) . toString ( ) . slice ( - 6 ) } ` ,
image : productForm.image
} )
} )
. then ( res = > res . json ( ) )
. then ( ( ) = > {
// Refresh products from backend
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/products/ ` )
2026-08-09 07:45:57 +00:00
. then ( r = > r . json ( ) )
2026-08-12 15:26:59 +00:00
. then ( prods = > {
if ( Array . isArray ( prods ) ) setProducts ( prods ) ;
else if ( prods && Array . isArray ( prods . results ) ) setProducts ( prods . results ) ;
} )
2026-08-09 07:45:57 +00:00
setIsEditingProduct ( false )
alert ( isEditingProduct ? 'Product modified successfully!' : 'Product uploaded successfully!' )
} )
. catch ( err = > console . error ( err ) )
2026-08-08 07:46:17 +00:00
// 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?' ) ) {
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/products/ ${ id } / ` , {
2026-08-09 07:45:57 +00:00
method : 'DELETE'
} )
. then ( ( ) = > {
setProducts ( products . filter ( p = > p . id !== id ) )
} )
. catch ( err = > console . error ( err ) )
2026-08-08 07:46:17 +00:00
}
}
2026-08-12 15:00:52 +00:00
const handleBulkUploadSubmit = async ( e : React.FormEvent ) = > {
e . preventDefault ( ) ;
if ( ! bulkCsvFile ) {
alert ( "Please select a CSV file to upload." ) ;
return ;
}
setIsParsingBulk ( true ) ;
setBulkLog ( [ 'Uploading files to server...' , 'Parsing CSV data and extracting ZIP images...' ] ) ;
2026-08-09 01:53:57 +00:00
2026-08-12 15:00:52 +00:00
const formData = new FormData ( ) ;
formData . append ( 'csv_file' , bulkCsvFile ) ;
if ( bulkZipFile ) {
formData . append ( 'zip_file' , bulkZipFile ) ;
}
2026-08-09 07:45:57 +00:00
2026-08-12 15:00:52 +00:00
try {
const token = localStorage . getItem ( 'access_token' ) ;
const response = await fetch ( ` ${ CONFIG . apiBaseUrl } /api/products/bulk-upload/ ` , {
2026-08-09 07:45:57 +00:00
method : 'POST' ,
2026-08-12 15:00:52 +00:00
headers : {
. . . ( token ? { 'Authorization' : ` Bearer ${ token } ` } : { } )
} ,
body : formData
} ) ;
const data = await response . json ( ) ;
if ( ! response . ok ) {
throw new Error ( data . error || 'Failed to complete bulk upload.' ) ;
}
setBulkLog ( [
'CSV file parsed successfully.' ,
` Extracted and matched images for SKUs from ZIP file. ` ,
` Successfully added ${ data . products ? . length || 0 } product listings! ` ,
] ) ;
// Refresh product list
const prodRes = await apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/products/ ` ) ;
const prods = await prodRes . json ( ) ;
if ( Array . isArray ( prods ) ) {
setProducts ( prods ) ;
2026-08-12 15:26:59 +00:00
} else if ( prods && Array . isArray ( prods . results ) ) {
setProducts ( prods . results ) ;
2026-08-12 15:00:52 +00:00
}
setBulkCsvFile ( null ) ;
setBulkZipFile ( null ) ;
} catch ( err : any ) {
setBulkLog ( prev = > [ . . . prev , ` Error: ${ err . message } ` ] ) ;
} finally {
setIsParsingBulk ( false ) ;
}
} ;
2026-08-08 07:46:17 +00:00
// 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
}
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/wallet/withdraw/ ` , {
2026-08-09 07:45:57 +00:00
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { amount : String ( amount ) } )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Insufficient funds or invalid request' ) ;
return res . json ( ) ;
} )
. then ( updatedWallet = > {
setWallet ( updatedWallet )
setWithdrawAmount ( '' )
alert ( ` Payout of $ ${ amount } successfully transferred! ` )
} )
. catch ( err = > {
alert ( err . message )
2026-08-08 07:46:17 +00:00
} )
}
// Returns actions
const handleReturnAction = ( id : string , action : 'Approved' | 'Rejected' ) = > {
2026-08-09 08:13:18 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/returns/ ${ id } /action/ ` , {
2026-08-09 07:45:57 +00:00
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { action : action } )
} )
. then ( res = > res . json ( ) )
. then ( updatedReturn = > {
setReturns ( returns . map ( ret = > ret . id === id ? updatedReturn : ret ) )
alert ( ` Return request ${ action . toLowerCase ( ) } ! ` )
} )
. catch ( err = > console . error ( err ) )
2026-08-08 07:46:17 +00:00
}
2026-08-09 08:04:52 +00:00
// Compute realtime metrics based on state loaded from backend
const computeRealtimeMetrics = ( ) = > {
const totalSales = orders
. filter ( o = > o . status !== 'Cancelled' && o . status !== 'Rejected' )
. reduce ( ( sum , o ) = > sum + Number ( o . total ) , 0 )
const totalEarned = Number ( wallet . outstanding ) + Number ( wallet . withdrawn )
const totalStock = products . reduce ( ( sum , p ) = > sum + Number ( p . stock ) , 0 )
const totalReturns = returns . length
2026-08-09 08:13:18 +00:00
const isLoggedIn = currentPage === 'dashboard' || currentPage === 'profile-completion' || currentPage === 'welcome-tour' || isProfileComplete
if ( isLoggedIn ) {
return {
totalSales ,
totalEarned ,
stockDetails : totalStock ,
returnedItems : totalReturns ,
chartValues : orders.length > 0
? orders . map ( o = > Number ( o . total ) )
: [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
}
}
2026-08-09 08:04:52 +00:00
return {
2026-08-09 08:13:18 +00:00
totalSales : 45280.00 ,
totalEarned : 38488.00 ,
stockDetails : 342 ,
returnedItems : 12 ,
2026-08-09 08:04:52 +00:00
chartValues : CONFIG.dashboardData.filters [ dateFilter ] ? . chartValues || [ 30 , 45 , 35 , 60 , 50 , 75 , 65 , 80 , 70 , 95 , 90 , 110 ]
}
}
const selectedMetrics = computeRealtimeMetrics ( )
2026-08-07 07:42:14 +00:00
return (
< >
2026-08-08 07:46:17 +00:00
{ /* 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 >
2026-08-07 07:42:14 +00:00
< / div >
2026-08-08 07:46:17 +00:00
< nav className = "nav-links" >
2026-08-09 01:53:57 +00:00
< button
2026-08-08 07:46:17 +00:00
className = { ` nav-link ${ currentPage === 'home' ? 'active' : '' } ` }
onClick = { ( ) = > navigateTo ( 'home' ) }
>
Platform
< / button >
2026-08-09 01:53:57 +00:00
< button
2026-08-08 07:46:17 +00:00
className = "nav-link"
onClick = { ( ) = > navigateTo ( 'home' ) }
>
Pricing
< / button >
2026-08-09 01:53:57 +00:00
< button
2026-08-08 07:46:17 +00:00
className = { ` nav-link ${ currentPage === 'about' ? 'active' : '' } ` }
onClick = { ( ) = > navigateTo ( 'about' ) }
>
Success Stories
< / button >
2026-08-09 01:53:57 +00:00
< button
2026-08-08 07:46:17 +00:00
className = { ` nav-link ${ currentPage === 'contact' ? 'active' : '' } ` }
onClick = { ( ) = > navigateTo ( 'contact' ) }
>
Support
< / button >
< / nav >
< div className = "nav-buttons" >
{ currentPage === 'dashboard' ? (
2026-08-10 12:32:20 +00:00
< button className = "btn btn-secondary" onClick = { handleLogout } >
2026-08-08 07:46:17 +00:00
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 >
< / >
) }
2026-08-07 07:42:14 +00:00
< / div >
2026-08-08 07:46:17 +00:00
< / header >
{ /* Main Content Area */ }
{ currentPage !== 'dashboard' ? (
< main className = { ` main-content ${ currentPage === 'home' ? 'full-width' : '' } ` } >
2026-08-09 01:53:57 +00:00
2026-08-08 07:46:17 +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"
2026-08-08 07:46:17 +00:00
/ >
< / 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"
2026-08-08 07:46:17 +00:00
/ >
< 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
2026-08-08 07:46:17 +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
2026-08-08 07:46:17 +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
2026-08-08 07:46:17 +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
2026-08-08 07:46:17 +00:00
className = { ` tab-btn ${ activeTab === 'login' ? 'active' : '' } ` }
onClick = { ( ) = > { setActiveTab ( 'login' ) ; navigateTo ( 'login' ) ; } }
2026-08-07 07:42:14 +00:00
>
2026-08-08 07:46:17 +00:00
Login
< / button >
2026-08-09 01:53:57 +00:00
< button
2026-08-08 07:46:17 +00:00
className = { ` tab-btn ${ activeTab === 'register' ? 'active' : '' } ` }
onClick = { ( ) = > { setActiveTab ( 'register' ) ; navigateTo ( 'signup' ) ; } }
2026-08-07 07:42:14 +00:00
>
2026-08-08 07:46:17 +00:00
Register
< / button >
< / div >
{ activeTab === 'login' ? (
< form onSubmit = { handleLoginSubmit } >
< h2 className = "form-card-title" > Supplier Portal Access < / h2 >
< div className = "form-group" >
2026-08-13 04:44:56 +00:00
< label htmlFor = "login-email" > Business Email or Phone Number < / label >
2026-08-09 01:53:57 +00:00
< input
2026-08-08 07:46:17 +00:00
id = "login-email"
2026-08-13 04:44:56 +00:00
type = "text"
2026-08-09 01:53:57 +00:00
className = "form-control"
2026-08-13 04:44:56 +00:00
placeholder = "Enter your email or phone number"
2026-08-08 07:46:17 +00:00
value = { email }
onChange = { ( e ) = > setEmail ( e . target . value ) }
2026-08-09 01:53:57 +00:00
required
2026-08-08 07:46:17 +00:00
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "login-password" > Password < / label >
2026-08-09 07:35:45 +00:00
< div style = { { position : 'relative' } } >
< input
id = "login-password"
type = { showLoginPass ? 'text' : 'password' }
className = "form-control"
placeholder = "Enter your password"
value = { password }
onChange = { ( e ) = > setPassword ( e . target . value ) }
required
style = { { paddingRight : '45px' } }
/ >
< button
type = "button"
onClick = { ( ) = > setShowLoginPass ( ! showLoginPass ) }
style = { {
position : 'absolute' ,
right : '12px' ,
top : '50%' ,
transform : 'translateY(-50%)' ,
background : 'none' ,
border : 'none' ,
cursor : 'pointer' ,
fontSize : '1.1rem' ,
color : 'var(--text-muted)'
} }
>
{ showLoginPass ? '👁️' : '🙈' }
< / button >
< / div >
2026-08-08 07:46:17 +00:00
< / 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 >
2026-08-08 07:46:17 +00:00
< / 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 >
2026-08-08 07:46:17 +00:00
< / 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
2026-08-08 07:46:17 +00:00
id = "reg-email"
2026-08-09 01:53:57 +00:00
type = "email"
className = "form-control"
placeholder = "Enter email address"
2026-08-08 07:46:17 +00:00
value = { email }
onChange = { ( e ) = > setEmail ( e . target . value ) }
2026-08-09 01:53:57 +00:00
required
2026-08-08 07:46:17 +00:00
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "reg-phone" > Mobile Number * < / label >
2026-08-09 01:53:57 +00:00
< input
2026-08-08 07:46:17 +00:00
id = "reg-phone"
2026-08-09 01:53:57 +00:00
type = "tel"
className = "form-control"
placeholder = "Enter 10-digit number"
2026-08-08 07:46:17 +00:00
value = { phone }
onChange = { ( e ) = > setPhone ( e . target . value ) }
2026-08-09 01:53:57 +00:00
required
2026-08-08 07:46:17 +00:00
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "reg-pass" > Create Password * < / label >
2026-08-09 07:35:45 +00:00
< div style = { { position : 'relative' } } >
< input
id = "reg-pass"
type = { showSignupPass ? 'text' : 'password' }
className = "form-control"
placeholder = "Minimum 8 characters"
value = { password }
onChange = { ( e ) = > setPassword ( e . target . value ) }
required
style = { { paddingRight : '45px' } }
/ >
< button
type = "button"
onClick = { ( ) = > setShowSignupPass ( ! showSignupPass ) }
style = { {
position : 'absolute' ,
right : '12px' ,
top : '50%' ,
transform : 'translateY(-50%)' ,
background : 'none' ,
border : 'none' ,
cursor : 'pointer' ,
fontSize : '1.1rem' ,
color : 'var(--text-muted)'
} }
>
{ showSignupPass ? '👁️' : '🙈' }
< / button >
< / div >
< / div >
< div className = "form-group" >
< label htmlFor = "reg-confirm-pass" > Confirm Password * < / label >
< div style = { { position : 'relative' } } >
< input
id = "reg-confirm-pass"
type = { showSignupConfirmPass ? 'text' : 'password' }
className = "form-control"
placeholder = "Re-enter password"
value = { confirmPassword }
onChange = { ( e ) = > setConfirmPassword ( e . target . value ) }
required
style = { { paddingRight : '45px' } }
/ >
< button
type = "button"
onClick = { ( ) = > setShowSignupConfirmPass ( ! showSignupConfirmPass ) }
style = { {
position : 'absolute' ,
right : '12px' ,
top : '50%' ,
transform : 'translateY(-50%)' ,
background : 'none' ,
border : 'none' ,
cursor : 'pointer' ,
fontSize : '1.1rem' ,
color : 'var(--text-muted)'
} }
>
{ showSignupConfirmPass ? '👁️' : '🙈' }
< / button >
< / div >
< / div >
< div className = "form-group" style = { { display : 'flex' , gap : '0.5rem' , alignItems : 'center' , margin : '1.25rem 0' } } >
2026-08-09 01:53:57 +00:00
< input
2026-08-09 07:35:45 +00:00
id = "reg-policy"
type = "checkbox"
checked = { policyAccepted }
onChange = { ( e ) = > setPolicyAccepted ( e . target . checked ) }
2026-08-09 01:53:57 +00:00
required
2026-08-08 07:46:17 +00:00
/ >
2026-08-09 07:35:45 +00:00
< label htmlFor = "reg-policy" style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' , marginBottom : 0 , cursor : 'pointer' } } >
I accept the < a href = "#terms" onClick = { ( e ) = > e . preventDefault ( ) } > Terms of Service < / a > and < a href = "#privacy" onClick = { ( e ) = > e . preventDefault ( ) } > Privacy Policy < / a > *
< / label >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-09 07:35:45 +00:00
< button type = "submit" className = "btn btn-primary" style = { { width : '100%' , padding : '0.75rem' , marginTop : '0.5rem' } } >
2026-08-08 07:46:17 +00:00
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-08 07:46:17 +00:00
/ >
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
2026-08-08 07:46:17 +00:00
/ >
< / 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-08 07:46:17 +00:00
/ >
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
2026-08-08 07:46:17 +00:00
/ >
< / 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-08 07:46:17 +00:00
/ >
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" >
2026-08-18 06:00:45 +00:00
< span className = "step-label" > Step { profileStep } of 7 : {
profileStep === 1 ? 'Welcome' :
profileStep === 2 ? 'Business Details' :
profileStep === 3 ? 'Identity Verification' :
profileStep === 4 ? 'Contact Verification' :
profileStep === 5 ? 'Choose Categories' :
profileStep === 6 ? 'Store Setup' :
'Verification'
2026-08-09 05:29:03 +00:00
} < / span >
< div className = "step-bar-container" >
2026-08-18 06:00:45 +00:00
< div className = "step-bar-fill" style = { { width : ` ${ ( profileStep / 7 ) * 100 } % ` } } > < / div >
2026-08-09 05:29:03 +00:00
< / div >
< / div >
< h2 className = "form-card-title" style = { { marginBottom : '1.5rem' } } > Complete Your Supplier Profile < / h2 >
< form onSubmit = { handleProfileSubmit } >
{ profileStep === 1 && (
2026-08-18 06:00:45 +00:00
< div style = { { textAlign : 'center' , padding : '1rem' } } >
< div style = { { fontSize : '3rem' , marginBottom : '1.5rem' } } > 👋 < / div >
< h3 style = { { fontSize : '1.25rem' , marginBottom : '1rem' , color : 'var(--primary)' } } > Welcome to Tradhox Onboarding < / h3 >
< p style = { { color : 'var(--text-muted)' , marginBottom : '2rem' , fontSize : '0.95rem' , lineHeight : '1.6' } } >
We bridge the gap between traditional Indian artistry and a global marketplace .
Let ' s set up your supplier profile in a few simple steps .
< / p >
< button
type = "button"
className = "btn btn-primary"
style = { { width : '100%' , padding : '0.8rem' , fontWeight : 'bold' } }
onClick = { ( ) = > setProfileStep ( 2 ) }
>
Begin Setup →
< / button >
< / div >
) }
{ profileStep === 2 && (
2026-08-09 05:29:03 +00:00
< div >
2026-08-18 06:00:45 +00:00
< h3 style = { { fontSize : '1.1rem' , marginBottom : '1rem' , color : 'var(--primary)' } } > Step 2 : Business Details < / h3 >
< div className = "form-group" >
< label > Business Type * < / label >
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '0.5rem' , marginBottom : '1.5rem' } } >
< label style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' , cursor : 'pointer' , padding : '0.75rem' , border : '1px solid var(--border)' , borderRadius : '6px' } } >
< input type = "radio" name = "business_type" value = "registered_company" checked = { businessType === 'registered_company' } onChange = { ( ) = > setBusinessType ( 'registered_company' ) } / >
Registered Company
< / label >
< label style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' , cursor : 'pointer' , padding : '0.75rem' , border : '1px solid var(--border)' , borderRadius : '6px' } } >
< input type = "radio" name = "business_type" value = "self_help_group" checked = { businessType === 'self_help_group' } onChange = { ( ) = > setBusinessType ( 'self_help_group' ) } / >
Self Help Group
< / label >
< label style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' , cursor : 'pointer' , padding : '0.75rem' , border : '1px solid var(--border)' , borderRadius : '6px' } } >
< input type = "radio" name = "business_type" value = "individual_maker" checked = { businessType === 'individual_maker' } onChange = { ( ) = > setBusinessType ( 'individual_maker' ) } / >
Individual Maker
< / label >
< / div >
< / div >
< 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 }
disabled = { isGstinVerified }
style = { { minWidth : '120px' } }
>
{ isGstinVerified ? 'Submitted ✓' : 'Submit GSTIN' }
< / button >
< / div >
{ isGstinVerified && (
< p style = { { color : 'var(--success)' , fontSize : '0.85rem' , marginTop : '0.5rem' , fontWeight : 600 } } >
✓ GSTIN verification will be completed within the next 24 hrs
< / p >
) }
< / 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 ( 1 ) } >
Back
< / button >
< button
type = "submit"
className = "btn btn-primary"
style = { { flex : 1 , backgroundColor : 'var(--accent)' , color : 'var(--primary)' , fontWeight : 'bold' } }
disabled = { ! gstin || ! isGstinVerified }
>
Next Step →
< / button >
< / div >
< / div >
) }
{ profileStep === 3 && (
< div >
< h3 style = { { fontSize : '1.1rem' , marginBottom : '1rem' , color : 'var(--primary)' } } > Step 3 : Identity Verification < / h3 >
{ /* 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 = { async ( e ) = > {
if ( e . target . files ? . [ 0 ] ) {
const file = e . target . files [ 0 ] ;
setAadharFile ( file . name ) ;
alert ( ` Aadhaar card selected: ${ file . name } . Uploading... ` ) ;
const s3Key = await uploadDocument ( file , 'aadhar' ) ;
setAadharS3Key ( s3Key ) ;
alert ( ` Aadhaar card uploaded successfully! ` ) ;
}
} }
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 = { async ( e ) = > {
if ( e . target . files ? . [ 0 ] ) {
const file = e . target . files [ 0 ] ;
setPanFile ( file . name ) ;
alert ( ` PAN card selected: ${ file . name } . Uploading... ` ) ;
const s3Key = await uploadDocument ( file , 'pan' ) ;
setPanS3Key ( s3Key ) ;
alert ( ` PAN card uploaded successfully! ` ) ;
}
} }
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 ( 2 ) } >
Back
< / button >
< button
type = "submit"
className = "btn btn-primary"
style = { { flex : 1 , backgroundColor : 'var(--accent)' , color : 'var(--primary)' , fontWeight : 'bold' } }
disabled = { ! aadharFile || ! panFile }
>
Next Step →
< / button >
< / div >
< / div >
) }
{ profileStep === 4 && (
< div >
< h3 style = { { fontSize : '1.1rem' , marginBottom : '1rem' , color : 'var(--primary)' } } > Step 4 : Verify Contacts < / h3 >
2026-08-09 05:29:03 +00:00
{ /* 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 = { ( ) = > {
2026-08-12 12:48:47 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/auth/verify-otp/ ` , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { type : 'phone' , otp : enteredPhoneOtp } )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Incorrect code. Enter 123456' ) ;
return res . json ( ) ;
} )
. then ( data = > {
if ( data . verified ) {
setPhoneVerified ( true ) ;
alert ( 'Phone verified successfully!' ) ;
} else {
alert ( 'Incorrect code. Enter 123456' ) ;
}
} )
. catch ( err = > {
alert ( err . message ) ;
} ) ;
2026-08-09 05:29:03 +00:00
} }
>
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 = { ( ) = > {
2026-08-12 12:48:47 +00:00
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/auth/verify-otp/ ` , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( { type : 'email' , otp : enteredEmailOtp } )
} )
. then ( res = > {
if ( ! res . ok ) throw new Error ( 'Incorrect code. Enter 123456' ) ;
return res . json ( ) ;
} )
. then ( data = > {
if ( data . verified ) {
setEmailVerified ( true ) ;
alert ( 'Email verified successfully!' ) ;
} else {
alert ( 'Incorrect code. Enter 123456' ) ;
}
} )
. catch ( err = > {
alert ( err . message ) ;
} ) ;
2026-08-09 05:29:03 +00:00
} }
>
Verify Code
< / button >
< / div >
) }
{ emailVerified && (
< div style = { { color : 'var(--success)' , fontWeight : 600 , fontSize : '0.9rem' } } >
✓ Email Verified
< / div >
) }
< / div >
2026-08-18 06:00:45 +00:00
< div style = { { display : 'flex' , justifyContent : 'space-between' , gap : '1rem' } } >
< button type = "button" className = "btn btn-outline-dark" style = { { flex : 1 } } onClick = { ( ) = > setProfileStep ( 3 ) } >
Back
< / button >
< button
type = "submit"
className = "btn btn-primary"
style = { { flex : 1 , backgroundColor : 'var(--accent)' , color : 'var(--primary)' , fontWeight : 'bold' } }
disabled = { ! phoneVerified || ! emailVerified }
>
Next Step →
< / button >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-09 05:29:03 +00:00
) }
2026-08-08 07:46:17 +00:00
2026-08-18 06:00:45 +00:00
{ profileStep === 5 && (
2026-08-09 05:29:03 +00:00
< div >
2026-08-18 06:00:45 +00:00
< h3 style = { { fontSize : '1.1rem' , marginBottom : '0.5rem' , color : 'var(--primary)' } } > Step 5 : Choose Product Categories < / h3 >
< p style = { { color : 'var(--text-muted)' , marginBottom : '1.5rem' , fontSize : '0.9rem' } } >
Select the categories that apply to your artisanal goods .
< / p >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.75rem' , marginBottom : '2rem' } } >
{ [ 'Sustainable Products' , 'Home Decor' , 'Eco-Friendly' , 'OPOD Products' , 'GI Tagged' , 'Textiles & Apparel' ] . map ( cat = > {
const isSelected = selectedCategories . includes ( cat ) ;
return (
< div
key = { cat }
onClick = { ( ) = > {
if ( isSelected ) {
setSelectedCategories ( selectedCategories . filter ( c = > c !== cat ) ) ;
} else {
setSelectedCategories ( [ . . . selectedCategories , cat ] ) ;
}
} }
style = { {
padding : '1rem' ,
border : isSelected ? '2px solid var(--primary)' : '1px solid var(--border)' ,
backgroundColor : isSelected ? 'rgba(107, 26, 44, 0.05)' : 'transparent' ,
borderRadius : '8px' ,
cursor : 'pointer' ,
display : 'flex' ,
alignItems : 'center' ,
justifyContent : 'center' ,
fontWeight : isSelected ? '600' : 'normal' ,
transition : 'all 0.2s ease' ,
textAlign : 'center'
} }
>
{ cat }
< / div >
) ;
} ) }
2026-08-09 05:29:03 +00:00
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , gap : '1rem' } } >
2026-08-18 06:00:45 +00:00
< button type = "button" className = "btn btn-outline-dark" style = { { flex : 1 } } onClick = { ( ) = > setProfileStep ( 4 ) } >
2026-08-09 05:29:03 +00:00
Back
< / button >
< button
type = "submit"
className = "btn btn-primary"
style = { { flex : 1 , backgroundColor : 'var(--accent)' , color : 'var(--primary)' , fontWeight : 'bold' } }
2026-08-18 06:00:45 +00:00
disabled = { selectedCategories . length === 0 }
2026-08-09 05:29:03 +00:00
>
2026-08-18 06:00:45 +00:00
Next Step →
2026-08-09 05:29:03 +00:00
< / button >
< / div >
< / div >
) }
2026-08-18 06:00:45 +00:00
{ profileStep === 6 && (
2026-08-09 05:29:03 +00:00
< div >
2026-08-18 06:00:45 +00:00
< h3 style = { { fontSize : '1.1rem' , marginBottom : '1rem' , color : 'var(--primary)' } } > Step 6 : Store Details & Pickup Location < / h3 >
2026-08-09 05:29:03 +00:00
2026-08-18 06:00:45 +00:00
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.75rem' } } className = "form-group" >
< div >
< label htmlFor = "store-name" > Store Display Name * < / label >
< input
id = "store-name"
type = "text"
className = "form-control"
value = { storeName }
onChange = { ( e ) = > setStoreName ( e . target . value ) }
required
/ >
< / div >
< div >
< label htmlFor = "store-slug" > Store Slug / Custom URL * < / label >
< input
id = "store-slug"
type = "text"
className = "form-control"
placeholder = "e.g. my-artisan-shop"
value = { storeSlug }
onChange = { ( e ) = > setStoreSlug ( e . target . value . toLowerCase ( ) . replace ( /[^a-z0-9\-]/g , '' ) ) }
required
/ >
< / div >
< / div >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.75rem' } } className = "form-group" >
< div >
< label htmlFor = "support-email" > Support Email * < / label >
< input
id = "support-email"
type = "email"
className = "form-control"
placeholder = "hello@shop.com"
value = { supportEmail }
onChange = { ( e ) = > setSupportEmail ( e . target . value ) }
required
/ >
< / div >
< div >
< label htmlFor = "support-phone" > Support Phone * < / label >
< input
id = "support-phone"
type = "tel"
className = "form-control"
placeholder = "+91..."
value = { supportPhone }
onChange = { ( e ) = > setSupportPhone ( e . target . value ) }
required
/ >
< / div >
2026-08-09 05:29:03 +00:00
< / div >
< div className = "form-group" >
2026-08-18 06:00:45 +00:00
< label htmlFor = "store-bio" > Store Description / Bio * < / label >
2026-08-09 05:29:03 +00:00
< textarea
id = "store-bio"
className = "form-control"
rows = { 2 }
value = { businessBio }
onChange = { ( e ) = > setBusinessBio ( e . target . value ) }
required
> < / textarea >
< / div >
< div className = "form-group" >
< label > Store Location on Map * < / label >
< div
style = { {
2026-08-18 06:00:45 +00:00
height : '150px' ,
2026-08-09 05:29:03 +00:00
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 `
} ) ) ;
} }
>
< 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)' ,
2026-08-18 06:00:45 +00:00
pointerEvents : 'none'
2026-08-09 05:29:03 +00:00
} }
>
📍
< / div >
2026-08-18 06:00:45 +00:00
< span style = { { fontSize : '0.85rem' , color : '#475569' , pointerEvents : 'none' , fontWeight : 600 } } > Click map to pin location < / span >
2026-08-09 05:29:03 +00:00
< / div >
< / div >
< div className = "form-group" >
2026-08-18 06:00:45 +00:00
< label htmlFor = "location-text" > Pickup Address * < / label >
2026-08-09 05:29:03 +00:00
< input
id = "location-text"
type = "text"
className = "form-control"
value = { address . street }
onChange = { ( e ) = > setAddress ( { . . . address , street : e.target.value } ) }
required
/ >
< / div >
2026-08-18 06:00:45 +00:00
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr 1fr' , gap : '0.5rem' } } className = "form-group" >
2026-08-09 05:29:03 +00:00
< 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 >
2026-08-18 06:00:45 +00:00
< div >
< label htmlFor = "loc-state" > State * < / label >
< input
id = "loc-state"
type = "text"
className = "form-control"
value = { address . state }
onChange = { ( e ) = > setAddress ( { . . . address , state : e.target.value } ) }
required
/ >
< / div >
2026-08-09 05:29:03 +00:00
< div >
< label htmlFor = "loc-pincode" > Pincode * < / label >
< input
id = "loc-pincode"
type = "text"
className = "form-control"
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' } } >
2026-08-18 06:00:45 +00:00
< button type = "button" className = "btn btn-outline-dark" style = { { flex : 1 } } onClick = { ( ) = > setProfileStep ( 5 ) } >
2026-08-09 05:29:03 +00:00
Back
< / button >
< button
type = "submit"
className = "btn btn-primary"
style = { { flex : 1 , backgroundColor : 'var(--accent)' , color : 'var(--primary)' , fontWeight : 'bold' } }
2026-08-18 06:00:45 +00:00
disabled = { ! storeName || ! storeSlug || ! supportEmail || ! supportPhone || ! address . street || ! address . city || ! address . state || ! address . pincode }
2026-08-09 05:29:03 +00:00
>
Submit Supplier Profile
< / button >
< / div >
< / div >
) }
2026-08-09 01:53:57 +00:00
2026-08-18 06:00:45 +00:00
{ profileStep === 7 && (
< div style = { { textAlign : 'center' , padding : '1rem' } } >
< div style = { { fontSize : '4rem' , marginBottom : '1.5rem' } } > 🎉 < / div >
< h3 style = { { fontSize : '1.25rem' , marginBottom : '1rem' , color : 'var(--primary)' } } > Setup Complete ! < / h3 >
< p style = { { color : 'var(--text-muted)' , marginBottom : '2rem' , fontSize : '0.95rem' } } >
Your supplier profile has been successfully submitted and is under review . You can now access your preview dashboard .
< / p >
< button
type = "button"
className = "btn btn-dark"
style = { { width : '100%' , padding : '0.8rem' , fontWeight : 'bold' } }
onClick = { ( ) = > {
setIsProfileComplete ( true ) ;
navigateTo ( 'welcome-tour' , true ) ;
} }
>
Go to Dashboard
< / button >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:00:45 +00:00
) }
< / form >
2026-08-08 07:46:17 +00:00
< / div >
) }
2026-08-09 05:29:03 +00:00
{ /* WELCOME PAGE & SETUP TOUR FOR NEW SELLERS */ }
{ currentPage === 'welcome-tour' && (
2026-08-09 08:24:20 +00:00
< WelcomeTourWizard onComplete = { ( ) = > navigateTo ( 'dashboard' ) } / >
2026-08-09 05:29:03 +00:00
) }
2026-08-08 07:46:17 +00:00
< / main >
) : (
/* --- FULL SERVICE SUPPLIER ACTIVE DASHBOARD PAGE --- */
< div className = "dashboard-container" >
2026-08-09 01:53:57 +00:00
2026-08-08 07:46:17 +00:00
{ /* Sidebar */ }
2026-08-18 06:52:31 +00:00
< aside className = "dashboard-sidebar" style = { { display : 'flex' , flexDirection : 'column' , justifyContent : 'space-between' , padding : '1.5rem 1rem' , minWidth : '260px' , borderRight : '1px solid var(--border)' , backgroundColor : '#FFFFFF' } } >
< div >
{ /* Logo (Maroon bold serif) */ }
< div style = { { padding : '0.5rem 1rem' , marginBottom : '2rem' } } >
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontWeight : 'bold' , fontSize : '1.8rem' , letterSpacing : '-0.5px' , margin : 0 } } > Tradhox < / h2 >
< / div >
{ /* Profile Card */ }
< div style = { { display : 'flex' , alignItems : 'center' , gap : '0.75rem' , padding : '0.75rem 1rem' , marginBottom : '1.5rem' , backgroundColor : '#F9F6F2' , borderRadius : '8px' } } >
< div style = { { width : '40px' , height : '40px' , borderRadius : '50%' , backgroundColor : 'var(--primary)' , color : 'white' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' , fontWeight : 'bold' , overflow : 'hidden' } } >
{ storeLogo ? < img src = { storeLogo } style = { { width : '100%' , height : '100%' , objectFit : 'cover' } } / > : < span style = { { fontSize : '1.2rem' } } > { CONFIG . logoLetter } < / span > }
< / div >
< div style = { { display : 'flex' , flexDirection : 'column' } } >
< span style = { { fontWeight : 'bold' , fontSize : '0.9rem' , color : '#4A4A4A' } } > { storeName || 'Tradhox Seller' } < / span >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' } } > Artisan Partner < / span >
< / div >
< / div >
< ul className = "sidebar-menu" style = { { listStyle : 'none' , padding : 0 , margin : 0 } } >
< li style = { { marginBottom : '0.5rem' } } >
< button
className = { ` sidebar-item-btn ${ dashTab === 'overview' ? 'active' : '' } ` }
onClick = { ( ) = > { setDashTab ( 'overview' ) ; setSelectedOrderDetail ( null ) ; } }
style = { { width : '100%' , padding : '0.75rem 1rem' , borderRadius : '4px' , textAlign : 'left' , display : 'flex' , alignItems : 'center' , gap : '0.75rem' , fontSize : '0.95rem' , fontWeight : 500 , border : 'none' , cursor : 'pointer' , backgroundColor : dashTab === 'overview' ? '#F9F6F2' : 'transparent' , color : dashTab === 'overview' ? 'var(--primary)' : '#4A4A4A' } }
>
🏠 Home
< / button >
< / li >
< li style = { { marginBottom : '0.5rem' } } >
< button
className = { ` sidebar-item-btn ${ dashTab === 'orders' ? 'active' : '' } ` }
onClick = { ( ) = > { setDashTab ( 'orders' ) ; setSelectedOrderDetail ( null ) ; } }
style = { { width : '100%' , padding : '0.75rem 1rem' , borderRadius : '4px' , textAlign : 'left' , display : 'flex' , alignItems : 'center' , gap : '0.75rem' , fontSize : '0.95rem' , fontWeight : 500 , border : 'none' , cursor : 'pointer' , backgroundColor : dashTab === 'orders' ? '#F9F6F2' : 'transparent' , color : dashTab === 'orders' ? 'var(--primary)' : '#4A4A4A' } }
>
🛒 Orders
< / button >
< / li >
< li style = { { marginBottom : '0.5rem' } } >
< button
className = { ` sidebar-item-btn ${ dashTab === 'products' ? 'active' : '' } ` }
onClick = { ( ) = > { setDashTab ( 'products' ) ; setProductWizardStep ( 0 ) ; setSelectedOrderDetail ( null ) ; } }
style = { { width : '100%' , padding : '0.75rem 1rem' , borderRadius : '4px' , textAlign : 'left' , display : 'flex' , alignItems : 'center' , gap : '0.75rem' , fontSize : '0.95rem' , fontWeight : 500 , border : 'none' , cursor : 'pointer' , backgroundColor : dashTab === 'products' ? '#F9F6F2' : 'transparent' , color : dashTab === 'products' ? 'var(--primary)' : '#4A4A4A' } }
>
📦 Products
< / button >
< / li >
< li style = { { marginBottom : '0.5rem' } } >
< button
className = { ` sidebar-item-btn ${ dashTab === 'wallet' ? 'active' : '' } ` }
onClick = { ( ) = > { setDashTab ( 'wallet' ) ; setSelectedOrderDetail ( null ) ; } }
style = { { width : '100%' , padding : '0.75rem 1rem' , borderRadius : '4px' , textAlign : 'left' , display : 'flex' , alignItems : 'center' , gap : '0.75rem' , fontSize : '0.95rem' , fontWeight : 500 , border : 'none' , cursor : 'pointer' , backgroundColor : dashTab === 'wallet' ? '#F9F6F2' : 'transparent' , color : dashTab === 'wallet' ? 'var(--primary)' : '#4A4A4A' } }
>
💵 Payments
< / button >
< / li >
< li style = { { marginBottom : '0.5rem' } } >
< button
className = { ` sidebar-item-btn ${ dashTab === 'analytics' ? 'active' : '' } ` }
onClick = { ( ) = > { setDashTab ( 'analytics' ) ; setSelectedOrderDetail ( null ) ; } }
style = { { width : '100%' , padding : '0.75rem 1rem' , borderRadius : '4px' , textAlign : 'left' , display : 'flex' , alignItems : 'center' , gap : '0.75rem' , fontSize : '0.95rem' , fontWeight : 500 , border : 'none' , cursor : 'pointer' , backgroundColor : dashTab === 'analytics' ? '#F9F6F2' : 'transparent' , color : dashTab === 'analytics' ? 'var(--primary)' : '#4A4A4A' } }
>
📊 Analytics
< / button >
< / li >
< li style = { { marginBottom : '0.5rem' } } >
< button
className = { ` sidebar-item-btn ${ dashTab === 'settings' ? 'active' : '' } ` }
onClick = { ( ) = > { setDashTab ( 'settings' ) ; setSelectedOrderDetail ( null ) ; } }
style = { { width : '100%' , padding : '0.75rem 1rem' , borderRadius : '4px' , textAlign : 'left' , display : 'flex' , alignItems : 'center' , gap : '0.75rem' , fontSize : '0.95rem' , fontWeight : 500 , border : 'none' , cursor : 'pointer' , backgroundColor : dashTab === 'settings' ? '#F9F6F2' : 'transparent' , color : dashTab === 'settings' ? 'var(--primary)' : '#4A4A4A' } }
>
⚙ ️ Settings
< / button >
< / li >
< / ul >
< / div >
{ /* View Store Button at bottom */ }
< div style = { { padding : '0.5rem' } } >
< button
className = "btn btn-outline-dark"
style = { { width : '100%' , borderRadius : '4px' , border : '1px solid var(--border)' , fontSize : '0.9rem' , padding : '0.6rem' , backgroundColor : 'transparent' , cursor : 'pointer' } }
onClick = { ( ) = > window . open ( storeSlug ? ` /store/ ${ storeSlug } ` : '#' , '_blank' ) }
>
View Store
< / button >
2026-08-08 07:46:17 +00:00
< / div >
< / aside >
{ /* Main Dashboard Space */ }
2026-08-18 06:52:31 +00:00
< section className = "dashboard-main" style = { { flex : 1 , padding : '2rem' , backgroundColor : '#F9F6F2' , overflowY : 'auto' } } >
2026-08-09 01:53:57 +00:00
2026-08-18 06:52:31 +00:00
{ /* OVERVIEW PANEL / HOME TAB */ }
{ dashTab === 'overview' && ! selectedOrderDetail && (
2026-08-08 07:46:17 +00:00
< div >
2026-08-18 06:52:31 +00:00
{ /* Header Row */ }
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2rem' } } >
< div style = { { position : 'relative' , width : '320px' } } >
< input
type = "text"
placeholder = "Search orders, products..."
style = { { width : '100%' , padding : '0.6rem 1rem 0.6rem 2.5rem' , borderRadius : '4px' , border : '1px solid var(--border)' , fontSize : '0.9rem' , outline : 'none' } }
/ >
< span style = { { position : 'absolute' , left : '0.8rem' , top : '50%' , transform : 'translateY(-50%)' , color : 'var(--text-muted)' } } > 🔍 < / span >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< div style = { { display : 'flex' , alignItems : 'center' , gap : '1.25rem' } } >
< span style = { { fontSize : '1.25rem' , cursor : 'pointer' , color : '#4A4A4A' } } > 🔔 < / span >
< span style = { { fontSize : '1.25rem' , cursor : 'pointer' , color : '#4A4A4A' } } > ❓ < / span >
< div style = { { width : '32px' , height : '32px' , borderRadius : '50%' , backgroundColor : 'var(--primary)' , color : 'white' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' , fontWeight : 'bold' , fontSize : '0.85rem' } } >
{ CONFIG . logoLetter }
2026-08-08 07:46:17 +00:00
< / div >
< / div >
< / div >
2026-08-18 06:52:31 +00:00
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '2.2rem' , marginBottom : '0.5rem' } } > Welcome back , Artisan ! < / h2 >
< p style = { { color : 'var(--text-muted)' , marginBottom : '2rem' , fontSize : '1.05rem' } } > Your store is looking great . Here is what ' s happening today . < / p >
{ /* Metrics Cards */ }
< div className = "metrics-row" style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr 1fr' , gap : '1.5rem' , marginBottom : '2.5rem' } } >
< div className = "metric-data-card" style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' , boxShadow : '0 4px 12px rgba(107, 26, 44, 0.02)' } } >
< div style = { { fontSize : '0.8rem' , fontWeight : 600 , color : 'var(--text-muted)' , textTransform : 'uppercase' , letterSpacing : '0.5px' } } > Total Sales ( ₹ ) < / div >
< div style = { { fontSize : '1.8rem' , fontFamily : 'var(--heading-font-family)' , fontWeight : 'bold' , color : 'var(--primary)' , margin : '0.5rem 0' } } > ₹ 42 , 500 < / div >
{ /* Wavy Sparkline */ }
< svg viewBox = "0 0 100 20" style = { { width : '100%' , height : '30px' } } >
< path d = "M0,15 Q15,5 30,12 T60,8 T90,14 T100,10 L100,20 L0,20 Z" fill = "rgba(107, 26, 44, 0.1)" stroke = "var(--primary)" strokeWidth = "1.5" / >
< / svg >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< div className = "metric-data-card" style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' , boxShadow : '0 4px 12px rgba(107, 26, 44, 0.02)' } } >
< div style = { { fontSize : '0.8rem' , fontWeight : 600 , color : 'var(--text-muted)' , textTransform : 'uppercase' , letterSpacing : '0.5px' } } > Active Orders < / div >
< div style = { { fontSize : '1.8rem' , fontFamily : 'var(--heading-font-family)' , fontWeight : 'bold' , color : 'var(--primary)' , margin : '0.5rem 0' } } > 14 < / div >
< svg viewBox = "0 0 100 20" style = { { width : '100%' , height : '30px' } } >
< path d = "M0,18 Q20,10 40,15 T80,5 T100,8 L100,20 L0,20 Z" fill = "rgba(107, 26, 44, 0.1)" stroke = "var(--primary)" strokeWidth = "1.5" / >
< / svg >
< / div >
< div className = "metric-data-card" style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' , boxShadow : '0 4px 12px rgba(107, 26, 44, 0.02)' } } >
< div style = { { fontSize : '0.8rem' , fontWeight : 600 , color : 'var(--text-muted)' , textTransform : 'uppercase' , letterSpacing : '0.5px' } } > Store Views < / div >
< div style = { { fontSize : '1.8rem' , fontFamily : 'var(--heading-font-family)' , fontWeight : 'bold' , color : 'var(--primary)' , margin : '0.5rem 0' } } > 1 , 204 < / div >
< svg viewBox = "0 0 100 20" style = { { width : '100%' , height : '30px' } } >
< path d = "M0,15 Q25,18 50,8 T80,14 T100,5 L100,20 L0,20 Z" fill = "rgba(107, 26, 44, 0.1)" stroke = "var(--primary)" strokeWidth = "1.5" / >
< / svg >
2026-08-08 07:46:17 +00:00
< / div >
< / div >
2026-08-09 01:53:57 +00:00
2026-08-18 06:52:31 +00:00
< div style = { { display : 'grid' , gridTemplateColumns : '2fr 1fr' , gap : '2rem' } } >
{ /* Recent Orders Table */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '1.5rem' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , margin : 0 } } > Recent Orders < / h3 >
< button onClick = { ( ) = > setDashTab ( 'orders' ) } style = { { background : 'none' , border : 'none' , color : 'var(--primary)' , fontWeight : 'bold' , fontSize : '0.9rem' , cursor : 'pointer' , display : 'flex' , alignItems : 'center' , gap : '0.25rem' } } >
View All →
< / button >
< / div >
< div className = "dashboard-table-wrapper" style = { { boxShadow : 'none' , border : 'none' } } >
2026-08-08 07:46:17 +00:00
< table className = "dashboard-table" >
< thead >
2026-08-18 06:52:31 +00:00
< tr style = { { borderBottom : '1px solid var(--border)' } } >
< th style = { { padding : '0.75rem 0.5rem' } } > Order ID < / th >
< th style = { { padding : '0.75rem 0.5rem' } } > Date < / th >
< th style = { { padding : '0.75rem 0.5rem' } } > Product Name < / th >
< th style = { { padding : '0.75rem 0.5rem' } } > Status < / th >
2026-08-08 07:46:17 +00:00
< / tr >
< / thead >
< tbody >
2026-08-18 06:52:31 +00:00
{ orders . slice ( 0 , 5 ) . map ( o = > (
< tr key = { o . id } style = { { borderBottom : '1px solid #F9F6F2' } } >
< td style = { { padding : '0.75rem 0.5rem' } } >
< button
onClick = { ( ) = > { setSelectedOrderDetail ( o ) ; setDashTab ( 'orders' ) ; } }
style = { { background : 'none' , border : 'none' , color : 'var(--primary)' , fontWeight : 'bold' , cursor : 'pointer' , padding : 0 } }
>
# { o . id }
< / button >
2026-08-08 07:46:17 +00:00
< / td >
2026-08-18 06:52:31 +00:00
< td style = { { padding : '0.75rem 0.5rem' } } > { o . date } < / td >
< td style = { { padding : '0.75rem 0.5rem' } } > { o . item } < / td >
< td style = { { padding : '0.75rem 0.5rem' } } >
< span style = { {
padding : '0.25rem 0.6rem' ,
borderRadius : '20px' ,
fontSize : '0.8rem' ,
fontWeight : 600 ,
backgroundColor : o.status === 'Delivered' ? 'rgba(42, 157, 143, 0.1)' : 'rgba(107, 26, 44, 0.1)' ,
color : o.status === 'Delivered' ? 'var(--success)' : 'var(--primary)'
} } >
{ o . status === 'Pending Acceptance' ? 'Pending' : o . status }
< / span >
2026-08-08 07:46:17 +00:00
< / td >
< / tr >
) ) }
< / tbody >
< / table >
< / div >
2026-08-18 06:52:31 +00:00
< / div >
2026-08-08 07:46:17 +00:00
2026-08-18 06:52:31 +00:00
{ /* Live Preview & Share Card */ }
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '1.5rem' } } >
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' , textAlign : 'center' } } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '1rem' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , margin : 0 } } > Live Preview < / h3 >
< span style = { { cursor : 'pointer' , fontSize : '1.1rem' } } > 🔗 < / span >
2026-08-09 05:29:03 +00:00
< / div >
2026-08-18 06:52:31 +00:00
{ /* Shop Preview Grid Box */ }
< div style = { { border : '1px solid var(--border)' , borderRadius : '6px' , overflow : 'hidden' , backgroundColor : '#F9F6F2' , padding : '1rem' , marginBottom : '1.5rem' } } >
< div style = { { backgroundColor : 'white' , padding : '0.5rem' , borderRadius : '4px' , display : 'inline-block' , fontWeight : 'bold' , fontSize : '0.8rem' , color : '#4A4A4A' , marginBottom : '1rem' , border : '1px solid var(--border)' } } >
{ storeName || 'Tradhox Artisan Co.' }
< / div >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.5rem' } } >
< div style = { { height : '80px' , backgroundColor : '#E5DFD9' , borderRadius : '4px' , overflow : 'hidden' } } >
{ products [ 0 ] ? < img src = { products [ 0 ] . image } style = { { width : '100%' , height : '100%' , objectFit : 'cover' } } / > : null }
< / div >
< div style = { { height : '80px' , backgroundColor : '#E5DFD9' , borderRadius : '4px' , overflow : 'hidden' } } >
{ products [ 1 ] ? < img src = { products [ 1 ] . image } style = { { width : '100%' , height : '100%' , objectFit : 'cover' } } / > : null }
< / div >
< / div >
< / div >
< p style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' , marginBottom : '1.5rem' } } > Looking good ! Your store is currently live . < / p >
< button
className = "btn btn-primary"
style = { { width : '100%' , padding : '0.75rem' , backgroundColor : 'var(--primary)' , color : 'white' , border : 'none' , borderRadius : '4px' , fontWeight : 'bold' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' , gap : '0.5rem' , cursor : 'pointer' } }
onClick = { ( ) = > alert ( ` Store Link: https://tradhox.com/store/ ${ storeSlug || 'artisan' } ` ) }
>
Share Store Link < span > 📤 < / span >
< / button >
< / div >
< / div >
< / div >
< / div >
) }
2026-08-09 05:29:03 +00:00
2026-08-18 06:52:31 +00:00
{ /* PRODUCTS TAB */ }
{ dashTab === 'products' && (
< div >
{ productWizardStep === 0 ? (
/* Catalog List View */
< div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2rem' } } >
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '2rem' , margin : 0 } } > Products < / h2 >
< button
className = "btn btn-primary"
style = { { backgroundColor : 'var(--primary)' , color : 'white' , padding : '0.75rem 1.5rem' , border : 'none' , borderRadius : '4px' , fontWeight : 'bold' , cursor : 'pointer' } }
onClick = { ( ) = > {
setProductFormDetails ( {
id : '' ,
name : '' ,
category : 'Textiles & Apparel' ,
description : '' ,
isGiTagged : false ,
primaryImage : '' ,
additionalViews : [ ] ,
videoUrl : '' ,
view360Url : '' ,
basePrice : '' ,
compareAtPrice : '' ,
trackInventory : true ,
sku : '' ,
initialStock : '' ,
shippingProfile : 'Standard Fragile' ,
processingDays : 3 ,
packageWeight : 1.0
} ) ;
setProductWizardStep ( 1 ) ;
} }
>
+ Add New Product
< / button >
< / div >
{ /* Filter Bar */ }
< div style = { { display : 'flex' , gap : '1rem' , marginBottom : '1.5rem' } } >
< select style = { { padding : '0.5rem 1rem' , borderRadius : '4px' , border : '1px solid var(--border)' , backgroundColor : '#FFFFFF' , cursor : 'pointer' } } >
< option > All Categories < / option >
< option > Textiles & Apparel < / option >
< option > Pottery & Ceramics < / option >
< option > Wood Carving < / option >
< option > Metalcraft < / option >
< / select >
< select style = { { padding : '0.5rem 1rem' , borderRadius : '4px' , border : '1px solid var(--border)' , backgroundColor : '#FFFFFF' , cursor : 'pointer' } } >
< option > All Status < / option >
< option > In Stock < / option >
< option > Low Stock < / option >
< option > Out of Stock < / option >
< / select >
< / div >
{ /* Products Grid Cards */ }
< div style = { { display : 'grid' , gridTemplateColumns : 'repeat(auto-fill, minmax(280px, 1fr))' , gap : '1.5rem' } } >
{ products . map ( p = > {
const isOut = p . stock === 0 ;
const isLow = p . stock > 0 && p . stock <= 5 ;
return (
< div key = { p . id } style = { { backgroundColor : '#FFFFFF' , borderRadius : '8px' , border : '1px solid var(--border)' , overflow : 'hidden' , display : 'flex' , flexDirection : 'column' , justifyContent : 'space-between' , boxShadow : '0 4px 12px rgba(107, 26, 44, 0.01)' } } >
< div >
{ /* Product Thumbnail Frame */ }
< div style = { { height : '200px' , backgroundColor : '#E5DFD9' , position : 'relative' , overflow : 'hidden' } } >
{ p . image ? (
< img src = { p . image } alt = { p . title } style = { { width : '100%' , height : '100%' , objectFit : 'cover' } } / >
) : (
< div style = { { display : 'flex' , alignItems : 'center' , justifyContent : 'center' , height : '100%' , color : 'var(--text-muted)' } } > 🖼 ️ No Image < / div >
) }
{ /* Stock status pill */ }
< span style = { {
position : 'absolute' ,
top : '0.75rem' ,
right : '0.75rem' ,
padding : '0.25rem 0.5rem' ,
borderRadius : '4px' ,
fontSize : '0.75rem' ,
fontWeight : 'bold' ,
backgroundColor : isOut ? '#FEE2E2' : isLow ? '#FEF3C7' : '#D1FAE5' ,
color : isOut ? '#991B1B' : isLow ? '#92400E' : '#065F46'
} } >
{ isOut ? '● Out of Stock' : isLow ? ` ● Low Stock ( ${ p . stock } ) ` : ` ● In Stock ( ${ p . stock } ) ` }
< / span >
< / div >
< div style = { { padding : '1.25rem' } } >
< div style = { { fontSize : '0.75rem' , fontWeight : 600 , color : 'var(--text-muted)' , textTransform : 'uppercase' , letterSpacing : '0.5px' , marginBottom : '0.25rem' } } >
{ p . category . toUpperCase ( ) } { ( p as any ) . is_gi_tagged ? '• GI TAGGED' : '' }
< / div >
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.2rem' , margin : '0 0 0.5rem 0' } } > { p . title } < / h4 >
< div style = { { fontSize : '1.1rem' , fontWeight : 'bold' , color : '#4A4A4A' } } > ₹ { Number ( p . price ) . toFixed ( 2 ) } < / div >
< / div >
< / div >
{ /* Actions Footer */ }
< div style = { { padding : '1.25rem' , borderTop : '1px solid var(--border)' , display : 'grid' , gridTemplateColumns : '1fr 40px' , gap : '0.5rem' } } >
< button
className = "btn btn-outline-dark"
style = { { width : '100%' , fontSize : '0.85rem' , padding : '0.5rem' , borderRadius : '4px' } }
onClick = { ( ) = > {
setProductFormDetails ( {
id : String ( p . id ) ,
name : p.title ,
category : p.category ,
description : ( p as any ) . description || 'Premium hand-crafted quality.' ,
isGiTagged : ( p as any ) . is_gi_tagged || false ,
primaryImage : p.image || '' ,
additionalViews : ( p as any ) . additional_images || [ ] ,
videoUrl : ( p as any ) . video_url || '' ,
view360Url : ( p as any ) . view_360_url || '' ,
basePrice : String ( p . price ) ,
compareAtPrice : ( p as any ) . compare_at_price ? String ( ( p as any ) . compare_at_price ) : '' ,
trackInventory : ( p as any ) . track_inventory !== false ,
sku : p.sku ,
initialStock : String ( p . stock ) ,
shippingProfile : ( p as any ) . shipping_profile || 'Standard Fragile' ,
processingDays : ( p as any ) . processing_days || 3 ,
packageWeight : ( p as any ) . package_weight || 1.0
} ) ;
setProductWizardStep ( 1 ) ;
} }
>
✏ ️ Edit
< / button >
< button
className = "btn btn-outline-dark"
style = { { color : 'var(--error)' , borderColor : 'var(--error)' , fontSize : '0.85rem' , padding : '0.5rem' , borderRadius : '4px' , cursor : 'pointer' } }
onClick = { ( ) = > handleDeleteProduct ( p . id ) }
>
🗑 ️
< / button >
< / div >
< / div >
) ;
} ) }
< / div >
< / div >
) : (
/* Add / Edit Product Wizard Flow */
< div style = { { backgroundColor : '#FFFFFF' , padding : '2rem' , borderRadius : '8px' , border : '1px solid var(--border)' , maxWidth : '1000px' , margin : '0 auto' } } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2rem' } } >
< div >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.6rem' , margin : 0 } } > Add New Product < / h3 >
< span style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' } } > Draft in progress < / span >
2026-08-09 05:29:03 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< button
className = "btn btn-outline-dark"
style = { { padding : '0.5rem 1rem' , fontSize : '0.85rem' , borderRadius : '4px' } }
onClick = { ( ) = > setProductWizardStep ( 0 ) }
>
Exit Wizard
< / button >
< / div >
2026-08-09 05:29:03 +00:00
2026-08-18 06:52:31 +00:00
{ /* Progress Indicator line */ }
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2.5rem' , borderBottom : '1px solid var(--border)' , paddingBottom : '1.5rem' } } >
{ [ 'Product Info' , 'Media Assets' , 'Pricing & Stock' , 'Shipping' , 'Final Review' ] . map ( ( label , idx ) = > {
const stepNum = idx + 1 ;
const isActive = productWizardStep === stepNum ;
const isDone = productWizardStep > stepNum ;
return (
< div key = { label } style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' , opacity : isActive || isDone ? 1 : 0.4 } } >
< div style = { {
width : '24px' ,
height : '24px' ,
borderRadius : '50%' ,
backgroundColor : isDone || isActive ? 'var(--primary)' : 'transparent' ,
color : isDone || isActive ? 'white' : '#4A4A4A' ,
border : isDone || isActive ? 'none' : '1.5px solid #4A4A4A' ,
display : 'flex' ,
alignItems : 'center' ,
justifyContent : 'center' ,
fontWeight : 'bold' ,
fontSize : '0.75rem'
} } >
{ isDone ? '✓' : stepNum }
< / div >
< span style = { { fontSize : '0.9rem' , fontWeight : isActive ? 'bold' : 'normal' } } > { label } < / span >
< / div >
) ;
} ) }
< / div >
{ /* Step Content Renderers */ }
< form onSubmit = { ( e ) = > {
e . preventDefault ( ) ;
if ( productWizardStep < 5 ) {
setProductWizardStep ( prev = > prev + 1 ) ;
} else {
// Submit logic matching Django models
const url = productFormDetails . id
? ` ${ CONFIG . apiBaseUrl } /api/products/ ${ productFormDetails . id } / `
: ` ${ CONFIG . apiBaseUrl } /api/products/ ` ;
const method = productFormDetails . id ? 'PUT' : 'POST' ;
apiFetch ( url , {
method : method ,
headers : { 'Content-Type' : 'application/json' } ,
body : JSON.stringify ( {
title : productFormDetails.name ,
category : productFormDetails.category ,
price : String ( productFormDetails . basePrice ) ,
stock : Number ( productFormDetails . initialStock ) ,
sku : productFormDetails.sku || ` PROD- ${ Date . now ( ) . toString ( ) . slice ( - 6 ) } ` ,
image : productFormDetails.primaryImage || 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=100' ,
description : productFormDetails.description ,
is_gi_tagged : productFormDetails.isGiTagged ,
additional_images : productFormDetails.additionalViews ,
video_url : productFormDetails.videoUrl ,
view_360_url : productFormDetails.view360Url ,
compare_at_price : productFormDetails.compareAtPrice ? String ( productFormDetails . compareAtPrice ) : null ,
track_inventory : productFormDetails.trackInventory ,
shipping_profile : productFormDetails.shippingProfile ,
processing_days : Number ( productFormDetails . processingDays ) ,
package_weight : Number ( productFormDetails . packageWeight )
} )
} )
. then ( res = > res . json ( ) )
. then ( ( ) = > {
apiFetch ( ` ${ CONFIG . apiBaseUrl } /api/products/ ` )
. then ( r = > r . json ( ) )
. then ( prods = > {
if ( Array . isArray ( prods ) ) setProducts ( prods ) ;
else if ( prods && Array . isArray ( prods . results ) ) setProducts ( prods . results ) ;
} ) ;
setProductWizardStep ( 0 ) ;
alert ( productFormDetails . id ? 'Product updated successfully!' : 'Product listed successfully!' ) ;
} )
. catch ( err = > alert ( err . message ) ) ;
}
} } >
{ /* STEP 1: PRODUCT INFO */ }
{ productWizardStep === 1 && (
< div >
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Product Information < / h4 >
< div className = "form-group" >
< label htmlFor = "w-name" > Product Name * < / label >
< input
id = "w-name"
type = "text"
className = "form-control"
placeholder = "e.g. Handwoven Pashmina Shawl"
value = { productFormDetails . name }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , name : e.target.value } ) }
required
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "w-category" > Category * < / label >
< select
id = "w-category"
className = "form-control"
value = { productFormDetails . category }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , category : e.target.value } ) }
>
< option value = "Textiles & Apparel" > Textiles & Apparel < / option >
< option value = "Pottery & Ceramics" > Pottery & Ceramics < / option >
< option value = "Wood Carving" > Wood Carving < / option >
< option value = "Metalcraft" > Metalcraft < / option >
< option value = "Home Decor" > Home Decor < / option >
< / select >
< / div >
< div className = "form-group" >
< label htmlFor = "w-desc" > Description * < / label >
< textarea
id = "w-desc"
className = "form-control"
rows = { 4 }
placeholder = "Describe the materials, process, and origin of your product..."
value = { productFormDetails . description }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , description : e.target.value } ) }
required
/ >
< span style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' } } > Minimum 50 words recommended < / span >
< / div >
< div style = { { border : '1px solid var(--border)' , borderRadius : '6px' , padding : '1rem' , display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginTop : '1.5rem' } } >
< div >
< strong style = { { fontSize : '0.95rem' } } > Geographical Indication ( GI ) Tag < / strong >
< p style = { { margin : 0 , fontSize : '0.85rem' , color : 'var(--text-muted)' } } > Does this product hold a certified GI tag from its region ? < / p >
< / div >
< input
type = "checkbox"
checked = { productFormDetails . isGiTagged }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , isGiTagged : e.target.checked } ) }
style = { { width : '20px' , height : '20px' , cursor : 'pointer' } }
/ >
< / div >
< div style = { { display : 'flex' , justifyContent : 'flex-end' , marginTop : '2rem' } } >
< button type = "submit" className = "btn btn-dark" > Continue to Media → < / button >
< / div >
2026-08-12 15:00:52 +00:00
< / div >
2026-08-18 06:52:31 +00:00
) }
2026-08-12 15:00:52 +00:00
2026-08-18 06:52:31 +00:00
{ /* STEP 2: MEDIA ASSETS */ }
{ productWizardStep === 2 && (
< div style = { { display : 'grid' , gridTemplateColumns : '2fr 1fr' , gap : '2rem' } } >
< div >
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Media Assets < / h4 >
< div className = "form-group" >
< label > Primary Image * < / label >
< div style = { { border : '2px dashed var(--border)' , borderRadius : '6px' , padding : '2rem' , textAlign : 'center' , backgroundColor : '#F9F6F2' } } >
{ productFormDetails . primaryImage ? (
< div style = { { position : 'relative' , display : 'inline-block' } } >
< img src = { productFormDetails . primaryImage } style = { { maxHeight : '150px' , borderRadius : '4px' } } / >
< button type = "button" onClick = { ( ) = > setProductFormDetails ( { . . . productFormDetails , primaryImage : '' } ) } style = { { position : 'absolute' , top : '-0.5rem' , right : '-0.5rem' , backgroundColor : 'var(--primary)' , color : 'white' , border : 'none' , borderRadius : '50%' , width : '20px' , height : '20px' , cursor : 'pointer' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' } } > x < / button >
< / div >
) : (
< div >
< span style = { { fontSize : '2rem' } } > 📸 < / span >
< p style = { { margin : '0.5rem 0' } } > Drag and drop your primary photo here < / p >
< button
type = "button"
className = "btn btn-outline-dark"
style = { { padding : '0.4rem 1rem' , fontSize : '0.85rem' } }
onClick = { ( ) = > setProductFormDetails ( { . . . productFormDetails , primaryImage : 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=300' } ) }
>
Browse Files
< / button >
< / div >
) }
< / div >
< / div >
< div className = "form-group" style = { { marginTop : '2rem' } } >
< label > Additional Views ( Optional ) < / label >
< div style = { { display : 'grid' , gridTemplateColumns : 'repeat(4, 1fr)' , gap : '0.75rem' } } >
{ [ 'Detail' , 'Scale' , 'Angle' , 'Packaging' ] . map ( view = > (
< div key = { view } style = { { border : '1px dashed var(--border)' , borderRadius : '4px' , height : '80px' , display : 'flex' , flexDirection : 'column' , alignItems : 'center' , justifyContent : 'center' , fontSize : '0.8rem' , color : 'var(--text-muted)' , backgroundColor : '#F9F6F2' } } >
< span > + < / span >
< span > { view } < / span >
< / div >
) ) }
< / div >
< / div >
< div className = "form-group" style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '1rem' , marginTop : '2rem' } } >
< div >
< label htmlFor = "w-video" > Video Link ( Optional ) < / label >
< input
id = "w-video"
type = "url"
className = "form-control"
placeholder = "Upload Video URL"
value = { productFormDetails . videoUrl }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , videoUrl : e.target.value } ) }
/ >
< / div >
< div >
< label htmlFor = "w-360" > Link 360 ° Asset ( Optional ) < / label >
< input
id = "w-360"
type = "url"
className = "form-control"
placeholder = "Link 360° Asset URL"
value = { productFormDetails . view360Url }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , view360Url : e.target.value } ) }
/ >
< / div >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , marginTop : '2.5rem' } } >
< button type = "button" className = "btn btn-outline-dark" onClick = { ( ) = > setProductWizardStep ( 1 ) } > Back < / button >
< button type = "submit" className = "btn btn-dark" > Continue to Pricing → < / button >
< / div >
< / div >
{ /* Media Tips sidebar */ }
< div style = { { backgroundColor : '#F9F6F2' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h5 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.1rem' , marginBottom : '1rem' } } > 💡 Artisanal Photography Tips < / h5 >
< ul style = { { paddingLeft : '1.25rem' , fontSize : '0.85rem' , color : '#4A4A4A' , lineHeight : '1.6' } } >
< li style = { { marginBottom : '0.75rem' } } > < strong > Use Natural Light < / strong > : Soft , indirect sunlight reveals true colors and prevents harsh shadows . < / li >
< li style = { { marginBottom : '0.75rem' } } > < strong > Highlight the Texture < / strong > : Include macro shots that show the weave , grain , or brushstrokes of your craft . < / li >
< li style = { { marginBottom : '0.75rem' } } > < strong > Provide Context for Scale < / strong > : Show the item in use or alongside a recognizable object to communicate size . < / li >
< li > < strong > Keep Backgrounds Clean < / strong > : Use simple , uncluttered backgrounds ( like linen or wood ) so the product stands out . < / li >
< / ul >
< / div >
2026-08-12 15:00:52 +00:00
< / div >
2026-08-18 06:52:31 +00:00
) }
2026-08-12 15:00:52 +00:00
2026-08-18 06:52:31 +00:00
{ /* STEP 3: PRICING & INVENTORY */ }
{ productWizardStep === 3 && (
< div >
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Pricing & Inventory < / h4 >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '1.5rem' , marginBottom : '2rem' } } >
< div className = "form-group" >
< label htmlFor = "w-price" > Base Price ( INR ) * < / label >
< input
id = "w-price"
type = "number"
className = "form-control"
placeholder = "₹ 0.00"
value = { productFormDetails . basePrice }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , basePrice : e.target.value } ) }
required
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "w-comp" > Compare at Price ( INR ) ( Optional ) < / label >
< input
id = "w-comp"
type = "number"
className = "form-control"
placeholder = "₹ 0.00"
value = { productFormDetails . compareAtPrice }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , compareAtPrice : e.target.value } ) }
/ >
< / div >
< / div >
< div style = { { border : '1px solid var(--border)' , borderRadius : '6px' , padding : '1rem' , display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2rem' } } >
< div >
< strong style = { { fontSize : '0.95rem' } } > Track Inventory < / strong >
< p style = { { margin : 0 , fontSize : '0.85rem' , color : 'var(--text-muted)' } } > Automatically stop selling when stock reaches zero . < / p >
< / div >
< input
type = "checkbox"
checked = { productFormDetails . trackInventory }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , trackInventory : e.target.checked } ) }
style = { { width : '20px' , height : '20px' , cursor : 'pointer' } }
/ >
< / div >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '1.5rem' } } >
< div className = "form-group" >
< label htmlFor = "w-sku" > SKU ( Stock Keeping Unit ) < / label >
< input
id = "w-sku"
type = "text"
className = "form-control"
placeholder = "e.g. BLK-MUG-001"
value = { productFormDetails . sku }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , sku : e.target.value } ) }
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "w-stock" > Initial Stock Level * < / label >
< input
id = "w-stock"
type = "number"
className = "form-control"
placeholder = "0"
value = { productFormDetails . initialStock }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , initialStock : e.target.value } ) }
required
/ >
< / div >
< / div >
2026-08-09 01:53:57 +00:00
2026-08-18 06:52:31 +00:00
< div style = { { display : 'flex' , justifyContent : 'space-between' , marginTop : '2.5rem' } } >
< button type = "button" className = "btn btn-outline-dark" onClick = { ( ) = > setProductWizardStep ( 2 ) } > Back to Media < / button >
< button type = "submit" className = "btn btn-dark" > Continue to Shipping → < / button >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
) }
2026-08-18 06:52:31 +00:00
{ /* STEP 4: SHIPPING */ }
{ productWizardStep === 4 && (
2026-08-08 07:46:17 +00:00
< div >
2026-08-18 06:52:31 +00:00
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Shipping Details < / h4 >
< div className = "form-group" >
< label htmlFor = "w-ship" > Shipping Profile * < / label >
< select
id = "w-ship"
className = "form-control"
value = { productFormDetails . shippingProfile }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , shippingProfile : e.target.value } ) }
>
< option value = "Standard Fragile" > Standard Fragile ( Glassware , Ceramics ) < / option >
< option value = "Standard Soft Goods" > Standard Soft Goods ( Textiles , Linens ) < / option >
< option value = "Heavy Goods" > Heavy Goods ( Furniture , Large Sculptures ) < / option >
< / select >
< / div >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '1.5rem' , marginTop : '1.5rem' } } >
< div className = "form-group" >
< label htmlFor = "w-proc" > Estimated Processing Time ( Days ) * < / label >
< input
id = "w-proc"
type = "number"
className = "form-control"
value = { productFormDetails . processingDays }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , processingDays : Number ( e . target . value ) } ) }
required
/ >
< / div >
< div className = "form-group" >
< label htmlFor = "w-weight" > Package Weight ( kg ) * < / label >
< input
id = "w-weight"
type = "number"
step = "0.1"
className = "form-control"
value = { productFormDetails . packageWeight }
onChange = { e = > setProductFormDetails ( { . . . productFormDetails , packageWeight : Number ( e . target . value ) } ) }
required
/ >
< / div >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , marginTop : '2.5rem' } } >
< button type = "button" className = "btn btn-outline-dark" onClick = { ( ) = > setProductWizardStep ( 3 ) } > Back < / button >
< button type = "submit" className = "btn btn-dark" > Continue to Final Review → < / button >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
) }
{ /* STEP 5: REVIEW & PUBLISH */ }
{ productWizardStep === 5 && (
2026-08-08 07:46:17 +00:00
< div >
2026-08-18 06:52:31 +00:00
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Review & Publish < / h4 >
< p style = { { color : 'var(--text-muted)' , marginBottom : '2rem' } } > Ensure all details are correct before listing your artisanal piece on the marketplace . < / p >
< div style = { { display : 'grid' , gridTemplateColumns : '2fr 1fr' , gap : '2rem' } } >
{ /* Product preview card design */ }
< div style = { { border : '1px solid var(--border)' , borderRadius : '8px' , overflow : 'hidden' , backgroundColor : '#FFFFFF' , display : 'grid' , gridTemplateColumns : '1fr 1fr' } } >
< div style = { { height : '100%' , minHeight : '240px' , backgroundColor : '#E5DFD9' } } >
< img src = { productFormDetails . primaryImage || 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=300' } style = { { width : '100%' , height : '100%' , objectFit : 'cover' } } / >
< / div >
< div style = { { padding : '1.5rem' , display : 'flex' , flexDirection : 'column' , justifyContent : 'space-between' } } >
< div >
< span style = { { fontSize : '0.75rem' , fontWeight : 600 , color : 'var(--text-muted)' , textTransform : 'uppercase' , padding : '0.25rem 0.5rem' , border : '1px solid var(--border)' , borderRadius : '4px' , display : 'inline-block' , marginBottom : '0.5rem' } } >
{ productFormDetails . isGiTagged ? 'GI Tagged' : 'Sustainable' }
< / span >
< div style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' , marginBottom : '0.25rem' } } > { productFormDetails . category } < / div >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.4rem' , margin : '0 0 0.5rem 0' } } > { productFormDetails . name || 'Untitled Craft' } < / h3 >
< p style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' , display : '-webkit-box' , WebkitLineClamp : 3 , WebkitBoxOrient : 'vertical' , overflow : 'hidden' } } > { productFormDetails . description || 'No description provided.' } < / p >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } } >
< div style = { { fontSize : '1.4rem' , fontWeight : 'bold' , color : 'var(--primary)' } } > ₹ { Number ( productFormDetails . basePrice || 0 ) . toFixed ( 2 ) } INR < / div >
< div style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' } } > SKU : { productFormDetails . sku || 'AUTO' } < / div >
< / div >
< / div >
< / div >
{ /* Summary Details lists */ }
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '1.5rem' } } >
< div style = { { backgroundColor : '#F9F6F2' , padding : '1.25rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< strong style = { { fontSize : '0.9rem' , color : '#4A4A4A' , display : 'block' , marginBottom : '0.75rem' } } > 📋 Inventory Status < / strong >
< div style = { { display : 'flex' , justifyContent : 'space-between' , fontSize : '0.85rem' , marginBottom : '0.5rem' } } >
< span > Available Stock : < / span >
< strong > { productFormDetails . initialStock } units < / strong >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , fontSize : '0.85rem' } } >
< span > Tracking status : < / span >
< strong > { productFormDetails . trackInventory ? 'Active' : 'Inactive' } < / strong >
< / div >
< / div >
< div style = { { backgroundColor : '#F9F6F2' , padding : '1.25rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< strong style = { { fontSize : '0.9rem' , color : '#4A4A4A' , display : 'block' , marginBottom : '0.75rem' } } > 🚚 Shipping details < / strong >
< div style = { { display : 'flex' , justifyContent : 'space-between' , fontSize : '0.85rem' , marginBottom : '0.5rem' } } >
< span > Profile : < / span >
< strong > { productFormDetails . shippingProfile } < / strong >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , fontSize : '0.85rem' , marginBottom : '0.5rem' } } >
< span > Processing time : < / span >
< strong > { productFormDetails . processingDays } Days < / strong >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , fontSize : '0.85rem' } } >
< span > Weight : < / span >
< strong > { productFormDetails . packageWeight } kg < / strong >
< / div >
< / div >
< / div >
< / div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , marginTop : '3rem' , borderTop : '1px solid var(--border)' , paddingTop : '1.5rem' } } >
< button type = "button" className = "btn btn-outline-dark" onClick = { ( ) = > setProductWizardStep ( 4 ) } > Back < / button >
< button type = "submit" className = "btn btn-dark" style = { { padding : '0.75rem 2rem' } } > Publish Product 📤 < / button >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
) }
2026-08-09 01:53:57 +00:00
2026-08-08 07:46:17 +00:00
< / form >
< / div >
2026-08-18 06:52:31 +00:00
) }
2026-08-08 07:46:17 +00:00
< / div >
) }
2026-08-18 06:52:31 +00:00
{ /* ORDERS TAB */ }
2026-08-08 07:46:17 +00:00
{ dashTab === 'orders' && (
< div >
2026-08-18 06:52:31 +00:00
{ ! selectedOrderDetail ? (
/* Standard List Queue */
< div >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2rem' } } >
< div >
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '2rem' , margin : 0 } } > Orders Management < / h2 >
< span style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' } } > View , track , and manage all your customer orders . < / span >
< / div >
< div style = { { display : 'flex' , gap : '0.75rem' } } >
< button className = "btn btn-outline-dark" style = { { fontSize : '0.85rem' , padding : '0.5rem 1rem' , borderRadius : '4px' } } > Export CSV < / button >
< button className = "btn btn-primary" style = { { backgroundColor : 'var(--primary)' , color : 'white' , border : 'none' , fontSize : '0.85rem' , padding : '0.5rem 1rem' , borderRadius : '4px' , fontWeight : 'bold' } } > + Create Order < / button >
< / div >
< / div >
{ /* Status Tabs row */ }
< div style = { { display : 'flex' , borderBottom : '1px solid var(--border)' , gap : '1.5rem' , marginBottom : '1.5rem' } } >
{ [ 'All Orders' , 'Pending' , 'Processing' , 'Shipped' , 'Delivered' , 'Cancelled' ] . map ( t = > {
const count = t === 'All Orders' ? orders.length : orders.filter ( o = > {
if ( t === 'Pending' ) return o . status === 'Pending Acceptance' ;
if ( t === 'Processing' ) return o . status === 'Ready to Ship' ;
return o . status === t ;
} ) . length ;
return (
< button
key = { t }
style = { {
background : 'none' ,
border : 'none' ,
borderBottom : t === 'All Orders' ? '2px solid var(--primary)' : 'none' ,
color : t === 'All Orders' ? 'var(--primary)' : 'var(--text-muted)' ,
padding : '0.5rem 0' ,
cursor : 'pointer' ,
fontWeight : t === 'All Orders' ? 'bold' : 'normal' ,
fontSize : '0.9rem'
} }
>
{ t } ( { count } )
< / button >
) ;
} ) }
< / div >
{ /* Table List Queue */ }
< div className = "dashboard-table-wrapper" style = { { border : 'none' , boxShadow : 'none' } } >
< table className = "dashboard-table" >
< thead >
< tr style = { { borderBottom : '1px solid var(--border)' } } >
< th style = { { width : '40px' } } > < input type = "checkbox" / > < / th >
< th > Order ID < / th >
< th > Date < / th >
< th > Customer < / th >
< th > Total < / th >
< th > Status < / th >
< th > Actions < / th >
< / tr >
< / thead >
< tbody >
{ orders . map ( o = > (
< tr key = { o . id } style = { { borderBottom : '1px solid #F9F6F2' } } >
< td > < input type = "checkbox" / > < / td >
< td >
< button
onClick = { ( ) = > setSelectedOrderDetail ( o ) }
style = { { background : 'none' , border : 'none' , color : 'var(--primary)' , fontWeight : 'bold' , cursor : 'pointer' , padding : 0 } }
2026-08-09 05:29:03 +00:00
>
2026-08-18 06:52:31 +00:00
# { o . id }
2026-08-09 05:29:03 +00:00
< / button >
2026-08-18 06:52:31 +00:00
< / td >
< td > { o . date } < / td >
< td style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' } } >
< div style = { { width : '28px' , height : '28px' , borderRadius : '50%' , backgroundColor : 'var(--border)' , color : '#4A4A4A' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' , fontSize : '0.75rem' , fontWeight : 'bold' } } >
{ o . customer . split ( ' ' ) . map ( ( n : string ) = > n [ 0 ] ) . join ( '' ) }
< / div >
< span > { o . customer } < / span >
< / td >
< td style = { { fontWeight : 600 } } > ₹ { Number ( o . total ) . toFixed ( 2 ) } < / td >
< td >
< span style = { {
padding : '0.25rem 0.6rem' ,
borderRadius : '20px' ,
fontSize : '0.8rem' ,
fontWeight : 600 ,
backgroundColor : o.status === 'Delivered' ? 'rgba(42, 157, 143, 0.1)' : o . status === 'Shipped' ? 'rgba(107, 26, 44, 0.05)' : 'rgba(107, 26, 44, 0.1)' ,
color : o.status === 'Delivered' ? 'var(--success)' : o . status === 'Shipped' ? '#4A4A4A' : 'var(--primary)'
} } >
{ o . status === 'Pending Acceptance' ? 'Pending' : o . status === 'Ready to Ship' ? 'Processing' : o . status }
< / span >
< / td >
< td >
< button
className = "btn btn-outline-dark"
style = { { padding : '0.3rem 0.6rem' , fontSize : '0.8rem' , borderRadius : '4px' } }
onClick = { ( ) = > setSelectedOrderDetail ( o ) }
2026-08-09 05:29:03 +00:00
>
2026-08-18 06:52:31 +00:00
👁 ️ View
2026-08-09 05:29:03 +00:00
< / button >
2026-08-18 06:52:31 +00:00
< / td >
< / tr >
) ) }
< / tbody >
< / table >
2026-08-09 05:29:03 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< / div >
) : (
/* Detailed Order View */
< div >
< button
onClick = { ( ) = > setSelectedOrderDetail ( null ) }
style = { { background : 'none' , border : 'none' , color : 'var(--primary)' , fontWeight : 'bold' , fontSize : '0.95rem' , cursor : 'pointer' , display : 'flex' , alignItems : 'center' , gap : '0.25rem' , marginBottom : '1.5rem' } }
2026-08-09 05:29:03 +00:00
>
2026-08-18 06:52:31 +00:00
← Back to Orders
2026-08-09 05:29:03 +00:00
< / button >
2026-08-18 06:52:31 +00:00
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '2rem' } } >
< div >
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '2rem' , margin : 0 } } > Order # { selectedOrderDetail . id } < / h2 >
< span style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' } } > Placed on { selectedOrderDetail . date } at 10 :45 AM < / span >
< / div >
< div style = { { display : 'flex' , gap : '0.75rem' } } >
< button className = "btn btn-outline-dark" style = { { fontSize : '0.85rem' , padding : '0.5rem 1.25rem' , borderRadius : '4px' } } onClick = { ( ) = > alert ( 'Printing shipping label...' ) } > Print Shipping Label < / button >
{ selectedOrderDetail . status === 'Pending Acceptance' ? (
< button
className = "btn btn-primary"
style = { { backgroundColor : 'var(--primary)' , color : 'white' , border : 'none' , fontSize : '0.85rem' , padding : '0.5rem 1.25rem' , borderRadius : '4px' , fontWeight : 'bold' , cursor : 'pointer' } }
onClick = { ( ) = > {
handleAcceptOrder ( selectedOrderDetail . id ) ;
setSelectedOrderDetail ( { . . . selectedOrderDetail , status : 'Ready to Ship' } ) ;
} }
>
Mark as Shipped →
< / button >
) : null }
< / div >
< / div >
2026-08-09 05:29:03 +00:00
2026-08-18 06:52:31 +00:00
< div style = { { display : 'grid' , gridTemplateColumns : '2fr 1fr' , gap : '2rem' } } >
{ /* Left Part */ }
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '2rem' } } >
{ /* Status tracker stepper */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' , borderBottom : '1px solid var(--border)' , paddingBottom : '0.75rem' } } > Order Status < / h3 >
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '1.5rem' , position : 'relative' , paddingLeft : '1.5rem' } } >
< div style = { { position : 'absolute' , left : '4px' , top : '8px' , bottom : '8px' , width : '2px' , backgroundColor : 'var(--primary)' } } > < / div >
< div style = { { position : 'relative' } } >
< span style = { { position : 'absolute' , left : '-22px' , top : '2px' , width : '10px' , height : '10px' , borderRadius : '50%' , backgroundColor : 'var(--primary)' } } > < / span >
< strong style = { { fontSize : '0.95rem' , display : 'block' } } > Order Placed < / strong >
< span style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' } } > Oct 24 , 2026 - 10 :45 AM < / span >
< / div >
< div style = { { position : 'relative' } } >
< span style = { { position : 'absolute' , left : '-22px' , top : '2px' , width : '10px' , height : '10px' , borderRadius : '50%' , backgroundColor : 'var(--primary)' } } > < / span >
< strong style = { { fontSize : '0.95rem' , display : 'block' } } > Payment Confirmed < / strong >
< span style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' } } > Oct 24 , 2026 - 10 :48 AM < / span >
< / div >
< div style = { { position : 'relative' , opacity : selectedOrderDetail.status === 'Delivered' || selectedOrderDetail . status === 'Shipped' ? 1 : 0.5 } } >
< span style = { { position : 'absolute' , left : '-22px' , top : '2px' , width : '10px' , height : '10px' , borderRadius : '50%' , backgroundColor : selectedOrderDetail.status === 'Delivered' || selectedOrderDetail . status === 'Shipped' ? 'var(--primary)' : 'var(--border)' } } > < / span >
< strong style = { { fontSize : '0.95rem' , display : 'block' } } > Processing & Transit < / strong >
< span style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' } } > Preparing items for shipment < / span >
< / div >
< / div >
< / div >
2026-08-13 04:55:49 +00:00
2026-08-18 06:52:31 +00:00
{ /* Items List */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Items Purchased < / h3 >
< div style = { { display : 'flex' , alignItems : 'center' , gap : '1rem' , borderBottom : '1px solid #F9F6F2' , paddingBottom : '1rem' } } >
< div style = { { width : '60px' , height : '60px' , borderRadius : '4px' , backgroundColor : '#E5DFD9' , overflow : 'hidden' } } >
{ products [ 0 ] ? < img src = { products [ 0 ] . image } style = { { width : '100%' , height : '100%' , objectFit : 'cover' } } / > : null }
< / div >
< div style = { { flex : 1 } } >
< h4 style = { { margin : 0 , fontSize : '0.95rem' , color : '#4A4A4A' } } > { selectedOrderDetail . item } < / h4 >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' } } > SKU : SHAWL - IND - 01 < / span >
< div style = { { marginTop : '0.25rem' } } >
< span style = { { fontSize : '0.7rem' , border : '1px solid var(--border)' , padding : '1px 4px' , borderRadius : '2px' , textTransform : 'uppercase' , fontWeight : 600 } } > GI Tagged < / span >
2026-08-13 04:55:49 +00:00
< / div >
< / div >
2026-08-18 06:52:31 +00:00
< div style = { { fontSize : '0.9rem' , color : 'var(--text-muted)' } } > QTY : { selectedOrderDetail . quantity } < / div >
< strong style = { { fontSize : '1rem' } } > ₹ { Number ( selectedOrderDetail . total ) . toFixed ( 2 ) } < / strong >
< / div >
< / div >
< / div >
2026-08-13 04:55:49 +00:00
2026-08-18 06:52:31 +00:00
{ /* Right Part (Customer & Notes) */ }
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '2rem' } } >
{ /* Customer Info */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '1rem' } } >
< strong style = { { fontSize : '0.95rem' , color : 'var(--primary)' } } > Customer < / strong >
< span > ✉ ️ < / span >
< / div >
< div style = { { display : 'flex' , alignItems : 'center' , gap : '0.75rem' , marginBottom : '1.25rem' } } >
< div style = { { width : '36px' , height : '36px' , borderRadius : '50%' , backgroundColor : 'var(--border)' , color : '#4A4A4A' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' , fontSize : '0.85rem' , fontWeight : 'bold' } } >
{ selectedOrderDetail . customer . split ( ' ' ) . map ( ( n : string ) = > n [ 0 ] ) . join ( '' ) }
2026-08-13 04:55:49 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< div >
< strong style = { { fontSize : '0.9rem' , display : 'block' } } > { selectedOrderDetail . customer } < / strong >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' } } > customer @example . com < / span >
< / div >
< / div >
< div style = { { fontSize : '0.85rem' , color : '#4A4A4A' } } >
< strong > Shipping Address : < / strong >
< p style = { { margin : '0.25rem 0 1rem' } } > 12 Weaver Lane , Kanchipuram , Tamil Nadu 631502 < / p >
< strong > Billing Address : < / strong >
< p style = { { margin : '0.25rem 0 0' } } > Same as shipping address < / p >
2026-08-13 04:55:49 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< / div >
{ /* Notes card */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h4 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.1rem' , marginBottom : '1rem' } } > Internal Notes < / h4 >
< textarea
rows = { 3 }
placeholder = "Add a private note about this order..."
className = "form-control"
value = { orderNotes }
onChange = { e = > setOrderNotes ( e . target . value ) }
style = { { marginBottom : '1rem' } }
/ >
< button
className = "btn btn-dark"
style = { { width : '100%' , fontSize : '0.85rem' , padding : '0.5rem' , borderRadius : '4px' } }
onClick = { ( ) = > { alert ( 'Note saved!' ) ; setOrderNotes ( '' ) ; } }
>
Save Note
< / button >
< / div >
2026-08-09 05:29:03 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< / div >
2026-08-09 05:29:03 +00:00
< / div >
2026-08-18 06:52:31 +00:00
) }
2026-08-09 05:29:03 +00:00
< / div >
) }
2026-08-18 06:52:31 +00:00
{ /* PAYMENTS TAB */ }
{ dashTab === 'wallet' && (
2026-08-08 07:46:17 +00:00
< div >
2026-08-18 06:52:31 +00:00
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '2rem' , marginBottom : '2rem' } } > Payments Overview < / h2 >
< div style = { { display : 'grid' , gridTemplateColumns : '2fr 1fr' , gap : '2rem' } } >
{ /* Payout metrics and withdrawal */ }
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '2rem' } } >
< div style = { { backgroundColor : '#FFFFFF' , padding : '2rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< div style = { { fontSize : '0.8rem' , fontWeight : 600 , color : 'var(--text-muted)' , textTransform : 'uppercase' , letterSpacing : '0.5px' } } > Total Earned ( All Time ) < / div >
< div style = { { fontSize : '2.5rem' , fontFamily : 'var(--heading-font-family)' , fontWeight : 'bold' , color : 'var(--primary)' , margin : '0.5rem 0' } } > ₹ 1 , 45 , 200 < / div >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '1.5rem' , borderTop : '1px solid var(--border)' , paddingTop : '1.5rem' , marginTop : '1.5rem' } } >
< div >
< span style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' } } > Pending Payout : < / span >
< div style = { { fontSize : '1.25rem' , fontWeight : 'bold' , color : '#4A4A4A' } } > ₹ 12 , 450 < / div >
< / div >
< div >
< span style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' } } > Next Payout Date : < / span >
< div style = { { fontSize : '1.25rem' , fontWeight : 'bold' , color : '#4A4A4A' } } > Oct 24 , 2026 < / div >
< / div >
< / div >
< button
className = "btn btn-primary"
style = { { width : '100%' , padding : '0.75rem' , backgroundColor : 'var(--primary)' , color : 'white' , border : 'none' , borderRadius : '4px' , fontWeight : 'bold' , marginTop : '2rem' , cursor : 'pointer' } }
onClick = { ( ) = > alert ( 'Funds withdrawal requested!' ) }
>
Withdraw Funds →
< / button >
< / div >
2026-08-08 07:46:17 +00:00
2026-08-18 06:52:31 +00:00
{ /* Transaction history list */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Transaction History < / h3 >
< div className = "dashboard-table-wrapper" style = { { border : 'none' , boxShadow : 'none' } } >
< table className = "dashboard-table" >
< thead >
< tr style = { { borderBottom : '1px solid var(--border)' } } >
< th > Date < / th >
< th > Order ID < / th >
< th > Amount < / th >
< th > Status < / th >
< / tr >
< / thead >
< tbody >
{ orders . slice ( 0 , 3 ) . map ( o = > (
< tr key = { o . id } style = { { borderBottom : '1px solid #F9F6F2' } } >
< td > { o . date } < / td >
< td > # { o . id } < / td >
< td style = { { fontWeight : 600 } } > ₹ { Number ( o . total ) . toFixed ( 2 ) } < / td >
< td > < span style = { { padding : '0.25rem 0.5rem' , borderRadius : '20px' , fontSize : '0.75rem' , fontWeight : 600 , backgroundColor : 'rgba(42, 157, 143, 0.1)' , color : 'var(--success)' } } > Completed < / span > < / td >
< / tr >
) ) }
< / tbody >
< / table >
< / div >
< / div >
< / div >
{ /* Bank Details Panel */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' , height : 'fit-content' } } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '1.5rem' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , margin : 0 } } > Verified Bank < / h3 >
< span style = { { fontSize : '1.5rem' , color : 'var(--primary)' } } > 🏦 < / span >
< / div >
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '1rem' , fontSize : '0.9rem' , color : '#4A4A4A' } } >
< div >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' } } > Bank Name < / span >
< strong style = { { display : 'block' , marginTop : '0.15rem' } } > State Bank of India < / strong >
< / div >
< div >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' } } > Account Number < / span >
< strong style = { { display : 'block' , marginTop : '0.15rem' } } > • • • • • • • • 4589 < / strong >
< / div >
< div style = { { marginTop : '0.5rem' } } >
< span style = { { padding : '0.25rem 0.5rem' , borderRadius : '4px' , fontSize : '0.75rem' , fontWeight : 600 , backgroundColor : 'rgba(42, 157, 143, 0.1)' , color : 'var(--success)' } } > ✓ Verified < / span >
< / div >
< button
style = { { background : 'none' , border : 'none' , color : 'var(--primary)' , fontWeight : 'bold' , fontSize : '0.85rem' , cursor : 'pointer' , textAlign : 'left' , marginTop : '1rem' , padding : 0 } }
onClick = { ( ) = > alert ( 'Bank details verification manager' ) }
>
Manage Account ✏ ️
< / button >
< / div >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
< / div >
) }
2026-08-18 06:52:31 +00:00
{ /* ANALYTICS TAB */ }
{ dashTab === 'analytics' && (
2026-08-08 07:46:17 +00:00
< div >
2026-08-18 06:52:31 +00:00
< h2 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '2rem' , marginBottom : '2rem' } } > Analytics Overview < / h2 >
{ /* Metric Summary row */ }
< div style = { { display : 'grid' , gridTemplateColumns : 'repeat(4, 1fr)' , gap : '1.25rem' , marginBottom : '2rem' } } >
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.25rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' , textTransform : 'uppercase' } } > Total Revenue < / span >
< h3 style = { { margin : '0.25rem 0' , fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.6rem' } } > ₹ 1 , 24 , 500 < / h3 >
< span style = { { fontSize : '0.75rem' , color : 'var(--success)' } } > ↗ + 12 % from last month < / span >
< / div >
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.25rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' , textTransform : 'uppercase' } } > Orders < / span >
< h3 style = { { margin : '0.25rem 0' , fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.6rem' } } > 342 < / h3 >
< span style = { { fontSize : '0.75rem' , color : 'var(--success)' } } > ↗ + 5 % from last month < / span >
< / div >
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.25rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' , textTransform : 'uppercase' } } > Avg . Order Value < / span >
< h3 style = { { margin : '0.25rem 0' , fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.6rem' } } > ₹ 364 < / h3 >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' } } > → Stable < / span >
< / div >
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.25rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< span style = { { fontSize : '0.75rem' , color : 'var(--text-muted)' , textTransform : 'uppercase' } } > Conversion Rate < / span >
< h3 style = { { margin : '0.25rem 0' , fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.6rem' } } > 3.2 % < / h3 >
< span style = { { fontSize : '0.75rem' , color : 'var(--success)' } } > ↗ + 0.4 % from last month < / span >
< / div >
< / div >
2026-08-09 01:53:57 +00:00
2026-08-18 06:52:31 +00:00
< div style = { { display : 'grid' , gridTemplateColumns : '2fr 1fr' , gap : '2rem' } } >
{ /* Sales over time bar chart mockup */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : '1.5rem' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , margin : 0 } } > Sales Over Time < / h3 >
< select style = { { padding : '0.25rem 0.5rem' , borderRadius : '4px' , border : '1px solid var(--border)' } } >
< option > Last 7 Days < / option >
< option > Last 30 Days < / option >
< / select >
< / div >
{ /* Simulated Bar Chart */ }
< div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'flex-end' , height : '180px' , padding : '1rem 0' } } >
{ [ { day : 'Mon' , val : 50 } , { day : 'Tue' , val : 90 } , { day : 'Wed' , val : 65 } , { day : 'Thu' , val : 120 } , { day : 'Fri' , val : 110 } , { day : 'Sat' , val : 160 } , { day : 'Sun' , val : 140 } ] . map ( bar = > (
< div key = { bar . day } style = { { display : 'flex' , flexDirection : 'column' , alignItems : 'center' , flex : 1 } } >
< div style = { { width : '70%' , height : ` ${ bar . val } px ` , backgroundColor : 'var(--primary)' , borderRadius : '2px 2px 0 0' } } > < / div >
< span style = { { fontSize : '0.8rem' , color : 'var(--text-muted)' , marginTop : '0.5rem' } } > { bar . day } < / span >
< / div >
) ) }
< / div >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
{ /* Top categories breakdown */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Top Categories < / h3 >
< div style = { { display : 'flex' , flexDirection : 'column' , gap : '1.25rem' } } >
{ [
{ name : 'Handloom Textiles' , pct : '45%' } ,
{ name : 'Pottery & Ceramics' , pct : '30%' } ,
{ name : 'Wood Carving' , pct : '15%' } ,
{ name : 'Jewelry' , pct : '10%' }
] . map ( c = > (
< div key = { c . name } >
< div style = { { display : 'flex' , justifyContent : 'space-between' , fontSize : '0.85rem' , marginBottom : '0.25rem' } } >
< span > { c . name } < / span >
< strong > { c . pct } < / strong >
< / div >
< div style = { { height : '6px' , backgroundColor : '#F9F6F2' , borderRadius : '3px' , overflow : 'hidden' } } >
< div style = { { height : '100%' , width : c.pct , backgroundColor : 'var(--primary)' } } > < / div >
< / div >
< / div >
) ) }
< / div >
2026-08-08 07:46:17 +00:00
< / div >
< / div >
2026-08-18 06:52:31 +00:00
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '2rem' , marginTop : '2rem' } } >
{ /* Customer demographics donut */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Customer Demographics < / h3 >
< div style = { { display : 'flex' , alignItems : 'center' , justifyContent : 'center' , gap : '2rem' , height : '180px' } } >
{ /* Semi circle visual placeholder */ }
< div style = { { position : 'relative' , width : '120px' , height : '60px' , border : '16px solid var(--border)' , borderBottom : 'none' , borderRadius : '60px 60px 0 0' , display : 'flex' , alignItems : 'center' , justifyContent : 'center' } } >
< div style = { { position : 'absolute' , width : '100%' , height : '100%' , border : '16px solid var(--primary)' , borderBottom : 'none' , borderRadius : '60px 60px 0 0' , left : '-16px' , top : '-16px' , clipPath : 'polygon(0 0, 80% 0, 80% 100%, 0 100%)' } } > < / div >
< strong style = { { fontSize : '1.2rem' , color : '#4A4A4A' , marginTop : '1.2rem' } } > 68 % < / strong >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
< div style = { { fontSize : '0.85rem' , color : '#4A4A4A' } } >
< div style = { { marginBottom : '0.5rem' } } > < span style = { { color : 'var(--primary)' } } > ● < / span > Domestic ( India ) < / div >
< div > < span style = { { color : 'var(--border)' } } > ● < / span > International < / div >
< / div >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
2026-08-18 06:52:31 +00:00
{ /* Top regions map graphic */ }
< div style = { { backgroundColor : '#FFFFFF' , padding : '1.5rem' , borderRadius : '8px' , border : '1px solid var(--border)' } } >
< h3 style = { { fontFamily : 'var(--heading-font-family)' , color : 'var(--primary)' , fontSize : '1.25rem' , marginBottom : '1.5rem' } } > Top Regions < / h3 >
< div style = { { position : 'relative' , height : '180px' , backgroundColor : '#F9F6F2' , borderRadius : '6px' , display : 'flex' , flexDirection : 'column' , alignItems : 'center' , justifyContent : 'center' , textAlign : 'center' , border : '1px solid var(--border)' } } >
< span style = { { fontSize : '0.85rem' , fontWeight : 600 , color : 'var(--text-muted)' } } > Where your crafts are loved most < / span >
< div style = { { display : 'flex' , gap : '1rem' , marginTop : '1rem' , fontSize : '0.8rem' , color : '#4A4A4A' } } >
< div > 📍 Bangalore < / div >
< div > 📍 Mumbai < / div >
< div > 📍 New Delhi < / div >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
< / div >
< / div >
2026-08-18 06:52:31 +00:00
2026-08-08 07:46:17 +00:00
< / 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
2026-08-18 06:00:45 +00:00
< form onSubmit = { e = > {
e . preventDefault ( ) ;
saveProfileBackend ( true )
. then ( ( ) = > alert ( 'Store configurations updated successfully!' ) )
. catch ( err = > alert ( err . message ) ) ;
} } >
< div className = "form-group" style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.75rem' } } >
< div >
< label htmlFor = "set-store" > Store Display Name * < / label >
< input
id = "set-store"
type = "text"
className = "form-control"
value = { storeName }
onChange = { e = > setStoreName ( e . target . value ) }
required
/ >
< / div >
< div >
< label htmlFor = "set-slug" > Store Slug / Custom URL * < / label >
< input
id = "set-slug"
type = "text"
className = "form-control"
value = { storeSlug }
onChange = { e = > setStoreSlug ( e . target . value . toLowerCase ( ) . replace ( /[^a-z0-9\-]/g , '' ) ) }
required
/ >
< / div >
2026-08-08 07:46:17 +00:00
< / 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
2026-08-08 07:46:17 +00:00
id = "set-logo"
2026-08-09 01:53:57 +00:00
type = "file"
accept = "image/*"
2026-08-08 07:46:17 +00:00
onChange = { handleLogoChange }
/ >
< / div >
< / div >
2026-08-18 06:00:45 +00:00
< div className = "form-group" style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.75rem' } } >
< div >
< label htmlFor = "set-email" > Support Email * < / label >
< input
id = "set-email"
type = "email"
className = "form-control"
value = { supportEmail }
onChange = { e = > setSupportEmail ( e . target . value ) }
required
/ >
< / div >
< div >
< label htmlFor = "set-phone" > Support Phone * < / label >
< input
id = "set-phone"
type = "tel"
className = "form-control"
value = { supportPhone }
onChange = { e = > setSupportPhone ( e . target . value ) }
required
/ >
< / div >
< / div >
2026-08-08 07:46:17 +00:00
< div className = "form-group" >
< label htmlFor = "set-bio" > About Your Craft / Business < / label >
2026-08-09 01:53:57 +00:00
< textarea
2026-08-08 07:46:17 +00:00
id = "set-bio"
2026-08-09 01:53:57 +00:00
className = "form-control"
rows = { 3 }
value = { businessBio }
2026-08-08 07:46:17 +00:00
onChange = { e = > setBusinessBio ( e . target . value ) }
> < / textarea >
< / div >
2026-08-18 06:00:45 +00:00
< div className = "form-group" >
< label > Product Categories < / label >
< div style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.5rem' , marginTop : '0.5rem' } } >
{ [ 'Sustainable Products' , 'Home Decor' , 'Eco-Friendly' , 'OPOD Products' , 'GI Tagged' , 'Textiles & Apparel' ] . map ( cat = > {
const isSelected = selectedCategories . includes ( cat ) ;
return (
< label key = { cat } style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' , cursor : 'pointer' , padding : '0.5rem' , border : '1px solid var(--border)' , borderRadius : '4px' } } >
< input
type = "checkbox"
checked = { isSelected }
onChange = { ( ) = > {
if ( isSelected ) {
setSelectedCategories ( selectedCategories . filter ( c = > c !== cat ) ) ;
} else {
setSelectedCategories ( [ . . . selectedCategories , cat ] ) ;
}
} }
/ >
{ cat }
< / label >
) ;
} ) }
< / div >
< / div >
2026-08-08 07:46:17 +00:00
< 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-08 07:46:17 +00:00
/ >
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
2026-08-08 07:46:17 +00:00
/ >
< / 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-08 07:46:17 +00:00
/ >
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
2026-08-08 07:46:17 +00:00
/ >
< / div >
< / div >
2026-08-18 06:00:45 +00:00
< div className = "form-group" style = { { display : 'grid' , gridTemplateColumns : '1fr 1fr' , gap : '0.75rem' } } >
< div >
< label htmlFor = "set-business-type" > Business Type < / label >
< input
id = "set-business-type"
type = "text"
className = "form-control"
value = { businessType . replace ( '_' , ' ' ) . toUpperCase ( ) }
disabled
/ >
< / div >
< div >
< label htmlFor = "set-gstin" > GSTIN Number < / label >
< input
id = "set-gstin"
type = "text"
className = "form-control"
value = { gstin }
disabled
/ >
< / div >
2026-08-08 07:46:17 +00:00
< / div >
< button type = "submit" className = "btn btn-dark" style = { { width : '100%' , marginTop : '2rem' } } >
Save Store Configurations
< / button >
< / form >
< / div >
) }
< / section >
2026-08-07 07:42:14 +00:00
< / div >
2026-08-08 07:46:17 +00:00
) }
2026-08-07 07:42:14 +00:00
2026-08-08 07:46:17 +00:00
{ /* 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-07 07:42:14 +00:00
< / >
)
}
2026-08-09 05:29:03 +00:00
2026-08-09 08:24:20 +00:00
function WelcomeTourWizard ( { onComplete } : { onComplete : ( ) = > void } ) {
2026-08-09 05:29:03 +00:00
const [ tourStep , setTourStep ] = useState ( 1 )
const steps = [
{
2026-08-09 07:11:11 +00:00
title : "Supplier Account Under Review ⏳" ,
description : ` Thank you for completing your profile! Your GSTIN, PAN, and Aadhaar card details have been submitted. Our compliance team is verifying your documents. This review is typically completed within the next 24 hours. While we verify your credentials, let's take a quick animated tour to get you familiar with your dashboard! ` ,
icon : "⏳" ,
action : "Start Guided Tour 🎬"
2026-08-09 05:29:03 +00:00
} ,
{
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 : "💼" ,
2026-08-09 07:11:11 +00:00
action : "Explore Dashboard 🚀"
2026-08-09 05:29:03 +00:00
}
]
const current = steps [ tourStep - 1 ]
return (
2026-08-09 07:11:11 +00:00
< div key = { tourStep } className = "form-card tour-card-animated" style = { { maxWidth : '640px' , margin : '2rem auto' , textAlign : 'center' , padding : '2.5rem' } } >
< div className = "tour-icon-animated" style = { { fontSize : '4.5rem' , marginBottom : '1rem' } } > { current . icon } < / div >
2026-08-09 05:29:03 +00:00
< h2 className = "form-card-title" > { current . title } < / h2 >
2026-08-09 07:11:11 +00:00
< p style = { { color : 'var(--text-muted)' , fontSize : '1.05rem' , margin : '1.5rem 0 2rem' , lineHeight : '1.6' } } >
2026-08-09 05:29:03 +00:00
{ current . description }
< / p >
< div style = { { display : 'flex' , justifyContent : 'center' , gap : '0.5rem' , marginBottom : '2rem' } } >
{ steps . map ( ( _ , idx ) = > (
< div
key = { idx }
2026-08-09 07:11:11 +00:00
className = { tourStep === idx + 1 ? 'tour-dot-active' : '' }
2026-08-09 05:29:03 +00:00
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 >
)
}