Demo site #2
|
|
@ -20,27 +20,19 @@ export class BetaSupplierSiteStack extends cdk.Stack {
|
||||||
encryption: s3.BucketEncryption.S3_MANAGED,
|
encryption: s3.BucketEncryption.S3_MANAGED,
|
||||||
});
|
});
|
||||||
|
|
||||||
const ec2Origin = new origins.HttpOrigin('api.tipro.in', {
|
const ec2Origin = new origins.HttpOrigin('api.tradhox.com', {
|
||||||
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
|
protocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY,
|
||||||
httpPort: 8080,
|
httpPort: 8080,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Look up the tipro.in hosted zone
|
// Look up the tradhox.com hosted zone
|
||||||
const zone = route53.HostedZone.fromLookup(this, 'TiproZone', {
|
const zone = route53.HostedZone.fromLookup(this, 'TradhoxZone', {
|
||||||
domainName: 'tipro.in',
|
domainName: 'tradhox.com',
|
||||||
});
|
|
||||||
|
|
||||||
// Create Route53 A Record for the EC2 API server
|
|
||||||
// This allows us to use an IP address indirectly, by mapping api.tipro.in to it.
|
|
||||||
new route53.ARecord(this, 'ApiRecord', {
|
|
||||||
recordName: 'api.tipro.in',
|
|
||||||
target: route53.RecordTarget.fromIpAddresses('16.113.57.127'),
|
|
||||||
zone
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a certificate in us-east-1 for CloudFront
|
// Create a certificate in us-east-1 for CloudFront
|
||||||
const certificate = new acm.DnsValidatedCertificate(this, 'SiteCertificate', {
|
const certificate = new acm.DnsValidatedCertificate(this, 'SiteCertificate', {
|
||||||
domainName: 'partners.tipro.in',
|
domainName: 'betapartners.tradhox.com',
|
||||||
hostedZone: zone,
|
hostedZone: zone,
|
||||||
region: 'us-east-1', // CloudFront requires certificates to be in us-east-1
|
region: 'us-east-1', // CloudFront requires certificates to be in us-east-1
|
||||||
});
|
});
|
||||||
|
|
@ -49,7 +41,7 @@ export class BetaSupplierSiteStack extends cdk.Stack {
|
||||||
// origins.S3BucketOrigin.withOriginAccessControl will automatically create an Origin Access Control (OAC)
|
// origins.S3BucketOrigin.withOriginAccessControl will automatically create an Origin Access Control (OAC)
|
||||||
// and update the S3 bucket policy to allow access only from this CloudFront distribution.
|
// and update the S3 bucket policy to allow access only from this CloudFront distribution.
|
||||||
const distribution = new cloudfront.Distribution(this, 'BetaSupplierSiteDistribution', {
|
const distribution = new cloudfront.Distribution(this, 'BetaSupplierSiteDistribution', {
|
||||||
domainNames: ['partners.tipro.in'],
|
domainNames: ['betapartners.tradhox.com'],
|
||||||
certificate: certificate,
|
certificate: certificate,
|
||||||
defaultRootObject: 'index.html',
|
defaultRootObject: 'index.html',
|
||||||
defaultBehavior: {
|
defaultBehavior: {
|
||||||
|
|
@ -97,7 +89,7 @@ export class BetaSupplierSiteStack extends cdk.Stack {
|
||||||
|
|
||||||
// 3. Create Route53 A Record to point to the CloudFront Distribution
|
// 3. Create Route53 A Record to point to the CloudFront Distribution
|
||||||
new route53.ARecord(this, 'SiteAliasRecord', {
|
new route53.ARecord(this, 'SiteAliasRecord', {
|
||||||
recordName: 'partners.tipro.in',
|
recordName: 'betapartners.tradhox.com',
|
||||||
target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
|
target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
|
||||||
zone
|
zone
|
||||||
});
|
});
|
||||||
|
|
|
||||||
28
index.html
|
|
@ -8,8 +8,34 @@
|
||||||
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<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" />
|
<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>
|
||||||
|
tailwind = {
|
||||||
|
config: {
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
brand: {
|
||||||
|
maroon: '#671B26',
|
||||||
|
maroonHover: '#52141e',
|
||||||
|
footerWine: '#791B2C',
|
||||||
|
cream: '#fbf9f5',
|
||||||
|
creamDark: '#f2eee6',
|
||||||
|
navy: '#1B2667',
|
||||||
|
border: '#e6e1d8'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['Inter', 'system-ui', '-apple-system', 'Segoe UI', 'Roboto', 'sans-serif']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
|
||||||
BIN
public/images/landing/benefit-1.jpg
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/images/landing/benefit-10.jpg
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
public/images/landing/benefit-2.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/images/landing/benefit-3.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/images/landing/benefit-4.jpg
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
public/images/landing/benefit-5.jpg
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
public/images/landing/benefit-6.jpg
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
public/images/landing/benefit-7.jpg
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
public/images/landing/benefit-8.jpg
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
public/images/landing/benefit-9.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/images/landing/cat-gi.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/images/landing/cat-odop.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/images/landing/cat-sustainable.jpg
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/images/landing/hero-showcase.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
public/images/landing/tradhox-logo.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/images/landing/tradhox-wordmark.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
120
src/App.test.tsx
|
|
@ -55,10 +55,9 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
|
||||||
it('renders landing page with correct primary titles', () => {
|
it('renders landing page with correct primary titles', () => {
|
||||||
render(<App />)
|
render(<App />)
|
||||||
|
|
||||||
expect(screen.getByText(/The Winter Weaves/i)).toBeInTheDocument()
|
expect(screen.getByText(/Sell Authentic Handcrafted Products Across India & Worldwide/i)).toBeInTheDocument()
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading', { name: /^Featured Seller Categories$/i })).toBeInTheDocument()
|
||||||
expect(screen.getByRole('heading', { name: /^Explore by Craft$/i })).toBeInTheDocument()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('navigates to Support page and handles contact form submission', () => {
|
it('navigates to Support page and handles contact form submission', () => {
|
||||||
|
|
@ -154,4 +153,119 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
|
||||||
expect(screen.getByText(/Available for Payout/i)).toBeInTheDocument()
|
expect(screen.getByText(/Available for Payout/i)).toBeInTheDocument()
|
||||||
expect(screen.getByText(/Transaction History/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()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows demo login with any custom email and password without server session', async () => {
|
||||||
|
const originalFetch = globalThis.fetch
|
||||||
|
globalThis.fetch = vi.fn().mockRejectedValue(new Error('Server offline'))
|
||||||
|
|
||||||
|
render(<App />)
|
||||||
|
|
||||||
|
const loginBtn = screen.getByText(/^Login$/i)
|
||||||
|
fireEvent.click(loginBtn)
|
||||||
|
|
||||||
|
const emailInput = screen.getByPlaceholderText(/you@example.com/i)
|
||||||
|
const passInput = screen.getByPlaceholderText(/••••••••/)
|
||||||
|
|
||||||
|
fireEvent.change(emailInput, { target: { value: 'random_artisan_demo@craft.org' } })
|
||||||
|
fireEvent.change(passInput, { target: { value: 'any_password_123' } })
|
||||||
|
|
||||||
|
const submitBtn = screen.getByRole('button', { name: /Sign In/i })
|
||||||
|
fireEvent.click(submitBtn)
|
||||||
|
|
||||||
|
expect(await screen.findByText(/Total Sales/i)).toBeInTheDocument()
|
||||||
|
|
||||||
|
globalThis.fetch = originalFetch
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
14
src/App.tsx
|
|
@ -1,9 +1,11 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SellerProvider, useSeller } from './context/SellerContext';
|
import { SellerProvider, useSeller } from './context/SellerContext';
|
||||||
import Header from './components/layout/Header';
|
import Header from './components/layout/Header';
|
||||||
import Footer from './components/layout/Footer';
|
import Footer from './components/layout/Footer';
|
||||||
import LandingPage from './components/pages/LandingPage';
|
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 AboutPage from './components/pages/AboutPage';
|
||||||
import ContactPage from './components/pages/ContactPage';
|
import ContactPage from './components/pages/ContactPage';
|
||||||
import AuthForms from './components/pages/AuthForms';
|
import AuthForms from './components/pages/AuthForms';
|
||||||
|
|
@ -17,12 +19,18 @@ function AppRouter() {
|
||||||
return <DashboardLayout />;
|
return <DashboardLayout />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentPage === 'home') {
|
||||||
|
return <LandingPage />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
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 />
|
<Header />
|
||||||
<main className="is-flex-grow-1">
|
<main className="is-flex-grow-1">
|
||||||
|
{currentPage === 'how-it-works' && <HowItWorksPage />}
|
||||||
|
{currentPage === 'pricing' && <PricingPage />}
|
||||||
|
{currentPage === 'grow-business' && <GrowBusinessPage />}
|
||||||
{currentPage === 'profile-completion' && <OnboardingWizard />}
|
{currentPage === 'profile-completion' && <OnboardingWizard />}
|
||||||
{currentPage === 'home' && <LandingPage />}
|
|
||||||
{currentPage === 'about' && <AboutPage />}
|
{currentPage === 'about' && <AboutPage />}
|
||||||
{currentPage === 'contact' && <ContactPage />}
|
{currentPage === 'contact' && <ContactPage />}
|
||||||
{(currentPage === 'login' || currentPage === 'signup') && <AuthForms />}
|
{(currentPage === 'login' || currentPage === 'signup') && <AuthForms />}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,130 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useSeller } from '../../context/SellerContext';
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
|
const { setCurrentPage } = useSeller();
|
||||||
|
|
||||||
|
const handleNav = (page: any) => {
|
||||||
|
setCurrentPage(page);
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="footer has-background-white-bis" style={{ borderTop: '1px solid #dac0c2' }}>
|
<footer className="trad-footer py-6 px-4" style={{ backgroundColor: 'var(--trad-footer-bg)', color: '#ffffff', borderTop: '1px solid #5a1420' }}>
|
||||||
<div className="container" style={{ maxWidth: '1120px' }}>
|
<div className="container is-max-widescreen">
|
||||||
<div className="columns">
|
<div className="columns is-variable is-6">
|
||||||
{/* Brand & Copyright */}
|
{/* Brand & Mission */}
|
||||||
<div className="column is-4">
|
<div className="column is-4 trad-footer-brand">
|
||||||
<h2 className="title is-4 has-text-primary mb-3" style={{ fontFamily: 'Libre Caslon Text, serif' }}>Tradhox</h2>
|
<h4 className="font-serif-trad" style={{ color: '#ffffff', fontSize: '1.65rem', fontWeight: 800, letterSpacing: '0.04em', marginBottom: '0.35rem' }}>
|
||||||
<p className="has-text-grey-dark">
|
TRADHOX
|
||||||
© 2026 Tradhox. Honoring Human Craftsmanship.
|
</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 & 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 & 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 & 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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Links 1 */}
|
<hr style={{ backgroundColor: 'rgba(255,255,255,0.12)', margin: '2rem 0 1.5rem 0' }} />
|
||||||
<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="is-flex is-justify-content-between is-align-items-center is-flex-wrap-wrap" style={{ gap: '1rem' }}>
|
||||||
<div className="column is-4">
|
<p style={{ color: '#c5b7b9', fontSize: '0.82rem', margin: 0 }}>
|
||||||
<ul style={{ listStyle: 'none', marginLeft: 0 }}>
|
© 2026 TRADHOX Central. All rights reserved. Celebrating authentic heritage craft across India.
|
||||||
<li className="mb-2"><a href="#" className="has-text-grey-dark hover-text-primary" style={{ transition: 'color 0.2s' }}>Sustainability Report</a></li>
|
</p>
|
||||||
<li><a href="#" className="has-text-grey-dark hover-text-primary" style={{ transition: 'color 0.2s' }}>Shipping Info</a></li>
|
<div className="is-flex" style={{ gap: '1.5rem' }}>
|
||||||
</ul>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>{`
|
<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>
|
`}</style>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -2,87 +2,141 @@ import React from 'react';
|
||||||
import { useSeller } from '../../context/SellerContext';
|
import { useSeller } from '../../context/SellerContext';
|
||||||
|
|
||||||
export default function Header() {
|
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 (
|
return (
|
||||||
<nav className="navbar has-background-white-bis" style={{ borderBottom: '1px solid #dac0c2' }} role="navigation" aria-label="main navigation">
|
<header className="trad-header-wrapper" style={{ borderBottom: '1px solid #e7ded9', background: '#ffffff', position: 'sticky', top: 0, zIndex: 90 }}>
|
||||||
<div className="container" style={{ maxWidth: '1120px' }}>
|
<div className="container is-max-widescreen px-4">
|
||||||
<div className="navbar-brand">
|
<nav className="navbar" role="navigation" aria-label="main navigation" style={{ background: 'transparent', minHeight: '4.25rem' }}>
|
||||||
<a className="navbar-item is-size-4 has-text-primary" style={{ fontFamily: 'Libre Caslon Text, serif', letterSpacing: '-0.02em', fontWeight: 700 }} onClick={() => setCurrentPage('home')}>
|
<div className="navbar-brand is-flex is-align-items-center">
|
||||||
Tradhox
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a role="button" className={`navbar-burger ${isMobileMenuOpen ? 'is-active' : ''}`} aria-label="menu" aria-expanded="false" onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} style={{ color: 'var(--bulma-primary)' }}>
|
|
||||||
<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' }}>
|
|
||||||
<a
|
<a
|
||||||
className="navbar-item has-text-weight-medium custom-nav-link"
|
className="navbar-item is-clickable is-flex is-align-items-center p-0 mr-5"
|
||||||
onClick={() => setCurrentPage('home')}
|
onClick={() => handleNav('home')}
|
||||||
style={{ color: currentPage === 'home' ? 'var(--bulma-primary)' : '#5f5e5b' }}
|
style={{ textDecoration: 'none' }}
|
||||||
>
|
>
|
||||||
Shop
|
<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>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
className="navbar-item has-text-weight-medium custom-nav-link"
|
role="button"
|
||||||
onClick={() => setCurrentPage('about')}
|
className={`navbar-burger ${isMobileMenuOpen ? 'is-active' : ''}`}
|
||||||
style={{ color: currentPage === 'about' ? 'var(--bulma-primary)' : '#5f5e5b' }}
|
aria-label="menu"
|
||||||
|
aria-expanded={isMobileMenuOpen}
|
||||||
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||||
|
style={{ color: 'var(--trad-maroon)', marginLeft: 'auto' }}
|
||||||
>
|
>
|
||||||
Our Story
|
<span aria-hidden="true"></span>
|
||||||
</a>
|
<span aria-hidden="true"></span>
|
||||||
<a
|
<span aria-hidden="true"></span>
|
||||||
className="navbar-item has-text-weight-medium custom-nav-link"
|
|
||||||
onClick={() => setCurrentPage('contact')}
|
|
||||||
style={{ color: currentPage === 'contact' ? 'var(--bulma-primary)' : '#5f5e5b' }}
|
|
||||||
>
|
|
||||||
Contact Us
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="navbar-end">
|
<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-item">
|
<div className="navbar-start is-flex-grow-1 is-justify-content-center" style={{ gap: '1.75rem' }}>
|
||||||
<div className="buttons">
|
<a
|
||||||
<a className="button is-ghost has-text-weight-semibold" style={{ color: '#5f5e5b' }} onClick={() => setCurrentPage('login')}>
|
className={`navbar-item is-size-6 has-text-weight-semibold trad-nav-item ${currentPage === 'home' ? 'is-active-nav' : ''}`}
|
||||||
Login
|
onClick={() => handleNav('home')}
|
||||||
</a>
|
>
|
||||||
<a className="button is-primary is-outlined has-text-weight-semibold" onClick={() => setCurrentPage('signup')}>
|
Home
|
||||||
Get started
|
</a>
|
||||||
</a>
|
<a
|
||||||
|
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 is-flex is-align-items-center">
|
||||||
|
<div className="navbar-item">
|
||||||
|
<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-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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>{`
|
<style>{`
|
||||||
.custom-nav-link {
|
.trad-nav-item {
|
||||||
position: relative;
|
color: #4b4746 !important;
|
||||||
background-color: transparent !important;
|
transition: color 0.15s ease;
|
||||||
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
.custom-nav-link:hover {
|
.trad-nav-item:hover, .trad-nav-item.is-active-nav {
|
||||||
color: var(--bulma-primary) !important;
|
color: var(--trad-maroon) !important;
|
||||||
}
|
}
|
||||||
.custom-nav-link::after {
|
@media screen and (min-width: 1024px) {
|
||||||
content: '';
|
.trad-nav-item {
|
||||||
position: absolute;
|
position: relative;
|
||||||
bottom: 0px;
|
padding: 0.5rem 0.25rem;
|
||||||
left: 50%;
|
}
|
||||||
transform: translateX(-50%);
|
.trad-nav-item.is-active-nav::after {
|
||||||
width: 0;
|
content: '';
|
||||||
height: 2px;
|
position: absolute;
|
||||||
background-color: var(--bulma-primary);
|
bottom: 0px;
|
||||||
transition: width 0.3s ease;
|
left: 0;
|
||||||
}
|
right: 0;
|
||||||
.custom-nav-link:hover::after {
|
height: 2px;
|
||||||
width: 80%;
|
background-color: var(--trad-maroon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
</nav>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
188
src/components/pages/GrowBusinessPage.tsx
Normal 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 & 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 & 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 & 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 & 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
252
src/components/pages/HowItWorksPage.tsx
Normal 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 India’s 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
296
src/components/pages/LoginPage.tsx
Normal 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 & 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 & 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 & 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
265
src/components/pages/PricingPage.tsx
Normal 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 & Export Compliance
|
||||||
|
</span>
|
||||||
|
<h2 className="title is-2 font-serif-trad mt-2" style={{ color: 'var(--trad-maroon)' }}>
|
||||||
|
AEO, Customs & 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||||
import { CONFIG, apiFetch } from '../config';
|
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 DashboardTab = 'overview' | 'products' | 'orders' | 'returns' | 'wallet' | 'settings' | 'barcode-generator' | 'analytics';
|
||||||
type DateFilter = 'year' | 'week' | 'day' | 'custom';
|
type DateFilter = 'year' | 'week' | 'day' | 'custom';
|
||||||
|
|
||||||
|
|
@ -82,7 +82,40 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
const [supportPhone, setSupportPhone] = useState('')
|
const [supportPhone, setSupportPhone] = useState('')
|
||||||
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
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 [storeName, setStoreName] = useState('My Artisan Handloom')
|
||||||
const [storeLogo, setStoreLogo] = useState<string | null>(null)
|
const [storeLogo, setStoreLogo] = useState<string | null>(null)
|
||||||
const [logoS3Key, setLogoS3Key] = useState<string | null>(null)
|
const [logoS3Key, setLogoS3Key] = useState<string | null>(null)
|
||||||
|
|
@ -122,10 +155,10 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
const [dateFilter, setDateFilter] = useState<DateFilter>('year')
|
const [dateFilter, setDateFilter] = useState<DateFilter>('year')
|
||||||
const [customDates, setCustomDates] = useState({ start: '2026-06-01', end: '2026-06-15' })
|
const [customDates, setCustomDates] = useState({ start: '2026-06-01', end: '2026-06-15' })
|
||||||
|
|
||||||
// Lists
|
// Lists with rich default mock data for demo mode
|
||||||
const [products, setProducts] = useState<Product[]>([])
|
const [products, setProducts] = useState<Product[]>(CONFIG.dashboardData.initialProducts || [])
|
||||||
const [orders, setOrders] = useState<Order[]>([])
|
const [orders, setOrders] = useState<Order[]>((CONFIG.dashboardData.initialOrders as Order[]) || [])
|
||||||
const [returns, setReturns] = useState<ReturnRequest[]>([])
|
const [returns, setReturns] = useState<ReturnRequest[]>((CONFIG.dashboardData.initialReturns as ReturnRequest[]) || [])
|
||||||
|
|
||||||
// Forms & Editing
|
// Forms & Editing
|
||||||
const [productForm, setProductForm] = useState({
|
const [productForm, setProductForm] = useState({
|
||||||
|
|
@ -231,9 +264,8 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error('Session restore failed:', err);
|
console.warn('Session restore fallback to active demo session:', err);
|
||||||
localStorage.removeItem('access_token')
|
setIsProfileComplete(true);
|
||||||
localStorage.removeItem('refresh_token');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -507,16 +539,28 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
navigateTo('profile-completion')
|
navigateTo('profile-completion')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
alert(err.message);
|
// Offline / demo fallback
|
||||||
|
localStorage.setItem('access_token', 'demo_access_token');
|
||||||
|
navigateTo('profile-completion');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLoginSubmit = (e: React.FormEvent) => {
|
const handleLoginSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
|
const fallbackDemoLogin = () => {
|
||||||
|
localStorage.setItem('access_token', 'demo_access_token');
|
||||||
|
setEmail(email.trim() || 'demo_artisan@tradhox.com');
|
||||||
|
setPhoneVerified(true);
|
||||||
|
setEmailVerified(true);
|
||||||
|
setIsGstinVerified(true);
|
||||||
|
setIsProfileComplete(true);
|
||||||
|
navigateTo('dashboard', true);
|
||||||
|
};
|
||||||
|
|
||||||
if (!email.trim()) {
|
if (!email.trim()) {
|
||||||
alert('Please enter your email or phone number.');
|
fallbackDemoLogin();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,7 +570,7 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
body: JSON.stringify({ username: email, password: password })
|
body: JSON.stringify({ username: email, password: password })
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (!res.ok) throw new Error('Invalid credentials.');
|
if (!res.ok) throw new Error('Demo mode activated.');
|
||||||
return res.json();
|
return res.json();
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
|
@ -536,7 +580,7 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
const profile = data.user.profile;
|
const profile = data.user.profile;
|
||||||
setPhone(profile.phone || '');
|
setPhone(profile.phone || '');
|
||||||
setPhoneVerified(profile.phone_verified || false);
|
setPhoneVerified(profile.phone_verified || false);
|
||||||
setEmail(data.user.email || '');
|
setEmail(data.user.email || email);
|
||||||
setEmailVerified(profile.email_verified || false);
|
setEmailVerified(profile.email_verified || false);
|
||||||
setGstin(profile.gstin || '29AAAAA1111A1Z1');
|
setGstin(profile.gstin || '29AAAAA1111A1Z1');
|
||||||
setIsGstinVerified(profile.is_gstin_verified || false);
|
setIsGstinVerified(profile.is_gstin_verified || false);
|
||||||
|
|
@ -578,8 +622,9 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
navigateTo('profile-completion');
|
navigateTo('profile-completion');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
alert(err.message);
|
// Backend not running or demo credentials -> seamless fallback to demo dashboard
|
||||||
|
fallbackDemoLogin();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -621,17 +666,15 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleProfileSubmit = (e: React.FormEvent) => {
|
const handleProfileSubmit = (e?: React.FormEvent) => {
|
||||||
e.preventDefault()
|
if (e && typeof e.preventDefault === 'function') {
|
||||||
saveProfileBackend(true)
|
e.preventDefault();
|
||||||
.then(() => {
|
}
|
||||||
setIsProfileComplete(true);
|
return saveProfileBackend(true)
|
||||||
setCurrentPage('dashboard');
|
|
||||||
})
|
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
alert(err.message);
|
alert(err.message);
|
||||||
});
|
})
|
||||||
}
|
};
|
||||||
|
|
||||||
// --- Dashboard Logic Actions ---
|
// --- Dashboard Logic Actions ---
|
||||||
|
|
||||||
|
|
@ -824,7 +867,8 @@ export const SellerProvider: React.FC<{children: React.ReactNode}> = ({ children
|
||||||
|
|
||||||
|
|
||||||
const contextValue = {
|
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 (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,84 @@
|
||||||
@import 'bulma/css/bulma.css';
|
@import 'bulma/css/bulma.css';
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--bulma-primary-h: 342deg;
|
--trad-maroon: #671B26;
|
||||||
--bulma-primary-s: 95%;
|
--trad-maroon-hover: #52141e;
|
||||||
--bulma-primary-l: 15%;
|
--trad-bronze: #675C1B;
|
||||||
--bulma-primary: #4d0218;
|
--trad-teal: #1B675C;
|
||||||
--bulma-link: #4d0218;
|
--trad-navy: #1B2667;
|
||||||
--bulma-body-background-color: #fbf9f8;
|
--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 {
|
[data-theme='light'], :root {
|
||||||
color-scheme: light;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||