reg complete
This commit is contained in:
1 parent
653055debc
commit
81c014f94c
6 files changed
+225
-193
No files matched your search
@@ -17,6 +17,10 @@ const AdvancedDropzone = ({ value, onChange }) => {
|
||||
const [videoSrc, setVideoSrc] = React.useState(undefined);
|
||||
const [hoveredId, setHoveredId] = React.useState(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
setExtFiles(value || []);
|
||||
}, [value]);
|
||||
|
||||
const updateFiles = (incomingFiles) => {
|
||||
console.log("incoming files", incomingFiles);
|
||||
setExtFiles(incomingFiles);
|
||||
|
||||
@@ -372,6 +372,11 @@ const LifestyleDetailsForm = ({
|
||||
Add Rasi
|
||||
</h3>
|
||||
{renderChartGrid("graha")}
|
||||
{errors.graha_duplicate && (
|
||||
<p style={{ color: "#d32f2f", fontSize: "0.75rem", marginTop: "4px" }}>
|
||||
{errors.graha_duplicate}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -381,6 +386,11 @@ const LifestyleDetailsForm = ({
|
||||
Add Navamsam
|
||||
</h3>
|
||||
{renderChartGrid("amsam")}
|
||||
{errors.amsam_duplicate && (
|
||||
<p style={{ color: "#d32f2f", fontSize: "0.75rem", marginTop: "4px" }}>
|
||||
{errors.amsam_duplicate}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import React from "react";
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { Navigation, Pagination } from "swiper/modules";
|
||||
import "swiper/css";
|
||||
import "swiper/css/navigation";
|
||||
import "swiper/css/pagination";
|
||||
import { Edit2,Info } from 'lucide-react';
|
||||
import {
|
||||
Card,
|
||||
@@ -75,10 +80,10 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
];
|
||||
|
||||
const renderValue = (key, value) => {
|
||||
if (key === "profiles" || key === "profile") {
|
||||
const list = Array.isArray(value) ? value : [];
|
||||
if (key === "profiles" || key === "profile" || key === "profile_images" || key === "images") {
|
||||
const list = Array.isArray(value) ? value : (value ? [value] : []);
|
||||
return (
|
||||
<Box display="flex" gap={0} flexWrap="wrap">
|
||||
<Box display="flex" gap={1} flexWrap="wrap">
|
||||
{list.length > 0 ? (
|
||||
list.map((imgObj, index) => {
|
||||
const src =
|
||||
@@ -99,7 +104,7 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
objectFit: "cover",
|
||||
borderRadius: "50%",
|
||||
border: "1px solid #ccc",
|
||||
marginLeft: "-20px",
|
||||
// marginLeft: "-20px",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -183,9 +188,69 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
<Divider />
|
||||
<CardContent sx={{ pt: 1, }}>
|
||||
{Object.entries(section.data || {}).map(([key, value]) => {
|
||||
// if (value && key !== 'profiles') {
|
||||
|
||||
|
||||
// Handle brothers and sisters arrays specifically
|
||||
if ((key === 'brothers' || key === 'sisters') && Array.isArray(value) && value.length > 0) {
|
||||
return (
|
||||
<Box key={key} sx={{ py: 2, borderBottom: "1px solid #e0e0e0" }}>
|
||||
<Typography color="text.secondary" sx={{ fontWeight: 600, mb: 1 }}>
|
||||
{key === 'brothers' ? 'Brothers Details' : 'Sisters Details'}
|
||||
</Typography>
|
||||
<style>
|
||||
{`
|
||||
.custom-swiper-${key} .swiper-button-next,
|
||||
.custom-swiper-${key} .swiper-button-prev {
|
||||
color: #d32f2f;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.custom-swiper-${key} .swiper-button-next::after,
|
||||
.custom-swiper-${key} .swiper-button-prev::after {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.custom-swiper-${key} .swiper-pagination-bullet-active {
|
||||
background-color: #d32f2f;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<Swiper
|
||||
className={`custom-swiper-${key}`}
|
||||
modules={[Navigation, Pagination]}
|
||||
spaceBetween={15}
|
||||
slidesPerView={1}
|
||||
navigation
|
||||
pagination={{ clickable: true }}
|
||||
style={{ padding: "4px 4px 30px 4px" }}
|
||||
>
|
||||
{value.map((sibling, idx) => (
|
||||
<SwiperSlide key={idx}>
|
||||
<Card variant="outlined" sx={{ bgcolor: '#fff', height: '100%' }}>
|
||||
<CardContent sx={{ p: 2, '&:last-child': { pb: 2 } }}>
|
||||
{Object.entries(sibling).map(([sKey, sVal]) => (
|
||||
<Box key={sKey} display="grid" gridTemplateColumns="45% 55%" gap={1} mb={0.8} alignItems="start">
|
||||
<Typography variant="caption" color="text.secondary" sx={{ fontWeight: 500 }}>
|
||||
{sKey
|
||||
.replace(/([A-Z])/g, ' $1')
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/\b\w/g, (l) => l.toUpperCase())
|
||||
.trim()}
|
||||
</Typography>
|
||||
<Typography variant="body2" fontWeight={600} sx={{ wordBreak: 'break-word' }}>
|
||||
{sVal || '-'}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
// Convert camelCase or camel_Snake_case to readable words
|
||||
const formattedKey = key
|
||||
.replace(/([A-Z])/g, ' $1')
|
||||
@@ -214,7 +279,7 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
</Typography>
|
||||
|
||||
{/* Special Case: Profiles Image Preview */}
|
||||
{key === "profiles" || key === "profile" ? (
|
||||
{key === "profiles" || key === "profile" || key === "profile_images" || key === "images" ? (
|
||||
content
|
||||
) : value ? (
|
||||
<Typography
|
||||
|
||||
+131
-95
@@ -114,6 +114,7 @@ const STEP1_SERVER_FIELD_MAP = {
|
||||
confirm_password: "confirmPassword",
|
||||
confirmPassword: "confirmPassword",
|
||||
profiles: "profiles",
|
||||
profile_images: "profiles",
|
||||
};
|
||||
const Stepper = ({ currentStep, onStepClick }) => {
|
||||
|
||||
@@ -191,6 +192,12 @@ const StepperForm = () => {
|
||||
if (!key) return key;
|
||||
const trimmed = String(key).trim();
|
||||
if (!trimmed) return trimmed;
|
||||
|
||||
// Map backend profile_images errors (e.g., profile_images.0) to the profiles field
|
||||
if (trimmed.startsWith("profile_images")) {
|
||||
return "profiles";
|
||||
}
|
||||
|
||||
return (
|
||||
STEP1_SERVER_FIELD_MAP[trimmed] ||
|
||||
STEP1_SERVER_FIELD_MAP[trimmed.toLowerCase()] ||
|
||||
@@ -446,92 +453,117 @@ const StepperForm = () => {
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
const buildRegisterStep1Payload = () => ({
|
||||
name: personalDetails.name,
|
||||
mobile: personalDetails.mobileNumber,
|
||||
email: personalDetails.email,
|
||||
pincode: personalDetails.pincode,
|
||||
gender: personalDetails.gender,
|
||||
dob: personalDetails.dob,
|
||||
height: personalDetails.height || "",
|
||||
weight: personalDetails.weight || "",
|
||||
marital_status: personalDetails.maritalStatus,
|
||||
religion: personalDetails.religion,
|
||||
profile_for: personalDetails.profileFor || "",
|
||||
caste: personalDetails.caste,
|
||||
sub_caste: personalDetails.subCaste || "",
|
||||
gothram: personalDetails.gothram || "",
|
||||
raasi: personalDetails.raasi || "",
|
||||
star: personalDetails.star || "",
|
||||
state: personalDetails.state,
|
||||
district: personalDetails.city,
|
||||
password: personalDetails.password || "",
|
||||
fcm_token: localStorage.getItem("fcm_token") || "",
|
||||
});
|
||||
const buildRegisterStep1Payload = async () => {
|
||||
const formData = new FormData();
|
||||
formData.append("name", personalDetails.name);
|
||||
formData.append("mobile", personalDetails.mobileNumber);
|
||||
formData.append("email", personalDetails.email);
|
||||
formData.append("pincode", personalDetails.pincode);
|
||||
formData.append("gender", personalDetails.gender);
|
||||
formData.append("dob", personalDetails.dob);
|
||||
formData.append("height", personalDetails.height || "");
|
||||
formData.append("weight", personalDetails.weight || "");
|
||||
formData.append("marital_status", personalDetails.maritalStatus);
|
||||
formData.append("religion", personalDetails.religion);
|
||||
formData.append("profile_for", personalDetails.profileFor || "");
|
||||
formData.append("caste", personalDetails.caste);
|
||||
formData.append("sub_caste", personalDetails.subCaste || "");
|
||||
formData.append("gothram", personalDetails.gothram || "");
|
||||
formData.append("raasi", personalDetails.raasi || "");
|
||||
formData.append("star", personalDetails.star || "");
|
||||
formData.append("state", personalDetails.state);
|
||||
formData.append("district", personalDetails.city);
|
||||
formData.append("password", personalDetails.password || "");
|
||||
formData.append("fcm_token", localStorage.getItem("fcm_token") || "");
|
||||
|
||||
const buildRegisterStep2Payload = () => ({
|
||||
college_name: educationalDetails.collegeName || "",
|
||||
study_field: educationalDetails.fieldOfStudy,
|
||||
education: educationalDetails.qualification,
|
||||
occupation: educationalDetails.occupation,
|
||||
company_name: educationalDetails.organization || "",
|
||||
employee_type: educationalDetails.employeeType,
|
||||
annual_income: educationalDetails.income,
|
||||
work_location: educationalDetails.workLocation || "",
|
||||
});
|
||||
if (personalDetails.profiles && Array.isArray(personalDetails.profiles)) {
|
||||
for (const [index, item] of personalDetails.profiles.entries()) {
|
||||
// If the file object is intact (e.g., just added), use it directly.
|
||||
if (item.file && (item.file instanceof Blob || (typeof item.file === 'object' && item.file !== null && item.file.name))) {
|
||||
formData.append(`profile_images[${index}]`, item.file);
|
||||
}
|
||||
// If the file object was lost due to Redux serialization,
|
||||
// try to recover it from the blob URL preview.
|
||||
else if (
|
||||
item.preview &&
|
||||
typeof item.preview === "string"
|
||||
) {
|
||||
try {
|
||||
const response = await fetch(item.preview);
|
||||
const blob = await response.blob();
|
||||
const fileName = item.name || `profile_image_${index}.jpg`;
|
||||
const fileType = item.type || "image/jpeg";
|
||||
const recoveredFile = new File([blob], fileName, { type: fileType });
|
||||
formData.append(`profile_images[${index}]`, recoveredFile);
|
||||
} catch (e) {
|
||||
console.error(`Could not recover file from blob URL: ${item.preview}`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return formData;
|
||||
};
|
||||
|
||||
const buildRegisterStep2Payload = () => {
|
||||
const formData = new FormData();
|
||||
formData.append("college_name", educationalDetails.collegeName || "");
|
||||
formData.append("study_field", educationalDetails.fieldOfStudy || "");
|
||||
formData.append("education", educationalDetails.qualification || "");
|
||||
formData.append("occupation", educationalDetails.occupation || "");
|
||||
formData.append("company_name", educationalDetails.organization || "");
|
||||
formData.append("employee_type", educationalDetails.employeeType || "");
|
||||
formData.append("annual_income", educationalDetails.income || "");
|
||||
formData.append("work_location", educationalDetails.workLocation || "");
|
||||
return formData;
|
||||
};
|
||||
|
||||
const buildRegisterStep3Payload = () => {
|
||||
const payload = {
|
||||
father_name: familyDetails.fatherName,
|
||||
father_occupation: familyDetails.fatherOccupation || "",
|
||||
mother_name: familyDetails.motherName,
|
||||
mother_occupation: familyDetails.motherOccupation || "",
|
||||
family_status: familyDetails.familyStatus,
|
||||
native_place: familyDetails.nativePlace || "",
|
||||
brother_count: familyDetails.brotherCount || 0,
|
||||
sister_count: familyDetails.sisterCount || 0,
|
||||
};
|
||||
const formData = new FormData();
|
||||
formData.append("father_name", familyDetails.fatherName);
|
||||
formData.append("father_occupation", familyDetails.fatherOccupation || "");
|
||||
formData.append("mother_name", familyDetails.motherName);
|
||||
formData.append("mother_occupation", familyDetails.motherOccupation || "");
|
||||
formData.append("family_status", familyDetails.familyStatus);
|
||||
formData.append("native_place", familyDetails.nativePlace || "");
|
||||
formData.append("brother_count", familyDetails.brotherCount || 0);
|
||||
formData.append("sister_count", familyDetails.sisterCount || 0);
|
||||
|
||||
(familyDetails.brothers || []).forEach((brother, index) => {
|
||||
payload[`brothers[${index}][name]`] = brother?.name || "";
|
||||
payload[`brothers[${index}][occupation]`] = brother?.occupation || "";
|
||||
payload[`brothers[${index}][marital_status]`] =
|
||||
brother?.maritalStatus || "";
|
||||
payload[`brothers[${index}][have_childrens]`] =
|
||||
brother?.haveChildrens ?? "";
|
||||
formData.append(`brothers[${index}][name]`, brother?.name || "");
|
||||
formData.append(`brothers[${index}][occupation]`, brother?.occupation || "");
|
||||
formData.append(`brothers[${index}][marital_status]`, brother?.maritalStatus || "");
|
||||
formData.append(`brothers[${index}][have_childrens]`, brother?.haveChildrens ?? "");
|
||||
});
|
||||
|
||||
(familyDetails.sisters || []).forEach((sister, index) => {
|
||||
payload[`sisters[${index}][name]`] = sister?.name || "";
|
||||
payload[`sisters[${index}][occupation]`] = sister?.occupation || "";
|
||||
payload[`sisters[${index}][marital_status]`] =
|
||||
sister?.maritalStatus || "";
|
||||
payload[`sisters[${index}][have_childrens]`] =
|
||||
sister?.haveChildrens ?? "";
|
||||
formData.append(`sisters[${index}][name]`, sister?.name || "");
|
||||
formData.append(`sisters[${index}][occupation]`, sister?.occupation || "");
|
||||
formData.append(`sisters[${index}][marital_status]`, sister?.maritalStatus || "");
|
||||
formData.append(`sisters[${index}][have_childrens]`, sister?.haveChildrens ?? "");
|
||||
});
|
||||
|
||||
return payload;
|
||||
return formData;
|
||||
};
|
||||
|
||||
const buildRegisterStep4Payload = () => {
|
||||
const payload = {
|
||||
dob: lifestyleDetails.dob,
|
||||
tob: lifestyleDetails.tob,
|
||||
};
|
||||
const formData = new FormData();
|
||||
formData.append("dob", lifestyleDetails.dob || "");
|
||||
formData.append("tob", lifestyleDetails.tob || "");
|
||||
formData.append("place_of_birth", lifestyleDetails.placeOfBirth || "");
|
||||
|
||||
(lifestyleDetails.diets || []).forEach((id, index) => {
|
||||
payload[`diets[${index}]`] = id;
|
||||
formData.append(`diets[${index}]`, id);
|
||||
});
|
||||
|
||||
(lifestyleDetails.hobbies || []).forEach((id, index) => {
|
||||
payload[`hobbies[${index}]`] = id;
|
||||
formData.append(`hobbies[${index}]`, id);
|
||||
});
|
||||
|
||||
const graha = lifestyleDetails.graha || {};
|
||||
Object.keys(graha).forEach((house) => {
|
||||
const values = graha[house] || [];
|
||||
values.forEach((value, index) => {
|
||||
payload[`graha_${house}[${index}]`] = value;
|
||||
formData.append(`graha_${house}[${index}]`, value);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -539,48 +571,47 @@ const StepperForm = () => {
|
||||
Object.keys(amsam).forEach((house) => {
|
||||
const values = amsam[house] || [];
|
||||
values.forEach((value, index) => {
|
||||
payload[`amsam_${house}[${index}]`] = value;
|
||||
formData.append(`amsam_${house}[${index}]`, value);
|
||||
});
|
||||
});
|
||||
|
||||
return payload;
|
||||
return formData;
|
||||
};
|
||||
|
||||
const buildRegisterStep5Payload = () => {
|
||||
const payload = {
|
||||
age_range: partnerPreferences.ageRange,
|
||||
annual_income: partnerPreferences.annualIncome,
|
||||
};
|
||||
const formData = new FormData();
|
||||
formData.append("age_range", partnerPreferences.ageRange || "");
|
||||
formData.append("annual_income", partnerPreferences.annualIncome || "");
|
||||
|
||||
(partnerPreferences.castes || []).forEach((id, index) => {
|
||||
payload[`castes[${index}]`] = id;
|
||||
formData.append(`castes[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.subCastes || []).forEach((id, index) => {
|
||||
payload[`sub_castes[${index}]`] = id;
|
||||
formData.append(`sub_castes[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.occupations || []).forEach((id, index) => {
|
||||
payload[`occupations[${index}]`] = id;
|
||||
formData.append(`occupations[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.educations || []).forEach((id, index) => {
|
||||
payload[`educations[${index}]`] = id;
|
||||
formData.append(`educations[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.hobbies || []).forEach((id, index) => {
|
||||
payload[`hobbies[${index}]`] = id;
|
||||
formData.append(`hobbies[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.states || []).forEach((id, index) => {
|
||||
payload[`states[${index}]`] = id;
|
||||
formData.append(`states[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.districts || []).forEach((id, index) => {
|
||||
payload[`districts[${index}]`] = id;
|
||||
formData.append(`districts[${index}]`, id);
|
||||
});
|
||||
|
||||
return payload;
|
||||
return formData;
|
||||
};
|
||||
|
||||
const extractAccessToken = (res) =>
|
||||
@@ -601,7 +632,7 @@ const StepperForm = () => {
|
||||
|
||||
try {
|
||||
if (currentStep === 1) {
|
||||
const payload = buildRegisterStep1Payload();
|
||||
const payload = await buildRegisterStep1Payload();
|
||||
const res = await registerStep1.mutateAsync(payload);
|
||||
const token = extractAccessToken(res);
|
||||
if (token) {
|
||||
@@ -624,24 +655,29 @@ const StepperForm = () => {
|
||||
setCurrentStep((prev) => Math.min(prev + 1, 6));
|
||||
window.scrollTo(0, 0);
|
||||
} catch (e) {
|
||||
if (currentStep === 1) {
|
||||
const serverErrors = mapServerErrors(e);
|
||||
if (Object.keys(serverErrors).length > 0) {
|
||||
const hasFieldErrors = Object.keys(serverErrors).some(
|
||||
(key) => key !== "_form"
|
||||
);
|
||||
if (hasFieldErrors) {
|
||||
setErrors(serverErrors);
|
||||
focusFirstError(serverErrors, STEP_FIELD_ORDER[1]);
|
||||
return;
|
||||
}
|
||||
if (serverErrors._form) {
|
||||
toast.error(serverErrors._form, { position: "top-right" });
|
||||
return;
|
||||
}
|
||||
const serverErrors = mapServerErrors(e);
|
||||
let handled = false;
|
||||
|
||||
if (Object.keys(serverErrors).length > 0) {
|
||||
const hasFieldErrors = Object.keys(serverErrors).some(
|
||||
(key) => key !== "_form"
|
||||
);
|
||||
if (hasFieldErrors) {
|
||||
setErrors(serverErrors);
|
||||
focusFirstError(serverErrors, STEP_FIELD_ORDER[currentStep]);
|
||||
// For step 1, we know mapping is correct so field errors are sufficient feedback
|
||||
if (currentStep === 1) handled = true;
|
||||
}
|
||||
if (serverErrors._form) {
|
||||
toast.error(serverErrors._form, { position: "top-right" });
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
alert("Failed to submit step. Please try again.");
|
||||
|
||||
if (!handled) {
|
||||
const msg = e?.response?.data?.message || e?.message || "Failed to submit step. Please try again.";
|
||||
toast.error(msg, { position: "top-right" });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -675,9 +711,9 @@ const StepperForm = () => {
|
||||
try {
|
||||
// final combined API call - replace with your final API
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
alert("Form submitted successfully!");
|
||||
toast.success("Form submitted successfully!", { position: "top-right" });
|
||||
} catch (e) {
|
||||
alert("Failed to submit form.");
|
||||
toast.error("Failed to submit form.", { position: "top-right" });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user