api registration done
This commit is contained in:
1 parent
fd0a327b13
commit
653055debc
38 files changed
+3411
-1385
No files matched your search
@@ -1,27 +1,137 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { updatePartnerPreferences } from "../redux/registrationFormSlice";
|
||||
import {
|
||||
Grid,
|
||||
TextField,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Select,
|
||||
MenuItem,
|
||||
Button,
|
||||
Checkbox,
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import { usePartnerPreferenceMasters } from "../hooks/useMasters";
|
||||
import { useCityMasters, useSubCasteMasters } from "../hooks/useDependentMasters";
|
||||
|
||||
const PartnerPreferencesForm = ({ onSubmitStep, onSkipStep, errors }) => {
|
||||
const PartnerPreferencesForm = ({
|
||||
onSubmitStep,
|
||||
onSkipStep,
|
||||
errors,
|
||||
onFieldChange,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const data = useSelector((state) => state.registerform.partnerPreferences);
|
||||
const inputRef = useRef(null);
|
||||
const requiredMark = <span style={{ color: "#d32f2f" }}> *</span>;
|
||||
|
||||
const { data: masters, isLoading: isPartnerMastersLoading } =
|
||||
usePartnerPreferenceMasters();
|
||||
const subCasteQuery = useSubCasteMasters(data.castes);
|
||||
const cityQuery = useCityMasters(data.states);
|
||||
|
||||
const ageRangeOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.ageRange || raw.age_range || [];
|
||||
}, [masters]);
|
||||
|
||||
const casteOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.caste || raw.castes || [];
|
||||
}, [masters]);
|
||||
|
||||
const occupationOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.occupation || raw.occupations || [];
|
||||
}, [masters]);
|
||||
|
||||
const educationOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.education || raw.educations || [];
|
||||
}, [masters]);
|
||||
|
||||
const hobbyOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.hobbies || raw.hobby || [];
|
||||
}, [masters]);
|
||||
|
||||
const annualIncomeOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.annual_income || raw.annualIncome || [];
|
||||
}, [masters]);
|
||||
|
||||
const stateOptions = useMemo(() => {
|
||||
const raw = masters;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.state || raw.states || [];
|
||||
}, [masters]);
|
||||
|
||||
const subCasteOptions = useMemo(() => {
|
||||
const raw = subCasteQuery.data;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) {
|
||||
const merged = raw.flatMap((entry) => {
|
||||
if (!entry) return [];
|
||||
if (Array.isArray(entry)) return entry;
|
||||
return entry.sub_caste || entry.subCaste || entry.data || [];
|
||||
});
|
||||
return merged;
|
||||
}
|
||||
return raw.sub_caste || raw.subCaste || raw.data || [];
|
||||
}, [subCasteQuery.data]);
|
||||
|
||||
const cityOptions = useMemo(() => {
|
||||
const raw = cityQuery.data;
|
||||
if (!raw) return [];
|
||||
if (Array.isArray(raw)) return raw;
|
||||
return raw.subCaste || raw.district || raw.data || [];
|
||||
}, [cityQuery.data]);
|
||||
|
||||
useEffect(() => {
|
||||
inputRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
const handleChange = (field, value) => {
|
||||
dispatch(updatePartnerPreferences({ [field]: value }));
|
||||
const arrayFields = new Set([
|
||||
"castes",
|
||||
"subCastes",
|
||||
"occupations",
|
||||
"educations",
|
||||
"hobbies",
|
||||
"states",
|
||||
"districts",
|
||||
]);
|
||||
const nextValue =
|
||||
arrayFields.has(field) && typeof value === "string"
|
||||
? value.split(",").filter(Boolean)
|
||||
: value;
|
||||
const updates = { [field]: nextValue };
|
||||
const fieldsToClear = [field];
|
||||
|
||||
if (field === "castes") {
|
||||
updates.subCastes = [];
|
||||
fieldsToClear.push("subCastes");
|
||||
}
|
||||
if (field === "states") {
|
||||
updates.districts = [];
|
||||
fieldsToClear.push("districts");
|
||||
}
|
||||
|
||||
dispatch(updatePartnerPreferences(updates));
|
||||
if (onFieldChange) onFieldChange(fieldsToClear);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
@@ -29,36 +139,98 @@ const PartnerPreferencesForm = ({ onSubmitStep, onSkipStep, errors }) => {
|
||||
onSubmitStep();
|
||||
};
|
||||
|
||||
const renderMultiSelect = ({
|
||||
name,
|
||||
label,
|
||||
options,
|
||||
value,
|
||||
getLabel,
|
||||
getValue,
|
||||
disabled,
|
||||
}) => (
|
||||
<FormControl fullWidth variant="outlined" error={Boolean(errors[name])}>
|
||||
<InputLabel id={`${name}-label`}>Select {label}</InputLabel>
|
||||
<Select
|
||||
labelId={`${name}-label`}
|
||||
label={`Select ${label}`}
|
||||
name={name}
|
||||
multiple
|
||||
value={value}
|
||||
onChange={(e) => handleChange(name, e.target.value)}
|
||||
disabled={disabled}
|
||||
renderValue={(selected) =>
|
||||
selected
|
||||
.map((id) => {
|
||||
const item = options.find((opt) => getValue(opt) === id);
|
||||
return item ? getLabel(item) : id;
|
||||
})
|
||||
.join(", ")
|
||||
}
|
||||
sx={{
|
||||
"& .MuiSelect-select.Mui-disabled": {
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{options.map((opt) => {
|
||||
const optValue = getValue(opt);
|
||||
const optLabel = getLabel(opt);
|
||||
return (
|
||||
<MenuItem key={optValue} value={optValue}>
|
||||
<Checkbox checked={value.indexOf(optValue) > -1} />
|
||||
<ListItemText primary={optLabel} />
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
{errors[name] && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors[name]}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-[1200px] mx-auto bg-[#fff2f2] 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">
|
||||
{/* Preferred Age Range */}
|
||||
{/* Age Range */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Preferred Age Range
|
||||
Age Range{requiredMark}
|
||||
</label>
|
||||
<FormControl
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
error={Boolean(errors.ageRange)}
|
||||
>
|
||||
<InputLabel id="ageRange-label">
|
||||
Select Preferred Age Range
|
||||
</InputLabel>
|
||||
<InputLabel id="ageRange-label">Select Age Range</InputLabel>
|
||||
<Select
|
||||
labelId="ageRange-label"
|
||||
label="Select Preferred Age Range"
|
||||
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",
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
<MenuItem value="25 - 28">25 - 28</MenuItem>
|
||||
<MenuItem value="29 - 32">29 - 32</MenuItem>
|
||||
<MenuItem value="33 - 36">33 - 36</MenuItem>
|
||||
{ageRangeOptions.map((opt) => (
|
||||
<MenuItem key={opt.id ?? opt} value={opt.id ?? opt}>
|
||||
{opt.name || opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.ageRange && (
|
||||
<p
|
||||
@@ -74,36 +246,120 @@ const PartnerPreferencesForm = ({ onSubmitStep, onSkipStep, errors }) => {
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
{/* Religion / Caste Preference */}
|
||||
{/* Caste */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Religion / Caste Preference
|
||||
Caste{requiredMark}
|
||||
</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,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Sub Caste */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Sub Caste{requiredMark}
|
||||
</label>
|
||||
{renderMultiSelect({
|
||||
name: "subCastes",
|
||||
label: "Sub Caste",
|
||||
options: subCasteOptions,
|
||||
value: data.subCastes,
|
||||
getLabel: (opt) =>
|
||||
opt.sub_caste_name || opt.subCaste_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
disabled: data.castes.length === 0 || subCasteQuery.isLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Occupation */}
|
||||
<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>
|
||||
{renderMultiSelect({
|
||||
name: "educations",
|
||||
label: "Qualification",
|
||||
options: educationOptions,
|
||||
value: data.educations,
|
||||
getLabel: (opt) => opt.education_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Lifestyle and Hobbies */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Lifestyle & Hobbies{requiredMark}
|
||||
</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,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Annual Income */}
|
||||
<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.religionCaste)}
|
||||
error={Boolean(errors.annualIncome)}
|
||||
>
|
||||
<InputLabel id="religionCaste-label">
|
||||
Select Religion / Caste Preference
|
||||
<InputLabel id="annualIncome-label">
|
||||
Select Annual Income
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="religionCaste-label"
|
||||
label="Select Religion / Caste Preference"
|
||||
name="religionCaste"
|
||||
value={data.religionCaste}
|
||||
onChange={(e) =>
|
||||
handleChange("religionCaste", e.target.value)
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
<MenuItem value="Hindu">Hindu</MenuItem>
|
||||
<MenuItem value="Muslim">Muslim</MenuItem>
|
||||
<MenuItem value="Christian">Christian</MenuItem>
|
||||
<MenuItem value="Any">Any</MenuItem>
|
||||
{annualIncomeOptions.map((opt) => (
|
||||
<MenuItem key={opt.id ?? opt} value={opt.id ?? opt}>
|
||||
{opt.annual_income_name || opt.name || opt}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.religionCaste && (
|
||||
{errors.annualIncome && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
@@ -111,167 +367,43 @@ const PartnerPreferencesForm = ({ onSubmitStep, onSkipStep, errors }) => {
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors.religionCaste}
|
||||
{errors.annualIncome}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
{/* Occupation Preference */}
|
||||
{/* State */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Occupation Preference
|
||||
State{requiredMark}
|
||||
</label>
|
||||
<FormControl
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
error={Boolean(errors.occupationPref)}
|
||||
>
|
||||
<InputLabel id="occupationPref-label">
|
||||
Select Occupation Preference
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="occupationPref-label"
|
||||
label="Select Occupation Preference"
|
||||
name="occupationPref"
|
||||
value={data.occupationPref}
|
||||
onChange={(e) =>
|
||||
handleChange("occupationPref", e.target.value)
|
||||
}
|
||||
|
||||
>
|
||||
|
||||
<MenuItem value="IT, Business">IT, Business</MenuItem>
|
||||
<MenuItem value="Doctor">Doctor</MenuItem>
|
||||
<MenuItem value="Engineer">Engineer</MenuItem>
|
||||
<MenuItem value="Any">Any</MenuItem>
|
||||
</Select>
|
||||
{errors.occupationPref && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors.occupationPref}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
{renderMultiSelect({
|
||||
name: "states",
|
||||
label: "State",
|
||||
options: stateOptions,
|
||||
value: data.states,
|
||||
getLabel: (opt) => opt.state_name || opt.name || String(opt),
|
||||
getValue: (opt) => opt.id ?? opt,
|
||||
disabled: isPartnerMastersLoading,
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Lifestyle & Habits Preference */}
|
||||
{/* City */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Lifestyle & Habits Preference
|
||||
City{requiredMark}
|
||||
</label>
|
||||
<FormControl
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
error={Boolean(errors.lifestylePref)}
|
||||
>
|
||||
<InputLabel id="lifestylePref-label">
|
||||
Select Lifestyle & Habits Preference
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="lifestylePref-label"
|
||||
label="Select Lifestyle & Habits Preference"
|
||||
name="lifestylePref"
|
||||
value={data.lifestylePref}
|
||||
onChange={(e) =>
|
||||
handleChange("lifestylePref", e.target.value)
|
||||
}
|
||||
|
||||
>
|
||||
|
||||
<MenuItem value="Non-Smoking, Non-Drinking">
|
||||
Non-Smoking, Non-Drinking
|
||||
</MenuItem>
|
||||
<MenuItem value="Social Drinker">Social Drinker</MenuItem>
|
||||
<MenuItem value="Any">Any</MenuItem>
|
||||
</Select>
|
||||
{errors.lifestylePref && (
|
||||
<p
|
||||
style={{
|
||||
color: "#d32f2f",
|
||||
margin: "3px 14px 0 14px",
|
||||
fontSize: "0.75rem",
|
||||
}}
|
||||
>
|
||||
{errors.lifestylePref}
|
||||
</p>
|
||||
)}
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
{/* Prefer Qualification */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Prefer Qualification
|
||||
</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
name="qualificationPref"
|
||||
label="Enter prefer Qualification"
|
||||
value={data.qualificationPref}
|
||||
onChange={(e) =>
|
||||
handleChange("qualificationPref", e.target.value)
|
||||
}
|
||||
error={Boolean(errors.qualificationPref)}
|
||||
helperText={errors.qualificationPref}
|
||||
variant="outlined"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Occupation (text) */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">Occupation</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
name="occupationText"
|
||||
label="Enter Occupation"
|
||||
value={data.occupationText}
|
||||
onChange={(e) =>
|
||||
handleChange("occupationText", e.target.value)
|
||||
}
|
||||
error={Boolean(errors.occupationText)}
|
||||
helperText={errors.occupationText}
|
||||
variant="outlined"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Prefer Annual Income */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Prefer Annual Income
|
||||
</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
name="incomePref"
|
||||
label="Enter Annual Income"
|
||||
value={data.incomePref}
|
||||
onChange={(e) => handleChange("incomePref", e.target.value)}
|
||||
error={Boolean(errors.incomePref)}
|
||||
helperText={errors.incomePref}
|
||||
variant="outlined"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Prefer Location */}
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="text-gray-900 text-[15px]">
|
||||
Prefer Location
|
||||
</label>
|
||||
<TextField
|
||||
fullWidth
|
||||
name="locationPref"
|
||||
label="Enter Prefer Location"
|
||||
value={data.locationPref}
|
||||
onChange={(e) => handleChange("locationPref", e.target.value)}
|
||||
error={Boolean(errors.locationPref)}
|
||||
helperText={errors.locationPref}
|
||||
variant="outlined"
|
||||
/>
|
||||
{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,
|
||||
disabled: data.states.length === 0 || cityQuery.isLoading,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user