Skip to content

Instantly share code, notes, and snippets.

@niftynihal
Created February 4, 2025 08:25
Show Gist options
  • Save niftynihal/407392559c20db45b75c950f8fe47fa7 to your computer and use it in GitHub Desktop.
Save niftynihal/407392559c20db45b75c950f8fe47fa7 to your computer and use it in GitHub Desktop.
changes to be done in apps/student-experience/src/components/LegalAgreementModal/index.tsx
First, update the DetailFormData interface:
```
interface DetailFormData {
name: string;
address: string;
panNumber: string;
aadharNumber: string;
dateOfBirth: string;
gender: string;
parentsName: string;
parentsEmail: string;
parentsMobileCountry: string;
parentsMobile: string;
currentStatus: string;
studyYear: string;
workDomain: string;
educationDetails: string;
graduationYear: string;
collegeName: string;
companyName: string;
workExperience: string;
ctc: string;
location: string;
}
```
Add the country codes data and validation functions just before the EnterDetailsStep component:
```
const countryCodes = [
{ code: '+91', country: 'India', length: 10 },
{ code: '+1', country: 'USA/Canada', length: 10 },
{ code: '+44', country: 'UK', length: 11 },
{ code: '+61', country: 'Australia', length: 9 },
// Add more countries as needed
];
const isValidPhoneNumber = (phone: string, countryCode: string) => {
const country = countryCodes.find(c => c.code === countryCode);
if (!country) return false;
return phone.length === country.length;
};
const getMaxDate = () => {
const today = new Date();
return today.toISOString().split('T')[0];
};
```
Update the initial state in the main component:
```
const [detailFormData, setDetailFormData] = useState<DetailFormData>({
name: data?.legalData?.name || '',
address: data?.legalData?.address || '',
panNumber: data?.legalData?.panNumber || '',
aadharNumber: data?.legalData?.aadharNumber || '',
dateOfBirth: data?.legalData?.dateOfBirth || '',
gender: data?.legalData?.gender || '',
parentsName: data?.legalData?.parentsName || '',
parentsEmail: data?.legalData?.parentsEmail || '',
parentsMobileCountry: data?.legalData?.parentsMobileCountry || '',
parentsMobile: data?.legalData?.parentsMobile || '',
currentStatus: data?.legalData?.currentStatus || '',
studyYear: data?.legalData?.studyYear || '',
workDomain: data?.legalData?.workDomain || '',
educationDetails: data?.legalData?.educationDetails || '',
graduationYear: data?.legalData?.graduationYear || '',
collegeName: data?.legalData?.collegeName || '',
companyName: data?.legalData?.companyName || '',
workExperience: data?.legalData?.workExperience || '',
ctc: data?.legalData?.ctc || '',
location: '',
});
```
Replace the EnterDetailsStep component with this updated version:
```
function EnterDetailsStep({ formData, handleChange }: EnterDetailsStepProps) {
const isInValidPan = formData.panNumber && formData.panNumber?.length < 10;
const isInValidAadhar = formData.aadharNumber && formData.aadharNumber?.length < 12;
const isInvalidParentMobile = formData.parentsMobile &&
!isValidPhoneNumber(formData.parentsMobile, formData.parentsMobileCountry);
const isInvalidGradYear = formData.graduationYear && !/^\d{4}$/.test(formData.graduationYear);
const isInvalidEmail = formData.parentsEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.parentsEmail);
return (
<div className="p-6 py-2">
<div className="space-y-4 px-32 py-4 border rounded-[12px] overflow-y-scroll scrollbar-hide max-h-[60%] xl:max-h-[64%]">
{/* Existing Name field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Name<span className="text-xs ml-1 text-gray-600">(As per aadhar card)</span>
<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="text"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="Enter Name"
value={formData.name}
onChange={e => handleChange('name', e.target.value)}
/>
</div>
{/* Existing Address field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Address<span className="text-xs ml-1 text-gray-600">(As per aadhar card)</span>
<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="text"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="Enter Address"
value={formData.address}
onChange={e => handleChange('address', e.target.value)}
/>
</div>
{/* Date of Birth field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Date of Birth<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="date"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.dateOfBirth}
onChange={e => handleChange('dateOfBirth', e.target.value)}
max={getMaxDate()}
/>
</div>
{/* Gender field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Gender<span className="ml-1 text-xs text-red-600">*</span>
</label>
<select
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.gender}
onChange={e => handleChange('gender', e.target.value)}
>
<option value="">Select Gender</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="prefer_not_to_say">Prefer not to say</option>
</select>
</div>
{/* Parent's Name field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Parent's Name<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="text"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="Enter Parent's Name"
value={formData.parentsName}
onChange={e => handleChange('parentsName', e.target.value)}
/>
</div>
{/* Parent's Email field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Parent's Email ID<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="email"
className={`w-full px-3 py-2 border ${
isInvalidEmail ? 'border-red-500' : 'border-gray-300'
} bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm`}
placeholder="Enter Parent's Email"
value={formData.parentsEmail}
onChange={e => handleChange('parentsEmail', e.target.value)}
/>
{isInvalidEmail && <span className="text-red-600 text-xs">Please enter a valid email address</span>}
</div>
{/* Parent's Mobile Number field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Parent's Mobile Number<span className="ml-1 text-xs text-red-600">*</span>
</label>
<div className="flex gap-2">
<select
className="px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.parentsMobileCountry}
onChange={e => handleChange('parentsMobileCountry', e.target.value)}
>
<option value="">Select</option>
{countryCodes.map(country => (
<option key={country.code} value={country.code}>
{country.code} ({country.country})
</option>
))}
</select>
<input
type="text"
className={`flex-1 px-3 py-2 border ${
isInvalidParentMobile ? 'border-red-500' : 'border-gray-300'
} bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm`}
placeholder="Enter Parent's Mobile Number"
value={formData.parentsMobile}
onChange={e => handleChange('parentsMobile', e.target.value.replace(/\D/g, ''))}
/>
</div>
{isInvalidParentMobile && (
<span className="text-red-600 text-xs">
Please enter a valid phone number for the selected country
</span>
)}
</div>
{/* Current Status field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Current Status<span className="ml-1 text-xs text-red-600">*</span>
</label>
<div className="space-y-2">
<select
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.currentStatus}
onChange={e => {
handleChange('currentStatus', e.target.value);
handleChange('studyYear', '');
handleChange('workDomain', '');
}}
>
<option value="">Select Current Status</option>
<option value="completed_12th">Completed 12th</option>
<option value="graduated_not_working">Graduated but not working</option>
<option value="studying">Studying</option>
<option value="working">Working</option>
</select>
{formData.currentStatus === 'studying' && (
<select
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.studyYear}
onChange={e => handleChange('studyYear', e.target.value)}
>
<option value="">Select Year</option>
<option value="first_year">I Year</option>
<option value="second_year">II Year</option>
<option value="pre_final">Pre-final Year</option>
<option value="final_year">Final Year</option>
</select>
)}
{formData.currentStatus === 'working' && (
<select
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.workDomain}
onChange={e => handleChange('workDomain', e.target.value)}
>
<option value="">Select Domain</option>
<option value="tech">Tech Domain</option>
<option value="non_tech">Non-tech Domain</option>
</select>
)}
</div>
</div>
{/* Education Details field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Education Details<span className="ml-1 text-xs text-red-600">*</span>
</label>
<select
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
value={formData.educationDetails}
onChange={e => handleChange('educationDetails', e.target.value)}
>
<option value="">Select Education Details</option>
<option value="btech_cs">BTech/B.E (CS)</option>
<option value="btech_non_cs">BTech/B.E (Non-CS)</option>
<option value="graduation_cs">Graduation (CS, e.g., B.Sc Computer Science, BCA)</option>
<option value="graduation_non_cs">Graduation (Non-CS, e.g., BA, BCom)</option>
<option value="post_graduation">Post Graduation</option>
<option value="completed_12th">Completed 12th/Diploma</option>
</select>
</div>
{/* Year of Graduation field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Year of Graduation (Bachelors)<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="text"
className={`w-full px-3 py-2 border ${
isInvalidGradYear ? 'border-red-500' : 'border-gray-300'
} bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm`}
placeholder="If you have not completed graduation or are a college dropout, mention the year of completion of your college"
value={formData.graduationYear}
onChange={e => handleChange('graduationYear', e.target.value)}
maxLength={4}
/>
{isInvalidGradYear && <span className="text-red-600 text-xs">Please enter a valid year (YYYY)</span>}
</div>
```
I'll continue with the remaining fields in the EnterDetailsStep component:
```
{/* College Name field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
College Name<span className="ml-1 text-xs text-red-600">*</span>
</label>
<input
type="text"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="If you are not currently studying, mention the last studied college name and school name if you completed only 12th"
value={formData.collegeName}
onChange={e => handleChange('collegeName', e.target.value)}
/>
</div>
{/* Current Company Name field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Current Company Name
</label>
<input
type="text"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="Mention NA if you are not working"
value={formData.companyName}
onChange={e => handleChange('companyName', e.target.value)}
/>
</div>
{/* Work Experience field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Number of Years of Work Experience
</label>
<input
type="number"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="Enter 0 for no experience"
value={formData.workExperience}
onChange={e => handleChange('workExperience', e.target.value)}
min="0"
step="0.1"
/>
</div>
{/* CTC field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
CTC p.a (if working)
</label>
<input
type="number"
className="w-full px-3 py-2 border border-gray-300 bg-[#F5F5F5] rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm"
placeholder="Enter annual CTC"
value={formData.ctc}
onChange={e => handleChange('ctc', e.target.value)}
min="0"
/>
</div>
{/* Existing PAN Number field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">PAN Number</label>
<input
type="text"
className={`w-full px-3 py-2 bg-[#F5F5F5] border ${
isInValidPan ? 'border-red-500' : 'border-gray-300'
} rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm`}
placeholder="Enter PAN Number"
value={formData.panNumber?.toUpperCase()}
onChange={e => handleChange('panNumber', e.target.value?.toUpperCase())}
maxLength={10}
/>
{isInValidPan && <span className="text-red-600 text-xs">Please enter valid PAN number</span>}
</div>
<div className="flex justify-between items-center gap-1">
<div className="flex-1 h-[1px] rounded-lg bg-gray-300" aria-hidden="true" />
<p className="text-sm text-gray-400">
OR <span className="text-xs text-red-600">*</span>
</p>
<div className="flex-1 h-[1px] rounded-lg bg-gray-300" aria-hidden="true" />
</div>
{/* Existing Aadhar Number field */}
<div>
<label htmlFor="aadharNumber" className="block text-sm font-medium text-gray-700 mb-1">
Aadhar Number
</label>
<input
type="text"
id="aadharNumber"
className={`w-full px-3 py-2 border ${
isInValidAadhar ? 'border-red-500' : 'border-gray-300'
} bg-[#F5F5F5] rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 text-sm`}
placeholder="Enter Aadhar Number"
value={formData.aadharNumber}
onChange={e => handleChange('aadharNumber', e.target.value)}
pattern="\d*"
onKeyPress={e => {
if (!/[0-9]/.test(e.key)) {
e.preventDefault();
}
}}
maxLength={12}
/>
{isInValidAadhar && <span className="text-red-600 text-xs">Please enter valid Aadhar number</span>}
</div>
</div>
</div>
);
}
```
Also, you'll want to update the isDisabled function in the main component to include validation for the new required fields:
```
const isDisabled = () => {
switch (currentStep) {
case 1:
const isAadharValid = detailFormData?.aadharNumber?.length === 12;
const isPanValid = detailFormData?.panNumber?.length === 10;
const hasName = !!detailFormData?.name;
const hasAddress = !!detailFormData?.address;
const hasRequiredFields =
!!detailFormData?.dateOfBirth &&
!!detailFormData?.gender &&
!!detailFormData?.parentsName &&
!!detailFormData?.parentsEmail &&
!!detailFormData?.parentsMobileCountry &&
!!detailFormData?.parentsMobile &&
!!detailFormData?.currentStatus &&
!!detailFormData?.educationDetails &&
!!detailFormData?.graduationYear &&
!!detailFormData?.collegeName;
// Additional validation for sub-dropdowns
const hasStudyYearIfStudying = detailFormData?.currentStatus !== 'studying' || !!detailFormData?.studyYear;
const hasWorkDomainIfWorking = detailFormData?.currentStatus !== 'working' || !!detailFormData?.workDomain;
if (!hasName || !hasAddress || !hasRequiredFields || !hasStudyYearIfStudying || !hasWorkDomainIfWorking) {
return true;
}
if (detailFormData?.aadharNumber && detailFormData?.panNumber) {
return !isAadharValid || !isPanValid;
} else if (detailFormData?.aadharNumber) {
return !isAadharValid;
} else if (detailFormData?.panNumber) {
return !isPanValid;
} else {
return true;
}
// ... rest of the cases remain the same
}
};
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment