feat: add core pages including Login, Pricing, and Grow Business, and rebrand UI with new design tokens and updated footer navigation.
All checks were successful
Beta CI/CD Pipeline / build-and-test (push) Successful in 1m9s
Beta CI/CD Pipeline / deploy-beta (push) Successful in 25s

This commit is contained in:
vickytechkey 2026-09-10 18:26:36 +05:30
parent d26d5f997f
commit c2f72e20dc
13 changed files with 2352 additions and 249 deletions

View file

@ -8,7 +8,8 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Libre+Caslon+Text:ital,wght@0,400;0,700;1,400&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Libre+Caslon+Text:ital,wght@0,400;0,700;1,400&family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<script>

View file

@ -153,4 +153,96 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
expect(screen.getByText(/Available for Payout/i)).toBeInTheDocument()
expect(screen.getByText(/Transaction History/i)).toBeInTheDocument()
})
it('navigates to How It Works page from landing nav and renders 6-step journey', () => {
render(<App />)
const howItWorksBtn = screen.getAllByRole('button', { name: /^How it works$/i })[0]
fireEvent.click(howItWorksBtn)
expect(screen.getByText(/How it works — The Seller Journey/i)).toBeInTheDocument()
expect(screen.getByText(/The 6-Step Journey/i)).toBeInTheDocument()
expect(screen.getByText(/Guaranteed 7-Day Payouts/i)).toBeInTheDocument()
})
it('navigates to Pricing page and calculates artisan net payout correctly', () => {
render(<App />)
const pricingBtn = screen.getAllByRole('button', { name: /^Pricing$/i })[0]
fireEvent.click(pricingBtn)
expect(screen.getByText(/Transparent Pricing Built Solely for Maker Prosperity/i)).toBeInTheDocument()
expect(screen.getByText(/Estimate Your Net Take-Home Earnings/i)).toBeInTheDocument()
expect(screen.getByText(/Net Bank Payout/i)).toBeInTheDocument()
})
it('navigates to Grow Your Business page and renders growth initiatives', () => {
render(<App />)
const growBtn = screen.getAllByRole('button', { name: /^Grow your business$/i })[0]
fireEvent.click(growBtn)
expect(screen.getByText(/Scale Your Authentic Artisan Brand With Tradhox/i)).toBeInTheDocument()
expect(screen.getByText(/Early Maker Initiative/i)).toBeInTheDocument()
expect(screen.getByText(/Curated Artisan Showcases/i)).toBeInTheDocument()
})
it('progresses through the full 7-step onboarding wizard to Application Submitted', async () => {
render(<App />)
// Sign up to enter wizard
const getStartedBtn = screen.getByText(/^Get started$/i)
fireEvent.click(getStartedBtn)
fireEvent.change(screen.getByPlaceholderText(/Enter your email/i), { target: { value: 'artisan@tradhox.com' } })
fireEvent.change(screen.getByPlaceholderText(/9876543210/i), { target: { value: '9876543210' } })
fireEvent.change(screen.getByPlaceholderText(/Create a password/i), { target: { value: 'artisanPass123' } })
fireEvent.change(screen.getByPlaceholderText(/Repeat your password/i), { target: { value: 'artisanPass123' } })
fireEvent.click(screen.getByLabelText(/I agree to the/i))
const alertMock = vi.spyOn(window, 'alert').mockImplementation(() => {})
fireEvent.click(screen.getByRole('button', { name: /Create Account/i }))
// Now in Step 1 of Onboarding Wizard
expect(await screen.findByText(/Welcome to Tradhox/i)).toBeInTheDocument()
expect(screen.getByText(/Step 1: Account/i)).toBeInTheDocument()
// Step 1 -> Step 2
fireEvent.click(screen.getByRole('button', { name: /Save & Continue/i }))
expect(screen.getByText(/Step 2: Business & GST/i)).toBeInTheDocument()
// Step 2 -> Step 3
fireEvent.click(screen.getByRole('button', { name: /Save & Continue/i }))
expect(screen.getByText(/Step 3: Pickup Address/i)).toBeInTheDocument()
// Step 3 -> Step 4
fireEvent.click(screen.getByRole('button', { name: /Save & Continue/i }))
expect(screen.getByText(/Step 4: Bank Details/i)).toBeInTheDocument()
// Step 4 -> Step 5
fireEvent.click(screen.getByRole('button', { name: /Save & Continue/i }))
expect(screen.getByText(/Step 5: Categories/i)).toBeInTheDocument()
// Select category in Step 5
const categoryCard = screen.getByText(/Handloom & Textiles/i)
fireEvent.click(categoryCard)
// Step 5 -> Step 6
fireEvent.click(screen.getByRole('button', { name: /Save & Continue/i }))
expect(screen.getByText(/Step 6: Products/i)).toBeInTheDocument()
// Step 6 -> Step 7
fireEvent.click(screen.getByRole('button', { name: /Save & Continue/i }))
expect(screen.getByText(/Step 7: Store Profile/i)).toBeInTheDocument()
// Step 7 Submit Application -> Application Submitted confirmation screen
const submitAppBtn = screen.getByRole('button', { name: /Submit Application/i })
fireEvent.click(submitAppBtn)
expect(screen.getByText(/Application submitted!/i)).toBeInTheDocument()
expect(screen.getByText(/What happens next:/i)).toBeInTheDocument()
alertMock.mockRestore()
})
})

View file

