new login screen added
This commit is contained in:
parent
6c7640737e
commit
26604fd7d1
BIN
public/assets/images/Re_Logo.png
Normal file
BIN
public/assets/images/Re_Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
public/assets/images/become_a_dealer.webp
Normal file
BIN
public/assets/images/become_a_dealer.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 255 KiB |
@ -1,14 +1,10 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Button } from '../ui/button';
|
import { Button } from '../ui/button';
|
||||||
import { Input } from '../ui/input';
|
import { Input } from '../ui/input';
|
||||||
import { Label } from '../ui/label';
|
|
||||||
import { Textarea } from '../ui/textarea';
|
import { Textarea } from '../ui/textarea';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
|
|
||||||
import { RadioGroup, RadioGroupItem } from '../ui/radio-group';
|
|
||||||
import { Checkbox } from '../ui/checkbox';
|
import { Checkbox } from '../ui/checkbox';
|
||||||
import { CheckCircle, Users, Star, LogIn, Award, TrendingUp, Handshake } from 'lucide-react';
|
import { LogIn, ChevronRight, ChevronDown } from 'lucide-react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
// import backgroundImage from 'figma:asset/ee01d864b6e23a8197b42f3168c98eedec9d2440.png';
|
|
||||||
import { onboardingService } from '../../services/onboarding.service';
|
import { onboardingService } from '../../services/onboarding.service';
|
||||||
import { masterService } from '../../services/master.service';
|
import { masterService } from '../../services/master.service';
|
||||||
|
|
||||||
@ -18,7 +14,7 @@ interface ApplicationFormPageProps {
|
|||||||
|
|
||||||
export function ApplicationFormPage({ onAdminLogin }: ApplicationFormPageProps) {
|
export function ApplicationFormPage({ onAdminLogin }: ApplicationFormPageProps) {
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
country: 'India', // Default to India
|
country: 'India',
|
||||||
stateId: '',
|
stateId: '',
|
||||||
districtId: '',
|
districtId: '',
|
||||||
name: '',
|
name: '',
|
||||||
@ -38,19 +34,16 @@ export function ApplicationFormPage({ onAdminLogin }: ApplicationFormPageProps)
|
|||||||
acceptTerms: false
|
acceptTerms: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [otpVerified, setOtpVerified] = useState(false);
|
||||||
const [states, setStates] = useState<any[]>([]);
|
const [states, setStates] = useState<any[]>([]);
|
||||||
const [districts, setDistricts] = useState<any[]>([]);
|
const [districts, setDistricts] = useState<any[]>([]);
|
||||||
const [fetchingStates, setFetchingStates] = useState(false);
|
|
||||||
const [fetchingDistricts, setFetchingDistricts] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchStates();
|
fetchStates();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchStates = async () => {
|
const fetchStates = async () => {
|
||||||
setFetchingStates(true);
|
|
||||||
try {
|
try {
|
||||||
// ZoneID is optional, public API should return all states if no zone override
|
|
||||||
const response: any = await masterService.getStates();
|
const response: any = await masterService.getStates();
|
||||||
if (response && response.data) {
|
if (response && response.data) {
|
||||||
setStates(response.data);
|
setStates(response.data);
|
||||||
@ -59,40 +52,36 @@ export function ApplicationFormPage({ onAdminLogin }: ApplicationFormPageProps)
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching states:', error);
|
console.error('Error fetching states:', error);
|
||||||
toast.error('Failed to load states. Please refresh the page.');
|
|
||||||
} finally {
|
|
||||||
setFetchingStates(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStateChange = async (selectedState: any) => {
|
const handleStateChange = async (stateId: string) => {
|
||||||
if (!selectedState) return;
|
if (!stateId) return;
|
||||||
|
setFormData(prev => ({ ...prev, stateId, districtId: '' }));
|
||||||
setFormData(prev => ({ ...prev, stateId: selectedState.id, districtId: '' }));
|
|
||||||
setDistricts([]);
|
setDistricts([]);
|
||||||
setFetchingDistricts(true);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response: any = await masterService.getDistricts(selectedState.id);
|
const response: any = await masterService.getDistricts(stateId);
|
||||||
if (response && response.data) {
|
if (response && response.data) setDistricts(response.data);
|
||||||
setDistricts(response.data);
|
else if (response && response.districts) setDistricts(response.districts);
|
||||||
} else if (response && response.districts) {
|
|
||||||
setDistricts(response.districts);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching districts:', error);
|
console.error('Error fetching districts:', error);
|
||||||
toast.error('Failed to load districts.');
|
|
||||||
} finally {
|
|
||||||
setFetchingDistricts(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleVerifyMobile = () => {
|
||||||
|
if (!formData.mobile || formData.mobile.length < 10) {
|
||||||
|
toast.error('Please enter a valid mobile number');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast.success('OTP sent to ' + formData.mobile);
|
||||||
|
setTimeout(() => {
|
||||||
|
setOtpVerified(true);
|
||||||
|
toast.success('Mobile number verified');
|
||||||
|
}, 1500);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Validate required fields
|
|
||||||
if (!formData.country || !formData.stateId || !formData.districtId || !formData.name ||
|
if (!formData.country || !formData.stateId || !formData.districtId || !formData.name ||
|
||||||
!formData.interestedCity || !formData.email || !formData.pincode || !formData.mobile ||
|
!formData.interestedCity || !formData.email || !formData.pincode || !formData.mobile ||
|
||||||
!formData.ownRoyalEnfield || !formData.age || !formData.education ||
|
!formData.ownRoyalEnfield || !formData.age || !formData.education ||
|
||||||
@ -102,9 +91,8 @@ export function ApplicationFormPage({ onAdminLogin }: ApplicationFormPageProps)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate Royal Enfield model
|
if (!otpVerified) {
|
||||||
if (formData.ownRoyalEnfield === 'yes' && !formData.royalEnfieldModel) {
|
toast.error('Please verify your mobile number');
|
||||||
toast.error('Please select your Royal Enfield model');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,605 +107,338 @@ export function ApplicationFormPage({ onAdminLogin }: ApplicationFormPageProps)
|
|||||||
const stateName = selectedState?.name || selectedState?.stateName || '';
|
const stateName = selectedState?.name || selectedState?.stateName || '';
|
||||||
const districtName = selectedDistrict?.name || selectedDistrict?.districtName || '';
|
const districtName = selectedDistrict?.name || selectedDistrict?.districtName || '';
|
||||||
|
|
||||||
// Map form data to backend expected format
|
|
||||||
const payload = {
|
const payload = {
|
||||||
applicantName: formData.name,
|
applicantName: formData.name,
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
phone: formData.mobile,
|
phone: formData.mobile,
|
||||||
state: stateName,
|
state: stateName,
|
||||||
city: formData.interestedCity, // Or district?
|
city: formData.interestedCity,
|
||||||
district: districtName, // Backward compatibility
|
district: districtName,
|
||||||
preferredLocation: `${formData.interestedCity}, ${stateName}`,
|
preferredLocation: `${formData.interestedCity}, ${stateName}`,
|
||||||
businessType: 'Dealership', // Default or derived
|
businessType: 'Dealership',
|
||||||
locationType: 'district',
|
locationType: 'district',
|
||||||
locationId: formData.districtId,
|
locationId: formData.districtId,
|
||||||
address: formData.address, // Need backend support?
|
address: formData.address,
|
||||||
pincode: formData.pincode, // Need backend support?
|
pincode: formData.pincode,
|
||||||
age: formData.age,
|
age: formData.age,
|
||||||
education: formData.education,
|
education: formData.education,
|
||||||
companyName: formData.companyName,
|
companyName: formData.companyName,
|
||||||
source: formData.source,
|
source: formData.source,
|
||||||
existingDealer: formData.existingDealer,
|
existingDealer: formData.existingDealer === 'yes',
|
||||||
ownRoyalEnfield: formData.ownRoyalEnfield,
|
ownRoyalEnfield: formData.ownRoyalEnfield === 'yes',
|
||||||
royalEnfieldModel: formData.royalEnfieldModel,
|
royalEnfieldModel: formData.royalEnfieldModel,
|
||||||
description: formData.description,
|
description: formData.description,
|
||||||
// flexible fields for now
|
experienceYears: 0,
|
||||||
experienceYears: 0, // Not in form
|
investmentCapacity: 'Unknown'
|
||||||
investmentCapacity: 'Unknown' // Not in form
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await onboardingService.submitApplication(payload);
|
await onboardingService.submitApplication(payload);
|
||||||
toast.success('Application submitted successfully! We will contact you soon.');
|
toast.success('Application submitted successfully');
|
||||||
|
|
||||||
// Reset form
|
|
||||||
setFormData({
|
setFormData({
|
||||||
country: 'India', stateId: '', districtId: '', name: '', interestedCity: '',
|
country: 'India', stateId: '', districtId: '', name: '', interestedCity: '',
|
||||||
email: '', pincode: '', mobile: '', ownRoyalEnfield: '', royalEnfieldModel: '',
|
email: '', pincode: '', mobile: '', ownRoyalEnfield: '', royalEnfieldModel: '',
|
||||||
age: '', education: '', companyName: '', source: '', existingDealer: '',
|
age: '', education: '', companyName: '', source: '', existingDealer: '',
|
||||||
description: '', address: '', acceptTerms: false
|
description: '', address: '', acceptTerms: false
|
||||||
});
|
});
|
||||||
|
setOtpVerified(false);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(error.response?.data?.message || 'Failed to submit application.');
|
toast.error(error.response?.data?.message || 'Failed to submit application.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const reModels = [
|
||||||
|
"Classic 650", "Scram 440", "Goan Classic 350", "Bear 650", "Guerrilla 450",
|
||||||
|
"Shotgun 650", "Himalayan 450", "Bullet 350", "Super Meteor 650", "Hunter 350",
|
||||||
|
"Scram 411", "Meteor 350", "Interceptor INT 650", "Continental GT 650",
|
||||||
|
"Classic 350", "Other Royal Enfield motorcycle"
|
||||||
|
];
|
||||||
|
|
||||||
|
const sourceOptions = [
|
||||||
|
"Existing RE dealer", "Customer", "RE Employee", "News Paper", "Website", "Friends", "Others"
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-slate-950">
|
<div className="min-h-screen relative flex flex-col font-['Montserrat']">
|
||||||
{/* Header */}
|
{/* Background Image Wrapper */}
|
||||||
<header className="bg-black/90 backdrop-blur-md border-b border-amber-500/20 sticky top-0 z-50 shadow-xl">
|
<div className="fixed inset-0 z-0">
|
||||||
<div className="max-w-7xl mx-auto px-6 py-5 flex items-center justify-between">
|
<img
|
||||||
<div className="flex items-center gap-4">
|
src="/assets/images/become_a_dealer.webp"
|
||||||
<div className="w-12 h-12 bg-gradient-to-br from-amber-500 to-orange-600 rounded-lg flex items-center justify-center shadow-lg">
|
alt="Royal Enfield Background"
|
||||||
<span className="text-white text-xl">RE</span>
|
className="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 bg-black/20" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<h1 className="text-white text-2xl tracking-tight">Royal Enfield</h1>
|
{/* Navigation Header */}
|
||||||
<p className="text-amber-400/80 text-xs tracking-wide uppercase">Dealer Partnership Portal</p>
|
<nav className="relative z-10 bg-black px-6 md:px-12 py-4 flex items-center justify-between border-b border-white/10">
|
||||||
</div>
|
<img src="/assets/images/Re_Logo.png" alt="Royal Enfield" className="h-10 md:h-12 w-auto" />
|
||||||
</div>
|
<Button variant="ghost" onClick={onAdminLogin} className="text-[10px] uppercase tracking-widest font-bold text-slate-400 hover:text-white transition-colors">
|
||||||
<Button
|
<LogIn className="w-3.5 h-3.5 mr-2" />
|
||||||
variant="outline"
|
Login
|
||||||
onClick={onAdminLogin}
|
|
||||||
className="flex items-center gap-2 bg-white/5 border-amber-500/30 text-amber-400 hover:bg-amber-500/10 hover:border-amber-500/50 hover:text-amber-300 transition-all"
|
|
||||||
>
|
|
||||||
<LogIn className="w-4 h-4" />
|
|
||||||
Admin Login
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</nav>
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Main Content Area over the background */}
|
||||||
<section className="relative py-24 overflow-hidden">
|
<main className="relative z-10 flex-grow flex flex-col items-center pt-24 pb-24 px-6">
|
||||||
<div className="absolute inset-0 bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950"></div>
|
{/* Content Container with white background */}
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,rgba(251,191,36,0.1),transparent_50%)]"></div>
|
<div className="w-full max-w-[1240px] bg-white shadow-2xl p-8 md:p-16">
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_bottom_left,rgba(251,146,60,0.1),transparent_50%)]"></div>
|
|
||||||
|
|
||||||
<div className="max-w-7xl mx-auto px-6 text-center relative z-10">
|
{/* Introductory Text */}
|
||||||
<div className="inline-block mb-6">
|
<section className="text-[#333333] mb-12">
|
||||||
<div className="bg-amber-500/10 border border-amber-500/30 rounded-full px-6 py-2">
|
<h1 className="text-[28px] font-bold mb-8 uppercase tracking-wide text-black">Become a Dealer</h1>
|
||||||
<p className="text-amber-400 text-sm tracking-wide">Since 1901 • Legacy of Excellence</p>
|
<div className="space-y-6 text-[15px] leading-relaxed">
|
||||||
</div>
|
<p>
|
||||||
</div>
|
At Royal Enfield, we endeavour to partner our patrons and customers in their journeys of exploration. Our main objective is to provide an immersive brand and retail experience in addition to ensuring a superior product experience. Our dealers, distributors and network teams are our extended partners in this task.
|
||||||
<h1 className="text-5xl md:text-6xl text-white mb-6 tracking-tight">
|
</p>
|
||||||
Join the Royal Enfield
|
<p>
|
||||||
<span className="block text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-orange-500">
|
Royal Enfield employs a comprehensive and professional process for Dealership allotment. Dealer selection is done based on a variety of criteria including a personal meeting with the applicant. It is only post completion of the evaluation and selection process, that other formalities are considered.
|
||||||
Partnership Network
|
</p>
|
||||||
</span>
|
<p>
|
||||||
</h1>
|
Royal Enfield does not accept or demand money / deposits from prospective partners prior to processing the application or candidature of the Dealership.
|
||||||
<p className="text-slate-300 text-lg md:text-xl max-w-3xl mx-auto mb-12 leading-relaxed">
|
</p>
|
||||||
Become part of our legendary heritage and bring the spirit of Pure Motorcycling to riders in your community
|
<p>
|
||||||
|
If you receive any communication offering allotment of Royal Enfield Dealership against payment / transfer of money and / or otherwise, we advise you to seek information / clarifications by writing to us at <b><a href="mailto:support@royalenfield.com" className="text-red-600">support@royalenfield.com</a></b> or by contacting us on our customer care toll-free number <b><a href="tel:18002100008" className="text-red-600">1800 210 0008</a></b>.
|
||||||
|
</p>
|
||||||
|
<p className="font-bold py-1 mt-8 text-black text-[15px]">
|
||||||
|
*This is the ONLY official website and central number for dealership enquiries for Royal Enfield and we do not have any other partner website(s).
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center gap-8">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-10 h-10 rounded-full bg-amber-500/20 flex items-center justify-center">
|
|
||||||
<CheckCircle className="w-5 h-5 text-amber-400" />
|
|
||||||
</div>
|
|
||||||
<span className="text-slate-200">120+ Year Heritage</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-10 h-10 rounded-full bg-amber-500/20 flex items-center justify-center">
|
|
||||||
<CheckCircle className="w-5 h-5 text-amber-400" />
|
|
||||||
</div>
|
|
||||||
<span className="text-slate-200">Global Recognition</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-10 h-10 rounded-full bg-amber-500/20 flex items-center justify-center">
|
|
||||||
<CheckCircle className="w-5 h-5 text-amber-400" />
|
|
||||||
</div>
|
|
||||||
<span className="text-slate-200">Premium Support</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Why Partner Section */}
|
{/* Form */}
|
||||||
<section className="py-20 bg-slate-900/50">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
<div className="max-w-7xl mx-auto px-6">
|
{/* Country Selection */}
|
||||||
<div className="text-center mb-16">
|
|
||||||
<h2 className="text-4xl text-white mb-4">Why Partner With Royal Enfield?</h2>
|
|
||||||
<p className="text-slate-400 text-lg">Unmatched benefits for ambitious entrepreneurs</p>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
||||||
{/* Premium Brand */}
|
|
||||||
<div className="group relative bg-gradient-to-br from-slate-800/50 to-slate-900/50 backdrop-blur border border-slate-700/50 rounded-2xl p-8 text-center hover:border-amber-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-amber-500/10">
|
|
||||||
<div className="w-16 h-16 bg-gradient-to-br from-amber-500 to-orange-600 rounded-2xl flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform shadow-lg">
|
|
||||||
<Star className="w-8 h-8 text-white" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-white text-xl mb-3">Premium Brand</h3>
|
|
||||||
<p className="text-slate-400 text-sm leading-relaxed">
|
|
||||||
Represent a legendary brand trusted by millions worldwide since 1901
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Strong Support */}
|
|
||||||
<div className="group relative bg-gradient-to-br from-slate-800/50 to-slate-900/50 backdrop-blur border border-slate-700/50 rounded-2xl p-8 text-center hover:border-amber-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-amber-500/10">
|
|
||||||
<div className="w-16 h-16 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-2xl flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform shadow-lg">
|
|
||||||
<Handshake className="w-8 h-8 text-white" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-white text-xl mb-3">Complete Support</h3>
|
|
||||||
<p className="text-slate-400 text-sm leading-relaxed">
|
|
||||||
Comprehensive training, marketing, and ongoing operational support
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Growth Opportunity */}
|
|
||||||
<div className="group relative bg-gradient-to-br from-slate-800/50 to-slate-900/50 backdrop-blur border border-slate-700/50 rounded-2xl p-8 text-center hover:border-amber-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-amber-500/10">
|
|
||||||
<div className="w-16 h-16 bg-gradient-to-br from-emerald-500 to-teal-600 rounded-2xl flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform shadow-lg">
|
|
||||||
<TrendingUp className="w-8 h-8 text-white" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-white text-xl mb-3">Growth Potential</h3>
|
|
||||||
<p className="text-slate-400 text-sm leading-relaxed">
|
|
||||||
Tap into expanding markets with increasing customer demand
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Proven Success */}
|
|
||||||
<div className="group relative bg-gradient-to-br from-slate-800/50 to-slate-900/50 backdrop-blur border border-slate-700/50 rounded-2xl p-8 text-center hover:border-amber-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-amber-500/10">
|
|
||||||
<div className="w-16 h-16 bg-gradient-to-br from-purple-500 to-pink-600 rounded-2xl flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform shadow-lg">
|
|
||||||
<Award className="w-8 h-8 text-white" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-white text-xl mb-3">Proven Model</h3>
|
|
||||||
<p className="text-slate-400 text-sm leading-relaxed">
|
|
||||||
Join thousands of successful dealers in our global network
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Application Form Section */}
|
|
||||||
<section className="relative py-24 overflow-hidden">
|
|
||||||
{/* Background Image with Overlay */}
|
|
||||||
<div className="absolute inset-0">
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-br from-slate-950/95 via-slate-900/90 to-slate-950/95 backdrop-blur-sm"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="max-w-4xl mx-auto px-6 relative z-10">
|
|
||||||
<div className="text-center mb-12">
|
|
||||||
<div className="inline-block mb-4">
|
|
||||||
<div className="bg-amber-500/10 border border-amber-500/30 rounded-full px-5 py-2">
|
|
||||||
<p className="text-amber-400 text-sm tracking-wide">Start Your Journey</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h2 className="text-4xl text-white mb-4">Dealership Application</h2>
|
|
||||||
<p className="text-slate-300 text-lg">
|
|
||||||
Complete the form below to begin your partnership with Royal Enfield
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="bg-slate-900/60 backdrop-blur-xl rounded-3xl border border-slate-700/50 p-10 shadow-2xl">
|
|
||||||
<div className="space-y-7">
|
|
||||||
{/* Name & Email */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="name" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<Users className="w-4 h-4 text-amber-400" />
|
|
||||||
Full Name <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="name"
|
|
||||||
placeholder="Enter your full name"
|
|
||||||
value={formData.name}
|
|
||||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="email" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">✉️</span>
|
|
||||||
Email Address <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="email"
|
|
||||||
type="email"
|
|
||||||
placeholder="your-email@example.com"
|
|
||||||
value={formData.email}
|
|
||||||
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Mobile & Age */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="mobile" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">📱</span>
|
|
||||||
Mobile Number <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="mobile"
|
|
||||||
type="tel"
|
|
||||||
placeholder="+91 98765 43210"
|
|
||||||
value={formData.mobile}
|
|
||||||
onChange={(e) => setFormData({ ...formData, mobile: e.target.value })}
|
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="age" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">👤</span>
|
|
||||||
Age <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="age"
|
|
||||||
type="number"
|
|
||||||
placeholder="Enter your age"
|
|
||||||
value={formData.age}
|
|
||||||
onChange={(e) => setFormData({ ...formData, age: e.target.value })}
|
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Country, State, District */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
<div>
|
<div className="relative">
|
||||||
<Label htmlFor="country" className="flex items-center gap-2 text-slate-200 mb-3">
|
<select
|
||||||
<span className="text-amber-400">🌍</span>
|
className="w-full h-[44px] px-4 border border-[#cccccc] appearance-none bg-white text-[14px] outline-none"
|
||||||
Country <span className="text-amber-500">*</span>
|
value={formData.country}
|
||||||
</Label>
|
onChange={(e) => setFormData({...formData, country: e.target.value})}
|
||||||
<Select value={formData.country} onValueChange={(value) => setFormData({ ...formData, country: value })} disabled>
|
>
|
||||||
<SelectTrigger className="bg-slate-800/50 border-slate-600/50 text-white focus:border-amber-500/50 focus:ring-amber-500/20 disabled:opacity-70 disabled:cursor-not-allowed">
|
<option value="India">India</option>
|
||||||
<SelectValue placeholder="Select country" />
|
<option value="Other">Others</option>
|
||||||
</SelectTrigger>
|
</select>
|
||||||
<SelectContent className="bg-slate-800 border-slate-700 text-white">
|
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500 pointer-events-none" />
|
||||||
<SelectItem value="India">India</SelectItem>
|
|
||||||
<SelectItem value="Nepal">Nepal</SelectItem>
|
|
||||||
<SelectItem value="Bangladesh">Bangladesh</SelectItem>
|
|
||||||
<SelectItem value="Sri Lanka">Sri Lanka</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="relative">
|
||||||
<Label htmlFor="state" className="flex items-center gap-2 text-slate-200 mb-3">
|
<select
|
||||||
<span className="text-amber-400">🏛️</span>
|
className="w-full h-[44px] px-4 border border-[#cccccc] appearance-none bg-white text-[14px] outline-none"
|
||||||
State <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Select
|
|
||||||
value={formData.stateId}
|
value={formData.stateId}
|
||||||
onValueChange={(value) => {
|
onChange={(e) => handleStateChange(e.target.value)}
|
||||||
const selectedState = states.find((s: any) => s.id === value);
|
|
||||||
handleStateChange(selectedState);
|
|
||||||
}}
|
|
||||||
disabled={fetchingStates}
|
|
||||||
>
|
>
|
||||||
<SelectTrigger className="bg-slate-800/50 border-slate-600/50 text-white focus:border-amber-500/50 focus:ring-amber-500/20">
|
<option value="">Select State*</option>
|
||||||
<SelectValue placeholder={fetchingStates ? "Loading states..." : "Select state"} />
|
{states.map(s => <option key={s.id} value={s.id}>{s.name || s.stateName}</option>)}
|
||||||
</SelectTrigger>
|
</select>
|
||||||
<SelectContent className="bg-slate-800 border-slate-700 text-white h-64">
|
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500 pointer-events-none" />
|
||||||
{states.map((state: any) => (
|
|
||||||
<SelectItem key={state.id} value={state.id}>
|
|
||||||
{state.name || state.stateName}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="relative">
|
||||||
<Label htmlFor="district" className="flex items-center gap-2 text-slate-200 mb-3">
|
<select
|
||||||
<span className="text-amber-400">📍</span>
|
className="w-full h-[44px] px-4 border border-[#cccccc] appearance-none bg-white text-[14px] outline-none"
|
||||||
District <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Select
|
|
||||||
value={formData.districtId}
|
value={formData.districtId}
|
||||||
onValueChange={(value) => setFormData({ ...formData, districtId: value })}
|
onChange={(e) => setFormData({...formData, districtId: e.target.value})}
|
||||||
disabled={!formData.stateId || fetchingDistricts}
|
|
||||||
>
|
>
|
||||||
<SelectTrigger className="bg-slate-800/50 border-slate-600/50 text-white focus:border-amber-500/50 focus:ring-amber-500/20">
|
<option value="">Select District*</option>
|
||||||
<SelectValue placeholder={fetchingDistricts ? "Loading districts..." : "Select district"} />
|
{districts.map(d => <option key={d.id} value={d.id}>{d.name || d.districtName}</option>)}
|
||||||
</SelectTrigger>
|
</select>
|
||||||
<SelectContent className="bg-slate-800 border-slate-700 text-white h-64">
|
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500 pointer-events-none" />
|
||||||
{districts.map((district: any) => (
|
|
||||||
<SelectItem key={district.id} value={district.id}>
|
|
||||||
{district.name || district.districtName}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Interested City & Pincode */}
|
{/* Personal Details - Two Column */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-10 gap-y-6">
|
||||||
<div>
|
|
||||||
<Label htmlFor="interestedCity" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">🏙️</span>
|
|
||||||
Interested City for Dealership <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
<Input
|
||||||
id="interestedCity"
|
placeholder="Name*"
|
||||||
placeholder="Enter city name"
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
|
value={formData.name}
|
||||||
|
onChange={(e) => setFormData({...formData, name: e.target.value})}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
placeholder="Interested city for Dealership*"
|
||||||
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
value={formData.interestedCity}
|
value={formData.interestedCity}
|
||||||
onChange={(e) => setFormData({ ...formData, interestedCity: e.target.value })}
|
onChange={(e) => setFormData({...formData, interestedCity: e.target.value})}
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="pincode" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">📮</span>
|
|
||||||
Pincode <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
<Input
|
||||||
id="pincode"
|
placeholder="Email Id*"
|
||||||
type="text"
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
placeholder="Enter pincode"
|
value={formData.email}
|
||||||
|
onChange={(e) => setFormData({...formData, email: e.target.value})}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
placeholder="Pincode*"
|
||||||
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
value={formData.pincode}
|
value={formData.pincode}
|
||||||
onChange={(e) => setFormData({ ...formData, pincode: e.target.value })}
|
onChange={(e) => setFormData({...formData, pincode: e.target.value})}
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Education & Company Name */}
|
<div className="relative">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="education" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">🎓</span>
|
|
||||||
Education Qualification <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Select value={formData.education} onValueChange={(value) => setFormData({ ...formData, education: value })}>
|
|
||||||
<SelectTrigger className="bg-slate-800/50 border-slate-600/50 text-white focus:border-amber-500/50 focus:ring-amber-500/20">
|
|
||||||
<SelectValue placeholder="Select qualification" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent className="bg-slate-800 border-slate-700 text-white">
|
|
||||||
<SelectItem value="high-school">High School</SelectItem>
|
|
||||||
<SelectItem value="diploma">Diploma</SelectItem>
|
|
||||||
<SelectItem value="bachelors">Bachelor's Degree</SelectItem>
|
|
||||||
<SelectItem value="masters">Master's Degree</SelectItem>
|
|
||||||
<SelectItem value="doctorate">Doctorate</SelectItem>
|
|
||||||
<SelectItem value="other">Other</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label htmlFor="companyName" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">🏢</span>
|
|
||||||
Company Name <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Input
|
<Input
|
||||||
id="companyName"
|
placeholder="Mobile No.*"
|
||||||
placeholder="Enter company name"
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
value={formData.companyName}
|
value={formData.mobile}
|
||||||
onChange={(e) => setFormData({ ...formData, companyName: e.target.value })}
|
onChange={(e) => setFormData({...formData, mobile: e.target.value})}
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
{!otpVerified ? (
|
||||||
</div>
|
<button
|
||||||
|
type="button"
|
||||||
{/* Source */}
|
onClick={handleVerifyMobile}
|
||||||
<div>
|
className="absolute right-4 top-1/2 -translate-y-1/2 text-[12px] font-bold text-red-600 hover:text-black transition-colors"
|
||||||
<Label htmlFor="source" className="flex items-center gap-2 text-slate-200 mb-3">
|
>
|
||||||
<span className="text-amber-400">📢</span>
|
Verify
|
||||||
How did you hear about us? <span className="text-amber-500">*</span>
|
</button>
|
||||||
</Label>
|
) : (
|
||||||
<Select value={formData.source} onValueChange={(value) => setFormData({ ...formData, source: value })}>
|
<span className="absolute right-4 top-1/2 -translate-y-1/2 text-[12px] font-bold text-green-600">Verified</span>
|
||||||
<SelectTrigger className="bg-slate-800/50 border-slate-600/50 text-white focus:border-amber-500/50 focus:ring-amber-500/20">
|
|
||||||
<SelectValue placeholder="Select source" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent className="bg-slate-800 border-slate-700 text-white">
|
|
||||||
<SelectItem value="existing-dealer">Existing RE Dealer</SelectItem>
|
|
||||||
<SelectItem value="customer">Customer</SelectItem>
|
|
||||||
<SelectItem value="re-employee">RE Employee</SelectItem>
|
|
||||||
<SelectItem value="newspaper">Newspaper</SelectItem>
|
|
||||||
<SelectItem value="website">Website</SelectItem>
|
|
||||||
<SelectItem value="friend">Friend</SelectItem>
|
|
||||||
<SelectItem value="other">Other</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Do you own a Royal Enfield? */}
|
|
||||||
<div>
|
|
||||||
<Label className="flex items-center gap-2 text-slate-200 mb-4">
|
|
||||||
<span className="text-amber-400">🏍️</span>
|
|
||||||
Do you own a Royal Enfield? <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<RadioGroup value={formData.ownRoyalEnfield} onValueChange={(value) => setFormData({ ...formData, ownRoyalEnfield: value, royalEnfieldModel: value === 'no' ? '' : formData.royalEnfieldModel })}>
|
|
||||||
<div className="flex items-center space-x-8">
|
|
||||||
<div className="flex items-center space-x-3">
|
|
||||||
<RadioGroupItem value="yes" id="own-yes" className="border-amber-400/60 hover:border-amber-400 data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500/20" />
|
|
||||||
<Label htmlFor="own-yes" className="cursor-pointer text-slate-200 hover:text-amber-300">Yes</Label>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center space-x-3">
|
|
||||||
<RadioGroupItem value="no" id="own-no" className="border-amber-400/60 hover:border-amber-400 data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500/20" />
|
|
||||||
<Label htmlFor="no" className="cursor-pointer text-slate-200 hover:text-amber-300">No</Label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Royal Enfield Model - Conditional */}
|
|
||||||
{formData.ownRoyalEnfield === 'yes' && (
|
|
||||||
<div className="animate-in fade-in slide-in-from-top-2 duration-300">
|
|
||||||
<Label htmlFor="royalEnfieldModel" className="flex items-center gap-2 text-slate-200 mb-3">
|
|
||||||
<span className="text-amber-400">🏍️</span>
|
|
||||||
Which Royal Enfield model do you own? <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Select value={formData.royalEnfieldModel} onValueChange={(value) => setFormData({ ...formData, royalEnfieldModel: value })}>
|
|
||||||
<SelectTrigger className="bg-slate-800/50 border-slate-600/50 text-white focus:border-amber-500/50 focus:ring-amber-500/20">
|
|
||||||
<SelectValue placeholder="Select your bike model" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent className="bg-slate-800 border-slate-700 text-white">
|
|
||||||
<SelectItem value="classic-350">Classic 350</SelectItem>
|
|
||||||
<SelectItem value="meteor-350">Meteor 350</SelectItem>
|
|
||||||
<SelectItem value="hunter-350">Hunter 350</SelectItem>
|
|
||||||
<SelectItem value="bullet-350">Bullet 350</SelectItem>
|
|
||||||
<SelectItem value="himalayan">Himalayan</SelectItem>
|
|
||||||
<SelectItem value="scram-411">Scram 411</SelectItem>
|
|
||||||
<SelectItem value="interceptor-650">Interceptor 650</SelectItem>
|
|
||||||
<SelectItem value="continental-gt-650">Continental GT 650</SelectItem>
|
|
||||||
<SelectItem value="super-meteor-650">Super Meteor 650</SelectItem>
|
|
||||||
<SelectItem value="shotgun-650">Shotgun 650</SelectItem>
|
|
||||||
<SelectItem value="himalayan-450">Himalayan 450</SelectItem>
|
|
||||||
<SelectItem value="other">Other</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Existing Dealer/Vendor */}
|
|
||||||
<div>
|
|
||||||
<Label className="flex items-center gap-2 text-slate-200 mb-4">
|
|
||||||
<span className="text-amber-400">🏪</span>
|
|
||||||
Are you an existing dealer/vendor of Royal Enfield? <span className="text-amber-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<RadioGroup value={formData.existingDealer} onValueChange={(value) => setFormData({ ...formData, existingDealer: value })}>
|
|
||||||
<div className="flex items-center space-x-8">
|
|
||||||
<div className="flex items-center space-x-3">
|
|
||||||
<RadioGroupItem value="yes" id="dealer-yes" className="border-amber-400/60 hover:border-amber-400 data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500/20" />
|
|
||||||
<Label htmlFor="dealer-yes" className="cursor-pointer text-slate-200 hover:text-amber-300">Yes</Label>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center space-x-3">
|
|
||||||
<RadioGroupItem value="no" id="dealer-no" className="border-amber-400/60 hover:border-amber-400 data-[state=checked]:border-amber-500 data-[state=checked]:bg-amber-500/20" />
|
|
||||||
<Label htmlFor="dealer-no" className="cursor-pointer text-slate-200 hover:text-amber-300">No</Label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</RadioGroup>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Address */}
|
<div className="flex items-center gap-10 h-[44px]">
|
||||||
<div>
|
<span className="text-[14px] font-medium text-[#333333]">Own a Royal Enfield?</span>
|
||||||
<Label htmlFor="address" className="flex items-center gap-2 text-slate-200 mb-3">
|
<div className="flex gap-8">
|
||||||
<span className="text-amber-400">🏠</span>
|
{['yes', 'no'].map(val => (
|
||||||
Address <span className="text-amber-500">*</span>
|
<label key={val} className="flex items-center gap-2 cursor-pointer">
|
||||||
</Label>
|
<div className={`w-5 h-5 rounded-full border flex items-center justify-center ${formData.ownRoyalEnfield === val ? 'border-red-600' : 'border-[#cccccc]'}`}>
|
||||||
<Textarea
|
{formData.ownRoyalEnfield === val && <div className="w-2.5 h-2.5 rounded-full bg-red-600" />}
|
||||||
id="address"
|
</div>
|
||||||
placeholder="Enter your complete address including landmarks"
|
<input
|
||||||
value={formData.address}
|
type="radio"
|
||||||
onChange={(e) => setFormData({ ...formData, address: e.target.value })}
|
className="hidden"
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
checked={formData.ownRoyalEnfield === val}
|
||||||
rows={3}
|
onChange={() => setFormData({...formData, ownRoyalEnfield: val})}
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
|
<span className="text-[14px] capitalize">{val}</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Description */}
|
<Input
|
||||||
<div>
|
placeholder="Age*"
|
||||||
<Label htmlFor="description" className="flex items-center gap-2 text-slate-200 mb-3">
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
<span className="text-amber-400">📝</span>
|
value={formData.age}
|
||||||
Description <span className="text-amber-500">*</span>
|
onChange={(e) => setFormData({...formData, age: e.target.value})}
|
||||||
</Label>
|
/>
|
||||||
|
|
||||||
|
<div className="relative">
|
||||||
|
<select
|
||||||
|
className="w-full h-[44px] px-4 border border-[#cccccc] appearance-none bg-white text-[14px] outline-none disabled:bg-slate-50"
|
||||||
|
value={formData.royalEnfieldModel}
|
||||||
|
disabled={formData.ownRoyalEnfield !== 'yes'}
|
||||||
|
onChange={(e) => setFormData({...formData, royalEnfieldModel: e.target.value})}
|
||||||
|
>
|
||||||
|
<option value="">Motorcycle Owned</option>
|
||||||
|
{reModels.map(m => <option key={m} value={m}>{m}</option>)}
|
||||||
|
</select>
|
||||||
|
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500 pointer-events-none" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
placeholder="Education Qualification*"
|
||||||
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
|
value={formData.education}
|
||||||
|
onChange={(e) => setFormData({...formData, education: e.target.value})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
placeholder="Company Name*"
|
||||||
|
className="h-[44px] border-[#cccccc] rounded-none px-4 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999]"
|
||||||
|
value={formData.companyName}
|
||||||
|
onChange={(e) => setFormData({...formData, companyName: e.target.value})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="relative">
|
||||||
|
<select
|
||||||
|
className="w-full h-[44px] px-4 border border-[#cccccc] appearance-none bg-white text-[14px] outline-none"
|
||||||
|
value={formData.source}
|
||||||
|
onChange={(e) => setFormData({...formData, source: e.target.value})}
|
||||||
|
>
|
||||||
|
<option value="">Select Source</option>
|
||||||
|
{sourceOptions.map(s => <option key={s} value={s}>{s}</option>)}
|
||||||
|
</select>
|
||||||
|
<ChevronDown className="absolute right-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-500 pointer-events-none" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col justify-center h-auto min-h-[44px] space-y-1">
|
||||||
|
<span className="text-[13px] font-medium text-[#333333]">Are you an existing Dealer / Vendor of Royal Enfield?</span>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
{['yes', 'no'].map(val => (
|
||||||
|
<label key={val} className="flex items-center gap-2 cursor-pointer">
|
||||||
|
<div className={`w-5 h-5 rounded-full border flex items-center justify-center ${formData.existingDealer === val ? 'border-red-600' : 'border-[#cccccc]'}`}>
|
||||||
|
{formData.existingDealer === val && <div className="w-2.5 h-2.5 rounded-full bg-red-600" />}
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
className="hidden"
|
||||||
|
checked={formData.existingDealer === val}
|
||||||
|
onChange={() => setFormData({...formData, existingDealer: val})}
|
||||||
|
/>
|
||||||
|
<span className="text-[14px] capitalize">{val}</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Full Width Text Areas */}
|
||||||
|
<div className="space-y-6 pt-4">
|
||||||
<Textarea
|
<Textarea
|
||||||
id="description"
|
placeholder="Description*"
|
||||||
placeholder="Tell us about your business background, experience, and why you want to become a Royal Enfield dealer..."
|
className="min-h-[120px] border-[#cccccc] rounded-none px-4 py-3 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999] resize-none"
|
||||||
value={formData.description}
|
value={formData.description}
|
||||||
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
onChange={(e) => setFormData({...formData, description: e.target.value})}
|
||||||
className="bg-slate-800/50 border-slate-600/50 text-white placeholder:text-slate-500 focus:border-amber-500/50 focus:ring-amber-500/20"
|
/>
|
||||||
rows={5}
|
<Textarea
|
||||||
required
|
placeholder="Address*"
|
||||||
|
className="min-h-[120px] border-[#cccccc] rounded-none px-4 py-3 text-[14px] focus-visible:ring-1 focus-visible:ring-black placeholder:text-[#999999] resize-none"
|
||||||
|
value={formData.address}
|
||||||
|
onChange={(e) => setFormData({...formData, address: e.target.value})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Terms and Conditions */}
|
{/* Terms & Submit */}
|
||||||
<div className="flex items-start space-x-3 bg-slate-800/30 p-5 rounded-xl border border-slate-700/50">
|
<div className="pt-6 space-y-8">
|
||||||
|
<div className="space-y-6">
|
||||||
|
<p className="text-[14px] text-[#666666] leading-relaxed">
|
||||||
|
Disclaimer: By signing this form/checking this box, you acknowledge and agree that we may use the information you share with us, to communicate with you through e-mails, text messages, WhatsApp and calls, in order to provide our product or service related information and/or for promotional and marketing purposes. All information provided will be secured and processed as per our <b>privacy policy</b>.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="terms"
|
id="terms"
|
||||||
|
className="w-5 h-5 border-[#cccccc] rounded-none data-[state=checked]:bg-black data-[state=checked]:border-black"
|
||||||
checked={formData.acceptTerms}
|
checked={formData.acceptTerms}
|
||||||
onCheckedChange={(checked) => setFormData({ ...formData, acceptTerms: checked as boolean })}
|
onCheckedChange={(checked) => setFormData({...formData, acceptTerms: checked as boolean})}
|
||||||
className="border-slate-600 data-[state=checked]:bg-amber-500 data-[state=checked]:border-amber-500 mt-0.5"
|
|
||||||
/>
|
/>
|
||||||
<div className="flex-1">
|
<label htmlFor="terms" className="text-[14px] font-medium cursor-pointer">
|
||||||
<Label htmlFor="terms" className="cursor-pointer text-slate-200">
|
I accept the <b>terms and conditions</b> as well as <b>privacy policy</b>.
|
||||||
I accept the terms and conditions <span className="text-amber-500">*</span>
|
</label>
|
||||||
</Label>
|
|
||||||
<p className="text-slate-400 text-xs mt-2 leading-relaxed">
|
|
||||||
By submitting this form, you agree to our privacy policy and terms of service.
|
|
||||||
We will use your information to process your dealership application.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Submit Button */}
|
<button
|
||||||
<Button
|
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-full bg-gradient-to-r from-amber-500 to-orange-600 hover:from-amber-600 hover:to-orange-700 text-white py-6 text-lg shadow-xl shadow-amber-500/20 hover:shadow-2xl hover:shadow-amber-500/30 transition-all duration-300"
|
className="h-12 px-10 bg-black text-white flex items-center gap-3 hover:bg-slate-900 transition-colors"
|
||||||
>
|
>
|
||||||
Submit Application
|
<span className="font-bold uppercase tracking-wider text-[14px]">Submit</span>
|
||||||
</Button>
|
<ChevronRight className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</main>
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<footer className="bg-black/90 backdrop-blur-md border-t border-slate-800 py-16">
|
<footer className="relative z-10 bg-black py-16">
|
||||||
<div className="max-w-7xl mx-auto px-6">
|
<div className="max-w-[1240px] mx-auto px-6 grid grid-cols-1 md:grid-cols-3 items-center gap-8">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-12">
|
<img src="/assets/images/Re_Logo.png" alt="Royal Enfield" className="h-10 w-auto opacity-100" />
|
||||||
{/* About Section */}
|
<div className="flex justify-center gap-12 text-[10px] font-bold uppercase tracking-widest text-slate-500">
|
||||||
<div>
|
<a href="#" className="hover:text-white transition-all">Legal</a>
|
||||||
<div className="w-12 h-12 bg-gradient-to-br from-amber-500 to-orange-600 rounded-lg flex items-center justify-center shadow-lg mb-6">
|
<a href="#" className="hover:text-white transition-all">Privacy</a>
|
||||||
<span className="text-white text-xl">RE</span>
|
<a href="#" className="hover:text-white transition-all">Terms</a>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-slate-400 text-sm leading-relaxed mb-4">
|
<p className="text-[10px] text-center md:text-right uppercase tracking-widest text-slate-500 font-bold">
|
||||||
Since 1901, Royal Enfield has been the world's oldest motorcycle brand in continuous production,
|
© 2026 Royal Enfield. All Rights Reserved.
|
||||||
creating timeless motorcycles that define the pure motorcycling experience.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Quick Links */}
|
|
||||||
<div>
|
|
||||||
<h3 className="text-white mb-6">Quick Links</h3>
|
|
||||||
<ul className="space-y-3 text-sm">
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">About Royal Enfield</a></li>
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">Our Motorcycles</a></li>
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">Service & Support</a></li>
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">Contact Us</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Dealership & Contact */}
|
|
||||||
<div>
|
|
||||||
<h3 className="text-white mb-6">Dealership Support</h3>
|
|
||||||
<ul className="space-y-3 text-sm mb-8">
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">Application Process</a></li>
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">Partnership Requirements</a></li>
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">Training & Support</a></li>
|
|
||||||
<li><a href="#" className="text-slate-400 hover:text-amber-400 transition-colors">FAQs</a></li>
|
|
||||||
</ul>
|
|
||||||
<div className="space-y-2 text-sm">
|
|
||||||
<p className="text-slate-400">Email: <span className="text-amber-400">dealership@royalenfield.com</span></p>
|
|
||||||
<p className="text-slate-400">Phone: <span className="text-amber-400">+91 1800-123-7567</span></p>
|
|
||||||
<p className="text-slate-500">Mon-Fri, 9:00 AM - 6:00 PM IST</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="border-t border-slate-800 mt-12 pt-8 text-center">
|
|
||||||
<p className="text-slate-500 text-sm">
|
|
||||||
© 2024 Royal Enfield. All rights reserved. | Made like a gun, goes like a bullet.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export const ZMManagement: React.FC<ZMManagementProps> = ({
|
|||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<CardTitle>Zonal Managers (ZM)</CardTitle>
|
<CardTitle>Zonal Managers (DD-ZM)</CardTitle>
|
||||||
<CardDescription>Manage Zonal Managers and their region assignments</CardDescription>
|
<CardDescription>Manage Zonal Managers and their region assignments</CardDescription>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={onAddZM} className="bg-amber-600 hover:bg-amber-700">
|
<Button onClick={onAddZM} className="bg-amber-600 hover:bg-amber-700">
|
||||||
|
|||||||
@ -52,33 +52,7 @@ export function ProspectiveApplicationDetails({ id, onBack }: Props) {
|
|||||||
const [isUploading, setIsUploading] = useState(false);
|
const [isUploading, setIsUploading] = useState(false);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
|
||||||
const normalizeStatus = (value?: string) =>
|
|
||||||
String(value || '')
|
|
||||||
.toLowerCase()
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
const getTimelineColorClass = (progressStatus?: string) => {
|
|
||||||
if (progressStatus === 'completed') {
|
|
||||||
return {
|
|
||||||
border: 'border-green-500',
|
|
||||||
dot: 'bg-green-500',
|
|
||||||
text: 'text-green-700'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (progressStatus === 'active') {
|
|
||||||
return {
|
|
||||||
border: 'border-sky-500',
|
|
||||||
dot: 'bg-sky-500',
|
|
||||||
text: 'text-sky-700'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Default and explicit pending
|
|
||||||
return {
|
|
||||||
border: 'border-amber-500',
|
|
||||||
dot: 'bg-amber-500',
|
|
||||||
text: 'text-amber-700'
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Statutory & Bank State
|
// Statutory & Bank State
|
||||||
const emptyForm = {
|
const emptyForm = {
|
||||||
@ -328,7 +302,7 @@ export function ProspectiveApplicationDetails({ id, onBack }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||||
<div className="lg:col-span-2 space-y-6">
|
<div className="lg:col-span-3 space-y-6">
|
||||||
{/* Statutory & Bank Details Form */}
|
{/* Statutory & Bank Details Form */}
|
||||||
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden" data-testid="onboarding-prospective-details-statutory-card">
|
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden" data-testid="onboarding-prospective-details-statutory-card">
|
||||||
<div className="p-4 bg-slate-900 text-white flex justify-between items-center">
|
<div className="p-4 bg-slate-900 text-white flex justify-between items-center">
|
||||||
@ -551,52 +525,7 @@ export function ProspectiveApplicationDetails({ id, onBack }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="lg:col-span-1 space-y-6">
|
|
||||||
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden" data-testid="onboarding-prospective-details-timeline-card">
|
|
||||||
<div className="p-4 bg-slate-50 border-b border-slate-200">
|
|
||||||
<h3 className="text-xs font-bold text-slate-900 flex items-center gap-2 uppercase tracking-widest">
|
|
||||||
<Clock className="w-4 h-4 text-amber-600" /> Recent Updates
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div className="p-6">
|
|
||||||
{(details.progressTracking || []).length > 0 ? (
|
|
||||||
<div className="relative space-y-6">
|
|
||||||
<div className="absolute left-[11px] top-2 bottom-4 w-0.5 bg-slate-100"></div>
|
|
||||||
{[...(details.progressTracking || [])]
|
|
||||||
.sort((a: any, b: any) => Number(a.stageOrder || 0) - Number(b.stageOrder || 0))
|
|
||||||
.map((item: any, idx: number) => {
|
|
||||||
const progressStatus = normalizeStatus(item.status);
|
|
||||||
const colorClass = getTimelineColorClass(progressStatus);
|
|
||||||
return (
|
|
||||||
<div key={item.id} className="relative pl-8 animate-in slide-in-from-left duration-300" style={{ animationDelay: `${idx * 100}ms` }} data-testid={`onboarding-prospective-details-timeline-item-${idx}`}>
|
|
||||||
<div className={`absolute left-0 top-1 w-[24px] h-[24px] rounded-full border-2 bg-white flex items-center justify-center shadow-sm ${colorClass.border}`}>
|
|
||||||
<div className={`w-1.5 h-1.5 rounded-full ${colorClass.dot}`}></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className={`text-xs font-bold uppercase tracking-tight ${colorClass.text}`} data-testid={`onboarding-prospective-details-timeline-stage-${idx}`}>{item.stageName}</p>
|
|
||||||
<p className="text-[10px] text-slate-400 font-medium">
|
|
||||||
{item.stageCompletedAt
|
|
||||||
? new Date(item.stageCompletedAt).toLocaleString('en-IN')
|
|
||||||
: item.stageStartedAt
|
|
||||||
? new Date(item.stageStartedAt).toLocaleString('en-IN')
|
|
||||||
: new Date(item.createdAt).toLocaleString('en-IN')}
|
|
||||||
</p>
|
|
||||||
<p className="text-[10px] text-slate-500 mt-1 italic leading-tight" data-testid={`onboarding-prospective-details-timeline-status-${idx}`}>
|
|
||||||
Status: {item.status || 'pending'}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="text-center py-6" data-testid="onboarding-prospective-details-timeline-empty">
|
|
||||||
<p className="text-xs text-slate-500 italic">No history available yet</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Public+Sans:ital,wght@0,100..900;1,100..900&display=swap');
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
@ -40,6 +41,12 @@
|
|||||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||||
--sidebar-border: oklch(0.922 0 0);
|
--sidebar-border: oklch(0.922 0 0);
|
||||||
--sidebar-ring: oklch(0.708 0 0);
|
--sidebar-ring: oklch(0.708 0 0);
|
||||||
|
|
||||||
|
/* Royal Enfield Brand Colors */
|
||||||
|
--re-red: #DA1A32;
|
||||||
|
--re-black: #000000;
|
||||||
|
--re-white: #FFFFFF;
|
||||||
|
--re-gray: #717171;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
@ -127,9 +134,46 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
|
font-family: 'Montserrat', sans-serif;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RE Branding Utilities */
|
||||||
|
.re-heading {
|
||||||
|
font-family: 'Montserrat', sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-card {
|
||||||
|
@apply bg-white border border-slate-200 rounded-none shadow-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-input {
|
||||||
|
@apply w-full px-4 py-3 border border-slate-300 rounded-none focus:border-red-600 focus:ring-1 focus:ring-red-600/20 outline-none transition-all duration-200 text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-label {
|
||||||
|
@apply block text-sm font-semibold text-slate-800 mb-1.5 uppercase tracking-wide;
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-btn-primary {
|
||||||
|
@apply bg-black text-white px-8 py-3 font-bold uppercase tracking-widest hover:bg-slate-900 transition-all active:scale-[0.98];
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-btn-outline {
|
||||||
|
@apply border-2 border-black text-black px-8 py-3 font-bold uppercase tracking-widest hover:bg-black hover:text-white transition-all active:scale-[0.98];
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-intro-text {
|
||||||
|
@apply text-slate-700 leading-relaxed text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-disclaimer {
|
||||||
|
@apply bg-slate-50 border-l-4 border-red-600 p-4 text-xs italic text-slate-600;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base typography. This is not applied to elements which have an ancestor with a Tailwind text class.
|
* Base typography. This is not applied to elements which have an ancestor with a Tailwind text class.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user