feat: extend onboarding process to 7 steps with new business details and store configuration fields
This commit is contained in:
parent
d9f4b380c1
commit
3748de8674
2 changed files with 457 additions and 242 deletions
5
prompt
5
prompt
|
|
@ -0,0 +1,5 @@
|
||||||
|
django server code : /home/vignesh/github/seller_central_backend
|
||||||
|
Don't push code without my command
|
||||||
|
beta site : https://betasuppliers.tipro.in/
|
||||||
|
in betasite only you need test with playwright
|
||||||
|
Read this repo and understand this project , once you ready let me know i will provide you instruction
|
||||||
694
src/App.tsx
694
src/App.tsx
|
|
@ -68,6 +68,13 @@ export default function App() {
|
||||||
const [aadharS3Key, setAadharS3Key] = useState<string | null>(null)
|
const [aadharS3Key, setAadharS3Key] = useState<string | null>(null)
|
||||||
const [panS3Key, setPanS3Key] = useState<string | null>(null)
|
const [panS3Key, setPanS3Key] = useState<string | null>(null)
|
||||||
|
|
||||||
|
// New onboarding customization states
|
||||||
|
const [businessType, setBusinessType] = useState<'registered_company' | 'self_help_group' | 'individual_maker'>('registered_company')
|
||||||
|
const [storeSlug, setStoreSlug] = useState('')
|
||||||
|
const [supportEmail, setSupportEmail] = useState('')
|
||||||
|
const [supportPhone, setSupportPhone] = useState('')
|
||||||
|
const [selectedCategories, setSelectedCategories] = useState<string[]>([])
|
||||||
|
|
||||||
// Step 3: Store and Location details
|
// Step 3: 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)
|
||||||
|
|
@ -158,6 +165,13 @@ export default function App() {
|
||||||
setPanFile(profile.pan_file || null);
|
setPanFile(profile.pan_file || null);
|
||||||
setAadharS3Key(profile.aadhar_s3_key || null);
|
setAadharS3Key(profile.aadhar_s3_key || null);
|
||||||
setPanS3Key(profile.pan_s3_key || null);
|
setPanS3Key(profile.pan_s3_key || null);
|
||||||
|
|
||||||
|
setBusinessType(profile.business_type || 'registered_company');
|
||||||
|
setStoreSlug(profile.store_slug || '');
|
||||||
|
setSupportEmail(profile.support_email || '');
|
||||||
|
setSupportPhone(profile.support_phone || '');
|
||||||
|
setSelectedCategories(profile.categories || []);
|
||||||
|
|
||||||
setStoreName(profile.store_name || 'My Artisan Handloom');
|
setStoreName(profile.store_name || 'My Artisan Handloom');
|
||||||
setStoreLogo(profile.store_logo || null);
|
setStoreLogo(profile.store_logo || null);
|
||||||
setLogoS3Key(profile.logo_s3_key || null);
|
setLogoS3Key(profile.logo_s3_key || null);
|
||||||
|
|
@ -173,7 +187,7 @@ export default function App() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const step = profile.onboarding_step;
|
const step = profile.onboarding_step;
|
||||||
if (step >= 4) {
|
if (step >= 7) {
|
||||||
setIsProfileComplete(true);
|
setIsProfileComplete(true);
|
||||||
setCurrentPage('dashboard');
|
setCurrentPage('dashboard');
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -529,6 +543,11 @@ export default function App() {
|
||||||
email_verified: emailVerified,
|
email_verified: emailVerified,
|
||||||
gstin: gstin,
|
gstin: gstin,
|
||||||
is_gstin_verified: isGstinVerified,
|
is_gstin_verified: isGstinVerified,
|
||||||
|
business_type: businessType,
|
||||||
|
store_slug: storeSlug,
|
||||||
|
support_email: supportEmail,
|
||||||
|
support_phone: supportPhone,
|
||||||
|
categories: selectedCategories,
|
||||||
aadhar_file: aadharFile,
|
aadhar_file: aadharFile,
|
||||||
pan_file: panFile,
|
pan_file: panFile,
|
||||||
aadhar_s3_key: aadharS3Key || 'suppliers/default/aadhar.pdf',
|
aadhar_s3_key: aadharS3Key || 'suppliers/default/aadhar.pdf',
|
||||||
|
|
@ -557,14 +576,13 @@ export default function App() {
|
||||||
if (profileStep === 2) {
|
if (profileStep === 2) {
|
||||||
setIsGstinVerified(true)
|
setIsGstinVerified(true)
|
||||||
}
|
}
|
||||||
const isLastStep = profileStep === 3;
|
const isLastStep = profileStep === 6;
|
||||||
saveProfileBackend(isLastStep)
|
saveProfileBackend(isLastStep)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (!isLastStep) {
|
if (!isLastStep) {
|
||||||
setProfileStep(prev => prev + 1)
|
setProfileStep(prev => prev + 1)
|
||||||
} else {
|
} else {
|
||||||
setIsProfileComplete(true)
|
setProfileStep(7);
|
||||||
navigateTo('welcome-tour', true)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
|
|
@ -1256,13 +1274,17 @@ export default function App() {
|
||||||
{currentPage === 'profile-completion' && (
|
{currentPage === 'profile-completion' && (
|
||||||
<div className="form-card" style={{ maxWidth: '640px' }}>
|
<div className="form-card" style={{ maxWidth: '640px' }}>
|
||||||
<div className="step-progress-wrapper">
|
<div className="step-progress-wrapper">
|
||||||
<span className="step-label">Step {profileStep} of 3: {
|
<span className="step-label">Step {profileStep} of 7: {
|
||||||
profileStep === 1 ? 'Contact Verification' :
|
profileStep === 1 ? 'Welcome' :
|
||||||
profileStep === 2 ? 'Tax & Identity Verification' :
|
profileStep === 2 ? 'Business Details' :
|
||||||
'Store & Pickup Location'
|
profileStep === 3 ? 'Identity Verification' :
|
||||||
|
profileStep === 4 ? 'Contact Verification' :
|
||||||
|
profileStep === 5 ? 'Choose Categories' :
|
||||||
|
profileStep === 6 ? 'Store Setup' :
|
||||||
|
'Verification'
|
||||||
}</span>
|
}</span>
|
||||||
<div className="step-bar-container">
|
<div className="step-bar-container">
|
||||||
<div className="step-bar-fill" style={{ width: `${(profileStep / 3) * 100}%` }}></div>
|
<div className="step-bar-fill" style={{ width: `${(profileStep / 7) * 100}%` }}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -1270,8 +1292,177 @@ export default function App() {
|
||||||
|
|
||||||
<form onSubmit={handleProfileSubmit}>
|
<form onSubmit={handleProfileSubmit}>
|
||||||
{profileStep === 1 && (
|
{profileStep === 1 && (
|
||||||
|
<div style={{ textAlign: 'center', padding: '1rem' }}>
|
||||||
|
<div style={{ fontSize: '3rem', marginBottom: '1.5rem' }}>👋</div>
|
||||||
|
<h3 style={{ fontSize: '1.25rem', marginBottom: '1rem', color: 'var(--primary)' }}>Welcome to Tradhox Onboarding</h3>
|
||||||
|
<p style={{ color: 'var(--text-muted)', marginBottom: '2rem', fontSize: '0.95rem', lineHeight: '1.6' }}>
|
||||||
|
We bridge the gap between traditional Indian artistry and a global marketplace.
|
||||||
|
Let's set up your supplier profile in a few simple steps.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary"
|
||||||
|
style={{ width: '100%', padding: '0.8rem', fontWeight: 'bold' }}
|
||||||
|
onClick={() => setProfileStep(2)}
|
||||||
|
>
|
||||||
|
Begin Setup →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{profileStep === 2 && (
|
||||||
<div>
|
<div>
|
||||||
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 1: Verify Contacts</h3>
|
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 2: Business Details</h3>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Business Type *</label>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem', marginBottom: '1.5rem' }}>
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', padding: '0.75rem', border: '1px solid var(--border)', borderRadius: '6px' }}>
|
||||||
|
<input type="radio" name="business_type" value="registered_company" checked={businessType === 'registered_company'} onChange={() => setBusinessType('registered_company')} />
|
||||||
|
Registered Company
|
||||||
|
</label>
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', padding: '0.75rem', border: '1px solid var(--border)', borderRadius: '6px' }}>
|
||||||
|
<input type="radio" name="business_type" value="self_help_group" checked={businessType === 'self_help_group'} onChange={() => setBusinessType('self_help_group')} />
|
||||||
|
Self Help Group
|
||||||
|
</label>
|
||||||
|
<label style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', padding: '0.75rem', border: '1px solid var(--border)', borderRadius: '6px' }}>
|
||||||
|
<input type="radio" name="business_type" value="individual_maker" checked={businessType === 'individual_maker'} onChange={() => setBusinessType('individual_maker')} />
|
||||||
|
Individual Maker
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="verify-gst">GSTIN Number *</label>
|
||||||
|
<div style={{ display: 'flex', gap: '0.75rem' }}>
|
||||||
|
<input
|
||||||
|
id="verify-gst"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Enter 15-digit GSTIN"
|
||||||
|
value={gstin}
|
||||||
|
onChange={(e) => setGstin(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`btn ${isGstinVerified ? 'btn-secondary' : 'btn-primary'}`}
|
||||||
|
onClick={handleVerifyGstin}
|
||||||
|
disabled={isGstinVerified}
|
||||||
|
style={{ minWidth: '120px' }}
|
||||||
|
>
|
||||||
|
{isGstinVerified ? 'Submitted ✓' : 'Submit GSTIN'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{isGstinVerified && (
|
||||||
|
<p style={{ color: 'var(--success)', fontSize: '0.85rem', marginTop: '0.5rem', fontWeight: 600 }}>
|
||||||
|
✓ GSTIN verification will be completed within the next 24 hrs
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', marginTop: '2rem' }}>
|
||||||
|
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(1)}>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-primary"
|
||||||
|
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
||||||
|
disabled={!gstin || !isGstinVerified}
|
||||||
|
>
|
||||||
|
Next Step →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{profileStep === 3 && (
|
||||||
|
<div>
|
||||||
|
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 3: Identity Verification</h3>
|
||||||
|
|
||||||
|
{/* Aadhaar Upload */}
|
||||||
|
<div className="form-group" style={{ marginBottom: '1.25rem' }}>
|
||||||
|
<label htmlFor="aadhar-upload">Aadhaar Card Upload *</label>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
||||||
|
<input
|
||||||
|
id="aadhar-upload"
|
||||||
|
type="file"
|
||||||
|
accept=".pdf,image/*"
|
||||||
|
onChange={async (e) => {
|
||||||
|
if (e.target.files?.[0]) {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
setAadharFile(file.name);
|
||||||
|
alert(`Aadhaar card selected: ${file.name}. Uploading...`);
|
||||||
|
const s3Key = await uploadDocument(file, 'aadhar');
|
||||||
|
setAadharS3Key(s3Key);
|
||||||
|
alert(`Aadhaar card uploaded successfully!`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-dark"
|
||||||
|
onClick={() => document.getElementById('aadhar-upload')?.click()}
|
||||||
|
>
|
||||||
|
📁 Select Aadhaar File
|
||||||
|
</button>
|
||||||
|
<span style={{ fontSize: '0.9rem', color: 'var(--text-muted)' }}>
|
||||||
|
{aadharFile ? `Selected: ${aadharFile}` : 'No file uploaded yet'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* PAN Upload */}
|
||||||
|
<div className="form-group" style={{ marginBottom: '2rem' }}>
|
||||||
|
<label htmlFor="pan-upload">PAN Card Upload *</label>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
||||||
|
<input
|
||||||
|
id="pan-upload"
|
||||||
|
type="file"
|
||||||
|
accept=".pdf,image/*"
|
||||||
|
onChange={async (e) => {
|
||||||
|
if (e.target.files?.[0]) {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
setPanFile(file.name);
|
||||||
|
alert(`PAN card selected: ${file.name}. Uploading...`);
|
||||||
|
const s3Key = await uploadDocument(file, 'pan');
|
||||||
|
setPanS3Key(s3Key);
|
||||||
|
alert(`PAN card uploaded successfully!`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-dark"
|
||||||
|
onClick={() => document.getElementById('pan-upload')?.click()}
|
||||||
|
>
|
||||||
|
📁 Select PAN File
|
||||||
|
</button>
|
||||||
|
<span style={{ fontSize: '0.9rem', color: 'var(--text-muted)' }}>
|
||||||
|
{panFile ? `Selected: ${panFile}` : 'No file uploaded yet'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
||||||
|
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(2)}>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-primary"
|
||||||
|
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
||||||
|
disabled={!aadharFile || !panFile}
|
||||||
|
>
|
||||||
|
Next Step →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{profileStep === 4 && (
|
||||||
|
<div>
|
||||||
|
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 4: Verify Contacts</h3>
|
||||||
|
|
||||||
{/* Phone/WhatsApp Verification */}
|
{/* Phone/WhatsApp Verification */}
|
||||||
<div className="form-group" style={{ padding: '1rem', backgroundColor: 'rgba(233, 196, 110, 0.08)', borderRadius: '8px', border: '1px solid var(--border)', marginBottom: '1rem' }}>
|
<div className="form-group" style={{ padding: '1rem', backgroundColor: 'rgba(233, 196, 110, 0.08)', borderRadius: '8px', border: '1px solid var(--border)', marginBottom: '1rem' }}>
|
||||||
|
|
@ -1417,169 +1608,151 @@ export default function App() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn btn-primary"
|
|
||||||
style={{ width: '100%', padding: '0.8rem', backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
|
||||||
disabled={!phoneVerified || !emailVerified}
|
|
||||||
>
|
|
||||||
Next Step: Identity Verification
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{profileStep === 2 && (
|
|
||||||
<div>
|
|
||||||
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 2: GSTIN, PAN & Aadhaar</h3>
|
|
||||||
|
|
||||||
{/* GSTIN verification */}
|
|
||||||
<div className="form-group">
|
|
||||||
<label htmlFor="verify-gst">GSTIN Number *</label>
|
|
||||||
<div style={{ display: 'flex', gap: '0.75rem' }}>
|
|
||||||
<input
|
|
||||||
id="verify-gst"
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
placeholder="Enter 15-digit GSTIN"
|
|
||||||
value={gstin}
|
|
||||||
onChange={(e) => setGstin(e.target.value)}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`btn ${isGstinVerified ? 'btn-secondary' : 'btn-primary'}`}
|
|
||||||
onClick={handleVerifyGstin}
|
|
||||||
disabled={isGstinVerified}
|
|
||||||
style={{ minWidth: '120px' }}
|
|
||||||
>
|
|
||||||
{isGstinVerified ? 'Submitted ✓' : 'Submit GSTIN'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{isGstinVerified && (
|
|
||||||
<p style={{ color: 'var(--success)', fontSize: '0.85rem', marginTop: '0.5rem', fontWeight: 600 }}>
|
|
||||||
verification will be completed within next 24 hrs
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Aadhaar Upload */}
|
|
||||||
<div className="form-group" style={{ marginBottom: '1.25rem' }}>
|
|
||||||
<label htmlFor="aadhar-upload">Aadhaar Card Upload *</label>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
|
||||||
<input
|
|
||||||
id="aadhar-upload"
|
|
||||||
type="file"
|
|
||||||
accept=".pdf,image/*"
|
|
||||||
onChange={async (e) => {
|
|
||||||
if (e.target.files?.[0]) {
|
|
||||||
const file = e.target.files[0];
|
|
||||||
setAadharFile(file.name);
|
|
||||||
alert(`Aadhaar card selected: ${file.name}. Uploading...`);
|
|
||||||
const s3Key = await uploadDocument(file, 'aadhar');
|
|
||||||
setAadharS3Key(s3Key);
|
|
||||||
alert(`Aadhaar card uploaded successfully!`);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-outline-dark"
|
|
||||||
onClick={() => document.getElementById('aadhar-upload')?.click()}
|
|
||||||
>
|
|
||||||
📁 Select Aadhaar File
|
|
||||||
</button>
|
|
||||||
<span style={{ fontSize: '0.9rem', color: 'var(--text-muted)' }}>
|
|
||||||
{aadharFile ? `Selected: ${aadharFile}` : 'No file uploaded yet'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* PAN Upload */}
|
|
||||||
<div className="form-group" style={{ marginBottom: '2rem' }}>
|
|
||||||
<label htmlFor="pan-upload">PAN Card Upload *</label>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
|
||||||
<input
|
|
||||||
id="pan-upload"
|
|
||||||
type="file"
|
|
||||||
accept=".pdf,image/*"
|
|
||||||
onChange={async (e) => {
|
|
||||||
if (e.target.files?.[0]) {
|
|
||||||
const file = e.target.files[0];
|
|
||||||
setPanFile(file.name);
|
|
||||||
alert(`PAN card selected: ${file.name}. Uploading...`);
|
|
||||||
const s3Key = await uploadDocument(file, 'pan');
|
|
||||||
setPanS3Key(s3Key);
|
|
||||||
alert(`PAN card uploaded successfully!`);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-outline-dark"
|
|
||||||
onClick={() => document.getElementById('pan-upload')?.click()}
|
|
||||||
>
|
|
||||||
📁 Select PAN File
|
|
||||||
</button>
|
|
||||||
<span style={{ fontSize: '0.9rem', color: 'var(--text-muted)' }}>
|
|
||||||
{panFile ? `Selected: ${panFile}` : 'No file uploaded yet'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
||||||
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(1)}>
|
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(3)}>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
||||||
disabled={!gstin || !aadharFile || !panFile}
|
disabled={!phoneVerified || !emailVerified}
|
||||||
>
|
>
|
||||||
Next Step: Store & Location
|
Next Step →
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{profileStep === 3 && (
|
{profileStep === 5 && (
|
||||||
<div>
|
<div>
|
||||||
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 3: Store Details & Location Map</h3>
|
<h3 style={{ fontSize: '1.1rem', marginBottom: '0.5rem', color: 'var(--primary)' }}>Step 5: Choose Product Categories</h3>
|
||||||
|
<p style={{ color: 'var(--text-muted)', marginBottom: '1.5rem', fontSize: '0.9rem' }}>
|
||||||
|
Select the categories that apply to your artisanal goods.
|
||||||
|
</p>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem', marginBottom: '2rem' }}>
|
||||||
|
{['Sustainable Products', 'Home Decor', 'Eco-Friendly', 'OPOD Products', 'GI Tagged', 'Textiles & Apparel'].map(cat => {
|
||||||
|
const isSelected = selectedCategories.includes(cat);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={cat}
|
||||||
|
onClick={() => {
|
||||||
|
if (isSelected) {
|
||||||
|
setSelectedCategories(selectedCategories.filter(c => c !== cat));
|
||||||
|
} else {
|
||||||
|
setSelectedCategories([...selectedCategories, cat]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
padding: '1rem',
|
||||||
|
border: isSelected ? '2px solid var(--primary)' : '1px solid var(--border)',
|
||||||
|
backgroundColor: isSelected ? 'rgba(107, 26, 44, 0.05)' : 'transparent',
|
||||||
|
borderRadius: '8px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
fontWeight: isSelected ? '600' : 'normal',
|
||||||
|
transition: 'all 0.2s ease',
|
||||||
|
textAlign: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{cat}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
||||||
|
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(4)}>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-primary"
|
||||||
|
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
||||||
|
disabled={selectedCategories.length === 0}
|
||||||
|
>
|
||||||
|
Next Step →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{profileStep === 6 && (
|
||||||
|
<div>
|
||||||
|
<h3 style={{ fontSize: '1.1rem', marginBottom: '1rem', color: 'var(--primary)' }}>Step 6: Store Details & Pickup Location</h3>
|
||||||
|
|
||||||
<div className="form-group">
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }} className="form-group">
|
||||||
<label htmlFor="store-name">Store Display Name *</label>
|
<div>
|
||||||
<input
|
<label htmlFor="store-name">Store Display Name *</label>
|
||||||
id="store-name"
|
<input
|
||||||
type="text"
|
id="store-name"
|
||||||
className="form-control"
|
type="text"
|
||||||
placeholder="Enter store name"
|
className="form-control"
|
||||||
value={storeName}
|
value={storeName}
|
||||||
onChange={(e) => setStoreName(e.target.value)}
|
onChange={(e) => setStoreName(e.target.value)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="store-slug">Store Slug / Custom URL *</label>
|
||||||
|
<input
|
||||||
|
id="store-slug"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="e.g. my-artisan-shop"
|
||||||
|
value={storeSlug}
|
||||||
|
onChange={(e) => setStoreSlug(e.target.value.toLowerCase().replace(/[^a-z0-9\-]/g, ''))}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }} className="form-group">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="support-email">Support Email *</label>
|
||||||
|
<input
|
||||||
|
id="support-email"
|
||||||
|
type="email"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="hello@shop.com"
|
||||||
|
value={supportEmail}
|
||||||
|
onChange={(e) => setSupportEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="support-phone">Support Phone *</label>
|
||||||
|
<input
|
||||||
|
id="support-phone"
|
||||||
|
type="tel"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="+91..."
|
||||||
|
value={supportPhone}
|
||||||
|
onChange={(e) => setSupportPhone(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label htmlFor="store-bio">About Your Craft / Business *</label>
|
<label htmlFor="store-bio">Store Description / Bio *</label>
|
||||||
<textarea
|
<textarea
|
||||||
id="store-bio"
|
id="store-bio"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
rows={2}
|
rows={2}
|
||||||
placeholder="Describe your craft, materials, and history..."
|
|
||||||
value={businessBio}
|
value={businessBio}
|
||||||
onChange={(e) => setBusinessBio(e.target.value)}
|
onChange={(e) => setBusinessBio(e.target.value)}
|
||||||
required
|
required
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Interactive Location Map Picker */}
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>Store Location on Map *</label>
|
<label>Store Location on Map *</label>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
height: '180px',
|
height: '150px',
|
||||||
backgroundColor: '#cbd5e1',
|
backgroundColor: '#cbd5e1',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
|
@ -1601,10 +1774,8 @@ export default function App() {
|
||||||
...prev,
|
...prev,
|
||||||
street: `Plot ${x}, Sector ${Math.round(y/10)}, Handicraft Park`
|
street: `Plot ${x}, Sector ${Math.round(y/10)}, Handicraft Park`
|
||||||
}));
|
}));
|
||||||
alert(`Location Pinned: Lat: ${(12.9 + y * 0.001).toFixed(4)}, Lng: ${(77.5 + x * 0.001).toFixed(4)}`);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Map Marker Pin */}
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|
@ -1613,43 +1784,28 @@ export default function App() {
|
||||||
transform: 'translate(-50%, -100%)',
|
transform: 'translate(-50%, -100%)',
|
||||||
fontSize: '2rem',
|
fontSize: '2rem',
|
||||||
color: 'var(--error)',
|
color: 'var(--error)',
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none'
|
||||||
textShadow: '0 2px 4px rgba(0,0,0,0.3)'
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
📍
|
📍
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<span style={{ fontSize: '0.85rem', color: '#475569', pointerEvents: 'none', fontWeight: 600 }}>Click map to pin location</span>
|
||||||
position: 'absolute',
|
|
||||||
bottom: '8px',
|
|
||||||
left: '8px',
|
|
||||||
backgroundColor: 'rgba(26, 43, 69, 0.85)',
|
|
||||||
color: 'white',
|
|
||||||
padding: '0.3rem 0.6rem',
|
|
||||||
borderRadius: '4px',
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
pointerEvents: 'none'
|
|
||||||
}}>
|
|
||||||
Coordinates: Lat {mapCoordinates.lat}, Lng {mapCoordinates.lng} (Click map to change pin)
|
|
||||||
</div>
|
|
||||||
<span style={{ fontSize: '0.85rem', color: '#475569', pointerEvents: 'none', fontWeight: 600 }}>Click anywhere on the map grid to pin location</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label htmlFor="location-text">Location in Text (Address) *</label>
|
<label htmlFor="location-text">Pickup Address *</label>
|
||||||
<input
|
<input
|
||||||
id="location-text"
|
id="location-text"
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder="Street, Landmark, District"
|
|
||||||
value={address.street}
|
value={address.street}
|
||||||
onChange={(e) => setAddress({ ...address, street: e.target.value })}
|
onChange={(e) => setAddress({ ...address, street: e.target.value })}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }} className="form-group">
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '0.5rem' }} className="form-group">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="loc-city">City *</label>
|
<label htmlFor="loc-city">City *</label>
|
||||||
<input
|
<input
|
||||||
|
|
@ -1661,13 +1817,23 @@ export default function App() {
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="loc-state">State *</label>
|
||||||
|
<input
|
||||||
|
id="loc-state"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
value={address.state}
|
||||||
|
onChange={(e) => setAddress({ ...address, state: e.target.value })}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="loc-pincode">Pincode *</label>
|
<label htmlFor="loc-pincode">Pincode *</label>
|
||||||
<input
|
<input
|
||||||
id="loc-pincode"
|
id="loc-pincode"
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
placeholder="6-digit Pincode"
|
|
||||||
value={address.pincode}
|
value={address.pincode}
|
||||||
onChange={(e) => setAddress({ ...address, pincode: e.target.value })}
|
onChange={(e) => setAddress({ ...address, pincode: e.target.value })}
|
||||||
required
|
required
|
||||||
|
|
@ -1676,79 +1842,45 @@ export default function App() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', marginTop: '2rem' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', marginTop: '2rem' }}>
|
||||||
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(2)}>
|
<button type="button" className="btn btn-outline-dark" style={{ flex: 1 }} onClick={() => setProfileStep(5)}>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
style={{ flex: 1, backgroundColor: 'var(--accent)', color: 'var(--primary)', fontWeight: 'bold' }}
|
||||||
|
disabled={!storeName || !storeSlug || !supportEmail || !supportPhone || !address.street || !address.city || !address.state || !address.pincode}
|
||||||
>
|
>
|
||||||
Submit Supplier Profile
|
Submit Supplier Profile
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{profileStep === 7 && (
|
||||||
|
<div style={{ textAlign: 'center', padding: '1rem' }}>
|
||||||
|
<div style={{ fontSize: '4rem', marginBottom: '1.5rem' }}>🎉</div>
|
||||||
|
<h3 style={{ fontSize: '1.25rem', marginBottom: '1rem', color: 'var(--primary)' }}>Setup Complete!</h3>
|
||||||
|
<p style={{ color: 'var(--text-muted)', marginBottom: '2rem', fontSize: '0.95rem' }}>
|
||||||
|
Your supplier profile has been successfully submitted and is under review. You can now access your preview dashboard.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-dark"
|
||||||
|
style={{ width: '100%', padding: '0.8rem', fontWeight: 'bold' }}
|
||||||
|
onClick={() => {
|
||||||
|
setIsProfileComplete(true);
|
||||||
|
navigateTo('welcome-tour', true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Go to Dashboard
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ONBOARDING CONFIRMATION / REVIEW STATUS VIEW (Step 3 of 3) */}
|
|
||||||
{currentPage === 'confirmation' && (
|
|
||||||
<div className="form-card" style={{ maxWidth: '640px', textAlign: 'center' }}>
|
|
||||||
<div className="step-progress-wrapper">
|
|
||||||
<span className="step-label">Step 3 of 3: Verification</span>
|
|
||||||
<div className="step-bar-container">
|
|
||||||
<div className="step-bar-fill" style={{ width: '100%' }}></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={{ fontSize: '4rem', marginBottom: '1.5rem' }}>🎉</div>
|
|
||||||
<h2 className="form-card-title">Welcome to {CONFIG.companyName}!</h2>
|
|
||||||
|
|
||||||
<p style={{ color: 'var(--text-muted)', marginBottom: '2rem', fontSize: '1.05rem' }}>
|
|
||||||
Your registration is under review. We will verify your GSTIN credentials and activate your dashboard access within 24-48 hours.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="conf-dashboard-preview">
|
|
||||||
<div className="mock-dash-header">
|
|
||||||
<div className="mock-dash-dot"></div>
|
|
||||||
<div className="mock-dash-dot"></div>
|
|
||||||
<div className="mock-dash-dot"></div>
|
|
||||||
</div>
|
|
||||||
<div className="mock-dash-body">
|
|
||||||
<div className="mock-dash-card">
|
|
||||||
<div className="mock-dash-card-title">Total Sales</div>
|
|
||||||
<div className="mock-dash-card-val">$0.00</div>
|
|
||||||
</div>
|
|
||||||
<div className="mock-dash-card">
|
|
||||||
<div className="mock-dash-card-title">Active Orders</div>
|
|
||||||
<div className="mock-dash-card-val">0</div>
|
|
||||||
</div>
|
|
||||||
<div className="mock-dash-card">
|
|
||||||
<div className="mock-dash-card-title">Balance</div>
|
|
||||||
<div className="mock-dash-card-val">$0.00</div>
|
|
||||||
</div>
|
|
||||||
<div className="mock-dash-chart">
|
|
||||||
<div className="mock-chart-bar" style={{ height: '40px' }}></div>
|
|
||||||
<div className="mock-chart-bar" style={{ height: '60px' }}></div>
|
|
||||||
<div className="mock-chart-bar" style={{ height: '50px' }}></div>
|
|
||||||
<div className="mock-chart-bar active" style={{ height: '80px' }}></div>
|
|
||||||
<div className="mock-chart-bar" style={{ height: '30px' }}></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
className="btn btn-dark"
|
|
||||||
style={{ marginTop: '2.5rem', width: '100%', padding: '0.8rem' }}
|
|
||||||
onClick={() => navigateTo('dashboard')}
|
|
||||||
>
|
|
||||||
Go to Dashboard (Preview Only)
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* WELCOME PAGE & SETUP TOUR FOR NEW SELLERS */}
|
{/* WELCOME PAGE & SETUP TOUR FOR NEW SELLERS */}
|
||||||
{currentPage === 'welcome-tour' && (
|
{currentPage === 'welcome-tour' && (
|
||||||
<WelcomeTourWizard onComplete={() => navigateTo('dashboard')} />
|
<WelcomeTourWizard onComplete={() => navigateTo('dashboard')} />
|
||||||
|
|
@ -2494,17 +2626,35 @@ export default function App() {
|
||||||
<div className="form-card" style={{ margin: 0, maxWidth: '640px' }}>
|
<div className="form-card" style={{ margin: 0, maxWidth: '640px' }}>
|
||||||
<h2 className="form-card-title" style={{ textAlign: 'left', marginBottom: '2rem' }}>Store Configurations</h2>
|
<h2 className="form-card-title" style={{ textAlign: 'left', marginBottom: '2rem' }}>Store Configurations</h2>
|
||||||
|
|
||||||
<form onSubmit={e => { e.preventDefault(); alert('Store configurations updated successfully!'); }}>
|
<form onSubmit={e => {
|
||||||
<div className="form-group">
|
e.preventDefault();
|
||||||
<label htmlFor="set-store">Store Display Name *</label>
|
saveProfileBackend(true)
|
||||||
<input
|
.then(() => alert('Store configurations updated successfully!'))
|
||||||
id="set-store"
|
.catch(err => alert(err.message));
|
||||||
type="text"
|
}}>
|
||||||
className="form-control"
|
<div className="form-group" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }}>
|
||||||
value={storeName}
|
<div>
|
||||||
onChange={e => setStoreName(e.target.value)}
|
<label htmlFor="set-store">Store Display Name *</label>
|
||||||
required
|
<input
|
||||||
/>
|
id="set-store"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
value={storeName}
|
||||||
|
onChange={e => setStoreName(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="set-slug">Store Slug / Custom URL *</label>
|
||||||
|
<input
|
||||||
|
id="set-slug"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
value={storeSlug}
|
||||||
|
onChange={e => setStoreSlug(e.target.value.toLowerCase().replace(/[^a-z0-9\-]/g, ''))}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
|
|
@ -2526,6 +2676,31 @@ export default function App() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }}>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="set-email">Support Email *</label>
|
||||||
|
<input
|
||||||
|
id="set-email"
|
||||||
|
type="email"
|
||||||
|
className="form-control"
|
||||||
|
value={supportEmail}
|
||||||
|
onChange={e => setSupportEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="set-phone">Support Phone *</label>
|
||||||
|
<input
|
||||||
|
id="set-phone"
|
||||||
|
type="tel"
|
||||||
|
className="form-control"
|
||||||
|
value={supportPhone}
|
||||||
|
onChange={e => setSupportPhone(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label htmlFor="set-bio">About Your Craft / Business</label>
|
<label htmlFor="set-bio">About Your Craft / Business</label>
|
||||||
<textarea
|
<textarea
|
||||||
|
|
@ -2537,6 +2712,31 @@ export default function App() {
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Product Categories</label>
|
||||||
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.5rem', marginTop: '0.5rem' }}>
|
||||||
|
{['Sustainable Products', 'Home Decor', 'Eco-Friendly', 'OPOD Products', 'GI Tagged', 'Textiles & Apparel'].map(cat => {
|
||||||
|
const isSelected = selectedCategories.includes(cat);
|
||||||
|
return (
|
||||||
|
<label key={cat} style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', cursor: 'pointer', padding: '0.5rem', border: '1px solid var(--border)', borderRadius: '4px' }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isSelected}
|
||||||
|
onChange={() => {
|
||||||
|
if (isSelected) {
|
||||||
|
setSelectedCategories(selectedCategories.filter(c => c !== cat));
|
||||||
|
} else {
|
||||||
|
setSelectedCategories([...selectedCategories, cat]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{cat}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>Pickup Location Address *</label>
|
<label>Pickup Location Address *</label>
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '0.75rem', marginBottom: '0.75rem' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '0.75rem', marginBottom: '0.75rem' }}>
|
||||||
|
|
@ -2577,17 +2777,27 @@ export default function App() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }}>
|
||||||
<label htmlFor="set-gstin">GSTIN Number</label>
|
<div>
|
||||||
<input
|
<label htmlFor="set-business-type">Business Type</label>
|
||||||
id="set-gstin"
|
<input
|
||||||
type="text"
|
id="set-business-type"
|
||||||
className="form-control"
|
type="text"
|
||||||
value={gstin}
|
className="form-control"
|
||||||
onChange={e => setGstin(e.target.value)}
|
value={businessType.replace('_', ' ').toUpperCase()}
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
<p style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginTop: '0.25rem' }}>GSTIN cannot be modified after verification.</p>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="set-gstin">GSTIN Number</label>
|
||||||
|
<input
|
||||||
|
id="set-gstin"
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
value={gstin}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" className="btn btn-dark" style={{ width: '100%', marginTop: '2rem' }}>
|
<button type="submit" className="btn btn-dark" style={{ width: '100%', marginTop: '2rem' }}>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue