Skip to content

Commit 258f2fb

Browse files
Merge pull request #235 from Payel-Manna/feature/admission-validation-modal
Feature: Add step validation modal for admission form
2 parents fcc97a9 + 7b24a01 commit 258f2fb

File tree

4 files changed

+407
-162
lines changed

4 files changed

+407
-162
lines changed

src/components/Templates/admission/DropDown.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
const Dropdown = ({
1010
placeholder,
1111
options,
12-
handleSelect,
12+
onChange,
1313
name,
1414
isRequired = false,
1515
errorMessage = 'This field is required.',
@@ -50,15 +50,16 @@ const Dropdown = ({
5050
// Sync selectedOption with Redux
5151
useEffect(() => {
5252
if (selectedOption !== placeholder) {
53-
if (find_index !== -1) {
53+
const idx = admission.findIndex(item => item.name === name);
54+
if (idx !== -1) {
5455
dispatch(
5556
setOneAdmission({ name, value: selectedOption }),
5657
);
5758
} else {
5859
dispatch(setAdmission({ name, value: selectedOption }));
5960
}
6061
}
61-
}, [selectedOption]);
62+
}, [selectedOption,admission]);
6263

6364
const validateDropdown = () => {
6465
if (
@@ -72,6 +73,7 @@ const Dropdown = ({
7273
};
7374
const handleOptionClick = option => {
7475
setSelectedOption(option);
76+
onChange && onChange({ target: { name, value: option } });
7577
setIsOpen(false);
7678
setIsError(false);
7779
};

src/components/Templates/admission/StepValidateModal.jsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import React from 'react';
22

3-
const StepValidateModal = ({ isOpen, onClose, title, message }) => {
3+
const StepValidateModal = ({
4+
isOpen,
5+
onClose,
6+
title,
7+
message,
8+
missingFields,
9+
}) => {
410
if (!isOpen) return null;
511

612
return (
@@ -11,7 +17,14 @@ const StepValidateModal = ({ isOpen, onClose, title, message }) => {
1117
{title}
1218
</h2>
1319
<p className='mt-4 text-gray-600'>{message}</p>
14-
<button
20+
{missingFields?.length > 0 && (
21+
<ul className='mt-3 list-disc pl-6 text-red-500'>
22+
{missingFields.map(field => (
23+
<li key={field}>{field}</li>
24+
))}
25+
</ul>
26+
)}
27+
<button type="button"
1528
onClick={onClose}
1629
className='mt-6 w-full bg-red-600 text-white py-2 rounded-lg hover:bg-red-700 transition'
1730
>

src/components/Templates/admission/Steps.jsx

Lines changed: 101 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,42 @@ import axios from 'axios';
1212
import admissionConstant from './admission.constant.mjs';
1313

1414
const Steps = () => {
15-
const [isModalOpen, setIsModalOpen] = useState(false);
15+
1616
const [activeStep, setActiveStep] = useState(0);
1717
const [isLoading, setIsLoading] = useState(false);
1818
const [image, setImage] = useState(null);
1919
const [imageUploadSuccess, setImageUploadSuccess] =
2020
useState(false);
21-
const [formData, setFormData] = useState({});
21+
2222
const [Avtor, setAvtor] = useState(null);
23-
24-
25-
useEffect(() => {
23+
const [missingFields, setMissingFields] = useState([]);
24+
const [showErrors, setShowErrors] = useState(false);
25+
26+
const [formData, setFormData] = useState({
27+
firstName: '',
28+
middleName: '',
29+
lastName: '',
30+
fatherName: '',
31+
motherName: '',
32+
AadharCardNumber: '',
33+
email: '',
34+
contactNumber: '',
35+
dateOfBirth: '',
36+
gender: '',
37+
nationality: '',
38+
street: '',
39+
city: '',
40+
state: '',
41+
pinCode: '',
42+
});
43+
useEffect(() => {
2644
const savedData = sessionStorage.getItem('admissionFormData');
2745
if (savedData) {
28-
setFormData(JSON.parse(savedData));
46+
setFormData(JSON.parse(savedData));
2947
}
30-
}, []);
31-
48+
}, []);
3249

50+
3351
let admission = useSelector(state => state.admission.admission);
3452

3553
let dispatch = useDispatch();
@@ -40,6 +58,9 @@ const Steps = () => {
4058
...prevData,
4159
[name]: value,
4260
}));
61+
62+
setMissingFields((prev) => prev.filter((err) => !err.toLowerCase().includes(name.toLowerCase())));
63+
4364
};
4465

4566
const handleDropdownChange = (name, value) => {
@@ -117,6 +138,8 @@ const Steps = () => {
117138
<YourInfo
118139
handleInputChange={handleInputChange}
119140
handleDropdownChange={handleDropdownChange}
141+
errors={missingFields}
142+
showErrors={showErrors}
120143
/>
121144
),
122145
},
@@ -144,37 +167,83 @@ const Steps = () => {
144167
];
145168

146169
const validateStep = () => {
147-
const requiredFields = [];
148-
149-
if (activeStep === 0) {
150-
requiredFields.push('firstName', 'lastName', 'email');
151-
} else if (activeStep === 1) {
152-
requiredFields.push('fatherName', 'motherName');
153-
} else if (activeStep === 4 && !image) {
154-
setIsModalOpen(true);
155-
return false;
156-
}
157-
//check values in formData
158-
for(let field of requiredFields){
159-
if(!formData[field] || formData[field].trim()===''){
160-
setIsModalOpen(true);
161-
return false;
170+
const stepValidationConfig = {
171+
0: [
172+
'firstName',
173+
'lastName',
174+
'email',
175+
'fatherName',
176+
'motherName',
177+
'AadharCardNumber',
178+
'contactNumber',
179+
'dateOfBirth',
180+
'gender',
181+
'nationality',
182+
'street',
183+
'city',
184+
'state',
185+
'pinCode',
186+
],
187+
1: ['Gname', 'Grelation', 'GcontactNumber'],
188+
2: [], // AreYouHuman step
189+
3: [
190+
'tenthBoard',
191+
'tenthGrade',
192+
'twelfthMarks',
193+
'twelfthGrade',
194+
],
195+
4: ['university', 'courseName', 'mode'],
196+
};
197+
198+
const missing = [];
199+
const requiredFields = stepValidationConfig[activeStep] || [];
200+
201+
for (const field of requiredFields) {
202+
const value = formData[field];
203+
if (
204+
value === undefined ||
205+
value === null ||
206+
(typeof value === 'string' && value.trim() === '')
207+
) {
208+
const formatted = field
209+
.replace(/([A-Z])/g, ' $1')
210+
.replace(/^./, str => str.toUpperCase());
211+
missing.push(formatted);
162212
}
163-
164213
}
165-
//Save current changes
166-
sessionStorage.setItem('admissionFormData', JSON.stringify(formData));
214+
215+
if (activeStep === 4 && !image) {
216+
missing.push('Profile Picture');
217+
}
218+
219+
sessionStorage.setItem(
220+
'admissionFormData',
221+
JSON.stringify(formData),
222+
);
167223

168-
return true;
224+
225+
226+
setMissingFields(missing);
227+
return missing.length === 0;
169228

170229
};
171230

172-
const handleNext = () => {
231+
const handleNext = (e) => {
232+
e.preventDefault();// Prevent accidental page reload
233+
setShowErrors(true);
173234
if (validateStep()) {
174235
if (activeStep < steps.length - 1) {
175236
setActiveStep(prevStep => prevStep + 1);
237+
setShowErrors(false);
176238
}
177-
}
239+
}else {
240+
// setIsModalOpen(true);
241+
242+
const firstErrorField = document.querySelector('.input-error');
243+
firstErrorField?.scrollIntoView({ behavior: 'smooth', block: 'center' });
244+
}
245+
246+
178247
};
179248

180249
const handlePrevious = () => {
@@ -303,13 +372,13 @@ const Steps = () => {
303372
</div>
304373
)}
305374
</form>
306-
307-
<StepValidateModal
375+
{/* <StepValidateModal
308376
isOpen={isModalOpen}
309377
onClose={() => setIsModalOpen(false)}
310378
title='Incomplete Form'
311379
message='Please fill in all fields before proceeding!'
312-
/>
380+
missingFields={missingFields}
381+
/> */}
313382
</>
314383
);
315384
};

0 commit comments

Comments
 (0)