Implement Subscription History and fix Interest Status Update flow
This commit is contained in:
1 parent
4ba4ce1e1b
commit
b3d33aca9c
42 files changed
+3950
-2677
No files matched your search
@@ -73,35 +73,31 @@ const EducationalDetailsForm = ({
|
||||
|
||||
dispatch(updateEducationalDetails(updates));
|
||||
setLocalErrors((prev) => ({ ...prev, [field]: "" }));
|
||||
|
||||
if (!isEditMode) {
|
||||
dispatch(clearAllStepsFrom(3));
|
||||
}
|
||||
};
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors = {};
|
||||
if (!data.study_field) newErrors.study_field = "Required";
|
||||
if (!data.education) newErrors.education = "Required";
|
||||
if (!data.education_detail) newErrors.education_detail = "Required";
|
||||
if (!data.employee_type) newErrors.employee_type = "Required";
|
||||
if (!data.study_field) newErrors.study_field = "Field of study is required";
|
||||
if (!data.education) newErrors.education = "Highest qualification is required";
|
||||
if (!data.education_detail) newErrors.education_detail = "Education detail is required";
|
||||
if (!data.employee_type) newErrors.employee_type = "Employee type is required";
|
||||
|
||||
if (!isUnemployed) {
|
||||
if (!data.occupation) newErrors.occupation = "Required";
|
||||
if (!data.occupation_detail) newErrors.occupation_detail = "Required";
|
||||
if (!data.income_currency) newErrors.income_currency = "Required";
|
||||
if (!data.annual_income) newErrors.annual_income = "Required";
|
||||
if (!data.work_country) newErrors.work_country = "Required";
|
||||
if (!data.occupation) newErrors.occupation = "Occupation is required";
|
||||
if (!data.occupation_detail) newErrors.occupation_detail = "Occupation detail is required";
|
||||
if (!data.income_currency) newErrors.income_currency = "Income currency is required";
|
||||
if (!data.annual_income) newErrors.annual_income = "Annual income is required";
|
||||
if (!data.work_country) newErrors.work_country = "Work country is required";
|
||||
|
||||
if (isIndia) {
|
||||
if (!data.work_state) newErrors.work_state = "Required";
|
||||
if (!data.work_district) newErrors.work_district = "Required";
|
||||
if (!data.work_state) newErrors.work_state = "Work state is required";
|
||||
if (!data.work_district) newErrors.work_district = "Work city is required";
|
||||
} else {
|
||||
if (!data.work_city) newErrors.work_city = "Required";
|
||||
if (!data.work_city) newErrors.work_city = "Work city is required";
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.address) newErrors.address = "Required";
|
||||
if (!data.address) newErrors.address = "Work address is required";
|
||||
|
||||
setLocalErrors(newErrors);
|
||||
return newErrors;
|
||||
|
||||
@@ -119,10 +119,6 @@ const FamilyDetailsForm = ({ onSubmitStep, onSkipStep, errors, onFieldChange, is
|
||||
|
||||
dispatch(updateFamilyDetails(updates));
|
||||
if (onFieldChange) onFieldChange(fieldsToClear);
|
||||
|
||||
if (!isEditMode) {
|
||||
dispatch(clearAllStepsFrom(4));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSiblingChange = (type, index, field, value) => {
|
||||
@@ -131,10 +127,6 @@ const FamilyDetailsForm = ({ onSubmitStep, onSkipStep, errors, onFieldChange, is
|
||||
list[index] = { ...list[index], [field]: value };
|
||||
dispatch(updateFamilyDetails({ [type]: list }));
|
||||
if (onFieldChange) onFieldChange(type);
|
||||
|
||||
if (!isEditMode) {
|
||||
dispatch(clearAllStepsFrom(4));
|
||||
}
|
||||
};
|
||||
|
||||
const scrollToError = (errorMap) => {
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
DialogActions,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { LocalizationProvider } from "@mui/x-date-pickers";
|
||||
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
|
||||
import { TimePicker } from "@mui/x-date-pickers/TimePicker";
|
||||
import { LocalizationProvider, DatePicker, TimePicker } from "@mui/x-date-pickers";
|
||||
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
|
||||
import { format } from "date-fns";
|
||||
import { useLifestyleMasters } from "../hooks/useMasters";
|
||||
import { useStarMasters, usePathamMasters } from "../hooks/useDependentMasters";
|
||||
import horoscopeImg from "../assets/images/horoscopeimg.png";
|
||||
|
||||
const LifestyleDetailsForm = ({
|
||||
@@ -34,30 +34,47 @@ const LifestyleDetailsForm = ({
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const data = useSelector((state) => state.registerform.lifestyleDetails);
|
||||
|
||||
if (!data) return null;
|
||||
|
||||
const inputRef = useRef(null);
|
||||
const requiredMark = <span style={{ color: "#d32f2f" }}> *</span>;
|
||||
|
||||
const { data: lifestyleMasters, isLoading: isLifestyleMastersLoading } =
|
||||
useLifestyleMasters();
|
||||
|
||||
const dietOptions = useMemo(() => {
|
||||
const raasiOptions = useMemo(() => {
|
||||
const raw = lifestyleMasters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.diet || raw.diets || [];
|
||||
return raw.raasis || raw.raasi || raw.rasi || [];
|
||||
}, [lifestyleMasters]);
|
||||
|
||||
const hobbyOptions = useMemo(() => {
|
||||
const panjangamOptions = useMemo(() => {
|
||||
const raw = lifestyleMasters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.hobbies || raw.hobby || [];
|
||||
return raw.panjangam_types || raw.panjangamTypes || [];
|
||||
}, [lifestyleMasters]);
|
||||
|
||||
const { data: starData } = useStarMasters(data.raasi);
|
||||
const starOptions = useMemo(() => {
|
||||
if (!starData) return [];
|
||||
return starData.stars || starData.star || starData.data || (Array.isArray(starData) ? starData : []);
|
||||
}, [starData]);
|
||||
|
||||
const { data: pathamData } = usePathamMasters(data.star);
|
||||
const pathamOptions = useMemo(() => {
|
||||
if (!pathamData) return [];
|
||||
return (
|
||||
pathamData.pathams ||
|
||||
pathamData.patham ||
|
||||
pathamData.data ||
|
||||
(Array.isArray(pathamData) ? pathamData : [])
|
||||
);
|
||||
}, [pathamData]);
|
||||
|
||||
const grahaOptions = useMemo(() => {
|
||||
const raw = lifestyleMasters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.grahas || raw.graha || [];
|
||||
}, [lifestyleMasters]);
|
||||
|
||||
@@ -74,13 +91,21 @@ const LifestyleDetailsForm = ({
|
||||
inputRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (data.dob) {
|
||||
const date = new Date(data.dob);
|
||||
if (!isNaN(date.getTime())) {
|
||||
const day = format(date, "EEEE");
|
||||
if (data.dayOfBirth !== day) {
|
||||
handleChange("dayOfBirth", day);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [data.dob]);
|
||||
|
||||
const handleChange = (field, value) => {
|
||||
dispatch(updateLifestyleDetails({ [field]: value }));
|
||||
if (onFieldChange) onFieldChange(field);
|
||||
|
||||
if (!isEditMode) {
|
||||
dispatch(clearAllStepsFrom(5));
|
||||
}
|
||||
};
|
||||
|
||||
const handleMultiChange = (field, value) => {
|
||||
@@ -189,7 +214,7 @@ const LifestyleDetailsForm = ({
|
||||
return `${h}:${m}`;
|
||||
};
|
||||
|
||||
const renderChartCell = (label, value, onChange) => (
|
||||
const renderChartCell = (label, value = [], onChange) => (
|
||||
<Tooltip title={value && value.length > 0 ? value.join(", ") : ""} arrow placement="top">
|
||||
<div className="bg-white border border-gray-300 rounded-lg p-2 flex flex-col items-center justify-center min-h-[70px]">
|
||||
<span className="text-[10px] font-medium text-gray-700 text-center">
|
||||
@@ -221,7 +246,7 @@ const LifestyleDetailsForm = ({
|
||||
>
|
||||
{grahaOptions.map((opt) => (
|
||||
<MenuItem key={opt} value={opt}>
|
||||
<Checkbox checked={value.indexOf(opt) > -1} />
|
||||
<Checkbox checked={Array.isArray(value) && value.indexOf(opt) > -1} />
|
||||
<ListItemText primary={opt} />
|
||||
</MenuItem>
|
||||
))}
|
||||
@@ -267,120 +292,13 @@ const LifestyleDetailsForm = ({
|
||||
return (
|
||||
<div className="w-full max-w-[1200px] mx-auto py-6 md:px-2 rounded-8">
|
||||
<form noValidate autoComplete="off" style={{ padding: 16 }}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-20 gap-y-10 mb-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Diet{requiredMark}
|
||||
</label>
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.diets)}>
|
||||
<InputLabel id="diets-label">Select Diet</InputLabel>
|
||||
<Select
|
||||
labelId="diets-label"
|
||||
label="Select Diet"
|
||||
name="diets"
|
||||
value={data.diets}
|
||||
onChange={(e) => handleChange("diets", e.target.value)}
|
||||
inputRef={inputRef}
|
||||
disabled={isLifestyleMastersLoading}
|
||||
sx={{
|
||||
"& .MuiSelect-select.Mui-disabled": {
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{dietOptions.map((opt) => {
|
||||
const value = opt.id ?? opt;
|
||||
const label = opt.diet_name || opt.name || String(opt);
|
||||
return (
|
||||
<MenuItem key={value} value={value}>
|
||||
{label}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
{errors.diets && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors.diets}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Hobbies & Interests (Multi-select){requiredMark}
|
||||
</label>
|
||||
<FormControl
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
error={Boolean(errors.hobbies)}
|
||||
>
|
||||
<InputLabel id="hobbies-label">
|
||||
Select Hobbies & Interests
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="hobbies-label"
|
||||
label="Select Hobbies & Interests"
|
||||
name="hobbies"
|
||||
multiple
|
||||
value={data.hobbies}
|
||||
onChange={(e) => handleMultiChange("hobbies", e.target.value)}
|
||||
disabled={isLifestyleMastersLoading}
|
||||
renderValue={(selected) =>
|
||||
selected
|
||||
.map((id) => {
|
||||
const item = hobbyOptions.find(
|
||||
(opt) => (opt.id ?? opt) === id
|
||||
);
|
||||
return item?.hobby_name || item?.name || id;
|
||||
})
|
||||
.join(", ")
|
||||
}
|
||||
sx={{
|
||||
"& .MuiSelect-select.Mui-disabled": {
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{hobbyOptions.map((opt) => {
|
||||
const value = opt.id ?? opt;
|
||||
const label = opt.hobby_name || opt.name || String(opt);
|
||||
return (
|
||||
<MenuItem key={value} value={value}>
|
||||
<Checkbox checked={data.hobbies.indexOf(value) > -1} />
|
||||
<ListItemText primary={label} />
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
{errors.hobbies && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors.hobbies}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center py-4">
|
||||
<h2 className="text-[18px] font-semibold text-gray-800">
|
||||
Astrology / Horoscope
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-[900px] mx-auto">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 w-full max-w-[1200px] mx-auto">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Date of Birth{requiredMark}
|
||||
@@ -403,6 +321,19 @@ const LifestyleDetailsForm = ({
|
||||
</LocalizationProvider>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Day of Birth</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
name="dayOfBirth"
|
||||
value={data.dayOfBirth}
|
||||
readOnly
|
||||
variant="outlined"
|
||||
placeholder="Day of Week"
|
||||
InputProps={{ readOnly: true }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Time of Birth{requiredMark}
|
||||
@@ -424,7 +355,7 @@ const LifestyleDetailsForm = ({
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Place of Birth</label>
|
||||
<label className="text-gray-900 text-[15px]">Place of Birth{requiredMark}</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
name="placeOfBirth"
|
||||
@@ -438,32 +369,186 @@ const LifestyleDetailsForm = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 w-full max-w-[950px] mx-auto mt-6">
|
||||
<div>
|
||||
<div className="py-4">
|
||||
<h3 className="text-base font-semibold text-gray-800 mb-3">
|
||||
Add Rasi
|
||||
</h3>
|
||||
{renderChartGrid("graha")}
|
||||
{errors.graha_duplicate && (
|
||||
<p style={{ color: "#d32f2f", fontSize: "0.75rem", marginTop: "4px" }}>
|
||||
{errors.graha_duplicate}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-[1200px] mx-auto mt-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Select Raasi{requiredMark}</label>
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.raasi)} id="raasi">
|
||||
<InputLabel id="raasi-label">Select Raasi</InputLabel>
|
||||
<Select
|
||||
labelId="raasi-label"
|
||||
label="Select Raasi"
|
||||
name="raasi"
|
||||
value={data.raasi}
|
||||
onChange={(e) => {
|
||||
handleChange("raasi", e.target.value);
|
||||
handleChange("star", "");
|
||||
handleChange("patham", "");
|
||||
}}
|
||||
>
|
||||
{raasiOptions.map((opt) => (
|
||||
<MenuItem key={opt.id} value={opt.id}>
|
||||
{opt.raasi_name || opt.rasi_name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="py-4">
|
||||
<h3 className="text-base font-semibold text-gray-800 mb-3">
|
||||
Add Navamsam
|
||||
</h3>
|
||||
{renderChartGrid("amsam")}
|
||||
{errors.amsam_duplicate && (
|
||||
<p style={{ color: "#d32f2f", fontSize: "0.75rem", marginTop: "4px" }}>
|
||||
{errors.amsam_duplicate}
|
||||
</p>
|
||||
)}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Select Birth Star{requiredMark}</label>
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.star)} id="star">
|
||||
<InputLabel id="star-label">Select Birth Star</InputLabel>
|
||||
<Select
|
||||
labelId="star-label"
|
||||
label="Select Birth Star"
|
||||
name="star"
|
||||
value={data.star}
|
||||
onChange={(e) => {
|
||||
handleChange("star", e.target.value);
|
||||
handleChange("patham", "");
|
||||
}}
|
||||
>
|
||||
{starOptions.map((opt) => (
|
||||
<MenuItem key={opt.id} value={opt.id}>
|
||||
{opt.star_name || opt.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Select Padham</label>
|
||||
<FormControl fullWidth variant="outlined" id="patham">
|
||||
<InputLabel id="patham-label">Select Padham</InputLabel>
|
||||
<Select
|
||||
labelId="patham-label"
|
||||
label="Select Padham"
|
||||
name="patham"
|
||||
value={data.patham}
|
||||
onChange={(e) => handleChange("patham", e.target.value)}
|
||||
>
|
||||
{pathamOptions.map((opt) => (
|
||||
<MenuItem key={opt} value={opt}>
|
||||
{opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Select Lagnam</label>
|
||||
<FormControl fullWidth variant="outlined" id="lagnam">
|
||||
<InputLabel id="lagnam-label">Select Lagnam</InputLabel>
|
||||
<Select
|
||||
labelId="lagnam-label"
|
||||
label="Select Lagnam"
|
||||
name="lagnam"
|
||||
value={data.lagnam}
|
||||
onChange={(e) => handleChange("lagnam", e.target.value)}
|
||||
>
|
||||
{raasiOptions.map((opt) => (
|
||||
<MenuItem key={opt.id} value={opt.id}>
|
||||
{opt.raasi_name || opt.rasi_name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Panjangam Type</label>
|
||||
<FormControl fullWidth variant="outlined" id="panjangam_type">
|
||||
<InputLabel id="panjangam-label">Select Panjangam Type</InputLabel>
|
||||
<Select
|
||||
labelId="panjangam-label"
|
||||
label="Select Panjangam Type"
|
||||
name="panjangam_type"
|
||||
value={data.panjangam_type}
|
||||
onChange={(e) => handleChange("panjangam_type", e.target.value)}
|
||||
>
|
||||
{panjangamOptions.map((opt) => (
|
||||
<MenuItem key={opt} value={opt}>
|
||||
{opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 w-full max-w-[1200px] mx-auto mt-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h3 className="text-base font-semibold text-gray-800 mb-3">Add Rasi</h3>
|
||||
{renderChartGrid("graha")}
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h3 className="text-base font-semibold text-gray-800 mb-3">Add Navamsam</h3>
|
||||
{renderChartGrid("amsam")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 w-full max-w-[1200px] mx-auto p-6 border border-gray-200 rounded-lg bg-gray-50">
|
||||
<h3 className="text-base font-semibold text-gray-800 mb-4">Dasa Details</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Dasa Type</label>
|
||||
<FormControl fullWidth variant="outlined" id="dasa_balance">
|
||||
<InputLabel id="dasa-label">Select Dasa Type</InputLabel>
|
||||
<Select
|
||||
labelId="dasa-label"
|
||||
label="Select Dasa Type"
|
||||
name="dasa_balance"
|
||||
value={data.dasa_balance}
|
||||
onChange={(e) => handleChange("dasa_balance", e.target.value)}
|
||||
>
|
||||
{grahaOptions.map((opt) => (
|
||||
<MenuItem key={opt} value={opt}>
|
||||
{opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Dasa Year</label>
|
||||
<TextField
|
||||
id="dasa_years"
|
||||
fullWidth
|
||||
name="dasa_years"
|
||||
value={data.dasa_years}
|
||||
onChange={(e) => handleChange("dasa_years", e.target.value)}
|
||||
placeholder="Enter Year"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Dasa Month</label>
|
||||
<TextField
|
||||
id="dasa_months"
|
||||
fullWidth
|
||||
name="dasa_months"
|
||||
value={data.dasa_months}
|
||||
onChange={(e) => handleChange("dasa_months", e.target.value)}
|
||||
placeholder="Enter Month"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Dasa Day</label>
|
||||
<TextField
|
||||
id="dasa_days"
|
||||
fullWidth
|
||||
name="dasa_days"
|
||||
value={data.dasa_days}
|
||||
onChange={(e) => handleChange("dasa_days", e.target.value)}
|
||||
placeholder="Enter Day"
|
||||
variant="outlined"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Button,
|
||||
Checkbox,
|
||||
ListItemText,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { usePartnerPreferenceMasters } from "../hooks/useMasters";
|
||||
import { useCityMasters, useSubCasteMasters } from "../hooks/useDependentMasters";
|
||||
@@ -30,11 +31,30 @@ const PartnerPreferencesForm = ({
|
||||
const subCasteQuery = useSubCasteMasters(data.castes);
|
||||
const cityQuery = useCityMasters(data.states);
|
||||
|
||||
const ageRangeOptions = useMemo(() => {
|
||||
const ageOptions = useMemo(() => Array.from({ length: 53 }, (_, i) => i + 18), []);
|
||||
|
||||
const heightOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.ageRange || raw.age_range || [];
|
||||
return raw.heights || raw.height || [];
|
||||
}, [masters]);
|
||||
|
||||
const maritalStatusOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
return raw.maritalStatus || raw.marital_status || [];
|
||||
}, [masters]);
|
||||
|
||||
const starOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
return raw.stars || raw.star || [];
|
||||
}, [masters]);
|
||||
|
||||
const employeeTypeOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
return raw.employeeTypes || raw.employee_type || [];
|
||||
}, [masters]);
|
||||
|
||||
const casteOptions = useMemo(() => {
|
||||
@@ -72,6 +92,8 @@ const PartnerPreferencesForm = ({
|
||||
return raw.annual_income || raw.annualIncome || [];
|
||||
}, [masters]);
|
||||
|
||||
const currencyOptions = useMemo(() => ["INR", "USD"], []);
|
||||
|
||||
const stateOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
@@ -96,8 +118,15 @@ const PartnerPreferencesForm = ({
|
||||
const cityOptions = useMemo(() => {
|
||||
const raw = cityQuery.data;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.subCaste || raw.district || raw.data || [];
|
||||
if (Array.isArray(raw)) {
|
||||
const merged = raw.flatMap((entry) => {
|
||||
if (!entry) return [];
|
||||
if (Array.isArray(entry)) return entry;
|
||||
return entry.district || entry.districts || entry.data || [];
|
||||
});
|
||||
return merged;
|
||||
}
|
||||
return raw.district || raw.districts || raw.data || [];
|
||||
}, [cityQuery.data]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -107,12 +136,15 @@ const PartnerPreferencesForm = ({
|
||||
const handleChange = (field, value) => {
|
||||
const arrayFields = new Set([
|
||||
"castes",
|
||||
"subCastes",
|
||||
"sub_castes",
|
||||
"occupations",
|
||||
"educations",
|
||||
"hobbies",
|
||||
"states",
|
||||
"districts",
|
||||
"marital_statuses",
|
||||
"birth_stars",
|
||||
"employee_types",
|
||||
"currencies",
|
||||
]);
|
||||
const nextValue =
|
||||
arrayFields.has(field) && typeof value === "string"
|
||||
@@ -122,8 +154,8 @@ const PartnerPreferencesForm = ({
|
||||
const fieldsToClear = [field];
|
||||
|
||||
if (field === "castes") {
|
||||
updates.subCastes = [];
|
||||
fieldsToClear.push("subCastes");
|
||||
updates.sub_castes = [];
|
||||
fieldsToClear.push("sub_castes");
|
||||
}
|
||||
if (field === "states") {
|
||||
updates.districts = [];
|
||||
@@ -201,215 +233,297 @@ const PartnerPreferencesForm = ({
|
||||
<div className="w-full max-w-[1200px] mx-auto py-6 md:px-2 rounded-8">
|
||||
<form noValidate autoComplete="off" style={{ padding: 16 }}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-20 gap-y-10 mb-6">
|
||||
{/* Age Range */}
|
||||
{/* 1. Age Range */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Age Range{requiredMark}
|
||||
</label>
|
||||
<FormControl
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
error={Boolean(errors.ageRange)}
|
||||
>
|
||||
<InputLabel id="ageRange-label">Select Age Range</InputLabel>
|
||||
<Select
|
||||
labelId="ageRange-label"
|
||||
label="Select Age Range"
|
||||
name="ageRange"
|
||||
value={data.ageRange}
|
||||
onChange={(e) => handleChange("ageRange", e.target.value)}
|
||||
inputRef={inputRef}
|
||||
disabled={isPartnerMastersLoading}
|
||||
sx={{
|
||||
"& .MuiSelect-select.Mui-disabled": {
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{ageRangeOptions.map((opt) => (
|
||||
<MenuItem key={opt.id ?? opt} value={opt.id ?? opt}>
|
||||
{opt.name || opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.ageRange && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
<label className="text-gray-900 text-[15px]">Age Range (From - To)</label>
|
||||
<div className="flex gap-2">
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.age_from)}>
|
||||
<InputLabel>From Age</InputLabel>
|
||||
<Select
|
||||
id="age_from"
|
||||
name="age_from"
|
||||
value={data.age_from}
|
||||
label="From Age"
|
||||
inputRef={inputRef}
|
||||
onChange={(e) => handleChange("age_from", e.target.value)}
|
||||
>
|
||||
{errors.ageRange}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
{ageOptions.map((age) => (
|
||||
<MenuItem key={age} value={age}>{age}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.age_from && (
|
||||
<p style={{ color: "#d32f2f", margin: "3px 14px 0 14px", fontSize: "0.75rem" }}>
|
||||
{errors.age_from}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.age_to)}>
|
||||
<InputLabel>To Age</InputLabel>
|
||||
<Select
|
||||
id="age_to"
|
||||
name="age_to"
|
||||
value={data.age_to}
|
||||
label="To Age"
|
||||
onChange={(e) => handleChange("age_to", e.target.value)}
|
||||
>
|
||||
{ageOptions.map((age) => (
|
||||
<MenuItem key={age} value={age}>{age}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.age_to && (
|
||||
<p style={{ color: "#d32f2f", margin: "3px 14px 0 14px", fontSize: "0.75rem" }}>
|
||||
{errors.age_to}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Caste */}
|
||||
{/* 2. Height Range */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Caste{requiredMark}
|
||||
</label>
|
||||
<label className="text-gray-900 text-[15px]">Height Range (From - To)</label>
|
||||
<div className="flex gap-2">
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.height_from)}>
|
||||
<InputLabel>From Height</InputLabel>
|
||||
<Select
|
||||
id="height_from"
|
||||
name="height_from"
|
||||
value={data.height_from}
|
||||
label="From Height"
|
||||
onChange={(e) => handleChange("height_from", e.target.value)}
|
||||
>
|
||||
{heightOptions.map((h) => (
|
||||
<MenuItem key={h.id} value={h.id}>{h.height_text}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.height_from && (
|
||||
<p style={{ color: "#d32f2f", margin: "3px 14px 0 14px", fontSize: "0.75rem" }}>
|
||||
{errors.height_from}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors.height_to)}>
|
||||
<InputLabel>To Height</InputLabel>
|
||||
<Select
|
||||
id="height_to"
|
||||
name="height_to"
|
||||
value={data.height_to}
|
||||
label="To Height"
|
||||
onChange={(e) => handleChange("height_to", e.target.value)}
|
||||
>
|
||||
{heightOptions.map((h) => (
|
||||
<MenuItem key={h.id} value={h.id}>{h.height_text}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.height_to && (
|
||||
<p style={{ color: "#d32f2f", margin: "3px 14px 0 14px", fontSize: "0.75rem" }}>
|
||||
{errors.height_to}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 3. Marital Status */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Marital Status</label>
|
||||
{renderMultiSelect({
|
||||
name: "marital_statuses",
|
||||
label: "Marital Status",
|
||||
options: maritalStatusOptions,
|
||||
value: data.marital_statuses,
|
||||
getLabel: (opt) => opt.marital_status_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 4. Birth Star */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Birth Star</label>
|
||||
{renderMultiSelect({
|
||||
name: "birth_stars",
|
||||
label: "Birth Star",
|
||||
options: starOptions,
|
||||
value: data.birth_stars,
|
||||
getLabel: (opt) => opt.star_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 5. Caste */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Caste</label>
|
||||
{renderMultiSelect({
|
||||
name: "castes",
|
||||
label: "Caste",
|
||||
options: casteOptions,
|
||||
value: data.castes,
|
||||
getLabel: (opt) => opt.caste_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
getLabel: (opt) => opt.caste_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Sub Caste */}
|
||||
{/* 6. Sub-Sect */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Sub Caste{requiredMark}
|
||||
</label>
|
||||
<label className="text-gray-900 text-[15px]">Sub-Sect</label>
|
||||
{renderMultiSelect({
|
||||
name: "subCastes",
|
||||
label: "Sub Caste",
|
||||
name: "sub_castes",
|
||||
label: "Sub-Sect",
|
||||
options: subCasteOptions,
|
||||
value: data.subCastes,
|
||||
getLabel: (opt) =>
|
||||
opt.sub_caste_name || opt.subCaste_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
value: data.sub_castes,
|
||||
getLabel: (opt) => opt.sub_caste_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: data.castes.length === 0 || subCasteQuery.isLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Occupation */}
|
||||
{/* 7. Qualification */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Occupation{requiredMark}
|
||||
</label>
|
||||
{renderMultiSelect({
|
||||
name: "occupations",
|
||||
label: "Occupation",
|
||||
options: occupationOptions,
|
||||
value: data.occupations,
|
||||
getLabel: (opt) => opt.occupation_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Qualification */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Qualification{requiredMark}
|
||||
</label>
|
||||
<label className="text-gray-900 text-[15px]">Qualification</label>
|
||||
{renderMultiSelect({
|
||||
name: "educations",
|
||||
label: "Qualification",
|
||||
options: educationOptions,
|
||||
value: data.educations,
|
||||
getLabel: (opt) => opt.education_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
getLabel: (opt) => opt.education_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Lifestyle and Hobbies */}
|
||||
{/* 8. Occupation */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Lifestyle & Hobbies{requiredMark}
|
||||
</label>
|
||||
<label className="text-gray-900 text-[15px]">Occupation</label>
|
||||
{renderMultiSelect({
|
||||
name: "hobbies",
|
||||
label: "Lifestyle & Hobbies",
|
||||
options: hobbyOptions,
|
||||
value: data.hobbies,
|
||||
getLabel: (opt) => opt.hobby_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
name: "occupations",
|
||||
label: "Occupation",
|
||||
options: occupationOptions,
|
||||
value: data.occupations,
|
||||
getLabel: (opt) => opt.occupation_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Annual Income */}
|
||||
{/* 9. Employee Type */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Annual Income{requiredMark}
|
||||
</label>
|
||||
<FormControl
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
error={Boolean(errors.annualIncome)}
|
||||
>
|
||||
<InputLabel id="annualIncome-label">
|
||||
Select Annual Income
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="annualIncome-label"
|
||||
label="Select Annual Income"
|
||||
name="annualIncome"
|
||||
value={data.annualIncome}
|
||||
onChange={(e) => handleChange("annualIncome", e.target.value)}
|
||||
disabled={isPartnerMastersLoading}
|
||||
sx={{
|
||||
"& .MuiSelect-select.Mui-disabled": {
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{annualIncomeOptions.map((opt) => (
|
||||
<MenuItem key={opt.id ?? opt} value={opt.id ?? opt}>
|
||||
{opt.annual_income_name || opt.name || opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.annualIncome && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors.annualIncome}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
<label className="text-gray-900 text-[15px]">Employee Type</label>
|
||||
{renderMultiSelect({
|
||||
name: "employee_types",
|
||||
label: "Employee Type",
|
||||
options: employeeTypeOptions,
|
||||
value: data.employee_types,
|
||||
getLabel: (opt) => opt.employee_type_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* State */}
|
||||
{/* 10. Currency Type */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
State{requiredMark}
|
||||
</label>
|
||||
<label className="text-gray-900 text-[15px]">Income Currency Type</label>
|
||||
{renderMultiSelect({
|
||||
name: "currencies",
|
||||
label: "Currency",
|
||||
options: currencyOptions,
|
||||
value: data.currencies,
|
||||
getLabel: (opt) => opt,
|
||||
getValue: (opt) => opt,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 11. Income Range */}
|
||||
{data.currencies.includes("INR") && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Annual Income (INR Range)</label>
|
||||
<div className="flex gap-2">
|
||||
<TextField
|
||||
id="inr_from"
|
||||
name="inr_from"
|
||||
fullWidth
|
||||
label="From (INR)"
|
||||
value={data.inr_from}
|
||||
error={Boolean(errors.inr_from)}
|
||||
helperText={errors.inr_from}
|
||||
onChange={(e) => handleChange("inr_from", e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
id="inr_to"
|
||||
name="inr_to"
|
||||
fullWidth
|
||||
label="To (INR)"
|
||||
value={data.inr_to}
|
||||
error={Boolean(errors.inr_to)}
|
||||
helperText={errors.inr_to}
|
||||
onChange={(e) => handleChange("inr_to", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{data.currencies.includes("USD") && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Annual Income (USD Range)</label>
|
||||
<div className="flex gap-2">
|
||||
<TextField
|
||||
id="usd_from"
|
||||
name="usd_from"
|
||||
fullWidth
|
||||
label="From (USD)"
|
||||
value={data.usd_from}
|
||||
error={Boolean(errors.usd_from)}
|
||||
helperText={errors.usd_from}
|
||||
onChange={(e) => handleChange("usd_from", e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
id="usd_to"
|
||||
name="usd_to"
|
||||
fullWidth
|
||||
label="To (USD)"
|
||||
value={data.usd_to}
|
||||
error={Boolean(errors.usd_to)}
|
||||
helperText={errors.usd_to}
|
||||
onChange={(e) => handleChange("usd_to", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 12. State */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">State</label>
|
||||
{renderMultiSelect({
|
||||
name: "states",
|
||||
label: "State",
|
||||
options: stateOptions,
|
||||
value: data.states,
|
||||
getLabel: (opt) => opt.state_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
getLabel: (opt) => opt.state_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* City */}
|
||||
{/* 13. City */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
City{requiredMark}
|
||||
</label>
|
||||
<label className="text-gray-900 text-[15px]">City</label>
|
||||
{renderMultiSelect({
|
||||
name: "districts",
|
||||
label: "City",
|
||||
options: cityOptions,
|
||||
value: data.districts,
|
||||
getLabel: (opt) =>
|
||||
opt.district_name || opt.city_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
getLabel: (opt) => opt.district_name || opt.city_name || opt.name,
|
||||
getValue: (opt) => opt.id,
|
||||
disabled: data.states.length === 0 || cityQuery.isLoading,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
size={12}
|
||||
style={{
|
||||
marginTop: 40,
|
||||
display: "flex",
|
||||
|
||||
@@ -126,13 +126,20 @@ const PersonalDetailsForm = ({ onSubmitStep, errors: externalErrors, onFieldChan
|
||||
dispatch(updatePersonalDetails(updates));
|
||||
if (onFieldChange) onFieldChange(fieldsToClear);
|
||||
|
||||
if (!isEditMode) {
|
||||
dispatch(clearAllStepsFrom(2));
|
||||
}
|
||||
|
||||
if (localErrors[field]) {
|
||||
setLocalErrors(prev => ({ ...prev, [field]: "" }));
|
||||
}
|
||||
|
||||
// Real-time password match validation
|
||||
if (field === "confirmPassword" || field === "password") {
|
||||
const p = field === "password" ? value : data.password;
|
||||
const cp = field === "confirmPassword" ? value : data.confirmPassword;
|
||||
if (p && cp && p !== cp) {
|
||||
setLocalErrors(prev => ({ ...prev, confirmPassword: "Passwords do not match" }));
|
||||
} else if (p && cp && p === cp) {
|
||||
setLocalErrors(prev => ({ ...prev, confirmPassword: "" }));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleMobileSubmit = async () => {
|
||||
@@ -198,21 +205,27 @@ const PersonalDetailsForm = ({ onSubmitStep, errors: externalErrors, onFieldChan
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors = {};
|
||||
if (!data.profile_for) newErrors.profile_for = "Required";
|
||||
if (!data.gender) newErrors.gender = "Required";
|
||||
if (!data.name) newErrors.name = "Required";
|
||||
if (!data.mobile) newErrors.mobile = "Required";
|
||||
if (!data.email) newErrors.email = "Required";
|
||||
if (!isEditMode && !data.password) newErrors.password = "Required";
|
||||
if (!isEditMode && data.password !== data.confirmPassword) newErrors.confirmPassword = "Passwords do not match";
|
||||
if (!data.marital_status) newErrors.marital_status = "Required";
|
||||
if (!data.height) newErrors.height = "Required";
|
||||
if (!data.complexion) newErrors.complexion = "Required";
|
||||
if (!data.physical_status) newErrors.physical_status = "Required";
|
||||
if (!data.mother_language) newErrors.mother_language = "Required";
|
||||
if (!data.do_you_speak_telugu && data.do_you_speak_telugu !== 0) newErrors.do_you_speak_telugu = "Required";
|
||||
if (!data.inter_caste_parents && data.inter_caste_parents !== 0) newErrors.inter_caste_parents = "Required";
|
||||
if (data.known_languages.length === 0) newErrors.known_languages = "Required";
|
||||
if (!data.profile_for) newErrors.profile_for = "Profile created for is required";
|
||||
if (!data.gender) newErrors.gender = "Gender is required";
|
||||
if (!data.name) newErrors.name = "Name is required";
|
||||
if (!data.mobile) newErrors.mobile = "Mobile number is required";
|
||||
if (!data.email) newErrors.email = "Email is required";
|
||||
if (!isEditMode && !data.password) newErrors.password = "Password is required";
|
||||
if (!isEditMode && !data.confirmPassword) newErrors.confirmPassword = "Confirm Password is required";
|
||||
if (!isEditMode && data.password && data.confirmPassword && data.password !== data.confirmPassword) {
|
||||
newErrors.confirmPassword = "Passwords do not match";
|
||||
}
|
||||
if (!data.caste) newErrors.caste = "Caste is required";
|
||||
if (!data.sub_caste) newErrors.sub_caste = "Sub-Sect is required";
|
||||
|
||||
if (!data.marital_status) newErrors.marital_status = "Marital status is required";
|
||||
if (!data.height) newErrors.height = "Height is required";
|
||||
if (!data.complexion) newErrors.complexion = "Complexion is required";
|
||||
if (!data.physical_status) newErrors.physical_status = "Physical status is required";
|
||||
if (!data.mother_language) newErrors.mother_language = "Mother tongue is required";
|
||||
if (!data.do_you_speak_telugu && data.do_you_speak_telugu !== 0) newErrors.do_you_speak_telugu = "Telugu speaking status is required";
|
||||
if (!data.inter_caste_parents && data.inter_caste_parents !== 0) newErrors.inter_caste_parents = "Inter-caste parents status is required";
|
||||
if (data.known_languages.length === 0) newErrors.known_languages = "Known languages are required";
|
||||
|
||||
setLocalErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
@@ -260,21 +273,27 @@ const PersonalDetailsForm = ({ onSubmitStep, errors: externalErrors, onFieldChan
|
||||
// 2. Perform general form validation
|
||||
if (!validateForm()) {
|
||||
const newErrors = {};
|
||||
if (!data.profile_for) newErrors.profile_for = "Required";
|
||||
if (!data.gender) newErrors.gender = "Required";
|
||||
if (!data.name) newErrors.name = "Required";
|
||||
if (!data.mobile) newErrors.mobile = "Required";
|
||||
if (!data.email) newErrors.email = "Required";
|
||||
if (!isEditMode && !data.password) newErrors.password = "Required";
|
||||
if (!isEditMode && data.password !== data.confirmPassword) newErrors.confirmPassword = "Passwords do not match";
|
||||
if (!data.marital_status) newErrors.marital_status = "Required";
|
||||
if (!data.height) newErrors.height = "Required";
|
||||
if (!data.complexion) newErrors.complexion = "Required";
|
||||
if (!data.physical_status) newErrors.physical_status = "Required";
|
||||
if (!data.mother_language) newErrors.mother_language = "Required";
|
||||
if (!data.do_you_speak_telugu && data.do_you_speak_telugu !== 0) newErrors.do_you_speak_telugu = "Required";
|
||||
if (!data.inter_caste_parents && data.inter_caste_parents !== 0) newErrors.inter_caste_parents = "Required";
|
||||
if (data.known_languages.length === 0) newErrors.known_languages = "Required";
|
||||
if (!data.profile_for) newErrors.profile_for = "Profile created for is required";
|
||||
if (!data.gender) newErrors.gender = "Gender is required";
|
||||
if (!data.name) newErrors.name = "Name is required";
|
||||
if (!data.mobile) newErrors.mobile = "Mobile number is required";
|
||||
if (!data.email) newErrors.email = "Email is required";
|
||||
if (!isEditMode && !data.password) newErrors.password = "Password is required";
|
||||
if (!isEditMode && !data.confirmPassword) newErrors.confirmPassword = "Confirm Password is required";
|
||||
if (!isEditMode && data.password && data.confirmPassword && data.password !== data.confirmPassword) {
|
||||
newErrors.confirmPassword = "Passwords do not match";
|
||||
}
|
||||
if (!data.caste) newErrors.caste = "Caste is required";
|
||||
if (!data.sub_caste) newErrors.sub_caste = "Sub-Sect is required";
|
||||
|
||||
if (!data.marital_status) newErrors.marital_status = "Marital status is required";
|
||||
if (!data.height) newErrors.height = "Height is required";
|
||||
if (!data.complexion) newErrors.complexion = "Complexion is required";
|
||||
if (!data.physical_status) newErrors.physical_status = "Physical status is required";
|
||||
if (!data.mother_language) newErrors.mother_language = "Mother tongue is required";
|
||||
if (!data.do_you_speak_telugu && data.do_you_speak_telugu !== 0) newErrors.do_you_speak_telugu = "Telugu speaking status is required";
|
||||
if (!data.inter_caste_parents && data.inter_caste_parents !== 0) newErrors.inter_caste_parents = "Inter-caste parents status is required";
|
||||
if (data.known_languages.length === 0) newErrors.known_languages = "Known languages are required";
|
||||
|
||||
toast.error("Please fill all mandatory fields");
|
||||
scrollToError(newErrors);
|
||||
@@ -581,8 +600,8 @@ const PersonalDetailsForm = ({ onSubmitStep, errors: externalErrors, onFieldChan
|
||||
|
||||
{/* 14. Caste / Community */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Caste / Community</label>
|
||||
<FormControl fullWidth disabled={casteQuery.isLoading}>
|
||||
<label className="text-gray-900 text-[15px]">Caste / Community{requiredMark}</label>
|
||||
<FormControl fullWidth disabled={casteQuery.isLoading} error={Boolean(errors.caste)} id="caste">
|
||||
<InputLabel>Select Caste</InputLabel>
|
||||
<Select
|
||||
value={data.caste}
|
||||
@@ -593,13 +612,14 @@ const PersonalDetailsForm = ({ onSubmitStep, errors: externalErrors, onFieldChan
|
||||
<MenuItem key={opt.id} value={opt.id}>{opt.caste_name}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.caste && <FormHelperText>{errors.caste}</FormHelperText>}
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
{/* 15. Sub-Sect */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Sub-Sect{requiredMark}</label>
|
||||
<FormControl fullWidth disabled={!data.caste || subCasteQuery.isLoading} id="sub_caste">
|
||||
<FormControl fullWidth disabled={!data.caste || subCasteQuery.isLoading} error={Boolean(errors.sub_caste)} id="sub_caste">
|
||||
<InputLabel>Select Sub-Sect</InputLabel>
|
||||
<Select
|
||||
value={data.sub_caste}
|
||||
@@ -610,6 +630,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors: externalErrors, onFieldChan
|
||||
<MenuItem key={opt.id} value={opt.id}>{opt.sub_caste_name}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.sub_caste && <FormHelperText>{errors.sub_caste}</FormHelperText>}
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
|
||||
Whitespace-only changes.
+311
-401
@@ -5,7 +5,7 @@ import { Navigation, Pagination } from "swiper/modules";
|
||||
import "swiper/css";
|
||||
import "swiper/css/navigation";
|
||||
import "swiper/css/pagination";
|
||||
import { Edit2,Info } from 'lucide-react';
|
||||
import { Edit2, Info } from 'lucide-react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { usePreviewDetails } from "../hooks/usePreview";
|
||||
import { isAuthenticated } from "../utills/auth";
|
||||
import { usePersonalMasters, usePartnerPreferenceMasters } from "../hooks/useMasters";
|
||||
import horoscopeImg from "../assets/images/horoscopeimg.png";
|
||||
import { updatePersonalDetails } from "../redux/registrationFormSlice";
|
||||
|
||||
@@ -42,8 +43,7 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
if (pd) {
|
||||
const images = pd.images || pd.profile_images;
|
||||
if (images && images.length > 0) {
|
||||
// Map images to ensure they have a consistent format for Redux
|
||||
const formattedImages = images.map(img =>
|
||||
const formattedImages = images.map(img =>
|
||||
typeof img === 'string' ? { url: img, preview: img } : img
|
||||
);
|
||||
dispatch(updatePersonalDetails({ profiles: formattedImages }));
|
||||
@@ -66,124 +66,50 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
setOpenConfirmDialog(false);
|
||||
};
|
||||
|
||||
const sections = previewData?.personal_details
|
||||
? [
|
||||
{
|
||||
title: "Personal Details",
|
||||
step: 1,
|
||||
data: previewData.personal_details,
|
||||
},
|
||||
{
|
||||
title: "Educational & Professional Details",
|
||||
step: 2,
|
||||
data: previewData.educational_details,
|
||||
},
|
||||
{
|
||||
title: "Family Details",
|
||||
step: 3,
|
||||
data: previewData.family_details,
|
||||
},
|
||||
{
|
||||
title: "Lifestyle & Habits",
|
||||
step: 4,
|
||||
data: previewData.lifestyle_details,
|
||||
},
|
||||
{
|
||||
title: "Partner Preferences",
|
||||
step: 5,
|
||||
data: previewData.partner_preferences,
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
title: 'Personal Details',
|
||||
step: 1,
|
||||
data: formData.personalDetails,
|
||||
},
|
||||
{
|
||||
title: 'Educational & Professional Details',
|
||||
step: 2,
|
||||
data: formData.educationalDetails,
|
||||
},
|
||||
{
|
||||
title: 'Family Details',
|
||||
step: 3,
|
||||
data: formData.familyDetails,
|
||||
},
|
||||
{
|
||||
title: 'Lifestyle & Habits',
|
||||
step: 4,
|
||||
data: formData.lifestyleDetails,
|
||||
},
|
||||
{
|
||||
title: 'Partner Preferences',
|
||||
step: 5,
|
||||
data: formData.partnerPreferences,
|
||||
},
|
||||
];
|
||||
|
||||
const renderValue = (key, value) => {
|
||||
if (key === "profiles" || key === "profile" || key === "profile_images" || key === "images") {
|
||||
const list = Array.isArray(value) ? value : (value ? [value] : []);
|
||||
return (
|
||||
<Box display="flex" gap={1} flexWrap="wrap">
|
||||
{list.length > 0 ? (
|
||||
list.map((imgObj, index) => {
|
||||
const src =
|
||||
typeof imgObj === "string"
|
||||
? imgObj
|
||||
: imgObj?.preview ||
|
||||
imgObj?.url ||
|
||||
(imgObj?.file ? URL.createObjectURL(imgObj.file) : null);
|
||||
if (!src) return null;
|
||||
return (
|
||||
<img
|
||||
key={index}
|
||||
src={src}
|
||||
alt="Profile"
|
||||
style={{
|
||||
width: "90px",
|
||||
height: "90px",
|
||||
objectFit: "cover",
|
||||
borderRadius: "50%",
|
||||
border: "1px solid #ccc",
|
||||
// marginLeft: "-20px",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Box display="flex" alignItems="center" gap={1} sx={{ color: "#888" }}>
|
||||
<Info size={16} />
|
||||
<Typography>No photos uploaded</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const renderValue = (value) => {
|
||||
if (value === null || value === undefined || value === "") return "-";
|
||||
if (Array.isArray(value)) {
|
||||
if (value.length === 0) return "-";
|
||||
if (typeof value[0] === "object") {
|
||||
return value.map((item, idx) => (
|
||||
<div key={idx}>{JSON.stringify(item)}</div>
|
||||
));
|
||||
}
|
||||
return value.join(", ");
|
||||
}
|
||||
|
||||
if (value && typeof value === "object") {
|
||||
return "-";
|
||||
if (typeof value === "boolean" || value === 1 || value === "1" || value === 0 || value === "0") {
|
||||
if (value === true || value === 1 || value === "1") return "Yes";
|
||||
if (value === false || value === 0 || value === "0") return "No";
|
||||
}
|
||||
|
||||
return value || "-";
|
||||
return value;
|
||||
};
|
||||
|
||||
const DetailRow = ({ label, value }) => (
|
||||
<Box display="grid" gridTemplateColumns="45% 55%" gap={1} mb={0.8} alignItems="start">
|
||||
<Typography color="text.secondary" sx={{ fontWeight: 500, fontSize: '0.875rem' }}>
|
||||
{label}:
|
||||
</Typography>
|
||||
<Typography variant="body2" fontWeight={600} sx={{ wordBreak: 'break-word' }}>
|
||||
{renderValue(value)}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
|
||||
const SectionTitle = ({ title, mt = 2 }) => (
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
sx={{
|
||||
fontWeight: 'bold',
|
||||
fontSize: '18px',
|
||||
color: '#111827',
|
||||
mt: mt,
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
);
|
||||
|
||||
const renderChartGrid = (getDataForCell, title) => {
|
||||
const renderCell = (i) => {
|
||||
const items = getDataForCell(i);
|
||||
const label = Array.isArray(items) ? items.join(', ') : '';
|
||||
|
||||
|
||||
return (
|
||||
<Tooltip key={i} title={label} arrow placement="top" disableHoverListener={!items || items.length === 0}>
|
||||
<Box
|
||||
@@ -204,12 +130,12 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
cursor: items && items.length > 0 ? 'help' : 'default'
|
||||
}}
|
||||
>
|
||||
{items && items.length > 2 ? (
|
||||
<Box>
|
||||
{items.slice(0, 2).join(', ')}
|
||||
<Box component="span" sx={{ color: 'primary.main', display: 'block', fontSize:'0.6rem' }}>+{items.length - 2}</Box>
|
||||
</Box>
|
||||
) : label}
|
||||
{items && items.length > 2 ? (
|
||||
<Box>
|
||||
{items.slice(0, 2).join(', ')}
|
||||
<Box component="span" sx={{ color: 'primary.main', display: 'block', fontSize: '0.6rem' }}>+{items.length - 2}</Box>
|
||||
</Box>
|
||||
) : label}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
);
|
||||
@@ -217,315 +143,299 @@ const PreviewScreen = ({ onEdit, onSubmit }) => {
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Typography variant="subtitle2" align="center" gutterBottom sx={{ fontWeight: 600 }}>{title}</Typography>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0.5, maxWidth: '300px', mx: 'auto', p: 1, bgcolor: '#fff3e0', borderRadius: 2 }}>
|
||||
{renderCell(1)} {renderCell(2)} {renderCell(3)} {renderCell(4)}
|
||||
{renderCell(5)}
|
||||
<Box sx={{ gridColumn: 'span 2', gridRow: 'span 2', bgcolor: '#fff', border: '1px solid #eee', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'0.7rem', fontWeight:'bold', color:'#aaa', overflow: 'hidden' }}>
|
||||
<img src={horoscopeImg} alt={title} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
|
||||
</Box>
|
||||
{renderCell(6)}
|
||||
{renderCell(7)} {renderCell(8)}
|
||||
{renderCell(9)} {renderCell(10)} {renderCell(11)} {renderCell(12)}
|
||||
<Typography variant="subtitle2" align="center" gutterBottom sx={{ fontWeight: 600, color: '#CC1F1F' }}>{title}</Typography>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0.5, maxWidth: '300px', mx: 'auto', p: 1, bgcolor: '#fff3e0', borderRadius: 2 }}>
|
||||
{renderCell(1)} {renderCell(2)} {renderCell(3)} {renderCell(4)}
|
||||
{renderCell(5)}
|
||||
<Box sx={{ gridColumn: 'span 2', gridRow: 'span 2', bgcolor: '#fff', border: '1px solid #eee', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '0.7rem', fontWeight: 'bold', color: '#aaa', overflow: 'hidden' }}>
|
||||
<img src={horoscopeImg} alt={title} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
|
||||
</Box>
|
||||
{renderCell(6)}
|
||||
{renderCell(7)} {renderCell(8)}
|
||||
{renderCell(9)} {renderCell(10)} {renderCell(11)} {renderCell(12)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box p={3} sx={{maxWidth:"1400px", width:"100%"}} mx="auto" >
|
||||
|
||||
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 my-10'>
|
||||
const { data: pm } = usePersonalMasters();
|
||||
const { data: ppm } = usePartnerPreferenceMasters();
|
||||
|
||||
const getNamesFromIds = (ids, options, labelKey = 'name', valueKey = 'id') => {
|
||||
if (!ids || (Array.isArray(ids) && ids.length === 0)) return null;
|
||||
if (!options) return Array.isArray(ids) ? ids.join(", ") : ids;
|
||||
|
||||
const idArray = Array.isArray(ids) ? ids : String(ids).split(",").map(v => v.trim());
|
||||
if (idArray.length === 0) return null;
|
||||
|
||||
// Check if the first element is already a name
|
||||
if (idArray[0] && typeof idArray[0] === 'string' && isNaN(Number(idArray[0]))) {
|
||||
return idArray.join(", ");
|
||||
}
|
||||
|
||||
const names = idArray.map(id => {
|
||||
const found = options.find(opt => String(opt[valueKey]) === String(id));
|
||||
if (found) return found[labelKey];
|
||||
return id;
|
||||
});
|
||||
return names.filter(Boolean).join(", ");
|
||||
};
|
||||
|
||||
const pInfo = previewData?.personal_details || formData.personalDetails;
|
||||
const eInfo = previewData?.educational_details || formData.educationalDetails;
|
||||
const fInfo = previewData?.family_details || formData.familyDetails;
|
||||
const lInfo = previewData?.lifestyle_details || formData.lifestyleDetails;
|
||||
// Helper to check if partner preferences from API are actually empty
|
||||
const isPartnerApiDataEmpty = (pp) => {
|
||||
if (!pp) return true;
|
||||
// Check for common fields that should have values if data was saved
|
||||
const hasData = pp.preferred_age_from || pp.age_from || pp.preferred_marital_status_ids?.length > 0 || pp.marital_statuses?.length > 0 || pp.preferred_castes_ids?.length > 0 || pp.castes?.length > 0;
|
||||
return !hasData;
|
||||
};
|
||||
|
||||
const prInfo = (!isPartnerApiDataEmpty(previewData?.partner_preferences)) ? previewData.partner_preferences :
|
||||
(!isPartnerApiDataEmpty(previewData?.preferred_details)) ? previewData.preferred_details :
|
||||
(!isPartnerApiDataEmpty(previewData?.partner_details)) ? previewData.partner_details :
|
||||
(formData.partnerPreferences || {});
|
||||
|
||||
return (
|
||||
<Box p={3} sx={{ maxWidth: "1400px", width: "100%" }} mx="auto">
|
||||
<div className='grid grid-cols-1 md:grid-cols-2 gap-6 my-10'>
|
||||
{isLoading && (
|
||||
<Box
|
||||
py={4}
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
sx={{ color: "#666" }}
|
||||
>
|
||||
<Box py={4} display="flex" justifyContent="center" sx={{ color: "#666", gridColumn: 'span 2' }}>
|
||||
Loading preview...
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{isError && (
|
||||
<Box
|
||||
py={4}
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
sx={{ color: "#d32f2f" }}
|
||||
>
|
||||
<Box py={4} display="flex" justifyContent="center" sx={{ color: "#d32f2f", gridColumn: 'span 2' }}>
|
||||
Failed to load preview.
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!isLoading &&
|
||||
sections.map((section) => (
|
||||
|
||||
<Card key={section.title} variant="outlined"
|
||||
sx={{ borderRadius: 2,
|
||||
// background:"#fff5ed"
|
||||
}}>
|
||||
{!isLoading && (
|
||||
<>
|
||||
{/* 1. Personal Details */}
|
||||
<Card variant="outlined" sx={{ borderRadius: 2 }}>
|
||||
<CardHeader
|
||||
title={
|
||||
<Typography variant="h6" fontWeight="bold">
|
||||
{section.title}
|
||||
</Typography>
|
||||
}
|
||||
action={
|
||||
<IconButton
|
||||
aria-label="edit"
|
||||
color="primary"
|
||||
onClick={() => onEdit(section.step)}
|
||||
size="large"
|
||||
>
|
||||
<Edit2 size={20} />
|
||||
</IconButton>
|
||||
}
|
||||
sx={{padding:"15px 15px", background:"#f5fbff" }}
|
||||
title={<Typography variant="h6" fontWeight="bold">Personal Details</Typography>}
|
||||
action={<IconButton color="primary" onClick={() => onEdit(1)} size="large"><Edit2 size={20} /></IconButton>}
|
||||
sx={{ padding: "15px 15px", background: "#f5fbff" }}
|
||||
/>
|
||||
{/* <Divider /> */}
|
||||
<CardContent sx={{ pt: 1, }}>
|
||||
{Object.entries(section.data || {}).map(([key, value]) => {
|
||||
// Filter out ID fields
|
||||
const hiddenFields = [
|
||||
"id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"phone_number_visibility",
|
||||
"chat_alert_notification",
|
||||
"chat_protection",
|
||||
"profile_photo_protect",
|
||||
"call_protection",
|
||||
"match_alert_preference",
|
||||
"who_can_message",
|
||||
"who_can_message_categories",
|
||||
"user_status",
|
||||
];
|
||||
if (hiddenFields.includes(key) || key.endsWith('_id') || key.endsWith('Id') || key.endsWith('_ids') || key.endsWith('Ids')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Handle Horoscope Chart (Server Data)
|
||||
if (key === 'horoscope' && value && typeof value === 'object') {
|
||||
return (
|
||||
<Box key={key} sx={{ width: '100%', mt: 2, mb: 2, borderTop: '1px solid #e0e0e0', pt: 2, gridColumn: '1 / -1' }}>
|
||||
<Typography variant="subtitle1" fontWeight="bold" gutterBottom>Horoscope Details</Typography>
|
||||
<Grid container spacing={4} justifyContent="center">
|
||||
<Grid item xs={12} md={6}>
|
||||
{renderChartGrid((i) => {
|
||||
const val = value[`graha_${i}`];
|
||||
return val ? val.split(',') : [];
|
||||
}, 'Rasi')}
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
{renderChartGrid((i) => {
|
||||
const val = value[`amsam_${i}`];
|
||||
return val ? val.split(',') : [];
|
||||
}, 'Navamsam')}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// Handle Horoscope Chart (Redux Data)
|
||||
if (key === 'graha' && value) {
|
||||
return (
|
||||
<Box key={key} sx={{ width: '100%', mt: 2, mb: 2, gridColumn: '1 / -1' }}>
|
||||
{renderChartGrid((i) => value[i] || [], 'Rasi')}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
if (key === 'amsam' && value) {
|
||||
return (
|
||||
<Box key={key} sx={{ width: '100%', mt: 2, mb: 2, gridColumn: '1 / -1' }}>
|
||||
{renderChartGrid((i) => value[i] || [], 'Navamsam')}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// 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;
|
||||
overflow: 'hidden';
|
||||
padding:5px;
|
||||
display: 'flex';
|
||||
align-items: 'center';
|
||||
justify-content: 'center';
|
||||
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: 8px;
|
||||
font-weight: bold;
|
||||
width:20px;
|
||||
|
||||
}
|
||||
.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]) => {
|
||||
if (sKey === 'id' || sKey.endsWith('_id') || sKey.endsWith('Id') || sKey === 'created_at' || sKey === 'updated_at') return null;
|
||||
let displayValue = sVal;
|
||||
if (sKey === 'haveChildrens' || sKey === 'have_childrens' || sKey === 'hasChildren' || sKey === 'has_children') {
|
||||
if (sVal === true || sVal === 1 || sVal === '1' || sVal === 'Yes') {
|
||||
displayValue = 'Yes';
|
||||
} else if (sVal === false || sVal === 0 || sVal === '0' || sVal === 'No') {
|
||||
displayValue = 'No';
|
||||
}
|
||||
}
|
||||
return (
|
||||
<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' }}>
|
||||
{displayValue ?? '-'}
|
||||
</Typography>
|
||||
</Box>
|
||||
)})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
// Convert camelCase or camel_Snake_case to readable words
|
||||
const formattedKey = key
|
||||
.replace(/([A-Z])/g, ' $1')
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/\b\w/g, (l) => l.toUpperCase())
|
||||
.trim();
|
||||
const content = renderValue(key, value);
|
||||
return (
|
||||
|
||||
<Box
|
||||
key={key}
|
||||
py={0.7}
|
||||
// borderBottom="1px solid #e0e0e0"
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: {
|
||||
xs: "1fr",
|
||||
sm: "1fr 1fr",
|
||||
},
|
||||
gap: "10px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography color="text.secondary" sx={{ fontWeight: 500 }}>
|
||||
{formattedKey}:
|
||||
</Typography>
|
||||
|
||||
{/* Special Case: Profiles Image Preview */}
|
||||
{key === "profiles" || key === "profile" || key === "profile_images" || key === "images" ? (
|
||||
content
|
||||
) : value ? (
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
wordBreak: "break-word",
|
||||
textAlign: "left",
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</Typography>
|
||||
) : (
|
||||
<Box
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
gap={1}
|
||||
sx={{ color: "#888", fontStyle: "italic" }}
|
||||
>
|
||||
<Info size={16} />
|
||||
<Typography>No data available</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
||||
})}
|
||||
<CardContent>
|
||||
<Box mb={2}>
|
||||
{/* Photos Preview */}
|
||||
<Typography color="text.secondary" sx={{ fontWeight: 600, mb: 1, fontSize: '0.75rem' }}>Profile Photos:</Typography>
|
||||
<Box display="flex" gap={1} flexWrap="wrap">
|
||||
{(pInfo.images || pInfo.profile_images || pInfo.profiles || []).map((imgObj, index) => {
|
||||
const src = typeof imgObj === "string" ? imgObj : imgObj?.preview || imgObj?.url;
|
||||
return src ? (
|
||||
<img key={index} src={src} alt="Profile" style={{ width: "80px", height: "80px", objectFit: "cover", borderRadius: "50%", border: "1px solid #ccc" }} />
|
||||
) : null;
|
||||
})}
|
||||
{!(pInfo.images || pInfo.profile_images || pInfo.profiles || []).length && <Typography variant="caption">No photos</Typography>}
|
||||
</Box>
|
||||
</Box>
|
||||
<DetailRow label="Profile Created For" value={pInfo.profile_for} />
|
||||
<DetailRow label="Gender" value={pInfo.gender} />
|
||||
<DetailRow label="Name" value={pInfo.name} />
|
||||
<DetailRow label="Mobile Number" value={pInfo.mobile || pInfo.mobileNumber || pInfo.mobile_number} />
|
||||
<DetailRow label="Email Id" value={pInfo.email || pInfo.emailId || pInfo.email_id} />
|
||||
<DetailRow label="Marital Status" value={getNamesFromIds(pInfo.marital_status, pm?.marital_status, 'marital_status_name')} />
|
||||
<DetailRow label="Height" value={getNamesFromIds(pInfo.height, pm?.heights, 'height_text')} />
|
||||
<DetailRow label="Weight" value={pInfo.weight} />
|
||||
<DetailRow label="Complexion" value={getNamesFromIds(pInfo.complexion, pm?.complexion, 'complexion_name')} />
|
||||
<DetailRow label="Physical Status" value={getNamesFromIds(pInfo.physical_status, pm?.physicalStatus, 'physical_status_name')} />
|
||||
<DetailRow label="Religion" value={getNamesFromIds(pInfo.religion, pm?.religion, 'religion_name')} />
|
||||
<DetailRow label="Caste / Community" value={getNamesFromIds(pInfo.caste, pm?.caste, 'caste_name')} />
|
||||
<DetailRow label="Sub-Sect" value={getNamesFromIds(pInfo.sub_caste, pm?.subCaste, 'sub_caste_name')} />
|
||||
<DetailRow label="Willing to marry from same sub-sect" value={pInfo.willing_to_marry} />
|
||||
<DetailRow label="Inter-Caste Parents" value={pInfo.inter_caste_parents === 1 || pInfo.inter_caste_parents === "1" ? "Yes" : "No"} />
|
||||
{ (pInfo.inter_caste_parents === 1 || pInfo.inter_caste_parents === "1") && <DetailRow label="Inter-Caste Parents Details" value={pInfo.inter_caste_parents_details} />}
|
||||
<DetailRow label="Gothram" value={pInfo.gothram} />
|
||||
<DetailRow label="Do you speak Telugu" value={pInfo.do_you_speak_telugu === 1 || pInfo.do_you_speak_telugu === "1" ? "Yes" : "No"} />
|
||||
<DetailRow label="About" value={pInfo.about_us} />
|
||||
<DetailRow label="Language Spoken" value={pInfo.known_languages} />
|
||||
<DetailRow label="Mother Tongue" value={getNamesFromIds(pInfo.mother_language, pm?.languages, 'language')} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
))}
|
||||
|
||||
</div>
|
||||
{/* 2. Educational & Professional Details */}
|
||||
<Card variant="outlined" sx={{ borderRadius: 2 }}>
|
||||
<CardHeader
|
||||
title={<Typography variant="h6" fontWeight="bold">Educational & Professional Details</Typography>}
|
||||
action={<IconButton color="primary" onClick={() => onEdit(2)} size="large"><Edit2 size={20} /></IconButton>}
|
||||
sx={{ padding: "15px 15px", background: "#f5fbff" }}
|
||||
/>
|
||||
<CardContent>
|
||||
<DetailRow label="Highest Qualification" value={getNamesFromIds(eInfo.education, ppm?.education || ppm?.educations, 'education_name')} />
|
||||
<DetailRow label="Field of Study" value={getNamesFromIds(eInfo.study_field, ppm?.study_fields || ppm?.studyFields, 'study_field_name')} />
|
||||
<DetailRow label="About" value={eInfo.education_detail || eInfo.educationDetail || eInfo.about} />
|
||||
<DetailRow label="College Name" value={eInfo.college_name} />
|
||||
<DetailRow label="Employee type" value={getNamesFromIds(eInfo.employee_type, ppm?.employeeTypes || ppm?.employee_type, 'employee_type_name')} />
|
||||
<DetailRow label="Occupation" value={getNamesFromIds(eInfo.occupation, ppm?.occupation || ppm?.occupations, 'occupation_name')} />
|
||||
<DetailRow label="Occupation Details" value={eInfo.occupation_detail || eInfo.occupationDetail} />
|
||||
<DetailRow label="Organization Name" value={eInfo.company_name || eInfo.organizationName || eInfo.companyName} />
|
||||
<DetailRow label="Income Currency Type" value={eInfo.income_currency} />
|
||||
<DetailRow label="Annual Income" value={eInfo.annual_income} />
|
||||
|
||||
<SectionTitle title="Work Location" />
|
||||
<DetailRow label="Country" value={eInfo.work_country_name || eInfo.work_country} />
|
||||
<DetailRow label="State" value={eInfo.work_state_name || eInfo.work_state} />
|
||||
<DetailRow label="City" value={eInfo.work_district_name || eInfo.work_city} />
|
||||
<DetailRow label="Address" value={eInfo.work_location || eInfo.address} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Grid item xs={12} sx={{display:"flex", justifyContent:"center"}}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="success"
|
||||
|
||||
size="large"
|
||||
onClick={handleConfirmSubmit}
|
||||
sx={{ borderRadius: 2 }}
|
||||
>
|
||||
Submit full Completed Data
|
||||
</Button>
|
||||
</Grid>
|
||||
{/* 3. Family Details */}
|
||||
<Card variant="outlined" sx={{ borderRadius: 2 }}>
|
||||
<CardHeader
|
||||
title={<Typography variant="h6" fontWeight="bold">Family Details</Typography>}
|
||||
action={<IconButton color="primary" onClick={() => onEdit(3)} size="large"><Edit2 size={20} /></IconButton>}
|
||||
sx={{ padding: "15px 15px", background: "#f5fbff" }}
|
||||
/>
|
||||
<CardContent>
|
||||
<DetailRow label="Father Name" value={fInfo.father_name || fInfo.fatherName} />
|
||||
<DetailRow label="Father Occupation" value={fInfo.father_occupation || fInfo.father_occupational || fInfo.fatherOccupation || fInfo.fatherOccupational || fInfo.father_occupation_name} />
|
||||
<DetailRow label="Mother Name" value={fInfo.mother_name || fInfo.motherName} />
|
||||
<DetailRow label="Mother Occupation" value={fInfo.mother_occupation || fInfo.mother_occupational || fInfo.motherOccupation || fInfo.motherOccupational || fInfo.mother_occupation_name} />
|
||||
|
||||
<Dialog
|
||||
open={openConfirmDialog}
|
||||
onClose={handleCancelSubmit}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
{/* Siblings */}
|
||||
{['brothers', 'sisters'].map(type => (
|
||||
(fInfo[type] && fInfo[type].length > 0) && (
|
||||
<Box key={type} mt={2} mb={2}>
|
||||
<Typography color="text.secondary" sx={{ fontWeight: 600, mb: 1, textTransform: 'capitalize' }}>{type} Details:</Typography>
|
||||
<Swiper modules={[Navigation, Pagination]} spaceBetween={10} slidesPerView={1} navigation pagination={{ clickable: true }} style={{ paddingBottom: '30px' }}>
|
||||
{fInfo[type].map((sib, i) => (
|
||||
<SwiperSlide key={i}>
|
||||
<Card variant="outlined" sx={{ p: 2, bgcolor: '#f9f9f9' }}>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 'bold' }}>{type.slice(0, -1)} {i + 1}</Typography>
|
||||
<DetailRow label="Name" value={sib.name} />
|
||||
<DetailRow label={type === 'brothers' ? 'Brother Type' : 'Sister Type'} value={sib.type} />
|
||||
<DetailRow label="Occupation" value={sib.occupation || sib.occupational || sib.occupation_name} />
|
||||
<DetailRow label="Marital Status" value={sib.marital_status || sib.maritalStatus || sib.marital_status_id} />
|
||||
<DetailRow label="Has Children" value={sib.has_children || sib.hasChildren || sib.thereHaveChildren} />
|
||||
<DetailRow label="Additional Details" value={sib.details || sib.additionalDetails || sib.additional_details} />
|
||||
</Card>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</Box>
|
||||
)
|
||||
))}
|
||||
|
||||
<DetailRow label="Family Status" value={fInfo.family_status || fInfo.familyStatus} />
|
||||
<DetailRow label="Native Place" value={fInfo.native_place || fInfo.nativePlace} />
|
||||
|
||||
<SectionTitle title="Location Living" />
|
||||
<DetailRow label="Country Living" value={fInfo.family_country_name || fInfo.living_country_name} />
|
||||
<DetailRow label="Residing State" value={fInfo.family_state_name || fInfo.living_state_name} />
|
||||
<DetailRow label="Residing City" value={fInfo.family_district_name || fInfo.family_city || fInfo.living_city_name} />
|
||||
<DetailRow label="Address" value={fInfo.address} />
|
||||
<DetailRow label="Expectations / Requirements Details" value={fInfo.expectation_details || fInfo.expectationDetails} />
|
||||
<DetailRow label="Willing to go abroad" value={fInfo.willing_to_go_abroad || fInfo.willingToGoAbroad} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 4. Lifestyle & Horoscope */}
|
||||
<Card variant="outlined" sx={{ borderRadius: 2 }}>
|
||||
<CardHeader
|
||||
title={<Typography variant="h6" fontWeight="bold">Lifestyle & Horoscope</Typography>}
|
||||
action={<IconButton color="primary" onClick={() => onEdit(4)} size="large"><Edit2 size={20} /></IconButton>}
|
||||
sx={{ padding: "15px 15px", background: "#f5fbff" }}
|
||||
/>
|
||||
<CardContent>
|
||||
<DetailRow label="Time of Birth" value={lInfo.time_of_birth_formated || lInfo.tob} />
|
||||
<DetailRow label="Place of Birth" value={lInfo.place_of_birth || lInfo.placeOfBirth} />
|
||||
<DetailRow label="Birth Star" value={lInfo.star_name || lInfo.star} />
|
||||
<DetailRow label="Padham" value={lInfo.patham} />
|
||||
<DetailRow label="Rasi" value={lInfo.raasi_name || lInfo.raasi} />
|
||||
<DetailRow label="Lagnam" value={lInfo.lagnam_name || lInfo.lagnam} />
|
||||
<DetailRow label="Panjangam" value={lInfo.panjangam_type} />
|
||||
<DetailRow label="Date of Birth" value={lInfo.date_of_birth_formated || lInfo.dob} />
|
||||
<DetailRow label="Dasa Balance" value={lInfo.dasa_balance} />
|
||||
<DetailRow label="Dasa Duration" value={(lInfo.dasa_years || lInfo.dasa_months || lInfo.dasa_days) ? `${lInfo.dasa_years || 0} Years, ${lInfo.dasa_months || 0} Months, ${lInfo.dasa_days || 0} Days` : "-"} />
|
||||
|
||||
{/* Horoscope Charts */}
|
||||
{lInfo.horoscope && (
|
||||
<Box mt={3}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid size={{ xs: 12, sm: 6 }}>
|
||||
{renderChartGrid((i) => lInfo.horoscope[`graha_${i}`]?.split(',') || (lInfo.graha && lInfo.graha[i]) || [], 'Rasi')}
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12, sm: 6 }}>
|
||||
{renderChartGrid((i) => lInfo.horoscope[`amsam_${i}`]?.split(',') || (lInfo.amsam && lInfo.amsam[i]) || [], 'Navamsam')}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 5. What am I looking for in a Partner */}
|
||||
<Card variant="outlined" sx={{ borderRadius: 2 }}>
|
||||
<CardHeader
|
||||
title={<Typography variant="h6" fontWeight="bold">What am I looking for in a Partner</Typography>}
|
||||
action={<IconButton color="primary" onClick={() => onEdit(5)} size="large"><Edit2 size={20} /></IconButton>}
|
||||
sx={{ padding: "15px 15px", background: "#f5fbff" }}
|
||||
/>
|
||||
<CardContent>
|
||||
<DetailRow label="Age Range" value={(prInfo.preferred_age_from || prInfo.age_from) && (prInfo.preferred_age_to || prInfo.age_to) ? `${prInfo.preferred_age_from || prInfo.age_from} - ${prInfo.preferred_age_to || prInfo.age_to}` : "-"} />
|
||||
<DetailRow label="Height" value={(getNamesFromIds(prInfo.preferred_height_from_id || prInfo.height_from, ppm?.heights, 'height_text') && getNamesFromIds(prInfo.preferred_height_to_id || prInfo.height_to, ppm?.heights, 'height_text')) ? `${getNamesFromIds(prInfo.preferred_height_from_id || prInfo.height_from, ppm?.heights, 'height_text')} - ${getNamesFromIds(prInfo.preferred_height_to_id || prInfo.height_to, ppm?.heights, 'height_text')}` : "-"} />
|
||||
<DetailRow label="Marital Status" value={getNamesFromIds(prInfo.preferred_marital_statuses || prInfo.marital_statuses || prInfo.preferred_marital_status || prInfo.marital_status, ppm?.maritalStatus || ppm?.marital_status, 'marital_status_name')} />
|
||||
<DetailRow label="Birth Star" value={getNamesFromIds(prInfo.preferred_birth_stars || prInfo.birth_stars || prInfo.preferred_birth_star || prInfo.birth_star, ppm?.stars || ppm?.star, 'star_name')} />
|
||||
<DetailRow label="Caste" value={getNamesFromIds(prInfo.preferred_castes || prInfo.castes || prInfo.preferred_caste || prInfo.caste, ppm?.caste || ppm?.castes, 'caste_name')} />
|
||||
<DetailRow label="Sub - Sect" value={getNamesFromIds(prInfo.preferred_sub_castes || prInfo.sub_castes || prInfo.preferred_sub_caste || prInfo.sub_caste, ppm?.sub_caste || ppm?.sub_castes, 'sub_caste_name')} />
|
||||
<DetailRow label="Qualification" value={getNamesFromIds(prInfo.preferred_educations || prInfo.educations || prInfo.preferred_education || prInfo.education, ppm?.education || ppm?.educations, 'education_name')} />
|
||||
<DetailRow label="Occupation" value={getNamesFromIds(prInfo.preferred_occupations || prInfo.occupations || prInfo.preferred_occupation || prInfo.occupation, ppm?.occupation || ppm?.occupations, 'occupation_name')} />
|
||||
|
||||
<DetailRow label="Employee Type" value={getNamesFromIds(prInfo.preferred_employee_types || prInfo.employee_types || prInfo.preferred_employee_type || prInfo.employee_type, ppm?.employeeTypes || ppm?.employee_type, 'employee_type_name')} />
|
||||
|
||||
<SectionTitle title="Prefer Annual Income" />
|
||||
{(prInfo.preferred_currencies || prInfo.currencies || []).includes("INR") && (
|
||||
<DetailRow label="Prefer Annual Income (INR)" value={(prInfo.preferred_inr_from || prInfo.inr_from || prInfo.preferred_inr_range) ? `From : ${prInfo.preferred_inr_from || prInfo.inr_from || ""} \nTo : ${prInfo.preferred_inr_to || prInfo.inr_to || ""}` : "-"} />
|
||||
)}
|
||||
{(prInfo.preferred_currencies || prInfo.currencies || []).includes("USD") && (
|
||||
<DetailRow label="Prefer Annual Income (USD)" value={(prInfo.preferred_usd_from || prInfo.usd_from || prInfo.preferred_usd_range) ? `From : ${prInfo.preferred_usd_from || prInfo.usd_from || ""} \nTo : ${prInfo.preferred_usd_to || prInfo.usd_to || ""}` : "-"} />
|
||||
)}
|
||||
|
||||
<DetailRow label="State" value={getNamesFromIds(prInfo.preferred_states || prInfo.states || prInfo.preferred_state || prInfo.state, ppm?.states, 'state_name')} />
|
||||
<DetailRow label="City" value={getNamesFromIds(prInfo.preferred_districts || prInfo.districts || prInfo.preferred_district || prInfo.district, ppm?.districts, 'district_name')} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Grid size={12} sx={{ display: "flex", justifyContent: "center" }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="success"
|
||||
size="large"
|
||||
onClick={handleConfirmSubmit}
|
||||
sx={{ borderRadius: 2 }}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{"Confirm Submission"}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Once you submit your details, you will not be able to edit the following fields: Place of Birth, Date of Birth, Rasi and Navamsam.
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleCancelSubmit}>Cancel</Button>
|
||||
<Button onClick={handleProceedSubmit} autoFocus>
|
||||
OK
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
Submit Full Completed Data
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<Dialog
|
||||
open={openConfirmDialog}
|
||||
onClose={handleCancelSubmit}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">{"Confirm Submission"}</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Once you submit your details, you will not be able to edit the following fields: Place of Birth, Date of Birth, Rasi and Navamsam.
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleCancelSubmit}>Cancel</Button>
|
||||
<Button onClick={handleProceedSubmit} autoFocus>OK</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
+315
-653
File diff suppressed because it is too large.
Load diff
+411
-190
@@ -84,15 +84,24 @@ const STEP_FIELD_ORDER = {
|
||||
"familyStatus",
|
||||
"nativePlace",
|
||||
],
|
||||
4: ["diets", "hobbies", "dob", "tob", "placeOfBirth"],
|
||||
4: ["dob", "tob", "placeOfBirth", "raasi", "star", "patham", "lagnam", "panjangam_type", "dasa_balance", "dasa_years", "dasa_months", "dasa_days"],
|
||||
5: [
|
||||
"ageRange",
|
||||
"age_from",
|
||||
"age_to",
|
||||
"height_from",
|
||||
"height_to",
|
||||
"marital_statuses",
|
||||
"birth_stars",
|
||||
"castes",
|
||||
"subCastes",
|
||||
"occupations",
|
||||
"sub_castes",
|
||||
"educations",
|
||||
"hobbies",
|
||||
"annualIncome",
|
||||
"occupations",
|
||||
"employee_types",
|
||||
"currencies",
|
||||
"inr_from",
|
||||
"inr_to",
|
||||
"usd_from",
|
||||
"usd_to",
|
||||
"states",
|
||||
"districts",
|
||||
],
|
||||
@@ -392,18 +401,23 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
||||
if (!firstKey) return;
|
||||
|
||||
setTimeout(() => {
|
||||
const element = document.getElementById(firstKey) ||
|
||||
document.querySelector(`[name="${firstKey}"]`) ||
|
||||
document.querySelector(`[aria-labelledby~="${firstKey}-label"]`);
|
||||
const element =
|
||||
document.getElementById(firstKey) ||
|
||||
document.querySelector(`[name="${firstKey}"]`) ||
|
||||
document.querySelector(`[id^="${firstKey}"]`) ||
|
||||
document.querySelector(`[name^="${firstKey}"]`) ||
|
||||
document.querySelector(`[aria-labelledby~="${firstKey}-label"]`);
|
||||
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||
|
||||
// Try to find a focusable element within the container
|
||||
const focusable = element.querySelector('input:not([type="hidden"]), select, textarea, [role="combobox"], [role="button"]') || element;
|
||||
const focusable =
|
||||
element.querySelector('input:not([type="hidden"]), select, textarea, [role="combobox"], [role="button"]') ||
|
||||
element;
|
||||
|
||||
if (focusable && typeof focusable.focus === "function") {
|
||||
focusable.focus();
|
||||
setTimeout(() => focusable.focus(), 300);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
@@ -460,32 +474,36 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const processData = async () => {
|
||||
if (personalDetailsData?.status === "success" && personalDetailsData?.personal_details) {
|
||||
const isSuccess = personalDetailsData?.status === "success" || personalDetailsData?.success === true;
|
||||
if (isSuccess && personalDetailsData?.personal_details) {
|
||||
const pd = personalDetailsData.personal_details;
|
||||
setIsStep1Update(true);
|
||||
|
||||
const rawImages = pd.profile_images || pd.images || [];
|
||||
const rawImages = pd.profile_images || pd.profiles || pd.images || [];
|
||||
const mappedImages = await Promise.all(
|
||||
rawImages.map(async (url, index) => {
|
||||
const imageUrl = typeof url === "string" ? url : url?.url;
|
||||
rawImages.map(async (img, index) => {
|
||||
const originalUrl = typeof img === "string" ? img : (img.url || img.preview || img.image_url);
|
||||
if (!originalUrl) return null;
|
||||
|
||||
// Rewrite URL to use proxy in development to avoid CORS
|
||||
const imageUrl = (import.meta.env.DEV && originalUrl.startsWith('https://www.thirukalyanam.amrithaa.net/backend'))
|
||||
? originalUrl.replace('https://www.thirukalyanam.amrithaa.net/backend', '/backend')
|
||||
: originalUrl;
|
||||
|
||||
const fileName = (typeof img === "object" && img.name) || `image-${index}.jpg`;
|
||||
let file = null;
|
||||
let mimeType = "image/jpeg";
|
||||
let fileName = `image-${index}.jpg`;
|
||||
|
||||
try {
|
||||
if (imageUrl) {
|
||||
const response = await fetch(imageUrl);
|
||||
const blob = await response.blob();
|
||||
if (blob.type) mimeType = blob.type;
|
||||
const ext = mimeType.split("/")[1] || "jpg";
|
||||
fileName = `image-${index}.${ext}`;
|
||||
file = new File([blob], fileName, { type: mimeType });
|
||||
}
|
||||
const response = await fetch(imageUrl);
|
||||
const blob = await response.blob();
|
||||
if (blob.type) mimeType = blob.type;
|
||||
file = new File([blob], fileName, { type: mimeType });
|
||||
} catch (error) {
|
||||
console.error("Error converting image URL to File:", error);
|
||||
}
|
||||
return {
|
||||
id: `server-${index}`,
|
||||
id: (typeof img === "object" && img.id) || `server-${index}`,
|
||||
preview: imageUrl,
|
||||
imageUrl: imageUrl,
|
||||
file: file,
|
||||
@@ -494,42 +512,61 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
||||
valid: true,
|
||||
};
|
||||
})
|
||||
);
|
||||
).then(res => res.filter(Boolean));
|
||||
|
||||
const formattedDob = pd.dob ? pd.dob.split("T")[0] : "";
|
||||
const dobVal = pd.dob || pd.date_of_birth || "";
|
||||
const formattedDob = dobVal ? dobVal.split("T")[0] : "";
|
||||
|
||||
dispatch(
|
||||
updatePersonalDetails({
|
||||
name: pd.name || "",
|
||||
mobile: pd.mobile || "",
|
||||
email: pd.email || "",
|
||||
gender: pd.gender || "",
|
||||
dob: formattedDob,
|
||||
height: pd.height_id || "",
|
||||
weight: pd.weight || "",
|
||||
marital_status: pd.marital_status_id || "",
|
||||
religion: pd.religion_id || "",
|
||||
profile_for: pd.profile_for_id || "",
|
||||
caste: pd.caste_id || "",
|
||||
sub_caste: pd.sub_caste_id || "",
|
||||
willing_to_marry: pd.willing_to_marry || "",
|
||||
inter_caste_parents: pd.inter_caste_parents || 0,
|
||||
inter_caste_parents_details: pd.inter_caste_parents_details || "",
|
||||
gothram: pd.gothram || "",
|
||||
do_you_speak_telugu: pd.do_you_speak_telugu || 0,
|
||||
about_us: pd.about_us || "",
|
||||
known_languages: pd.known_language_ids || [],
|
||||
mother_language: pd.mother_language_id || "",
|
||||
complexion: pd.complexion_id || "",
|
||||
physical_status: pd.physical_status_id || "",
|
||||
raasi: pd.raasi_id || "",
|
||||
star: pd.star_id || "",
|
||||
state: pd.state_id || "",
|
||||
city: pd.district_id || "",
|
||||
pincode: pd.pincode || "",
|
||||
profiles: mappedImages,
|
||||
})
|
||||
);
|
||||
const updates = {};
|
||||
if (pd.name) updates.name = pd.name;
|
||||
const mobile = pd.mobile || pd.mobileNumber || pd.mobile_number;
|
||||
if (mobile) updates.mobile = mobile;
|
||||
const email = pd.email || pd.emailId || pd.email_id;
|
||||
if (email) updates.email = email;
|
||||
if (pd.gender) updates.gender = pd.gender;
|
||||
if (formattedDob) updates.dob = formattedDob;
|
||||
const height = pd.height_id || pd.height;
|
||||
if (height) updates.height = height;
|
||||
if (pd.weight) updates.weight = pd.weight;
|
||||
const marital_status = pd.marital_status_id || pd.marital_status;
|
||||
if (marital_status) updates.marital_status = marital_status;
|
||||
const religion = pd.religion_id || pd.religion;
|
||||
if (religion) updates.religion = religion;
|
||||
const profile_for = pd.profile_for_id || pd.profile_for;
|
||||
if (profile_for) updates.profile_for = profile_for;
|
||||
const caste = pd.caste_id || pd.caste;
|
||||
if (caste) updates.caste = caste;
|
||||
const sub_caste = pd.sub_caste_id || pd.sub_caste;
|
||||
if (sub_caste) updates.sub_caste = sub_caste;
|
||||
if (pd.willing_to_marry) updates.willing_to_marry = pd.willing_to_marry;
|
||||
if (pd.inter_caste_parents !== undefined) updates.inter_caste_parents = pd.inter_caste_parents ?? 0;
|
||||
if (pd.inter_caste_parents_details) updates.inter_caste_parents_details = pd.inter_caste_parents_details;
|
||||
const gothram = pd.gothram || pd.gothram_id;
|
||||
if (gothram) updates.gothram = gothram;
|
||||
if (pd.do_you_speak_telugu !== undefined) updates.do_you_speak_telugu = pd.do_you_speak_telugu ?? 0;
|
||||
if (pd.about_us) updates.about_us = pd.about_us;
|
||||
const known_languages = pd.known_language_ids || pd.known_languages;
|
||||
if (known_languages) updates.known_languages = known_languages;
|
||||
const mother_language = pd.mother_language_id || pd.mother_language;
|
||||
if (mother_language) updates.mother_language = mother_language;
|
||||
const complexion = pd.complexion_id || pd.complexion;
|
||||
if (complexion) updates.complexion = complexion;
|
||||
const physical_status = pd.physical_status_id || pd.physical_status;
|
||||
if (physical_status) updates.physical_status = physical_status;
|
||||
const raasi = pd.raasi_id || pd.raasi;
|
||||
if (raasi) updates.raasi = raasi;
|
||||
const star = pd.star_id || pd.star;
|
||||
if (star) updates.star = star;
|
||||
const state = pd.state_id || pd.state;
|
||||
if (state) updates.state = state;
|
||||
const city = pd.district_id || pd.city;
|
||||
if (city) updates.city = city;
|
||||
if (pd.pincode) updates.pincode = pd.pincode;
|
||||
if (mappedImages && mappedImages.length > 0) updates.profiles = mappedImages;
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
dispatch(updatePersonalDetails(updates));
|
||||
}
|
||||
}
|
||||
};
|
||||
processData();
|
||||
@@ -546,31 +583,64 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
||||
enabled: isAuth || shouldHideStepper,
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnMount: true,
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (educationalData?.status === "success" && educationalData?.educational_details) {
|
||||
useEffect(() => {
|
||||
const isSuccess = educationalData?.status === "success" || educationalData?.success === true;
|
||||
if (isSuccess && educationalData?.educational_details) {
|
||||
const ed = educationalData.educational_details;
|
||||
dispatch(
|
||||
updateEducationalDetails({
|
||||
study_field: ed.study_field_id || "",
|
||||
education: ed.education_id || "",
|
||||
education_detail: ed.education_detail || "",
|
||||
college_name: ed.college_name || "",
|
||||
employee_type: ed.employee_type_id || "",
|
||||
occupation: ed.occupation_id || "",
|
||||
occupation_detail: ed.occupation_detail || "",
|
||||
company_name: ed.company_name || "",
|
||||
income_currency: ed.income_currency || "INR",
|
||||
annual_income: ed.annual_income || "",
|
||||
work_country: ed.work_country_id || "",
|
||||
work_state: ed.work_state_id || "",
|
||||
work_district: ed.work_district_id || "",
|
||||
work_city: ed.work_city || "",
|
||||
address: ed.address || ed.work_location || "",
|
||||
})
|
||||
);
|
||||
const updates = {};
|
||||
|
||||
const study_field = ed.study_field_id || ed.study_field || ed.education_id;
|
||||
if (study_field) updates.study_field = study_field;
|
||||
|
||||
const education = ed.education_id || ed.education || ed.qualification_id;
|
||||
if (education) updates.education = education;
|
||||
|
||||
const education_detail = ed.education_detail || ed.education_details || ed.educationDetail;
|
||||
if (education_detail) updates.education_detail = education_detail;
|
||||
|
||||
const college_name = ed.college_name || ed.collegeName || ed.college;
|
||||
if (college_name) updates.college_name = college_name;
|
||||
|
||||
const employee_type = ed.employee_type_id || ed.employee_type || ed.employeeType;
|
||||
if (employee_type) updates.employee_type = employee_type;
|
||||
|
||||
const occupation = ed.occupation_id || ed.occupation || ed.occupational;
|
||||
if (occupation) updates.occupation = occupation;
|
||||
|
||||
const occupation_detail = ed.occupation_detail || ed.occupationDetail || ed.occupation_details;
|
||||
if (occupation_detail) updates.occupation_detail = occupation_detail;
|
||||
|
||||
const company_name = ed.company_name || ed.companyName || ed.organization_name;
|
||||
if (company_name) updates.company_name = company_name;
|
||||
|
||||
const income_currency = ed.income_currency || ed.currency || "INR";
|
||||
if (income_currency) updates.income_currency = income_currency;
|
||||
|
||||
const annual_income = ed.annual_income || ed.annual_income_id || ed.income;
|
||||
if (annual_income) updates.annual_income = annual_income;
|
||||
|
||||
const work_country = ed.work_country_id || ed.work_country || ed.country_id;
|
||||
if (work_country) updates.work_country = work_country;
|
||||
|
||||
const work_state = ed.work_state_id || ed.work_state || ed.state_id;
|
||||
if (work_state) updates.work_state = work_state;
|
||||
|
||||
const work_district = ed.work_district_id || ed.work_district || ed.district_id;
|
||||
if (work_district) updates.work_district = work_district;
|
||||
|
||||
const work_city = ed.work_city || ed.city || ed.work_location;
|
||||
if (work_city) updates.work_city = work_city;
|
||||
|
||||
const address = ed.address || ed.work_location || "";
|
||||
if (address) updates.address = address;
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
dispatch(updateEducationalDetails(updates));
|
||||
}
|
||||
}
|
||||
}, [educationalData, dispatch]);
|
||||
|
||||
@@ -586,49 +656,59 @@ const {data:familyData} = useQuery({
|
||||
enabled: isAuth || shouldHideStepper,
|
||||
retry:false,
|
||||
refetchOnWindowFocus:false,
|
||||
refetchOnMount: true,
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (familyData?.status === "success" && familyData?.family_details) {
|
||||
const fd = familyData.family_details;
|
||||
dispatch(
|
||||
updateFamilyDetails({
|
||||
fatherName: fd.father_name || "",
|
||||
fatherOccupation: fd.father_occupation || "",
|
||||
motherName: fd.mother_name || "",
|
||||
motherOccupation: fd.mother_occupation || "",
|
||||
familyStatus: fd.family_status_id || "",
|
||||
nativePlace: fd.native_place || "",
|
||||
familyCountry: fd.family_country_id || "",
|
||||
familyState: fd.family_state_id || "",
|
||||
familyDistrict: fd.family_district_id || "",
|
||||
familyCity: fd.family_city || "",
|
||||
address: fd.address || "",
|
||||
expectationDetails: fd.expectation_details || "",
|
||||
willingToGoAbroad: fd.willing_to_go_abroad || "",
|
||||
brotherCount: fd.brother_count || 0,
|
||||
sisterCount: fd.sister_count || 0,
|
||||
brothers: (fd.brothers || []).map((b) => ({
|
||||
const isSuccess = familyData?.status === "success" || familyData?.success === true;
|
||||
if (isSuccess && familyData?.family_details) {
|
||||
const fd = familyData.family_details;
|
||||
const updates = {};
|
||||
|
||||
if (fd.father_name || fd.fatherName) updates.fatherName = fd.father_name || fd.fatherName || "";
|
||||
if (fd.father_occupation || fd.fatherOccupation || fd.father_occupation_id) updates.fatherOccupation = fd.father_occupation ?? fd.fatherOccupation ?? fd.father_occupation_id ?? "";
|
||||
if (fd.mother_name || fd.motherName) updates.motherName = fd.mother_name || fd.motherName || "";
|
||||
if (fd.mother_occupation || fd.motherOccupation || fd.mother_occupation_id) updates.motherOccupation = fd.mother_occupation ?? fd.motherOccupation ?? fd.mother_occupation_id ?? "";
|
||||
if (fd.family_status_id || fd.familyStatus || fd.family_status) updates.familyStatus = fd.family_status_id || fd.familyStatus || fd.family_status || "";
|
||||
if (fd.native_place || fd.nativePlace) updates.nativePlace = fd.native_place || fd.nativePlace || "";
|
||||
if (fd.brother_count !== undefined) updates.brotherCount = fd.brother_count || 0;
|
||||
if (fd.sister_count !== undefined) updates.sisterCount = fd.sister_count || 0;
|
||||
if (fd.family_country_id || fd.family_country_name || fd.familyCountry) updates.familyCountry = fd.family_country_id || fd.familyCountry || "";
|
||||
if (fd.family_state_id || fd.family_state_name || fd.familyState) updates.familyState = fd.family_state_id || fd.familyState || "";
|
||||
if (fd.family_district_id || fd.family_district_name || fd.familyDistrict) updates.familyDistrict = fd.family_district_id || fd.familyDistrict || "";
|
||||
if (fd.family_city || fd.familyCity) updates.familyCity = fd.family_city || fd.familyCity || "";
|
||||
if (fd.address) updates.address = fd.address || "";
|
||||
if (fd.expectation_details || fd.expectationDetails) updates.expectationDetails = fd.expectation_details || fd.expectationDetails || "";
|
||||
if (fd.willing_to_go_abroad !== undefined) updates.willingToGoAbroad = fd.willing_to_go_abroad || "";
|
||||
|
||||
if (fd.brothers || fd.brother_details) {
|
||||
updates.brothers = (fd.brothers || fd.brother_details || []).map((b) => ({
|
||||
name: b.name || "",
|
||||
occupation: b.occupation_name || "",
|
||||
maritalStatus: b.marital_status || "",
|
||||
occupation: b.occupation || b.occupational || b.occupation_name || "",
|
||||
maritalStatus: b.marital_status || b.maritalStatus || b.marital_status_id || "",
|
||||
type: b.type || "",
|
||||
hasChildren: b.has_children || "",
|
||||
details: b.additional_details || ""
|
||||
})),
|
||||
sisters: (fd.sisters || []).map((s) => ({
|
||||
hasChildren: b.has_children || b.hasChildren || b.thereHaveChildren || "",
|
||||
details: b.details || b.additional_details || b.additionalDetails || "",
|
||||
}));
|
||||
}
|
||||
|
||||
if (fd.sisters || fd.sister_details) {
|
||||
updates.sisters = (fd.sisters || fd.sister_details || []).map((s) => ({
|
||||
name: s.name || "",
|
||||
occupation: s.occupation_name || "",
|
||||
maritalStatus: s.marital_status || "",
|
||||
occupation: s.occupation || s.occupational || s.occupation_name || "",
|
||||
maritalStatus: s.marital_status || s.maritalStatus || s.marital_status_id || "",
|
||||
type: s.type || "",
|
||||
hasChildren: s.has_children || "",
|
||||
details: s.additional_details || ""
|
||||
})),
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [familyData, dispatch]);
|
||||
hasChildren: s.has_children || s.hasChildren || s.thereHaveChildren || "",
|
||||
details: s.details || s.additional_details || s.additionalDetails || "",
|
||||
}));
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
dispatch(updateFamilyDetails(updates));
|
||||
}
|
||||
}
|
||||
}, [familyData, dispatch]);
|
||||
|
||||
// Fetch Lifestyle Details
|
||||
const { data: lifestyleData } = useQuery({
|
||||
@@ -644,7 +724,8 @@ useEffect(() => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (lifestyleData?.status === "success" && lifestyleData?.lifestyle_details) {
|
||||
const isSuccess = lifestyleData?.status === "success" || lifestyleData?.success === true;
|
||||
if (isSuccess && lifestyleData?.lifestyle_details) {
|
||||
const ld = lifestyleData.lifestyle_details;
|
||||
const horoscope = ld.horoscope || {};
|
||||
|
||||
@@ -653,18 +734,35 @@ useEffect(() => {
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
const key = `${prefix}_${i}`;
|
||||
const val = horoscope[key];
|
||||
chart[i] = val ? val.split(",") : [];
|
||||
chart[i] = val ? (Array.isArray(val) ? val : val.split(",")) : [];
|
||||
}
|
||||
return chart;
|
||||
};
|
||||
|
||||
const dobVal = ld.dob || ld.date_of_birth || "";
|
||||
const formattedDob = dobVal ? dobVal.split("T")[0] : "";
|
||||
|
||||
let formattedTob = ld.tob || ld.time_of_birth || "";
|
||||
if (!formattedTob && ld.time_of_birth_formated) {
|
||||
if (ld.time_of_birth_formated.includes(":")) {
|
||||
formattedTob = ld.time_of_birth_formated.substring(0, 5);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(
|
||||
updateLifestyleDetails({
|
||||
diets: ld.diet_id || "",
|
||||
hobbies: ld.hobbies_ids || [],
|
||||
dob: ld.time_of_birth ? ld.time_of_birth.split("T")[0] : "",
|
||||
tob: ld.time_of_birth_formated ? ld.time_of_birth_formated.substring(0, 5) : "",
|
||||
placeOfBirth: ld.place_of_birth || "",
|
||||
dob: formattedDob,
|
||||
tob: formattedTob,
|
||||
placeOfBirth: ld.place_of_birth || ld.placeOfBirth || "",
|
||||
raasi: ld.raasi_id || horoscope.raasi_id || ld.raasi || "",
|
||||
star: ld.star_id || horoscope.star_id || ld.star || "",
|
||||
patham: ld.patham || horoscope.patham || "",
|
||||
lagnam: ld.lagnam_id || ld.lagnam || horoscope.lagnam || "",
|
||||
panjangam_type: ld.panjangam_type || horoscope.panjangam_type || "",
|
||||
dasa_balance: ld.dasa_balance || horoscope.dasa_balance || "",
|
||||
dasa_years: ld.dasa_years || horoscope.dasa_years || "",
|
||||
dasa_months: ld.dasa_months || horoscope.dasa_months || "",
|
||||
dasa_days: ld.dasa_days || horoscope.dasa_days || "",
|
||||
graha: mapChart("graha"),
|
||||
amsam: mapChart("amsam"),
|
||||
})
|
||||
@@ -686,21 +784,86 @@ useEffect(() => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (partnerData?.status === "success" && partnerData?.partner_preferences) {
|
||||
const isSuccess = partnerData?.status === "success" || partnerData?.success === true;
|
||||
if (isSuccess && partnerData?.partner_preferences) {
|
||||
const pp = partnerData.partner_preferences;
|
||||
dispatch(
|
||||
updatePartnerPreferences({
|
||||
ageRange: pp.preferred_age_range_id || "",
|
||||
annualIncome: pp.preferred_annual_income_id || "",
|
||||
castes: pp.preferred_castes_ids || [],
|
||||
subCastes: pp.preferred_sub_castes_ids || [],
|
||||
occupations: pp.preferred_occupations_ids || [],
|
||||
educations: pp.preferred_educations_ids || [],
|
||||
hobbies: pp.preferred_hobbies_ids || [],
|
||||
states: pp.preferred_states_ids || [],
|
||||
districts: pp.preferred_districts_ids || [],
|
||||
})
|
||||
);
|
||||
const updates = {};
|
||||
|
||||
const age_from = pp.preferred_age_from ?? pp.age_from ?? pp.preferred_age_from_id ?? pp.age_from_id;
|
||||
if (age_from !== undefined && age_from !== null) updates.age_from = age_from;
|
||||
|
||||
const age_to = pp.preferred_age_to ?? pp.age_to ?? pp.preferred_age_to_id ?? pp.age_to_id;
|
||||
if (age_to !== undefined && age_to !== null) updates.age_to = age_to;
|
||||
|
||||
const height_from = pp.preferred_height_from_id ?? pp.height_from_id ?? pp.preferred_height_from ?? pp.height_from;
|
||||
if (height_from !== undefined && height_from !== null) updates.height_from = height_from;
|
||||
|
||||
const height_to = pp.preferred_height_to_id ?? pp.height_to_id ?? pp.preferred_height_to ?? pp.height_to;
|
||||
if (height_to !== undefined && height_to !== null) updates.height_to = height_to;
|
||||
|
||||
const mapMulti = (val) => {
|
||||
if (!val) return [];
|
||||
if (Array.isArray(val)) return val;
|
||||
return String(val).split(",").map(v => v.trim()).filter(Boolean);
|
||||
};
|
||||
|
||||
if (pp.preferred_marital_status_ids || pp.marital_status_ids || pp.preferred_marital_statuses || pp.marital_status) {
|
||||
const val = mapMulti(pp.preferred_marital_status_ids || pp.marital_status_ids || pp.preferred_marital_statuses || pp.marital_status);
|
||||
if (val.length > 0) updates.marital_statuses = val;
|
||||
}
|
||||
if (pp.preferred_birth_star_ids || pp.birth_star_ids || pp.preferred_birth_stars || pp.birth_star) {
|
||||
const val = mapMulti(pp.preferred_birth_star_ids || pp.birth_star_ids || pp.preferred_birth_stars || pp.birth_star);
|
||||
if (val.length > 0) updates.birth_stars = val;
|
||||
}
|
||||
if (pp.preferred_castes_ids || pp.castes_ids || pp.preferred_castes || pp.caste) {
|
||||
const val = mapMulti(pp.preferred_castes_ids || pp.castes_ids || pp.preferred_castes || pp.caste);
|
||||
if (val.length > 0) updates.castes = val;
|
||||
}
|
||||
if (pp.preferred_sub_castes_ids || pp.sub_castes_ids || pp.preferred_sub_castes || pp.sub_caste) {
|
||||
const val = mapMulti(pp.preferred_sub_castes_ids || pp.sub_castes_ids || pp.preferred_sub_castes || pp.sub_caste);
|
||||
if (val.length > 0) updates.sub_castes = val;
|
||||
}
|
||||
if (pp.preferred_occupations_ids || pp.occupations_ids || pp.preferred_occupations || pp.occupation) {
|
||||
const val = mapMulti(pp.preferred_occupations_ids || pp.occupations_ids || pp.preferred_occupations || pp.occupation);
|
||||
if (val.length > 0) updates.occupations = val;
|
||||
}
|
||||
if (pp.preferred_educations_ids || pp.educations_ids || pp.preferred_educations || pp.education) {
|
||||
const val = mapMulti(pp.preferred_educations_ids || pp.educations_ids || pp.preferred_educations || pp.education);
|
||||
if (val.length > 0) updates.educations = val;
|
||||
}
|
||||
if (pp.preferred_employee_type_ids || pp.employee_type_ids || pp.preferred_employee_types || pp.employee_type) {
|
||||
const val = mapMulti(pp.preferred_employee_type_ids || pp.employee_type_ids || pp.preferred_employee_types || pp.employee_type);
|
||||
if (val.length > 0) updates.employee_types = val;
|
||||
}
|
||||
if (pp.preferred_currencies || pp.currencies) {
|
||||
const val = mapMulti(pp.preferred_currencies || pp.currencies);
|
||||
if (val.length > 0) updates.currencies = val;
|
||||
}
|
||||
|
||||
const inr_from = pp.preferred_inr_from ?? pp.inr_from ?? pp.preferred_inr_from_id;
|
||||
if (inr_from !== undefined && inr_from !== null) updates.inr_from = inr_from;
|
||||
|
||||
const inr_to = pp.preferred_inr_to ?? pp.inr_to ?? pp.preferred_inr_to_id;
|
||||
if (inr_to !== undefined && inr_to !== null) updates.inr_to = inr_to;
|
||||
|
||||
const usd_from = pp.preferred_usd_from ?? pp.usd_from ?? pp.preferred_usd_from_id;
|
||||
if (usd_from !== undefined && usd_from !== null) updates.usd_from = usd_from;
|
||||
|
||||
const usd_to = pp.preferred_usd_to ?? pp.usd_to ?? pp.preferred_usd_to_id;
|
||||
if (usd_to !== undefined && usd_to !== null) updates.usd_to = usd_to;
|
||||
|
||||
if (pp.preferred_states_ids || pp.states_ids || pp.preferred_states || pp.state) {
|
||||
const val = mapMulti(pp.preferred_states_ids || pp.states_ids || pp.preferred_states || pp.state);
|
||||
if (val.length > 0) updates.states = val;
|
||||
}
|
||||
if (pp.preferred_districts_ids || pp.districts_ids || pp.preferred_districts || pp.district) {
|
||||
const val = mapMulti(pp.preferred_districts_ids || pp.districts_ids || pp.preferred_districts || pp.district);
|
||||
if (val.length > 0) updates.districts = val;
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
dispatch(updatePartnerPreferences(updates));
|
||||
}
|
||||
}
|
||||
}, [partnerData, dispatch]);
|
||||
|
||||
@@ -722,6 +885,7 @@ useEffect(() => {
|
||||
"marital_status",
|
||||
"profile_for",
|
||||
"caste",
|
||||
"sub_caste",
|
||||
"email",
|
||||
"mother_language",
|
||||
"complexion",
|
||||
@@ -795,7 +959,7 @@ useEffect(() => {
|
||||
];
|
||||
required.forEach((field) => {
|
||||
if (!familyDetails[field]) {
|
||||
// newErrors[field] = "This field is required";
|
||||
// newErrors[field] = `${label} is required`;
|
||||
const label = field
|
||||
.replace(/([A-Z])/g, " $1")
|
||||
.replace(/^./, (str) => str.toUpperCase());
|
||||
@@ -810,7 +974,7 @@ useEffect(() => {
|
||||
newErrors.motherName = "Mother Name must contain only alphabets";
|
||||
}
|
||||
} else if (step === 4) {
|
||||
const required = ["diets", "hobbies", "dob", "tob"];
|
||||
const required = ["dob", "tob", "placeOfBirth", "raasi", "star"];
|
||||
required.forEach((field) => {
|
||||
const value = lifestyleDetails[field];
|
||||
if (Array.isArray(value)) {
|
||||
@@ -818,7 +982,10 @@ useEffect(() => {
|
||||
if (field === "hobbies") {
|
||||
newErrors[field] = "Hobbies and Interests is required";
|
||||
} else {
|
||||
newErrors[field] = "This field is required";
|
||||
const label = field
|
||||
.replace(/([A-Z])/g, " $1")
|
||||
.replace(/^./, (str) => str.toUpperCase());
|
||||
newErrors[field] = `${label} is required`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,8 +997,11 @@ useEffect(() => {
|
||||
else if (field === "tob") {
|
||||
newErrors[field] = "Time of Birth is required";
|
||||
}
|
||||
else if (field === "diets") {
|
||||
newErrors[field] = "Diet is required";
|
||||
else if (field === "raasi") {
|
||||
newErrors[field] = "Raasi is required";
|
||||
}
|
||||
else if (field === "star") {
|
||||
newErrors[field] = "Birth Star is required";
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -843,33 +1013,53 @@ useEffect(() => {
|
||||
}
|
||||
});
|
||||
} else if (step === 5) {
|
||||
const required = [
|
||||
"ageRange",
|
||||
"castes",
|
||||
"subCastes",
|
||||
"occupations",
|
||||
"educations",
|
||||
"hobbies",
|
||||
"annualIncome",
|
||||
"states",
|
||||
"districts",
|
||||
];
|
||||
// Range Validations
|
||||
if (partnerPreferences.age_from && partnerPreferences.age_to) {
|
||||
if (Number(partnerPreferences.age_from) > Number(partnerPreferences.age_to)) {
|
||||
newErrors.age_from = "From Age cannot be greater than To Age";
|
||||
newErrors.age_to = "To Age cannot be less than From Age";
|
||||
}
|
||||
}
|
||||
|
||||
if (partnerPreferences.height_from && partnerPreferences.height_to) {
|
||||
if (Number(partnerPreferences.height_from) > Number(partnerPreferences.height_to)) {
|
||||
newErrors.height_from = "From Height cannot be greater than To Height";
|
||||
newErrors.height_to = "To Height cannot be less than From Height";
|
||||
}
|
||||
}
|
||||
|
||||
if (partnerPreferences.currencies.includes("INR")) {
|
||||
const from = parseFloat(partnerPreferences.inr_from);
|
||||
const to = parseFloat(partnerPreferences.inr_to);
|
||||
if (!isNaN(from) && !isNaN(to) && from > to) {
|
||||
newErrors.inr_from = "From Income cannot be greater than To Income";
|
||||
newErrors.inr_to = "To Income cannot be less than From Income";
|
||||
}
|
||||
}
|
||||
|
||||
if (partnerPreferences.currencies.includes("USD")) {
|
||||
const from = parseFloat(partnerPreferences.usd_from);
|
||||
const to = parseFloat(partnerPreferences.usd_to);
|
||||
if (!isNaN(from) && !isNaN(to) && from > to) {
|
||||
newErrors.usd_from = "From Income cannot be greater than To Income";
|
||||
newErrors.usd_to = "To Income cannot be less than From Income";
|
||||
}
|
||||
}
|
||||
|
||||
// Required fields
|
||||
const required = ["age_from", "age_to", "height_from", "height_to", "castes", "educations", "states"];
|
||||
required.forEach((field) => {
|
||||
const value = partnerPreferences[field];
|
||||
let isMissing = false;
|
||||
if (Array.isArray(value)) {
|
||||
if (value.length === 0) {
|
||||
// newErrors[field] = "This field is required";
|
||||
const label = field
|
||||
.replace(/([A-Z])/g, " $1")
|
||||
.replace(/^./, (str) => str.toUpperCase());
|
||||
newErrors[field] = `${label} is required`;
|
||||
}
|
||||
return;
|
||||
isMissing = value.length === 0;
|
||||
} else {
|
||||
isMissing = !value && value !== 0;
|
||||
}
|
||||
if (!value) {
|
||||
// newErrors[field] = "This field is required";
|
||||
|
||||
if (isMissing) {
|
||||
const label = field
|
||||
.replace(/([A-Z])/g, " $1")
|
||||
.replace(/_/g, " ")
|
||||
.replace(/^./, (str) => str.toUpperCase());
|
||||
newErrors[field] = `${label} is required`;
|
||||
}
|
||||
@@ -928,7 +1118,13 @@ useEffect(() => {
|
||||
|
||||
if (!isValidFile && item.preview && typeof item.preview === "string") {
|
||||
try {
|
||||
const response = await fetch(item.preview);
|
||||
// Rewrite URL to use proxy in development to avoid CORS
|
||||
const finalUrl = (import.meta.env.DEV && item.preview.startsWith('https://www.thirukalyanam.amrithaa.net/backend'))
|
||||
? item.preview.replace('https://www.thirukalyanam.amrithaa.net/backend', '/backend')
|
||||
: item.preview;
|
||||
|
||||
const response = await fetch(finalUrl);
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
const blob = await response.blob();
|
||||
const mimeType = blob.type || "image/jpeg";
|
||||
const ext = mimeType.split("/")[1] || "jpg";
|
||||
@@ -983,12 +1179,16 @@ useEffect(() => {
|
||||
formData.append("mother_name", familyDetails.motherName);
|
||||
formData.append("mother_occupation", familyDetails.motherOccupation || "");
|
||||
formData.append("family_status", familyDetails.familyStatus);
|
||||
formData.append("family_status_id", familyDetails.familyStatus);
|
||||
formData.append("native_place", familyDetails.nativePlace || "");
|
||||
formData.append("brother_count", familyDetails.brotherCount || 0);
|
||||
formData.append("sister_count", familyDetails.sisterCount || 0);
|
||||
formData.append("family_country", familyDetails.familyCountry || "");
|
||||
formData.append("family_country_id", familyDetails.familyCountry || "");
|
||||
formData.append("family_state", familyDetails.familyState || "");
|
||||
formData.append("family_state_id", familyDetails.familyState || "");
|
||||
formData.append("family_district", familyDetails.familyDistrict || "");
|
||||
formData.append("family_district_id", familyDetails.familyDistrict || "");
|
||||
formData.append("family_city", familyDetails.familyCity || "");
|
||||
formData.append("address", familyDetails.address || "");
|
||||
formData.append("expectation_details", familyDetails.expectationDetails || "");
|
||||
@@ -1001,6 +1201,7 @@ useEffect(() => {
|
||||
formData.append(`brothers[${index}][type]`, brother?.type || "");
|
||||
formData.append(`brothers[${index}][has_children]`, brother?.hasChildren || "");
|
||||
formData.append(`brothers[${index}][details]`, brother?.details || "");
|
||||
formData.append(`brothers[${index}][additional_details]`, brother?.details || "");
|
||||
});
|
||||
|
||||
(familyDetails.sisters || []).forEach((sister, index) => {
|
||||
@@ -1010,6 +1211,7 @@ useEffect(() => {
|
||||
formData.append(`sisters[${index}][type]`, sister?.type || "");
|
||||
formData.append(`sisters[${index}][has_children]`, sister?.hasChildren || "");
|
||||
formData.append(`sisters[${index}][details]`, sister?.details || "");
|
||||
formData.append(`sisters[${index}][additional_details]`, sister?.details || "");
|
||||
});
|
||||
|
||||
return formData;
|
||||
@@ -1020,12 +1222,17 @@ useEffect(() => {
|
||||
formData.append("dob", lifestyleDetails.dob || "");
|
||||
formData.append("tob", lifestyleDetails.tob || "");
|
||||
formData.append("place_of_birth", lifestyleDetails.placeOfBirth || "");
|
||||
|
||||
formData.append("diets", lifestyleDetails.diets || "");
|
||||
|
||||
(lifestyleDetails.hobbies || []).forEach((id, index) => {
|
||||
formData.append(`hobbies[${index}]`, id);
|
||||
});
|
||||
formData.append("raasi", lifestyleDetails.raasi || "");
|
||||
formData.append("raasi_id", lifestyleDetails.raasi || "");
|
||||
formData.append("star", lifestyleDetails.star || "");
|
||||
formData.append("star_id", lifestyleDetails.star || "");
|
||||
formData.append("patham", lifestyleDetails.patham || "");
|
||||
formData.append("lagnam", lifestyleDetails.lagnam || "");
|
||||
formData.append("panjangam_type", lifestyleDetails.panjangam_type || "");
|
||||
formData.append("dasa_balance", lifestyleDetails.dasa_balance || "");
|
||||
formData.append("dasa_years", lifestyleDetails.dasa_years || "");
|
||||
formData.append("dasa_months", lifestyleDetails.dasa_months || "");
|
||||
formData.append("dasa_days", lifestyleDetails.dasa_days || "");
|
||||
|
||||
const graha = lifestyleDetails.graha || {};
|
||||
Object.keys(graha).forEach((house) => {
|
||||
@@ -1048,35 +1255,54 @@ useEffect(() => {
|
||||
|
||||
const buildRegisterStep5Payload = () => {
|
||||
const formData = new FormData();
|
||||
formData.append("age_range", partnerPreferences.ageRange || "");
|
||||
formData.append("annual_income", partnerPreferences.annualIncome || "");
|
||||
|
||||
formData.append("preferred_age_from", partnerPreferences.age_from || "");
|
||||
formData.append("preferred_age_to", partnerPreferences.age_to || "");
|
||||
formData.append("preferred_height_from", partnerPreferences.height_from || "");
|
||||
formData.append("preferred_height_to", partnerPreferences.height_to || "");
|
||||
formData.append("preferred_inr_from", partnerPreferences.inr_from || "");
|
||||
formData.append("preferred_inr_to", partnerPreferences.inr_to || "");
|
||||
formData.append("preferred_usd_from", partnerPreferences.usd_from || "");
|
||||
formData.append("preferred_usd_to", partnerPreferences.usd_to || "");
|
||||
|
||||
(partnerPreferences.castes || []).forEach((id, index) => {
|
||||
formData.append(`castes[${index}]`, id);
|
||||
(partnerPreferences.marital_statuses || []).forEach((id, index) => {
|
||||
formData.append(`preferred_marital_status_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.subCastes || []).forEach((id, index) => {
|
||||
formData.append(`sub_castes[${index}]`, id);
|
||||
(partnerPreferences.employee_types || []).forEach((id, index) => {
|
||||
formData.append(`preferred_employee_type_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.birth_stars || []).forEach((id, index) => {
|
||||
formData.append(`preferred_birth_star_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.currencies || []).forEach((curr, index) => {
|
||||
formData.append(`preferred_currencies[${index}]`, curr);
|
||||
});
|
||||
|
||||
(partnerPreferences.castes || []).forEach((id, index) => {
|
||||
formData.append(`preferred_castes_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.sub_castes || []).forEach((id, index) => {
|
||||
formData.append(`preferred_sub_castes_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.occupations || []).forEach((id, index) => {
|
||||
formData.append(`occupations[${index}]`, id);
|
||||
formData.append(`preferred_occupations_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.educations || []).forEach((id, index) => {
|
||||
formData.append(`educations[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.hobbies || []).forEach((id, index) => {
|
||||
formData.append(`hobbies[${index}]`, id);
|
||||
formData.append(`preferred_educations_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.states || []).forEach((id, index) => {
|
||||
formData.append(`states[${index}]`, id);
|
||||
formData.append(`preferred_states_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
(partnerPreferences.districts || []).forEach((id, index) => {
|
||||
formData.append(`districts[${index}]`, id);
|
||||
formData.append(`preferred_districts_ids[${index}]`, id);
|
||||
});
|
||||
|
||||
return formData;
|
||||
@@ -1256,11 +1482,6 @@ useEffect(() => {
|
||||
|
||||
if (!enabledSteps.includes(step)) return;
|
||||
|
||||
// If moving backwards during registration, clear the unsaved data of the step we are leaving
|
||||
if (step < currentStep && !shouldHideStepper) {
|
||||
dispatch(clearAllStepsFrom(currentStep));
|
||||
}
|
||||
|
||||
setCurrentStep(step);
|
||||
setErrors({});
|
||||
window.scrollTo(0, 0);
|
||||
@@ -1378,7 +1599,7 @@ useEffect(() => {
|
||||
return required.every(field => familyDetails[field]);
|
||||
}
|
||||
if (stepNum === 4) {
|
||||
const required = ["diets", "hobbies", "dob", "tob"];
|
||||
const required = ["dob", "tob", "placeOfBirth", "raasi", "star"];
|
||||
return required.every(field => {
|
||||
const val = lifestyleDetails[field];
|
||||
return Array.isArray(val) ? val.length > 0 : !!val;
|
||||
|
||||
Reference in new issue
Block a user