@ -1,9 +1,11 @@
import React from 'react';
import { SellerProvider, useSeller } from './context/SellerContext';
import Header from './components/layout/Header';
import Footer from './components/layout/Footer';
import LandingPage from './components/pages/LandingPage';
import HowItWorksPage from './components/pages/HowItWorksPage';
import PricingPage from './components/pages/PricingPage';
import GrowBusinessPage from './components/pages/GrowBusinessPage';
import AboutPage from './components/pages/AboutPage';
import ContactPage from './components/pages/ContactPage';
import AuthForms from './components/pages/AuthForms';
@ -22,9 +24,12 @@ function AppRouter() {
}
return (
<div className="is-flex is-flex-direction-column" style={{ minHeight: '100vh' }}>
<div className="is-flex is-flex-direction-column" style={{ minHeight: '100vh', backgroundColor: 'var(--trad-bg)' }}>
<Header />
<main className="is-flex-grow-1">
{currentPage === 'how-it-works' && <HowItWorksPage />}
{currentPage === 'pricing' && <PricingPage />}
{currentPage === 'grow-business' && <GrowBusinessPage />}
{currentPage === 'profile-completion' && <OnboardingWizard />}
{currentPage === 'about' && <AboutPage />}
{currentPage === 'contact' && <ContactPage />}

View file

@ -1,37 +1,130 @@
import React from 'react';
import { useSeller } from '../../context/SellerContext';
export default function Footer() {
const { setCurrentPage } = useSeller();
const handleNav = (page: any) => {
setCurrentPage(page);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
return (
<footer className="footer has-background-white-bis" style={{ borderTop: '1px solid #dac0c2' }}>
<div className="container" style={{ maxWidth: '1120px' }}>
<div className="columns">
{/* Brand & Copyright */}
<div className="column is-4">
<h2 className="title is-4 has-text-primary mb-3" style={{ fontFamily: 'Libre Caslon Text, serif' }}>Tradhox</h2>
<p className="has-text-grey-dark">
© 2026 Tradhox. Honoring Human Craftsmanship.
<footer className="trad-footer py-6 px-4" style={{ backgroundColor: 'var(--trad-footer-bg)', color: '#ffffff', borderTop: '1px solid #5a1420' }}>
<div className="container is-max-widescreen">
<div className="columns is-variable is-6">
{/* Brand & Mission */}
<div className="column is-4 trad-footer-brand">
<h4 className="font-serif-trad" style={{ color: '#ffffff', fontSize: '1.65rem', fontWeight: 800, letterSpacing: '0.04em', marginBottom: '0.35rem' }}>
TRADHOX
</h4>
<p style={{ color: '#f5d5d8', fontSize: '0.75rem', textTransform: 'uppercase', letterSpacing: '0.14em', fontWeight: 700, marginBottom: '1rem' }}>
FROM MAKERS TO THE WORLD.
</p>
<p style={{ color: '#e5e2e1', fontSize: '0.9rem', lineHeight: 1.65, maxWidth: '340px' }}>
Empowering verified Indian craftsmanship and creative makers with seamless nationwide commerce, transparent weekly payouts, and cultural storytelling.
</p>
<div className="is-flex is-align-items-center mt-4" style={{ gap: '1rem' }}>
<span className="tag is-dark is-rounded" style={{ backgroundColor: '#57131e', color: '#ffdee2', fontSize: '0.75rem' }}>
<i className="fa-solid fa-shield-halved mr-1"></i> AEO &amp; GI Verified
</span>
<span className="tag is-dark is-rounded" style={{ backgroundColor: '#57131e', color: '#ffdee2', fontSize: '0.75rem' }}>
<i className="fa-solid fa-truck-fast mr-1"></i> 15,000+ Pincodes
</span>
</div>
</div>
{/* Quick Links */}
<div className="column is-2 is-offset-1">
<h5 style={{ color: '#ffffff', fontSize: '0.8rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: '1.25rem' }}>
Quick Links
</h5>
<ul style={{ listStyle: 'none', paddingLeft: 0, margin: 0 }}>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('home')}>Home</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('how-it-works')}>How it works</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('pricing')}>Pricing &amp; Fees</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('grow-business')}>Grow your business</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('signup')}>Register as Seller</a>
</li>
</ul>
</div>
{/* Seller Support */}
<div className="column is-2">
<h5 style={{ color: '#ffffff', fontSize: '0.8rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: '1.25rem' }}>
Support &amp; Trust
</h5>
<ul style={{ listStyle: 'none', paddingLeft: 0, margin: 0 }}>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('contact')}>Artisan Help Desk</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('about')}>About TRADHOX</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" href="#logistics">Logistics Guidelines</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" href="#gi-tag">GI Craft Certification</a>
</li>
<li className="mb-2">
<a className="trad-footer-link" onClick={() => handleNav('login')}>Seller Login</a>
</li>
</ul>
</div>
{/* Contact & Hours */}
<div className="column is-3">
<h5 style={{ color: '#ffffff', fontSize: '0.8rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: '1.25rem' }}>
Artisan Helpline
</h5>
<p style={{ color: '#e5e2e1', fontSize: '0.875rem', marginBottom: '0.5rem' }}>
<i className="fa-solid fa-phone mr-2" style={{ color: '#d8aa76' }}></i> 1800-TRADHOX (Toll-Free)
</p>
<p style={{ color: '#e5e2e1', fontSize: '0.875rem', marginBottom: '0.5rem' }}>
<i className="fa-solid fa-envelope mr-2" style={{ color: '#d8aa76' }}></i> sellers@tradhox.com
</p>
<p style={{ color: '#b9a5a7', fontSize: '0.75rem', marginTop: '0.75rem' }}>
Dedicated support available Mon - Sat: 9:00 AM - 7:00 PM IST
</p>
</div>
{/* Links 1 */}
<div className="column is-4">
<ul style={{ listStyle: 'none', marginLeft: 0 }}>
<li className="mb-2"><a href="#" className="has-text-grey-dark hover-text-primary" style={{ transition: 'color 0.2s' }}>Privacy Policy</a></li>
<li><a href="#" className="has-text-grey-dark hover-text-primary" style={{ transition: 'color 0.2s' }}>Terms of Service</a></li>
</ul>
</div>
{/* Links 2 */}
<div className="column is-4">
<ul style={{ listStyle: 'none', marginLeft: 0 }}>
<li className="mb-2"><a href="#" className="has-text-grey-dark hover-text-primary" style={{ transition: 'color 0.2s' }}>Sustainability Report</a></li>
<li><a href="#" className="has-text-grey-dark hover-text-primary" style={{ transition: 'color 0.2s' }}>Shipping Info</a></li>
</ul>
<hr style={{ backgroundColor: 'rgba(255,255,255,0.12)', margin: '2rem 0 1.5rem 0' }} />
<div className="is-flex is-justify-content-between is-align-items-center is-flex-wrap-wrap" style={{ gap: '1rem' }}>
<p style={{ color: '#c5b7b9', fontSize: '0.82rem', margin: 0 }}>
© 2026 TRADHOX Central. All rights reserved. Celebrating authentic heritage craft across India.
</p>
<div className="is-flex" style={{ gap: '1.5rem' }}>
<a href="#" className="trad-footer-link" style={{ fontSize: '0.82rem' }}>Privacy Policy</a>
<a href="#" className="trad-footer-link" style={{ fontSize: '0.82rem' }}>Terms of Service</a>
<a href="#" className="trad-footer-link" style={{ fontSize: '0.82rem' }}>Seller Agreement</a>
</div>
</div>
</div>
<style>{`
.hover-text-primary:hover { color: var(--bulma-primary) !important; }
.trad-footer-link {
color: #e7dcd9 !important;
text-decoration: none;
cursor: pointer;
font-size: 0.875rem;
transition: color 0.15s ease;
}
.trad-footer-link:hover {
color: #ffffff !important;
text-decoration: underline;
}
`}</style>
</footer>
);

View file

@ -2,87 +2,141 @@ import React from 'react';
import { useSeller } from '../../context/SellerContext';
export default function Header() {
const { currentPage, setCurrentPage, isMobileMenuOpen, setIsMobileMenuOpen } = useSeller();
const { currentPage, setCurrentPage, isMobileMenuOpen, setIsMobileMenuOpen, isProfileComplete } = useSeller();
const handleNav = (page: any) => {
setCurrentPage(page);
setIsMobileMenuOpen(false);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
return (
<nav className="navbar has-background-white-bis" style={{ borderBottom: '1px solid #dac0c2' }} role="navigation" aria-label="main navigation">
<div className="container" style={{ maxWidth: '1120px' }}>
<div className="navbar-brand">
<a className="navbar-item is-size-4 has-text-primary" style={{ fontFamily: 'Libre Caslon Text, serif', letterSpacing: '-0.02em', fontWeight: 700 }} onClick={() => setCurrentPage('home')}>
Tradhox
<header className="trad-header-wrapper" style={{ borderBottom: '1px solid #e7ded9', background: '#ffffff', position: 'sticky', top: 0, zIndex: 90 }}>
<div className="container is-max-widescreen px-4">
<nav className="navbar" role="navigation" aria-label="main navigation" style={{ background: 'transparent', minHeight: '4.25rem' }}>
<div className="navbar-brand is-flex is-align-items-center">
<a
className="navbar-item is-clickable is-flex is-align-items-center p-0 mr-5"
onClick={() => handleNav('home')}
style={{ textDecoration: 'none' }}
>
<span className="font-serif-trad has-text-weight-bold" style={{ fontSize: '1.65rem', color: 'var(--trad-maroon)', letterSpacing: '-0.02em' }}>
TRADHOX
</span>
<span className="tag is-rounded ml-2 is-hidden-mobile" style={{ fontSize: '0.65rem', fontWeight: 700, letterSpacing: '0.08em', backgroundColor: '#f5e8e8', color: 'var(--trad-maroon)' }}>
SELLER HUB
</span>
</a>
<a role="button" className={`navbar-burger ${isMobileMenuOpen ? 'is-active' : ''}`} aria-label="menu" aria-expanded="false" onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} style={{ color: 'var(--bulma-primary)' }}>
<a
role="button"
className={`navbar-burger ${isMobileMenuOpen ? 'is-active' : ''}`}
aria-label="menu"
aria-expanded={isMobileMenuOpen}
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
style={{ color: 'var(--trad-maroon)', marginLeft: 'auto' }}
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div className={`navbar-menu ${isMobileMenuOpen ? 'is-active' : ''}`} style={{ backgroundColor: 'transparent' }}>
<div className="navbar-start" style={{ margin: '0 auto', gap: '2rem' }}>
<div className={`navbar-menu ${isMobileMenuOpen ? 'is-active' : ''}`} style={{ backgroundColor: isMobileMenuOpen ? '#ffffff' : 'transparent', boxShadow: isMobileMenuOpen ? '0 8px 16px rgba(0,0,0,0.1)' : 'none' }}>
<div className="navbar-start is-flex-grow-1 is-justify-content-center" style={{ gap: '1.75rem' }}>
<a
className="navbar-item has-text-weight-medium custom-nav-link"
onClick={() => setCurrentPage('home')}
style={{ color: currentPage === 'home' ? 'var(--bulma-primary)' : '#5f5e5b' }}
className={`navbar-item is-size-6 has-text-weight-semibold trad-nav-item ${currentPage === 'home' ? 'is-active-nav' : ''}`}
onClick={() => handleNav('home')}
>
Shop
</a>
<a
className="navbar-item has-text-weight-medium custom-nav-link"
onClick={() => setCurrentPage('about')}
style={{ color: currentPage === 'about' ? 'var(--bulma-primary)' : '#5f5e5b' }}
>
Our Story
Home
</a>
<a
className="navbar-item has-text-weight-medium custom-nav-link"
onClick={() => setCurrentPage('contact')}
style={{ color: currentPage === 'contact' ? 'var(--bulma-primary)' : '#5f5e5b' }}
className={`navbar-item is-size-6 has-text-weight-semibold trad-nav-item ${currentPage === 'how-it-works' ? 'is-active-nav' : ''}`}
onClick={() => handleNav('how-it-works')}
>
How it works
</a>
<a
className={`navbar-item is-size-6 has-text-weight-semibold trad-nav-item ${currentPage === 'pricing' ? 'is-active-nav' : ''}`}
onClick={() => handleNav('pricing')}
>
Pricing
</a>
<a
className={`navbar-item is-size-6 has-text-weight-semibold trad-nav-item ${currentPage === 'grow-business' ? 'is-active-nav' : ''}`}
onClick={() => handleNav('grow-business')}
>
Grow your business
</a>
<a
className={`navbar-item is-size-6 has-text-weight-semibold trad-nav-item ${currentPage === 'contact' ? 'is-active-nav' : ''}`}
onClick={() => handleNav('contact')}
>
Contact Us
</a>
</div>
<div className="navbar-end">
<div className="navbar-end is-flex is-align-items-center">
<div className="navbar-item">
<div className="buttons">
<a className="button is-ghost has-text-weight-semibold" style={{ color: '#5f5e5b' }} onClick={() => setCurrentPage('login')}>
<div className="buttons is-align-items-center mb-0">
{isProfileComplete ? (
<button
className="button is-rounded is-small has-text-weight-bold"
onClick={() => handleNav('dashboard')}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff' }}
>
<i className="fa-solid fa-gauge-high mr-2"></i> Seller Dashboard
</button>
) : (
<>
<a
className="button is-ghost has-text-weight-bold mr-2"
onClick={() => handleNav('login')}
style={{ color: 'var(--trad-text-main)', textDecoration: 'none' }}
>
Login
</a>
<a className="button is-primary is-outlined has-text-weight-semibold" onClick={() => setCurrentPage('signup')}>
Get started
<a
className="button is-rounded has-text-weight-bold px-5"
onClick={() => handleNav('signup')}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', border: 'none', transition: 'all 0.2s' }}
>
Start Selling
</a>
</>
)}
</div>
</div>
</div>
</div>
</nav>
</div>
<style>{`
.custom-nav-link {
.trad-nav-item {
color: #4b4746 !important;
transition: color 0.15s ease;
background: transparent !important;
}
.trad-nav-item:hover, .trad-nav-item.is-active-nav {
color: var(--trad-maroon) !important;
}
@media screen and (min-width: 1024px) {
.trad-nav-item {
position: relative;
background-color: transparent !important;
padding: 0.5rem 0.25rem;
}
.custom-nav-link:hover {
color: var(--bulma-primary) !important;
}
.custom-nav-link::after {
.trad-nav-item.is-active-nav::after {
content: '';
position: absolute;
bottom: 0px;
left: 50%;
transform: translateX(-50%);
width: 0;
left: 0;
right: 0;
height: 2px;
background-color: var(--bulma-primary);
transition: width 0.3s ease;
background-color: var(--trad-maroon);
}
.custom-nav-link:hover::after {
width: 80%;
}
`}</style>
</nav>
</header>
);
}

View file

@ -0,0 +1,188 @@
import React from 'react';
import { useSeller } from '../../context/SellerContext';
export default function GrowBusinessPage() {
const { setCurrentPage } = useSeller();
const initiatives = [
{
title: 'Curated Artisan Showcases',
tag: 'Marketing',
icon: 'fa-bullhorn',
desc: 'Get featured on festive curation pages (Diwali, Pongal, Handloom Day), thematic catalogs, and heritage story reels distributed to verified buyers.'
},
{
title: 'Craft Analytics & Trends',
tag: 'Intelligence',
icon: 'fa-chart-line',
desc: 'Understand which designs, materials, and colors are trending across metro cities. Optimize your inventory with data-backed demand forecasts.'
},
{
title: '1-on-1 Cluster Mentorship',
tag: 'Support',
icon: 'fa-user-group',
desc: 'Work directly with dedicated craft managers who assist with professional product photography tips, SKU descriptions, and GI certifications.'
},
{
title: 'Safe Storage & Fast Dispatch',
tag: 'Logistics',
icon: 'fa-warehouse',
desc: 'Store inventory in secure regional facilities or dispatch straight from your workshop. Enjoy seamless doorstep pickups covering 15,000+ pin codes.'
},
{
title: 'Global Export Facilitation',
tag: 'Export Ready',
icon: 'fa-earth-americas',
desc: 'Expand your reach to international art lovers and Indian diaspora with simplified customs paperwork and discounted international air freight.'
},
{
title: 'Direct Patron Relationships',
tag: 'Community',
icon: 'fa-comments',
desc: 'Connect your personal story with connoisseurs. Share weaving traditions, generational techniques, and receive custom bespoke craft commissions.'
}
];
return (
<div className="grow-business-page has-background-white-ter" style={{ minHeight: '100vh' }}>
{/* Hero */}
<section className="py-6 px-4" style={{ background: 'linear-gradient(180deg, #f7eeee 0%, #fcf9f8 100%)', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-desktop has-text-centered py-5">
<span className="tag is-rounded is-small mb-3" style={{ backgroundColor: '#f2dede', color: 'var(--trad-maroon)', fontWeight: 700, letterSpacing: '0.08em' }}>
ACCELERATOR &amp; SCALE PROGRAMMES
</span>
<h1 className="title is-1 font-serif-trad mb-4" style={{ color: 'var(--trad-maroon)', fontSize: '2.75rem' }}>
Scale Your Authentic Artisan Brand With Tradhox
</h1>
<p className="subtitle is-5 has-text-grey-dark mx-auto mb-6" style={{ maxWidth: '750px', lineHeight: 1.6 }}>
Unlock tailored marketing campaigns, comprehensive analytics, dedicated maker account mentorship, and streamlined logistics designed specifically for heritage craftsmen, GI-tagged clusters, and regional creators.
</p>
<div className="is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap mb-5" style={{ gap: '1.25rem' }}>
<span className="tag is-light is-rounded has-text-weight-bold" style={{ color: 'var(--trad-maroon)', backgroundColor: '#faeef0' }}>
Zero listing fee · Guaranteed direct payouts
</span>
<span className="tag is-light is-rounded has-text-weight-bold" style={{ color: 'var(--trad-navy)', backgroundColor: '#edf0fb' }}>
Dedicated Maker Mentorship
</span>
<span className="tag is-light is-rounded has-text-weight-bold" style={{ color: 'var(--trad-teal)', backgroundColor: '#edf7f5' }}>
GI &amp; Cluster Certification Support
</span>
</div>
<button
className="button is-large is-rounded has-text-weight-bold px-6"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', border: 'none', boxShadow: '0 8px 24px rgba(103,27,38,0.2)' }}
>
Start Growing Today <i className="fa-solid fa-arrow-right ml-3"></i>
</button>
</div>
</section>
{/* Impact Stats Banner */}
<section className="py-5 px-4" style={{ backgroundColor: '#ffffff', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-widescreen">
<div className="columns is-mobile is-multiline has-text-centered">
<div className="column is-3-desktop is-6-mobile">
<p className="title is-2 mb-1" style={{ color: 'var(--trad-maroon)', fontWeight: 800 }}>Day 1</p>
<p className="has-text-grey is-size-6">Direct Storefront Setup</p>
</div>
<div className="column is-3-desktop is-6-mobile">
<p className="title is-2 mb-1" style={{ color: 'var(--trad-teal)', fontWeight: 800 }}>1-on-1</p>
<p className="has-text-grey is-size-6">Dedicated Craft Mentorship</p>
</div>
<div className="column is-3-desktop is-6-mobile">
<p className="title is-2 mb-1" style={{ color: 'var(--trad-navy)', fontWeight: 800 }}>100%</p>
<p className="has-text-grey is-size-6">Direct Artisan Bank Payouts</p>
</div>
<div className="column is-3-desktop is-6-mobile">
<p className="title is-2 mb-1" style={{ color: 'var(--trad-bronze)', fontWeight: 800 }}>0</p>
<p className="has-text-grey is-size-6">Upfront Setup &amp; Joining Cost</p>
</div>
</div>
</div>
</section>
{/* Growth Initiatives Grid */}
<section className="py-6 px-4">
<div className="container is-max-widescreen">
<div className="has-text-centered mb-6">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', letterSpacing: '0.1em', fontSize: '0.85rem' }}>
Specialized Initiatives
</span>
<h2 className="title is-2 font-serif-trad mt-2" style={{ color: 'var(--trad-maroon)' }}>
Every Advantage Built Into Your Storefront
</h2>
<p className="has-text-grey-dark">
From catalog digitisation to global shipping, we provide the infrastructure so authentic traditions thrive.
</p>
</div>
<div className="columns is-multiline">
{initiatives.map((item, i) => (
<div key={i} className="column is-4-desktop is-6-tablet">
<div className="box p-5 is-flex is-flex-direction-column" style={{ height: '100%', borderRadius: '12px', border: '1px solid #e7ded9' }}>
<div className="is-flex is-justify-content-between is-align-items-center mb-3">
<div style={{ width: '40px', height: '40px', borderRadius: '8px', backgroundColor: '#faeef0', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--trad-maroon)', fontSize: '1.15rem' }}>
<i className={`fa-solid ${item.icon}`}></i>
</div>
<span className="tag is-light is-rounded has-text-weight-semibold" style={{ color: 'var(--trad-navy)', backgroundColor: '#edf0fb', fontSize: '0.75rem' }}>
{item.tag}
</span>
</div>
<h3 className="title is-5 mb-2" style={{ color: '#2b2523' }}>
{item.title}
</h3>
<p className="has-text-grey-dark is-size-6" style={{ lineHeight: 1.6 }}>
{item.desc}
</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* Artisan Spotlight Quote */}
<section className="py-6 px-4" style={{ backgroundColor: '#ffffff', borderTop: '1px solid #e7ded9', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-desktop">
<div className="box p-6" style={{ backgroundColor: '#fdf9f7', border: '1px solid #dacfc9', borderRadius: '16px', position: 'relative' }}>
<div className="is-flex is-align-items-center mb-4">
<span className="tag is-rounded is-medium has-text-weight-bold" style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff' }}>
EARLY MAKER INITIATIVE
</span>
</div>
<p className="font-serif-trad is-size-4 mb-4" style={{ color: '#2b2523', fontStyle: 'italic', lineHeight: 1.6 }}>
Be among the first heritage artisan clusters and master makers to launch on Tradhox. Get priority catalog placement, professional storytelling assistance, and zero upfront platform charges from day one.
</p>
<p className="has-text-weight-bold" style={{ color: 'var(--trad-bronze)' }}>
Tradhox Maker Onboarding &amp; Cultural Council
</p>
</div>
</div>
</section>
{/* Bottom CTA */}
<section className="py-6 px-4">
<div className="container is-max-desktop">
<div className="box has-text-centered py-6 px-4" style={{ background: 'linear-gradient(135deg, var(--trad-maroon) 0%, var(--trad-burgundy) 100%)', color: '#ffffff', borderRadius: '16px' }}>
<h2 className="title is-2 font-serif-trad mb-3" style={{ color: '#ffffff' }}>
Take your craft brand to patrons across India and beyond
</h2>
<p className="subtitle is-5 mb-5" style={{ color: '#fad4d8', maxWidth: '600px', margin: '0 auto' }}>
Simple registration. Dedicated onboarding support. Zero upfront fees.
</p>
<button
className="button is-rounded is-large has-text-weight-bold px-6"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ backgroundColor: '#ffffff', color: 'var(--trad-maroon)', border: 'none' }}
>
Register as a Maker
</button>
</div>
</div>
</section>
</div>
);
}

View file

@ -0,0 +1,252 @@
import React, { useState } from 'react';
import { useSeller } from '../../context/SellerContext';
export default function HowItWorksPage() {
const { setCurrentPage } = useSeller();
const [activeFaq, setActiveFaq] = useState<number | null>(null);
const steps = [
{
num: 1,
title: 'Create Your Profile',
badge: 'Step 1: Setup',
icon: 'fa-user-check',
desc: 'Register with your mobile number, PAN, and GSTIN (or artisan registration). Set up your unique craft store URL and artisan bio in minutes.'
},
{
num: 2,
title: 'List Your Craft Catalog',
badge: 'Step 2: Showcase',
icon: 'fa-boxes-stacked',
desc: 'Upload high-resolution images, highlight GI tags, artisan technique details, and fair-pricing tiers with zero upfront listing fees.'
},
{
num: 3,
title: 'Receive Customer Orders',
badge: 'Step 3: Alert',
icon: 'fa-bell',
desc: 'Get immediate notifications via SMS, WhatsApp, and your dashboard whenever a customer falls in love with your creation.'
},
{
num: 4,
title: 'Craft Safe Packaging',
badge: 'Step 4: Protect',
icon: 'fa-box-open',
desc: 'Pack your authentic creations securely using standard or eco-friendly materials. Generate and stick the pre-printed courier dispatch label.'
},
{
num: 5,
title: 'Doorstep Courier Pickup',
badge: 'Step 5: Transit',
icon: 'fa-truck-ramp-box',
desc: 'Our certified logistics partners collect the parcels directly from your workshop or home across 15,000+ pin codes in India.'
},
{
num: 6,
title: 'Guaranteed 7-Day Payouts',
badge: 'Step 6: Payout',
icon: 'fa-indian-rupee-sign',
desc: 'Receive 100% direct bank deposits for every delivered order within 7 days. Full transparency, zero hidden commission deductions.'
}
];
const faqs = [
{
q: 'Do I need a GST number to sell on Tradhox?',
a: 'If you sell within the state (intra-state) under current government threshold exemptions for small artisans and handicraft makers, enrollment IDs may qualify. For pan-India shipping, a GST number is recommended and our team assists with quick registration.'
},
{
q: 'How does pickup work from remote artisan villages?',
a: 'We partner with Indias leading logistics providers reaching over 15,000 pin codes. If your village has courier accessibility, pickups are scheduled at your doorstep.'
},
{
q: 'When and how do I receive money for my sales?',
a: 'Payouts are transferred directly into your verified bank account via NEFT/IMPS within 7 business days after customer delivery is confirmed.'
},
{
q: 'Are there any registration or listing fees?',
a: 'None! Tradhox has zero registration fees and zero listing fees. You only pay a transparent marketplace fee when your product actually sells.'
}
];
return (
<div className="how-it-works-page has-background-white-ter" style={{ minHeight: '100vh' }}>
{/* Hero Section */}
<section className="py-6 px-4" style={{ background: 'linear-gradient(180deg, #f7eeee 0%, #fcf9f8 100%)', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-desktop has-text-centered py-5">
<span className="tag is-rounded is-small mb-3" style={{ backgroundColor: '#f2dede', color: 'var(--trad-maroon)', fontWeight: 700, letterSpacing: '0.08em' }}>
EMPOWERING INDIAN ARTISANS
</span>
<h1 className="title is-1 font-serif-trad mb-4" style={{ color: 'var(--trad-maroon)', fontSize: '2.75rem' }}>
How it works The Seller Journey
</h1>
<p className="subtitle is-5 has-text-grey-dark mx-auto mb-6" style={{ maxWidth: '720px', lineHeight: 1.6 }}>
A transparent, step-by-step pathway empowering verified Indian craftsmen and creative masters to showcase heritage artistry, fulfill orders effortlessly, and reach patrons nationwide.
</p>
<div className="is-flex is-justify-content-center is-align-items-center is-flex-wrap-wrap mb-5" style={{ gap: '1.5rem' }}>
<span className="has-text-weight-semibold" style={{ color: '#4a4543' }}>
<i className="fa-solid fa-circle-check mr-2" style={{ color: 'var(--trad-teal)' }}></i> Zero Listing Fees
</span>
<span className="has-text-grey-light"></span>
<span className="has-text-weight-semibold" style={{ color: '#4a4543' }}>
<i className="fa-solid fa-circle-check mr-2" style={{ color: 'var(--trad-teal)' }}></i> 7-Day Direct Payouts
</span>
<span className="has-text-grey-light"></span>
<span className="has-text-weight-semibold" style={{ color: '#4a4543' }}>
<i className="fa-solid fa-circle-check mr-2" style={{ color: 'var(--trad-teal)' }}></i> 15,000+ Pin Codes Pickup
</span>
</div>
<div>
<button
className="button is-large is-rounded has-text-weight-bold px-6"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', border: 'none', boxShadow: '0 8px 24px rgba(103,27,38,0.2)' }}
>
Register as a seller <i className="fa-solid fa-arrow-right ml-3"></i>
</button>
</div>
</div>
</section>
{/* 6-Step Journey Grid */}
<section className="py-6 px-4">
<div className="container is-max-widescreen">
<div className="has-text-centered mb-6">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', letterSpacing: '0.1em', fontSize: '0.85rem' }}>
The 6-Step Journey
</span>
<h2 className="title is-2 font-serif-trad mt-2" style={{ color: 'var(--trad-maroon)' }}>
From artisan workshop to nationwide doorstep delivery
</h2>
</div>
<div className="columns is-multiline">
{steps.map((step) => (
<div key={step.num} className="column is-4-desktop is-6-tablet">
<div className="box p-5 is-flex is-flex-direction-column" style={{ height: '100%', borderRadius: '12px', border: '1px solid #e7ded9', boxShadow: '0 4px 14px rgba(0,0,0,0.03)' }}>
<div className="is-flex is-justify-content-between is-align-items-center mb-4">
<span className="trad-badge-step is-active" style={{ fontSize: '1.1rem' }}>
{step.num}
</span>
<span className="tag is-light is-rounded has-text-weight-semibold" style={{ color: 'var(--trad-maroon)', backgroundColor: '#faeef0' }}>
{step.badge}
</span>
</div>
<h3 className="title is-4 mb-3" style={{ color: '#2b2523' }}>
{step.title}
</h3>
<p className="has-text-grey-dark is-size-6" style={{ lineHeight: 1.6 }}>
{step.desc}
</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* Logistics & Support Highlight */}
<section className="py-6 px-4" style={{ backgroundColor: '#ffffff', borderTop: '1px solid #e7ded9', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-desktop">
<div className="columns is-vcentered">
<div className="column is-6">
<span className="tag is-warning is-light is-rounded has-text-weight-bold mb-3">
ARTISAN FIRST LOGISTICS
</span>
<h2 className="title is-2 font-serif-trad mb-4" style={{ color: 'var(--trad-maroon)' }}>
We handle the heavy lifting, so you can focus on your craft.
</h2>
<p className="has-text-grey-dark mb-4" style={{ lineHeight: 1.7 }}>
Traditional handlooms and handicraft items require careful transit. Tradhox works closely with certified regional partners who know how to protect fragile clay, delicate silk, and intricate woodwork.
</p>
<ul style={{ listStyle: 'none', paddingLeft: 0 }}>
<li className="mb-3 is-flex is-align-items-center">
<i className="fa-solid fa-circle-check mr-3" style={{ color: 'var(--trad-teal)' }}></i>
<span>Automated tracking links sent to your patrons</span>
</li>
<li className="mb-3 is-flex is-align-items-center">
<i className="fa-solid fa-circle-check mr-3" style={{ color: 'var(--trad-teal)' }}></i>
<span>Zero fines for delayed dispatches due to seasonal weather</span>
</li>
<li className="mb-3 is-flex is-align-items-center">
<i className="fa-solid fa-circle-check mr-3" style={{ color: 'var(--trad-teal)' }}></i>
<span>Free doorstep return inspection to protect maker goods</span>
</li>
</ul>
</div>
<div className="column is-6">
<div className="box p-5" style={{ backgroundColor: '#fdf9f7', border: '1px solid #dacfc9', borderRadius: '12px' }}>
<h4 className="title is-4 mb-4" style={{ color: 'var(--trad-navy)' }}>
<i className="fa-solid fa-hand-holding-heart mr-2" style={{ color: 'var(--trad-maroon)' }}></i>
Maker Support Pledge
</h4>
<p className="is-size-6 mb-4 has-text-grey-dark">
Need help taking catalog photos or writing your story? Our regional field coordinators visit artisan clusters across Rajasthan, Bengal, Tamil Nadu, and UP to help you digitize.
</p>
<div className="notification is-light p-3" style={{ backgroundColor: '#ffffff', border: '1px solid #e7ded9' }}>
<p className="is-size-7 has-text-weight-semibold" style={{ color: 'var(--trad-maroon)' }}>
<i className="fa-solid fa-phone mr-1"></i> Dedicated Maker Helpline: 1800-TRADHOX
</p>
</div>
</div>
</div>
</div>
</div>
</section>
{/* FAQ Section */}
<section className="py-6 px-4">
<div className="container is-max-desktop">
<div className="has-text-centered mb-6">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', letterSpacing: '0.1em', fontSize: '0.85rem' }}>
Got Questions?
</span>
<h2 className="title is-2 font-serif-trad mt-2" style={{ color: 'var(--trad-maroon)' }}>
Frequently Asked Questions
</h2>
</div>
<div className="faq-list">
{faqs.map((faq, i) => (
<div key={i} className="box mb-4 p-5" style={{ border: '1px solid #e7ded9', borderRadius: '8px' }}>
<div
className="is-flex is-justify-content-between is-align-items-center is-clickable"
onClick={() => setActiveFaq(activeFaq === i ? null : i)}
>
<h4 className="title is-5 mb-0" style={{ color: '#2b2523' }}>
{faq.q}
</h4>
<i className={`fa-solid ${activeFaq === i ? 'fa-chevron-up' : 'fa-chevron-down'}`} style={{ color: 'var(--trad-maroon)' }}></i>
</div>
{activeFaq === i && (
<p className="mt-4 has-text-grey-dark is-size-6" style={{ lineHeight: 1.6 }}>
{faq.a}
</p>
)}
</div>
))}
</div>
{/* CTA Banner */}
<div className="box has-text-centered py-6 px-4 mt-6" style={{ background: 'linear-gradient(135deg, var(--trad-maroon) 0%, var(--trad-burgundy) 100%)', color: '#ffffff', borderRadius: '16px' }}>
<h2 className="title is-2 font-serif-trad mb-3" style={{ color: '#ffffff' }}>
Ready to introduce your craft to the world?
</h2>
<p className="subtitle is-5 mb-5" style={{ color: '#fad4d8', maxWidth: '600px', margin: '0 auto' }}>
Join thousands of Indian artisans and heritage makers expanding their livelihood through Tradhox.
</p>
<button
className="button is-rounded is-large has-text-weight-bold px-6"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ backgroundColor: '#ffffff', color: 'var(--trad-maroon)', border: 'none' }}
>
Start Selling Today
</button>
</div>
</div>
</section>
</div>
);
}

View file

@ -421,9 +421,27 @@ export default function LandingPage() {
{/* Desktop Navigation Links & Primary CTA */}
<div className="flex items-center gap-8">
<nav className="hidden lg:flex items-center space-x-8 text-sm font-medium text-slate-700">
<a className="hover:text-brand-maroon transition-colors" href="#how-it-works">How it works</a>
<a className="hover:text-brand-maroon transition-colors" href="#pricing">Pricing</a>
<a className="hover:text-brand-maroon transition-colors" href="#why-sell">Grow your business</a>
<button
className="hover:text-brand-maroon transition-colors text-slate-700 font-medium cursor-pointer"
onClick={() => { setCurrentPage('how-it-works'); window.scrollTo(0, 0); }}
type="button"
>
How it works
</button>
<button
className="hover:text-brand-maroon transition-colors text-slate-700 font-medium cursor-pointer"
onClick={() => { setCurrentPage('pricing'); window.scrollTo(0, 0); }}
type="button"
>
Pricing
</button>
<button
className="hover:text-brand-maroon transition-colors text-slate-700 font-medium cursor-pointer"
onClick={() => { setCurrentPage('grow-business'); window.scrollTo(0, 0); }}
type="button"
>
Grow your business
</button>
<a className="hover:text-brand-maroon transition-colors" href="#categories">Resources</a>
<button
className="hover:text-brand-maroon transition-colors text-slate-700 font-medium cursor-pointer"
@ -956,16 +974,34 @@ export default function LandingPage() {
{/* Column 2: Quick Links */}
<div className="flex flex-col space-y-2.5">
<h4 className="font-bold text-white text-xs uppercase tracking-wider mb-1">Quick links</h4>
<a className="hover:text-amber-300 transition-colors text-xs sm:text-sm text-stone-200" href="#how-it-works">How it works</a>
<a className="hover:text-amber-300 transition-colors text-xs sm:text-sm text-stone-200" href="#pricing">Pricing</a>
<button
className="text-left hover:text-amber-300 transition-colors text-xs sm:text-sm text-stone-200 cursor-pointer"
onClick={() => { setCurrentPage('how-it-works'); window.scrollTo(0, 0); }}
type="button"
>
How it works
</button>
<button
className="text-left hover:text-amber-300 transition-colors text-xs sm:text-sm text-stone-200 cursor-pointer"
onClick={() => { setCurrentPage('pricing'); window.scrollTo(0, 0); }}
type="button"
>
Pricing
</button>
<button
className="text-left hover:text-amber-300 transition-colors text-xs sm:text-sm font-semibold text-amber-300 cursor-pointer"
onClick={() => openModal('register')}
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
type="button"
>
Register
</button>
<a className="hover:text-amber-300 transition-colors text-xs sm:text-sm text-stone-200" href="#why-sell">Grow your business</a>
<button
className="text-left hover:text-amber-300 transition-colors text-xs sm:text-sm text-stone-200 cursor-pointer"
onClick={() => { setCurrentPage('grow-business'); window.scrollTo(0, 0); }}
type="button"
>
Grow your business
</button>
</div>
{/* Column 3: Company */}

View file

@ -0,0 +1,296 @@
import React, { useState } from 'react';
import { useSeller } from '../../context/SellerContext';
export default function LoginPage() {
const {
email, setEmail,
password, setPassword,
phone, setPhone,
handleLoginSubmit,
showLoginPass, setShowLoginPass,
setCurrentPage,
} = useSeller();
const [activeTab, setActiveTab] = useState<'email' | 'otp'>('email');
const [otpSent, setOtpSent] = useState(false);
const [enteredOtp, setEnteredOtp] = useState('');
const [rememberMe, setRememberMe] = useState(true);
const handleSendOtp = () => {
if (!phone || phone.length < 10) {
alert('Please enter a valid 10-digit mobile number');
return;
}
setOtpSent(true);
alert(`OTP 123456 sent to +91 ${phone}`);
};
const handleOtpLogin = (e: React.FormEvent) => {
e.preventDefault();
if (!enteredOtp) {
alert('Please enter the OTP');
return;
}
// Simulate login
handleLoginSubmit(e);
};
return (
<div className="seller-login-page py-6 px-4" style={{ minHeight: 'calc(100vh - 120px)', backgroundColor: 'var(--trad-bg)', display: 'flex', alignItems: 'center' }}>
<div className="container is-max-desktop">
<div className="box p-0 overflow-hidden" style={{ borderRadius: '16px', border: '1px solid #e7ded9', boxShadow: '0 8px 30px rgba(103,27,38,0.08)' }}>
<div className="columns is-gapless mb-0">
{/* Left Column: Artisan Branding Panel */}
<div className="column is-5 is-hidden-touch p-6 is-flex is-flex-direction-column is-justify-content-between" style={{ background: 'linear-gradient(135deg, var(--trad-maroon) 0%, var(--trad-burgundy) 100%)', color: '#ffffff' }}>
<div>
<span className="tag is-rounded is-small mb-4" style={{ backgroundColor: 'rgba(255,255,255,0.15)', color: '#ffffff', fontWeight: 700, letterSpacing: '0.08em' }}>
SELLER HUB
</span>
<h2 className="title is-2 font-serif-trad mb-4" style={{ color: '#ffffff', lineHeight: 1.3 }}>
Beginning our journey to connect authentic Indian artisans with the world.
</h2>
<p className="subtitle is-6 mb-6" style={{ color: '#fed7db', lineHeight: 1.6 }}>
Direct access to manage orders, inventory, weekly settlements, and cultural storytelling from one verified portal.
</p>
<div className="value-props mt-4">
<div className="is-flex is-align-items-center mb-4">
<div style={{ width: '28px', height: '28px', borderRadius: '50%', backgroundColor: 'rgba(255,255,255,0.2)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: '12px' }}>
<i className="fa-solid fa-check" style={{ color: '#ffffff', fontSize: '0.8rem' }}></i>
</div>
<span className="is-size-6 has-text-weight-medium">Zero registration &amp; zero listing fees</span>
</div>
<div className="is-flex is-align-items-center mb-4">
<div style={{ width: '28px', height: '28px', borderRadius: '50%', backgroundColor: 'rgba(255,255,255,0.2)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: '12px' }}>
<i className="fa-solid fa-check" style={{ color: '#ffffff', fontSize: '0.8rem' }}></i>
</div>
<span className="is-size-6 has-text-weight-medium">100% direct bank payouts on schedule</span>
</div>
<div className="is-flex is-align-items-center mb-4">
<div style={{ width: '28px', height: '28px', borderRadius: '50%', backgroundColor: 'rgba(255,255,255,0.2)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: '12px' }}>
<i className="fa-solid fa-check" style={{ color: '#ffffff', fontSize: '0.8rem' }}></i>
</div>
<span className="is-size-6 has-text-weight-medium">Pan-India delivery covering 15,000+ pin codes</span>
</div>
</div>
</div>
<div className="mt-6 pt-4" style={{ borderTop: '1px solid rgba(255,255,255,0.15)' }}>
<p className="is-size-7" style={{ color: 'rgba(255,255,255,0.7)' }}>
Protected by 256-bit SSL encryption &amp; AEO certification standards.
</p>
</div>
</div>
{/* Right Column: Login Forms */}
<div className="column is-7 p-6 has-background-white is-flex is-flex-direction-column is-justify-content-center">
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', letterSpacing: '0.1em', fontSize: '0.75rem' }}>
Seller ID Portal
</span>
<h1 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Welcome back, Maker
</h1>
<p className="has-text-grey is-size-6">
Access your dashboard, manage orders, and grow your authentic craft brand.
</p>
</div>
{/* Login Method Tabs */}
<div className="tabs is-boxed mb-5">
<ul style={{ borderBottomColor: '#e7ded9' }}>
<li className={activeTab === 'email' ? 'is-active' : ''}>
<a onClick={() => setActiveTab('email')} className="has-text-weight-semibold">
<i className="fa-solid fa-envelope mr-2"></i> Email &amp; Password
</a>
</li>
<li className={activeTab === 'otp' ? 'is-active' : ''}>
<a onClick={() => setActiveTab('otp')} className="has-text-weight-semibold">
<i className="fa-solid fa-mobile-screen mr-2"></i> Mobile OTP Login
</a>
</li>
</ul>
</div>
{/* Tab 1: Email & Password Form */}
{activeTab === 'email' ? (
<form onSubmit={handleLoginSubmit}>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey" htmlFor="seller-email">
Registered Email Address
</label>
<div className="control has-icons-left">
<input
id="seller-email"
type="text"
className="input"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
<span className="icon is-left has-text-grey">
<i className="fa-solid fa-envelope"></i>
</span>
</div>
</div>
<div className="field mb-4">
<div className="is-flex is-justify-content-between is-align-items-center mb-1">
<label className="label is-size-7 is-uppercase has-text-grey mb-0" htmlFor="seller-pass">
Password
</label>
<a href="#" className="is-size-7 has-text-weight-semibold" style={{ color: 'var(--trad-maroon)', textDecoration: 'none' }}>
Forgot password?
</a>
</div>
<div className="control has-icons-left has-icons-right">
<input
id="seller-pass"
type={showLoginPass ? 'text' : 'password'}
className="input"
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
<span className="icon is-left has-text-grey">
<i className="fa-solid fa-lock"></i>
</span>
<span
className="icon is-right is-clickable"
onClick={() => setShowLoginPass(!showLoginPass)}
style={{ pointerEvents: 'all' }}
>
<i className={`fa-solid ${showLoginPass ? 'fa-eye-slash' : 'fa-eye'}`}></i>
</span>
</div>
</div>
<div className="field mb-5">
<div className="control">
<label className="checkbox is-size-7 has-text-grey is-flex is-align-items-center">
<input
type="checkbox"
checked={rememberMe}
onChange={(e) => setRememberMe(e.target.checked)}
className="mr-2"
style={{ accentColor: 'var(--trad-maroon)' }}
/>
Remember this device for 30 days
</label>
</div>
</div>
<button
type="submit"
className="button is-fullwidth has-text-weight-bold mb-4"
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', borderRadius: '8px', padding: '0.75rem', height: 'auto' }}
>
Sign In
</button>
</form>
) : (
/* Tab 2: Mobile OTP Form */
<form onSubmit={handleOtpLogin}>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">
Registered Mobile Number
</label>
<div className="field has-addons">
<p className="control">
<a className="button is-static" style={{ borderColor: '#e7ded9', borderRadius: '8px 0 0 8px' }}>
<span className="has-text-weight-bold mr-1">IN</span> +91
</a>
</p>
<p className="control is-expanded">
<input
type="tel"
className="input"
placeholder="e.g. 9876543210"
maxLength={10}
value={phone}
onChange={(e) => setPhone(e.target.value)}
style={{ borderColor: '#e7ded9' }}
/>
</p>
<p className="control">
<button
type="button"
className="button has-text-weight-semibold"
onClick={handleSendOtp}
style={{ backgroundColor: '#faeef0', color: 'var(--trad-maroon)', borderColor: '#e7ded9', borderRadius: '0 8px 8px 0' }}
>
{otpSent ? 'Resend OTP' : 'Get OTP'}
</button>
</p>
</div>
<p className="help has-text-grey">A 6-digit verification code will be sent via SMS.</p>
</div>
{otpSent && (
<div className="field mb-5">
<label className="label is-size-7 is-uppercase has-text-grey">
Enter 6-digit OTP
</label>
<div className="control has-icons-left">
<input
type="text"
className="input"
placeholder="123456"
maxLength={6}
value={enteredOtp}
onChange={(e) => setEnteredOtp(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
<span className="icon is-left has-text-grey">
<i className="fa-solid fa-key"></i>
</span>
</div>
</div>
)}
<button
type="submit"
className="button is-fullwidth has-text-weight-bold mb-4"
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', borderRadius: '8px', padding: '0.75rem', height: 'auto' }}
>
Log In to Seller Hub
</button>
</form>
)}
<div className="has-text-centered mt-4 pt-4" style={{ borderTop: '1px solid #e7ded9' }}>
<p className="is-size-6 has-text-grey">
Don't have a seller account yet?{' '}
<a
className="has-text-weight-bold is-clickable"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ color: 'var(--trad-maroon)' }}
>
Register as a seller
</a>
</p>
</div>
{/* Trust badges footer */}
<div className="is-flex is-justify-content-center is-align-items-center mt-5 pt-3" style={{ gap: '1.25rem' }}>
<span className="is-size-7 has-text-grey">
<i className="fa-solid fa-lock mr-1" style={{ color: 'var(--trad-teal)' }}></i> SSL Bank Encryption
</span>
<span className="is-size-7 has-text-grey"></span>
<span className="is-size-7 has-text-grey">
<i className="fa-solid fa-certificate mr-1" style={{ color: 'var(--trad-bronze)' }}></i> GI Verified Artisans
</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

View file

@ -1,15 +1,16 @@
import React from 'react';
import React, { useState } from 'react';
import { useSeller } from '../../context/SellerContext';
const CRAFT_CATEGORIES = [
'Apparel',
'Home Decor',
'Jewelry',
'Textiles',
'Pottery & Ceramics',
'Woodwork',
'Art & Collectibles',
'Bath & Beauty',
const CRAFT_CATEGORIES_DATA = [
{ id: 'textiles', title: 'Handloom & Textiles', desc: 'Chanderi, Banarasi, Ikat, Pashmina, Jamdani', icon: 'fa-shirt', isGi: true },
{ id: 'pottery', title: 'Pottery & Ceramics', desc: 'Khurja, Blue Pottery, Terracotta, Black Pottery', icon: 'fa-jar', isGi: true },
{ id: 'woodwork', title: 'Woodwork & Carving', desc: 'Saharanpur carving, Walnut wood, Sandalwood', icon: 'fa-tree', isGi: false },
{ id: 'metal', title: 'Metal Craft & Dhokra', desc: 'Lost-wax casting, Bell metal, Bidriware, Brass', icon: 'fa-hammer', isGi: true },
{ id: 'paintings', title: 'Traditional Art & Paintings', desc: 'Madhubani, Tanjore, Warli, Pattachitra, Gond', icon: 'fa-palette', isGi: true },
{ id: 'jewelry', title: 'Heritage Jewelry', desc: 'Kundan, Meenakari, Silver Filigree, Dokra beads', icon: 'fa-gem', isGi: false },
{ id: 'leather', title: 'Leather & Juti', desc: 'Kolhapuri chappals, Shantiniketan embossed craft', icon: 'fa-shoe-prints', isGi: true },
{ id: 'fiber', title: 'Natural Fiber & Basketry', desc: 'Jute, Bamboo, Cane, Sabai grass, Moonj', icon: 'fa-basket-shopping', isGi: false },
{ id: 'stone', title: 'Stone Craft & Inlay', desc: 'Marble inlay, Soapstone, Sandstone sculpture', icon: 'fa-monument', isGi: true },
];
export default function OnboardingWizard() {
@ -19,147 +20,866 @@ export default function OnboardingWizard() {
storeSlug, setStoreSlug,
supportEmail, setSupportEmail,
supportPhone, setSupportPhone,
selectedCategories, setSelectedCategories
selectedCategories, setSelectedCategories,
storeName, setStoreName,
businessBio, setBusinessBio,
address, setAddress,
gstin, setGstin,
isGstinVerified, setIsGstinVerified,
email, setEmail,
phone, setPhone,
onboardingStep, setOnboardingStep,
bankDetails, setBankDetails,
pickupAddress, setPickupAddress,
initialProduct, setInitialProduct,
applicationId,
setCurrentPage,
setIsProfileComplete
} = useSeller();
const handleCategoryToggle = (category: string) => {
if (selectedCategories.includes(category)) {
setSelectedCategories(selectedCategories.filter((c: string) => c !== category));
const [localStep, setLocalStep] = useState<number>(onboardingStep || 1);
const [isSubmitted, setIsSubmitted] = useState(false);
const [gstLoading, setGstLoading] = useState(false);
const [pincodeLoading, setPincodeLoading] = useState(false);
const [pincodeVerified, setPincodeVerified] = useState(false);
const stepLabels = [
{ num: 1, label: 'Account' },
{ num: 2, label: 'Business & GST' },
{ num: 3, label: 'Pickup Address' },
{ num: 4, label: 'Bank Details' },
{ num: 5, label: 'Categories' },
{ num: 6, label: 'First Product' },
{ num: 7, label: 'Store Profile' },
];
const handleCategoryToggle = (categoryTitle: string) => {
if (selectedCategories.includes(categoryTitle)) {
setSelectedCategories(selectedCategories.filter((c: string) => c !== categoryTitle));
} else {
setSelectedCategories([...selectedCategories, category]);
setSelectedCategories([...selectedCategories, categoryTitle]);
}
};
const handleVerifyGst = () => {
if (!gstin || gstin.length < 15) {
alert('Please enter a valid 15-character GSTIN');
return;
}
setGstLoading(true);
setTimeout(() => {
setGstLoading(false);
setIsGstinVerified(true);
alert('GSTIN Verified Successfully: Active Taxpayer');
}, 600);
};
const handleCheckPincode = () => {
if (!pickupAddress.pincode || pickupAddress.pincode.length !== 6) {
alert('Please enter a valid 6-digit PIN code');
return;
}
setPincodeLoading(true);
setTimeout(() => {
setPincodeLoading(false);
setPincodeVerified(true);
alert(`PIN Code ${pickupAddress.pincode} is serviceable for doorstep artisan pickup!`);
}, 500);
};
const goToStep = (step: number) => {
setLocalStep(step);
if (setOnboardingStep) setOnboardingStep(step);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
const handleNext = (e?: React.FormEvent) => {
if (e) e.preventDefault();
if (localStep < 7) {
goToStep(localStep + 1);
} else {
// Final submission
if (handleProfileSubmit) {
handleProfileSubmit(e);
}
setIsSubmitted(true);
window.scrollTo({ top: 0, behavior: 'smooth' });
}
};
const handlePrev = () => {
if (localStep > 1) {
goToStep(localStep - 1);
}
};
// If application is submitted, display Screen 12: Application Submitted
if (isSubmitted) {
return (
<section className="has-background-white" style={{ minHeight: 'calc(100vh - 4rem)' }}>
<div className="container is-max-desktop py-6">
<h1 className="title is-2 has-text-dark mb-4" style={{ fontFamily: 'Libre Caslon Text, serif' }}>
Welcome to Tradhox
<section className="py-6 px-4" style={{ minHeight: '80vh', backgroundColor: 'var(--trad-bg)' }}>
<div className="container is-max-desktop">
<div className="box p-6 has-text-centered" style={{ borderRadius: '16px', border: '1px solid #e7ded9', boxShadow: '0 8px 30px rgba(0,0,0,0.05)', backgroundColor: '#ffffff' }}>
<div className="mb-4" style={{ width: '72px', height: '72px', borderRadius: '50%', backgroundColor: '#e6f4ea', color: 'var(--trad-teal)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: '2rem' }}>
<i className="fa-solid fa-circle-check"></i>
</div>
<span className="tag is-success is-light is-rounded has-text-weight-bold mb-3" style={{ fontSize: '0.85rem' }}>
APPLICATION UNDER REVIEW
</span>
<h1 className="title is-2 font-serif-trad mb-2" style={{ color: 'var(--trad-maroon)' }}>
Application submitted!
</h1>
<p className="subtitle is-5 has-text-grey-dark mb-6">
Let's get to know your business. Tell us about what you do so we can help you reach the right audience.
<p className="subtitle is-5 has-text-grey-dark mb-4">
Thank you for registering your workshop on TRADHOX Central.
</p>
<form onSubmit={handleProfileSubmit} className="box p-5" style={{ border: '1px solid #d7c3b0', boxShadow: '0 4px 20px rgba(107,26,44,0.05)' }}>
<div className="notification is-light p-4 mx-auto mb-5" style={{ maxWidth: '480px', backgroundColor: '#fdf9f7', border: '1px solid #dacfc9', borderRadius: '10px' }}>
<p className="is-size-7 has-text-weight-bold has-text-grey-dark is-uppercase">Application Reference Number</p>
<p className="title is-4 has-text-weight-bold mb-0" style={{ color: 'var(--trad-maroon)', letterSpacing: '0.05em' }}>
{applicationId || 'TRD-849201'}
</p>
</div>
<div className="field mb-5">
<label className="label has-text-dark">Business Type</label>
<div className="control">
<label className="radio mr-4">
<input
type="radio"
name="businessType"
value="registered_company"
checked={businessType === 'registered_company'}
onChange={(e) => setBusinessType(e.target.value as any)}
className="mr-2"
/>
Registered Company
</label>
<label className="radio mr-4">
<input
type="radio"
name="businessType"
value="self_help_group"
checked={businessType === 'self_help_group'}
onChange={(e) => setBusinessType(e.target.value as any)}
className="mr-2"
/>
Self Help Group
</label>
<label className="radio">
<input
type="radio"
name="businessType"
value="individual_maker"
checked={businessType === 'individual_maker'}
onChange={(e) => setBusinessType(e.target.value as any)}
className="mr-2"
/>
Individual Maker
</label>
<div className="has-text-left mx-auto mb-6" style={{ maxWidth: '560px' }}>
<h4 className="title is-5 mb-3 has-text-grey-dark">What happens next:</h4>
<ul style={{ listStyle: 'none', paddingLeft: 0 }}>
<li className="mb-3 is-flex is-align-items-start">
<span className="trad-badge-step is-active mr-3" style={{ width: '24px', height: '24px', fontSize: '0.75rem', minWidth: '24px' }}>1</span>
<span className="is-size-6 has-text-grey-dark">
<strong>Cluster Document Verification:</strong> Our verification team will review your GSTIN/artisan certificates within 24 to 48 business hours.
</span>
</li>
<li className="mb-3 is-flex is-align-items-start">
<span className="trad-badge-step is-active mr-3" style={{ width: '24px', height: '24px', fontSize: '0.75rem', minWidth: '24px' }}>2</span>
<span className="is-size-6 has-text-grey-dark">
<strong>Dedicated Onboarding Call:</strong> A regional craft manager will get in touch to assist with professional catalog photography and story listing.
</span>
</li>
<li className="mb-3 is-flex is-align-items-start">
<span className="trad-badge-step is-active mr-3" style={{ width: '24px', height: '24px', fontSize: '0.75rem', minWidth: '24px' }}>3</span>
<span className="is-size-6 has-text-grey-dark">
<strong>Doorstep Pickup Activation:</strong> Your registered pickup address will be verified for courier test dispatches.
</span>
</li>
</ul>
</div>
<div className="buttons is-centered">
<button
className="button is-medium has-text-weight-bold px-6"
onClick={() => {
setIsProfileComplete(true);
setCurrentPage('dashboard');
}}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', borderRadius: '8px' }}
>
Go to Seller Dashboard <i className="fa-solid fa-arrow-right ml-2"></i>
</button>
<button
className="button is-medium is-outlined has-text-weight-semibold px-5"
onClick={() => setCurrentPage('contact')}
style={{ borderColor: 'var(--trad-maroon)', color: 'var(--trad-maroon)', borderRadius: '8px' }}
>
Artisan Support
</button>
</div>
</div>
</div>
</section>
);
}
return (
<section className="onboarding-wizard-section py-6 px-4" style={{ minHeight: 'calc(100vh - 120px)', backgroundColor: 'var(--trad-bg)' }}>
<div className="container is-max-widescreen">
{/* Welcome Header */}
<div className="has-text-centered mb-5">
<span className="tag is-rounded is-small mb-2" style={{ backgroundColor: '#faeef0', color: 'var(--trad-maroon)', fontWeight: 700, letterSpacing: '0.08em' }}>
STEP {localStep} OF 7 · SELLER ONBOARDING
</span>
<h1 className="title is-2 font-serif-trad mb-2" style={{ color: 'var(--trad-maroon)' }}>
Welcome to Tradhox
</h1>
<p className="subtitle is-6 has-text-grey-dark mx-auto" style={{ maxWidth: '640px' }}>
Complete your artisan verification in 7 easy steps to begin showcasing authentic Indian craftsmanship.
</p>
</div>
{/* Stepper Progress Bar */}
<div className="box p-4 mb-6" style={{ borderRadius: '12px', border: '1px solid #e7ded9', backgroundColor: '#ffffff', overflowX: 'auto' }}>
<div className="is-flex is-justify-content-between is-align-items-center" style={{ minWidth: '680px', position: 'relative' }}>
{stepLabels.map((s) => {
const isCompleted = s.num < localStep;
const isActive = s.num === localStep;
return (
<div
key={s.num}
className="is-flex is-flex-direction-column is-align-items-center is-clickable"
onClick={() => goToStep(s.num)}
style={{ zIndex: 2, flex: 1 }}
>
<div
className={`trad-badge-step mb-1 ${isActive ? 'is-active' : isCompleted ? 'is-completed' : 'is-pending'}`}
style={{ transition: 'all 0.2s ease' }}
>
{isCompleted ? <i className="fa-solid fa-check" style={{ fontSize: '0.8rem' }}></i> : s.num}
</div>
<span
className="is-size-7 has-text-weight-semibold has-text-centered"
style={{ color: isActive ? 'var(--trad-maroon)' : isCompleted ? 'var(--trad-teal)' : '#7a706b' }}
>
{s.label}
</span>
</div>
);
})}
</div>
</div>
<div className="field mb-5">
<label className="label has-text-dark">Store URL Slug</label>
<div className="control">
<input
className="input"
type="text"
placeholder="e.g. my-artisan-store"
value={storeSlug}
onChange={(e) => setStoreSlug(e.target.value)}
required
/>
</div>
<p className="help">This will be your unique Tradhox web address (e.g., tradhox.com/store/your-slug).</p>
{/* Main Step Form Container */}
<div className="box p-6 mx-auto" style={{ maxWidth: '840px', borderRadius: '16px', border: '1px solid #e7ded9', boxShadow: '0 4px 20px rgba(103,27,38,0.05)', backgroundColor: '#ffffff' }}>
{/* STEP 1: Account & Verification */}
{localStep === 1 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 1: Account
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Create your seller account
</h2>
<p className="has-text-grey is-size-6">
Verify your primary contact credentials for order alerts and two-factor authentication.
</p>
</div>
<div className="columns mb-5">
<div className="column is-half">
<div className="field">
<label className="label has-text-dark">Support Email</label>
<div className="control">
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Registered Email Address</label>
<div className="control has-icons-left">
<input
className="input"
type="email"
placeholder="support@example.com"
value={supportEmail}
onChange={(e) => setSupportEmail(e.target.value)}
required
/>
</div>
</div>
</div>
<div className="column is-half">
<div className="field">
<label className="label has-text-dark">Support Phone</label>
<div className="control">
<input
className="input"
type="tel"
placeholder="+91 XXXXX XXXXX"
value={supportPhone}
onChange={(e) => setSupportPhone(e.target.value)}
required
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<span className="icon is-left has-text-grey">
<i className="fa-solid fa-envelope"></i>
</span>
</div>
</div>
<div className="field mb-6">
<label className="label has-text-dark">Categories</label>
<p className="help mb-3">Select the categories that best describe your crafts.</p>
<div className="columns is-multiline">
{CRAFT_CATEGORIES.map(category => (
<div key={category} className="column is-4 pb-2 pt-2">
<label className="checkbox">
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Primary Phone Number</label>
<div className="control has-icons-left">
<input
type="checkbox"
className="mr-2"
checked={selectedCategories.includes(category)}
onChange={() => handleCategoryToggle(category)}
type="tel"
className="input"
placeholder="e.g. 9876543210"
value={phone}
onChange={(e) => setPhone(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
{category}
</label>
<span className="icon is-left has-text-grey">
<i className="fa-solid fa-phone"></i>
</span>
</div>
</div>
<div className="notification is-light p-3 mb-4" style={{ backgroundColor: '#fdf9f7', border: '1px solid #dacfc9', borderRadius: '8px' }}>
<p className="is-size-7 has-text-grey-dark">
<i className="fa-solid fa-shield mr-1" style={{ color: 'var(--trad-teal)' }}></i>
Two-factor authentication and dispatch OTPs will be delivered to this verified phone.
</p>
</div>
</div>
)}
{/* STEP 2: Business & GST Details */}
{localStep === 2 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 2: Business &amp; GST
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Business &amp; GST Details
</h2>
<p className="has-text-grey is-size-6">
Tell us about your craft business entity and tax classification.
</p>
</div>
<div className="field mb-5">
<label className="label is-size-7 is-uppercase has-text-grey mb-3">Select Entity Type</label>
<div className="columns is-multiline">
{[
{ val: 'individual_maker', title: 'Artisan / Individual Maker', desc: 'Direct craftsman or independent workshop' },
{ val: 'registered_company', title: 'Registered Business', desc: 'Proprietorship, Partnership, or Pvt Ltd' },
{ val: 'self_help_group', title: 'Self-Help Group (SHG) / NGO', desc: 'Artisan cooperative or weaver society' }
].map((ent) => (
<div key={ent.val} className="column is-4">
<div
className={`box p-4 trad-card-interactive ${businessType === ent.val ? 'is-selected' : ''}`}
onClick={() => setBusinessType(ent.val as any)}
style={{ height: '100%', borderRadius: '10px' }}
>
<p className="has-text-weight-bold mb-1" style={{ fontSize: '0.9rem', color: businessType === ent.val ? 'var(--trad-maroon)' : '#2b2523' }}>
{ent.title}
</p>
<p className="has-text-grey is-size-7">{ent.desc}</p>
</div>
</div>
))}
</div>
</div>
<div className="field mt-5">
<div className="control has-text-right">
<button type="submit" className="button is-primary is-medium is-rounded">
<span>Complete Profile</span>
<span className="icon is-small ml-2">
<span className="material-symbols-outlined">arrow_forward</span>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Goods and Services Tax Identification (GSTIN)</label>
<div className="field has-addons">
<p className="control is-expanded">
<input
type="text"
className="input is-uppercase"
placeholder="e.g. 29AAAAA1111A1Z1"
value={gstin}
maxLength={15}
onChange={(e) => setGstin(e.target.value.toUpperCase())}
style={{ borderColor: '#e7ded9', borderRadius: '8px 0 0 8px' }}
/>
</p>
<p className="control">
<button
type="button"
className={`button has-text-weight-bold ${gstLoading ? 'is-loading' : ''}`}
onClick={handleVerifyGst}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', borderRadius: '0 8px 8px 0' }}
>
Verify GSTIN
</button>
</p>
</div>
{isGstinVerified && (
<p className="help has-text-success has-text-weight-semibold">
<i className="fa-solid fa-circle-check mr-1"></i> GSTIN verified: Active taxpayer
</p>
)}
</div>
</div>
)}
{/* STEP 3: Pickup Address */}
{localStep === 3 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 3: Pickup Address
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Where should we collect your craft orders?
</h2>
<p className="has-text-grey is-size-6">
Provide the workshop or studio address where couriers can collect packed consignments.
</p>
</div>
<div className="columns is-multiline">
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Building / Workshop Name</label>
<input
type="text"
className="input"
placeholder="e.g. Handloom Weaving Center"
value={pickupAddress.buildingName}
onChange={(e) => setPickupAddress({ ...pickupAddress, buildingName: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Street Address</label>
<input
type="text"
className="input"
placeholder="123 Handloom Lane"
value={address.street}
onChange={(e) => {
setAddress({ ...address, street: e.target.value });
setPickupAddress({ ...pickupAddress, street: e.target.value });
}}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-4">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">PIN Code</label>
<div className="field has-addons">
<p className="control is-expanded">
<input
type="text"
className="input"
maxLength={6}
placeholder="560001"
value={address.pincode}
onChange={(e) => {
setAddress({ ...address, pincode: e.target.value });
setPickupAddress({ ...pickupAddress, pincode: e.target.value });
}}
style={{ borderColor: '#e7ded9', borderRadius: '8px 0 0 8px' }}
/>
</p>
<p className="control">
<button
type="button"
className={`button has-text-weight-bold ${pincodeLoading ? 'is-loading' : ''}`}
onClick={handleCheckPincode}
style={{ backgroundColor: '#faeef0', color: 'var(--trad-maroon)', borderColor: '#e7ded9', borderRadius: '0 8px 8px 0' }}
>
Check
</button>
</p>
</div>
</div>
</div>
<div className="column is-4">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">City</label>
<input
type="text"
className="input"
placeholder="Textile Town"
value={address.city}
onChange={(e) => {
setAddress({ ...address, city: e.target.value });
setPickupAddress({ ...pickupAddress, city: e.target.value });
}}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-4">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">State</label>
<input
type="text"
className="input"
placeholder="Karnataka"
value={address.state}
onChange={(e) => {
setAddress({ ...address, state: e.target.value });
setPickupAddress({ ...pickupAddress, state: e.target.value });
}}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
</div>
{pincodeVerified && (
<div className="notification is-success is-light p-3 mt-2" style={{ borderRadius: '8px' }}>
<p className="is-size-7 has-text-weight-bold">
<i className="fa-solid fa-truck-fast mr-2"></i>
Fast doorstep pickup is active in your pincode area.
</p>
</div>
)}
</div>
)}
{/* STEP 4: Bank Details */}
{localStep === 4 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 4: Bank Details
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Direct Payouts to Your Bank Account
</h2>
<p className="has-text-grey is-size-6">
Earnings are settled weekly directly via automated NEFT/IMPS.
</p>
</div>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Account Holder Legal Name</label>
<input
type="text"
className="input"
placeholder="As printed on bank passbook / cheque"
value={bankDetails.accountHolderName}
onChange={(e) => setBankDetails({ ...bankDetails, accountHolderName: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
<div className="columns is-multiline">
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Bank Account Number</label>
<input
type="password"
className="input"
placeholder="Enter account number"
value={bankDetails.accountNumber}
onChange={(e) => setBankDetails({ ...bankDetails, accountNumber: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Confirm Account Number</label>
<input
type="text"
className="input"
placeholder="Re-enter account number"
value={bankDetails.confirmAccountNumber}
onChange={(e) => setBankDetails({ ...bankDetails, confirmAccountNumber: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">IFSC Code</label>
<input
type="text"
className="input is-uppercase"
placeholder="e.g. SBIN0001234"
maxLength={11}
value={bankDetails.ifscCode}
onChange={(e) => setBankDetails({ ...bankDetails, ifscCode: e.target.value.toUpperCase() })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Account Type</label>
<div className="select is-fullwidth">
<select
value={bankDetails.accountType}
onChange={(e) => setBankDetails({ ...bankDetails, accountType: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
>
<option value="Current">Current Account</option>
<option value="Savings">Savings Account</option>
</select>
</div>
</div>
</div>
</div>
<div className="notification is-light p-3 mt-3" style={{ backgroundColor: '#fdf9f7', border: '1px solid #dacfc9', borderRadius: '8px' }}>
<p className="is-size-7 has-text-grey-dark">
<i className="fa-solid fa-lock mr-2" style={{ color: 'var(--trad-teal)' }}></i>
Bank data is encrypted with 256-bit bank-grade TLS encryption.
</p>
</div>
</div>
)}
{/* STEP 5: Categories */}
{localStep === 5 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 5: Categories
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Select Your Craft Categories
</h2>
<p className="has-text-grey is-size-6">
Choose all categories that apply to your workshop creations.
</p>
</div>
<div className="columns is-multiline">
{CRAFT_CATEGORIES_DATA.map((cat) => {
const isSelected = selectedCategories.includes(cat.title);
return (
<div key={cat.id} className="column is-6">
<div
className={`box p-4 trad-card-interactive ${isSelected ? 'is-selected' : ''}`}
onClick={() => handleCategoryToggle(cat.title)}
style={{ height: '100%', borderRadius: '12px', position: 'relative' }}
>
<div className="is-flex is-justify-content-between is-align-items-start mb-2">
<div style={{ width: '38px', height: '38px', borderRadius: '8px', backgroundColor: isSelected ? 'var(--trad-maroon)' : '#faeef0', color: isSelected ? '#ffffff' : 'var(--trad-maroon)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '1.1rem' }}>
<i className={`fa-solid ${cat.icon}`}></i>
</div>
{cat.isGi && (
<span className="tag is-rounded is-small has-text-weight-bold" style={{ backgroundColor: '#eef8f5', color: 'var(--trad-teal)' }}>
GI Certified
</span>
)}
</div>
<h4 className="title is-6 mb-1" style={{ color: '#2b2523' }}>{cat.title}</h4>
<p className="has-text-grey is-size-7">{cat.desc}</p>
</div>
</div>
);
})}
</div>
<div className="notification is-light p-3 mt-4" style={{ backgroundColor: '#ffffff', border: '1px solid #e7ded9', borderRadius: '8px' }}>
<p className="is-size-7 has-text-grey">
<strong>Selected:</strong> {selectedCategories.length > 0 ? selectedCategories.join(', ') : 'None selected yet'}
</p>
</div>
</div>
)}
{/* STEP 6: Products */}
{localStep === 6 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 6: Products
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
List Your First Masterpiece
</h2>
<p className="has-text-grey is-size-6">
Showcase a sample product so our curation team can review craft authenticity.
</p>
</div>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Product Title</label>
<input
type="text"
className="input"
placeholder="e.g. Handwoven Chanderi Silk Saree with Zari Border"
value={initialProduct.title}
onChange={(e) => setInitialProduct({ ...initialProduct, title: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
<div className="columns is-multiline">
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Craft Category</label>
<div className="select is-fullwidth">
<select
value={initialProduct.category}
onChange={(e) => setInitialProduct({ ...initialProduct, category: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
>
<option value="Handloom & Textiles">Handloom &amp; Textiles</option>
<option value="Pottery & Ceramics">Pottery &amp; Ceramics</option>
<option value="Woodwork & Carving">Woodwork &amp; Carving</option>
<option value="Metal Craft & Dhokra">Metal Craft &amp; Dhokra</option>
<option value="Traditional Paintings">Traditional Paintings</option>
<option value="Heritage Jewelry">Heritage Jewelry</option>
</select>
</div>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Selling Price ()</label>
<div className="control has-icons-left">
<input
type="number"
className="input"
placeholder="2450"
value={initialProduct.price}
onChange={(e) => setInitialProduct({ ...initialProduct, price: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
<span className="icon is-left has-text-weight-bold" style={{ color: 'var(--trad-maroon)' }}></span>
</div>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Available Stock Quantity</label>
<input
type="number"
className="input"
placeholder="10"
value={initialProduct.stock}
onChange={(e) => setInitialProduct({ ...initialProduct, stock: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">SKU / Item Code (Optional)</label>
<input
type="text"
className="input"
placeholder="e.g. CHN-SLK-01"
value={initialProduct.sku}
onChange={(e) => setInitialProduct({ ...initialProduct, sku: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
</div>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Artisan Description &amp; Technique</label>
<textarea
className="textarea"
rows={3}
placeholder="Describe the weaving technique, generational motifs, natural dyes, or materials used..."
value={initialProduct.description}
onChange={(e) => setInitialProduct({ ...initialProduct, description: e.target.value })}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
)}
{/* STEP 7: Store Profile */}
{localStep === 7 && (
<div>
<div className="mb-5">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', fontSize: '0.75rem', letterSpacing: '0.1em' }}>
Step 7: Store Profile
</span>
<h2 className="title is-3 font-serif-trad mt-1 mb-2" style={{ color: 'var(--trad-maroon)' }}>
Create Your Artisan Storefront
</h2>
<p className="has-text-grey is-size-6">
Build your brand identity and showcase your craft to patrons worldwide.
</p>
</div>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Store Display Name</label>
<input
type="text"
className="input"
placeholder="e.g. Maheshwar Heritage Weavers"
value={storeName}
onChange={(e) => {
setStoreName(e.target.value);
if (!storeSlug) {
setStoreSlug(e.target.value.toLowerCase().replace(/[^a-z0-9]/g, '-'));
}
}}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Store URL / Handle</label>
<div className="field has-addons">
<p className="control">
<a className="button is-static" style={{ borderColor: '#e7ded9', borderRadius: '8px 0 0 8px' }}>
tradhox.com/stores/
</a>
</p>
<p className="control is-expanded">
<input
type="text"
className="input"
placeholder="maheshwar-weavers"
value={storeSlug}
onChange={(e) => setStoreSlug(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '0 8px 8px 0' }}
/>
</p>
</div>
</div>
<div className="field mb-4">
<label className="label is-size-7 is-uppercase has-text-grey">Artisan Bio &amp; Craft Story</label>
<textarea
className="textarea"
rows={4}
placeholder="Tell patrons about your family tradition, the history of your craft cluster, and your commitment to authentic quality..."
value={businessBio}
onChange={(e) => setBusinessBio(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
<div className="columns is-multiline">
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Support Email</label>
<input
type="email"
className="input"
placeholder="contact@artisanweavers.com"
value={supportEmail}
onChange={(e) => setSupportEmail(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
<div className="column is-6">
<div className="field">
<label className="label is-size-7 is-uppercase has-text-grey">Support Phone</label>
<input
type="tel"
className="input"
placeholder="+91 98765 43210"
value={supportPhone}
onChange={(e) => setSupportPhone(e.target.value)}
style={{ borderColor: '#e7ded9', borderRadius: '8px' }}
/>
</div>
</div>
</div>
</div>
)}
{/* Navigation / Action Buttons */}
<div className="is-flex is-justify-content-between is-align-items-center mt-6 pt-5" style={{ borderTop: '1px solid #e7ded9' }}>
{localStep > 1 ? (
<button
type="button"
className="button is-rounded has-text-weight-semibold px-5"
onClick={handlePrev}
style={{ borderColor: '#e7ded9', color: '#4a4543' }}
>
<i className="fa-solid fa-arrow-left mr-2"></i> Previous Step
</button>
) : (
<span />
)}
<button
type="button"
className="button is-rounded has-text-weight-bold px-6"
onClick={() => handleNext()}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', border: 'none', boxShadow: '0 4px 14px rgba(103,27,38,0.2)' }}
>
{localStep === 7 ? (
<>Submit Application <i className="fa-solid fa-check ml-2"></i></>
) : (
<>Save &amp; Continue <i className="fa-solid fa-arrow-right ml-2"></i></>
)}
</button>
</div>
</div>
</form>
</div>
</section>
);

View file

@ -0,0 +1,265 @@
import React, { useState } from 'react';
import { useSeller } from '../../context/SellerContext';
export default function PricingPage() {
const { setCurrentPage } = useSeller();
const [calcPrice, setCalcPrice] = useState<number>(1500);
const [isGiTagged, setIsGiTagged] = useState<boolean>(true);
// Commission is 5% for GI-tagged/artisan heritage, 8% for standard handmade
const commissionRate = isGiTagged ? 0.05 : 0.08;
const commission = Math.round(calcPrice * commissionRate);
const paymentGatewayFee = Math.round(calcPrice * 0.015);
const netEarnings = Math.max(0, calcPrice - commission - paymentGatewayFee);
const pillars = [
{
title: 'No registration fee',
desc: 'Start your digital seller journey completely free. We provide seamless Aadhaar and artisan cluster onboarding without subscription charges.',
badge: '₹0 Upfront Cost',
icon: 'fa-id-card'
},
{
title: 'No listing fee',
desc: 'Publish your full catalog of authentic handmade creations with zero upfront slot or cataloging charges. All verified artisan products receive equal organic discovery.',
badge: 'Unlimited Listings',
icon: 'fa-tags'
},
{
title: 'No hidden deductions',
desc: 'Every rupee earned on your verified craft is safeguarded. We guarantee zero hidden deductions with a 100% transparent split on every order.',
badge: '100% Transparent',
icon: 'fa-file-invoice-dollar'
},
{
title: 'Fast 7-day settlement',
desc: 'Receive accelerated disbursements directly into your registered bank account as soon as your craft reaches the customer, keeping your working capital fluid.',
badge: 'Weekly Direct NEFT',
icon: 'fa-bolt-lightning'
},
{
title: 'No penalization fees',
desc: 'A maker-first community that supports craftsmanship rather than imposing arbitrary SLAs or algorithmic penalty deductions for artisan lead times.',
badge: 'Artisan Protected',
icon: 'fa-heart-circle-check'
}
];
return (
<div className="pricing-page has-background-white-ter" style={{ minHeight: '100vh' }}>
{/* Hero */}
<section className="py-6 px-4" style={{ background: 'linear-gradient(180deg, #f7eeee 0%, #fcf9f8 100%)', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-desktop has-text-centered py-5">
<span className="tag is-rounded is-small mb-3" style={{ backgroundColor: '#f2dede', color: 'var(--trad-maroon)', fontWeight: 700, letterSpacing: '0.08em' }}>
TRANSPARENT ARTISAN COMMERCE
</span>
<h1 className="title is-1 font-serif-trad mb-4" style={{ color: 'var(--trad-maroon)', fontSize: '2.75rem' }}>
Transparent Pricing Built Solely for Maker Prosperity
</h1>
<p className="subtitle is-5 has-text-grey-dark mx-auto mb-6" style={{ maxWidth: '750px', lineHeight: 1.6 }}>
Empowering traditional artisans, GI-tagged clusters, and direct creators across India with 100% transparent fee structures, zero upfront charges, and guaranteed weekly bank payouts.
</p>
<button
className="button is-large is-rounded has-text-weight-bold px-6"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ backgroundColor: 'var(--trad-maroon)', color: '#ffffff', border: 'none', boxShadow: '0 8px 24px rgba(103,27,38,0.2)' }}
>
Register as a seller <i className="fa-solid fa-arrow-right ml-3"></i>
</button>
</div>
</section>
{/* 5 Core Pillars */}
<section className="py-6 px-4">
<div className="container is-max-widescreen">
<div className="has-text-centered mb-6">
<h2 className="title is-2 font-serif-trad" style={{ color: 'var(--trad-maroon)' }}>
Zero Upfront Costs. Only Pay When You Sell.
</h2>
<p className="has-text-grey-dark">
Traditional marketplaces charge heavy listing and membership fees. Tradhox changes the rules for India's creators.
</p>
</div>
<div className="columns is-multiline">
{pillars.map((p, i) => (
<div key={i} className="column is-4-desktop is-6-tablet">
<div className="box p-5 is-flex is-flex-direction-column" style={{ height: '100%', borderRadius: '12px', border: '1px solid #e7ded9' }}>
<div className="is-flex is-justify-content-between is-align-items-center mb-4">
<div style={{ width: '42px', height: '42px', borderRadius: '10px', backgroundColor: '#faeef0', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--trad-maroon)', fontSize: '1.25rem' }}>
<i className={`fa-solid ${p.icon}`}></i>
</div>
<span className="tag is-success is-light is-rounded has-text-weight-bold" style={{ fontSize: '0.75rem' }}>
{p.badge}
</span>
</div>
<h3 className="title is-5 mb-2" style={{ color: '#2b2523' }}>
{p.title}
</h3>
<p className="has-text-grey-dark is-size-6" style={{ lineHeight: 1.6 }}>
{p.desc}
</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* Interactive Fee & Payout Calculator */}
<section className="py-6 px-4" style={{ backgroundColor: '#ffffff', borderTop: '1px solid #e7ded9', borderBottom: '1px solid #e7ded9' }}>
<div className="container is-max-desktop">
<div className="has-text-centered mb-5">
<span className="tag is-warning is-light is-rounded has-text-weight-bold mb-2">
ARTISAN PROFIT CALCULATOR
</span>
<h2 className="title is-2 font-serif-trad" style={{ color: 'var(--trad-maroon)' }}>
Estimate Your Net Take-Home Earnings
</h2>
<p className="has-text-grey-dark">
See the exact transparent fee breakdown on any handcrafted item price.
</p>
</div>
<div className="box p-6" style={{ border: '1px solid #e7ded9', borderRadius: '16px', backgroundColor: '#fcf9f8' }}>
<div className="columns is-vcentered">
<div className="column is-6 pr-5">
<div className="field mb-5">
<label className="label has-text-weight-semibold">Your Product Selling Price ()</label>
<div className="control has-icons-left">
<input
type="number"
className="input is-medium has-text-weight-bold"
value={calcPrice}
onChange={(e) => setCalcPrice(Math.max(0, Number(e.target.value)))}
style={{ borderColor: 'var(--trad-border)' }}
/>
<span className="icon is-left has-text-weight-bold" style={{ color: 'var(--trad-maroon)' }}></span>
</div>
</div>
<div className="field mb-4">
<label className="label has-text-weight-semibold mb-2">Heritage Classification</label>
<div className="control">
<label className="checkbox is-flex is-align-items-center">
<input
type="checkbox"
checked={isGiTagged}
onChange={(e) => setIsGiTagged(e.target.checked)}
className="mr-2"
style={{ accentColor: 'var(--trad-maroon)', transform: 'scale(1.2)' }}
/>
<span className="is-size-6">
GI-Tagged / Artisan Certified (Reduced 5% fee tier)
</span>
</label>
</div>
</div>
<p className="is-size-7 has-text-grey mt-4">
*Standard handmade crafts without GI certification have an 8% flat marketplace platform fee. Payment gateway fee is ~1.5%.
</p>
</div>
<div className="column is-6">
<div className="box p-5" style={{ backgroundColor: '#ffffff', border: '1px solid #e7ded9', borderRadius: '12px' }}>
<h4 className="title is-5 mb-4 has-text-grey-dark">Order Payout Breakdown</h4>
<div className="is-flex is-justify-content-between mb-3">
<span className="has-text-grey">Gross Selling Price:</span>
<span className="has-text-weight-semibold">{calcPrice.toLocaleString('en-IN')}</span>
</div>
<div className="is-flex is-justify-content-between mb-3">
<span className="has-text-grey">
Tradhox Fee ({isGiTagged ? '5% GI Rate' : '8% Standard'}):
</span>
<span className="has-text-danger has-text-weight-semibold">- {commission.toLocaleString('en-IN')}</span>
</div>
<div className="is-flex is-justify-content-between mb-4">
<span className="has-text-grey">Payment Gateway (1.5%):</span>
<span className="has-text-danger has-text-weight-semibold">- {paymentGatewayFee.toLocaleString('en-IN')}</span>
</div>
<hr style={{ margin: '1rem 0', backgroundColor: '#e7ded9' }} />
<div className="is-flex is-justify-content-between is-align-items-center">
<div>
<p className="has-text-weight-bold" style={{ color: 'var(--trad-maroon)', fontSize: '1.25rem' }}>Net Bank Payout</p>
<p className="is-size-7 has-text-grey">Credited in 7 days after delivery</p>
</div>
<span className="has-text-weight-bold" style={{ fontSize: '1.75rem', color: 'var(--trad-teal)' }}>
{netEarnings.toLocaleString('en-IN')}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{/* AEO & Customs Compliance Info */}
<section className="py-6 px-4">
<div className="container is-max-desktop">
<div className="has-text-centered mb-6">
<span className="has-text-weight-bold is-uppercase" style={{ color: 'var(--trad-bronze)', letterSpacing: '0.1em', fontSize: '0.85rem' }}>
Frequently Asked · AEO &amp; Export Compliance
</span>
<h2 className="title is-2 font-serif-trad mt-2" style={{ color: 'var(--trad-maroon)' }}>
AEO, Customs &amp; Seller Pricing Questions
</h2>
</div>
<div className="content">
<div className="box p-5 mb-4" style={{ border: '1px solid #e7ded9' }}>
<h4 className="title is-5 mb-2" style={{ color: 'var(--trad-navy)' }}>
What is Tradhox's AEO (Authorised Economic Operator) framework, and how does it benefit sellers?
</h4>
<p className="has-text-grey-dark">
Tradhox operates under AEO-certified customs and export logistics facilitation. This grants verified Indian artisan goods fast-track export customs clearance, prioritized cargo screening, and zero unexpected customs handling charges on outbound international consignments.
</p>
</div>
<div className="box p-5 mb-4" style={{ border: '1px solid #e7ded9' }}>
<h4 className="title is-5 mb-2" style={{ color: 'var(--trad-navy)' }}>
How does the 7-day settlement cycle work?
</h4>
<p className="has-text-grey-dark">
Once courier delivery is confirmed at the customer doorstep, the return buffer period begins. Payouts are computed automatically and credited via NEFT/RTGS into your registered bank account every Tuesday.
</p>
</div>
<div className="box p-5 mb-4" style={{ border: '1px solid #e7ded9' }}>
<h4 className="title is-5 mb-2" style={{ color: 'var(--trad-navy)' }}>
Do I have to pay for marketing or buyer ads?
</h4>
<p className="has-text-grey-dark">
No. Unlike other platforms where sellers must pay for sponsored slots to be seen, Tradhox gives equal organic showcase to all authentic artisan workshops.
</p>
</div>
</div>
{/* Bottom CTA */}
<div className="box has-text-centered py-6 px-4 mt-6" style={{ background: 'linear-gradient(135deg, var(--trad-maroon) 0%, var(--trad-burgundy) 100%)', color: '#ffffff', borderRadius: '16px' }}>
<h2 className="title is-2 font-serif-trad mb-3" style={{ color: '#ffffff' }}>
Ready to start selling your authentic creations?
</h2>
<p className="subtitle is-5 mb-5" style={{ color: '#fad4d8', maxWidth: '600px', margin: '0 auto' }}>
No upfront charges. No hidden contracts. Just fair craft trade.
</p>
<button
className="button is-rounded is-large has-text-weight-bold px-6"
onClick={() => { setCurrentPage('signup'); window.scrollTo(0, 0); }}
style={{ backgroundColor: '#ffffff', color: 'var(--trad-maroon)', border: 'none' }}
>
Join Tradhox Today
</button>
</div>
</div>
</section>
</div>
);
}

View file

@ -1,7 +1,7 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import { CONFIG, apiFetch } from '../config';
type Page = 'home' | 'about' | 'contact' | 'login' | 'signup' | 'profile-completion' | 'confirmation' | 'dashboard' | 'forgot-password' | 'login-otp' | 'welcome-tour';
type Page = 'home' | 'about' | 'contact' | 'login' | 'signup' | 'how-it-works' | 'pricing' | 'grow-business' | 'profile-completion' | 'confirmation' | 'dashboard' | 'forgot-password' | 'login-otp' | 'welcome-tour' | 'application-submitted';
type DashboardTab = 'overview' | 'products' | 'orders' | 'returns' | 'wallet' | 'settings' | 'barcode-generator' | 'analytics';
type DateFilter = 'year' | 'week' | 'day' | 'custom';
@ -82,7 +82,40 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
const [supportPhone, setSupportPhone] = useState('')
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
// Step 3: Store and Location details
// 7-step onboarding state
const [onboardingStep, setOnboardingStep] = useState<number>(1)
const [applicationId, setApplicationId] = useState<string>('TRD-' + Math.floor(100000 + Math.random() * 900000))
const [bankDetails, setBankDetails] = useState({
accountHolderName: '',
accountNumber: '',
confirmAccountNumber: '',
ifscCode: '',
bankName: '',
branchName: '',
accountType: 'Current'
})
const [pickupAddress, setPickupAddress] = useState({
buildingName: '',
street: '123 Handloom Lane',
landmark: '',
city: 'Textile Town',
state: 'Karnataka',
pincode: '560001',
contactPerson: '',
contactPhone: ''
})
const [initialProduct, setInitialProduct] = useState({
title: '',
category: 'Handloom & Textiles',
price: '',
stock: '',
description: '',
sku: '',
materials: '',
image: ''
})
// Store and Location details
const [storeName, setStoreName] = useState('My Artisan Handloom')
const [storeLogo, setStoreLogo] = useState<string | null>(null)
const [logoS3Key, setLogoS3Key] = useState<string | null>(null)
@ -621,17 +654,15 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
});
};
const handleProfileSubmit = (e: React.FormEvent) => {
e.preventDefault()
saveProfileBackend(true)
.then(() => {
setIsProfileComplete(true);
setCurrentPage('dashboard');
})
const handleProfileSubmit = (e?: React.FormEvent) => {
if (e && typeof e.preventDefault === 'function') {
e.preventDefault();
}
return saveProfileBackend(true)
.catch(err => {
alert(err.message);
});
}
})
};
// --- Dashboard Logic Actions ---
@ -824,7 +855,8 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
const contextValue = {
setBusinessBio, email, resetPassword, setLogoS3Key, setStoreName, setShowLoginPass, storeName, otpLoginSent, setOtpLoginSent, aadharS3Key, logoS3Key, customDates, setProductFormDetails, handleBulkUploadSubmit, setMapCoordinates, setAadharFile, gstin, mapCoordinates, setIsGstinVerified, enteredPhoneOtp, address, setEmailVerified, dashTab, selectedOrderDetail, setShowSignupConfirmPass, handleRegisterSubmit, setBulkCsvFile, confirmPassword, navigateTo, setResetPassword, orderNotes, setOrders, handleRejectOrder, barcodeProductSku, setEnteredEmailOtp, setIsEditingProduct, setBulkLog, isMobileMenuOpen, resetOtp, productWizardStep, setCustomDates, setConfirmPassword, isGstinVerified, bulkCsvFile, setAddress, storeLogo, handleProfileSubmit, setPhoneOtpSent, setOrderNotes, handleDeleteProduct, setWallet, policyAccepted, emailOtpSent, setResetOtpSent, setGstin, phoneOtpSent, showLoginPass, showSignupConfirmPass, setPhoneVerified, aadharFile, setDateFilter, activeTab, computeRealtimeMetrics, setIsParsingBulk, handleLogout, panS3Key, setCurrentPage, selectedCategories, setEmailOtpSent, showSignupPass, resetEmail, handleLogoChange, dateFilter, setShowSignupPass, businessBio, setWithdrawAmount, phoneVerified, currentPage, setResetOtp, enteredEmailOtp, setEnteredPhoneOtp, setPanFile, setIsSidebarOpen, setSelectedOrderDetail, handleAcceptOrder, saveProfileBackend, supportPhone, handleEditClick, setStoreLogo, setEmail, password, setOtpLoginPhone, bulkLog, businessType, setPanS3Key, setProducts, setSupportEmail, setOtpLoginCode, withdrawAmount, handleSaveProduct, setStoreSlug, setBarcodeProductSku, setProductForm, setBulkZipFile, productFormDetails, setIsProfileComplete, otpLoginPhone, orders, setActiveTab, bulkZipFile, isSidebarOpen, setBarcodeGenerated, setBusinessType, handleReturnAction, setSupportPhone, barcodeGenerated, products, productForm, setProductWizardStep, resetOtpSent, emailVerified, panFile, isParsingBulk, setDashTab, setReturns, setPassword, handleWithdrawRequest, uploadDocument, setPolicyAccepted, isEditingProduct, setIsMobileMenuOpen, isProfileComplete, setSelectedCategories, storeSlug, phone, setPhone, setAadharS3Key, handleVerifyGstin, returns, handleLoginSubmit, setResetEmail, wallet, otpLoginCode, supportEmail, aadharUrl, setAadharUrl, panUrl, setPanUrl
setBusinessBio, email, resetPassword, setLogoS3Key, setStoreName, setShowLoginPass, storeName, otpLoginSent, setOtpLoginSent, aadharS3Key, logoS3Key, customDates, setProductFormDetails, handleBulkUploadSubmit, setMapCoordinates, setAadharFile, gstin, mapCoordinates, setIsGstinVerified, enteredPhoneOtp, address, setEmailVerified, dashTab, selectedOrderDetail, setShowSignupConfirmPass, handleRegisterSubmit, setBulkCsvFile, confirmPassword, navigateTo, setResetPassword, orderNotes, setOrders, handleRejectOrder, barcodeProductSku, setEnteredEmailOtp, setIsEditingProduct, setBulkLog, isMobileMenuOpen, resetOtp, productWizardStep, setCustomDates, setConfirmPassword, isGstinVerified, bulkCsvFile, setAddress, storeLogo, handleProfileSubmit, setPhoneOtpSent, setOrderNotes, handleDeleteProduct, setWallet, policyAccepted, emailOtpSent, setResetOtpSent, setGstin, phoneOtpSent, showLoginPass, showSignupConfirmPass, setPhoneVerified, aadharFile, setDateFilter, activeTab, computeRealtimeMetrics, setIsParsingBulk, handleLogout, panS3Key, setCurrentPage, selectedCategories, setEmailOtpSent, showSignupPass, resetEmail, handleLogoChange, dateFilter, setShowSignupPass, businessBio, setWithdrawAmount, phoneVerified, currentPage, setResetOtp, enteredEmailOtp, setEnteredPhoneOtp, setPanFile, setIsSidebarOpen, setSelectedOrderDetail, handleAcceptOrder, saveProfileBackend, supportPhone, handleEditClick, setStoreLogo, setEmail, password, setOtpLoginPhone, bulkLog, businessType, setPanS3Key, setProducts, setSupportEmail, setOtpLoginCode, withdrawAmount, handleSaveProduct, setStoreSlug, setBarcodeProductSku, setProductForm, setBulkZipFile, productFormDetails, setIsProfileComplete, otpLoginPhone, orders, setActiveTab, bulkZipFile, isSidebarOpen, setBarcodeGenerated, setBusinessType, handleReturnAction, setSupportPhone, barcodeGenerated, products, productForm, setProductWizardStep, resetOtpSent, emailVerified, panFile, isParsingBulk, setDashTab, setReturns, setPassword, handleWithdrawRequest, uploadDocument, setPolicyAccepted, isEditingProduct, setIsMobileMenuOpen, isProfileComplete, setSelectedCategories, storeSlug, phone, setPhone, setAadharS3Key, handleVerifyGstin, returns, handleLoginSubmit, setResetEmail, wallet, otpLoginCode, supportEmail, aadharUrl, setAadharUrl, panUrl, setPanUrl,
onboardingStep, setOnboardingStep, applicationId, setApplicationId, bankDetails, setBankDetails, pickupAddress, setPickupAddress, initialProduct, setInitialProduct
};
return (

View file

@ -1,15 +1,84 @@
@import 'bulma/css/bulma.css';
:root {
--bulma-primary-h: 342deg;
--bulma-primary-s: 95%;
--bulma-primary-l: 15%;
--bulma-primary: #4d0218;
--bulma-link: #4d0218;
--bulma-body-background-color: #fbf9f8;
--trad-maroon: #671B26;
--trad-maroon-hover: #52141e;
--trad-bronze: #675C1B;
--trad-teal: #1B675C;
--trad-navy: #1B2667;
--trad-burgundy: #791B2C;
--trad-footer-bg: #791B2C;
--trad-bg: #FCF9F8;
--trad-surface: #ffffff;
--trad-border: #e6ded9;
--trad-text-main: #2b2523;
--trad-text-muted: #6e6561;
--bulma-primary: #671B26;
--bulma-primary-h: 351deg;
--bulma-primary-s: 58%;
--bulma-primary-l: 25%;
--bulma-link: #671B26;
--bulma-body-background-color: #fcf9f8;
--bulma-body-family: 'Plus Jakarta Sans', 'Inter', sans-serif;
}
[data-theme='light'], :root {
color-scheme: light;
--bulma-scheme-main: #fbf9f8;
--bulma-scheme-main: #fcf9f8;
}
body {
font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background-color: var(--trad-bg);
color: var(--trad-text-main);
}
.font-serif-trad {
font-family: 'Libre Caslon Text', Georgia, serif;
}
.trad-badge-step {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 50%;
font-weight: 700;
font-size: 0.9rem;
}
.trad-badge-step.is-active {
background-color: var(--trad-maroon);
color: #fff;
}
.trad-badge-step.is-completed {
background-color: var(--trad-teal);
color: #fff;
}
.trad-badge-step.is-pending {
background-color: #e5dfda;
color: #7a706b;
}
.trad-card-interactive {
transition: all 0.2s ease-in-out;
border: 1px solid var(--trad-border);
background: #fff;
cursor: pointer;
}
.trad-card-interactive:hover {
transform: translateY(-2px);
border-color: var(--trad-maroon);
box-shadow: 0 8px 24px rgba(103, 27, 38, 0.08);
}
.trad-card-interactive.is-selected {
border-color: var(--trad-maroon);
background-color: #fdf5f5;
box-shadow: 0 0 0 2px var(--trad-maroon);
}