433 lines
14 KiB
JavaScript
433 lines
14 KiB
JavaScript
import React, { useEffect, useMemo, useRef } from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import { updateFamilyDetails } from "../redux/registrationFormSlice";
|
|
import {
|
|
Grid,
|
|
TextField,
|
|
FormControl,
|
|
InputLabel,
|
|
Select,
|
|
MenuItem,
|
|
Button,
|
|
Box,
|
|
} from "@mui/material";
|
|
import { useFamilyMasters } from "../hooks/useMasters";
|
|
|
|
const FamilyDetailsForm = ({ onSubmitStep, onSkipStep, errors, onFieldChange }) => {
|
|
const dispatch = useDispatch();
|
|
const data = useSelector((state) => state.registerform.familyDetails);
|
|
const inputRef = useRef(null);
|
|
const requiredMark = <span style={{ color: "#d32f2f" }}> *</span>;
|
|
|
|
const { data: familyMasters, isLoading: isFamilyMastersLoading } =
|
|
useFamilyMasters();
|
|
|
|
const occupationOptions = useMemo(() => {
|
|
const raw = familyMasters;
|
|
if (!raw) return [];
|
|
if (Array.isArray(raw)) return raw;
|
|
return raw.occupation || raw.occupations || [];
|
|
}, [familyMasters]);
|
|
|
|
const maritalStatusOptions = useMemo(() => {
|
|
const raw = familyMasters;
|
|
if (!raw) return [];
|
|
if (Array.isArray(raw)) return raw;
|
|
return raw.maritalStatus || raw.marital_status || [];
|
|
}, [familyMasters]);
|
|
|
|
const familyStatusOptions = useMemo(() => {
|
|
const raw = familyMasters;
|
|
if (!raw) return [];
|
|
if (Array.isArray(raw)) return [];
|
|
return raw.familyStatus || raw.family_status || [];
|
|
}, [familyMasters]);
|
|
|
|
useEffect(() => {
|
|
inputRef.current?.focus();
|
|
}, []);
|
|
|
|
const createSibling = () => ({
|
|
name: "",
|
|
occupation: "",
|
|
maritalStatus: "",
|
|
haveChildrens: "",
|
|
});
|
|
|
|
const syncSiblingArray = (arr, count) => {
|
|
const target = Math.max(0, Number(count) || 0);
|
|
const next = [...(arr || [])];
|
|
while (next.length < target) {
|
|
next.push(createSibling());
|
|
}
|
|
if (next.length > target) {
|
|
next.length = target;
|
|
}
|
|
return next;
|
|
};
|
|
|
|
const handleChange = (field, value) => {
|
|
const updates = { [field]: value };
|
|
const fieldsToClear = [field];
|
|
|
|
if (field === "brotherCount") {
|
|
const count = Number(value) || 0;
|
|
updates.brotherCount = count;
|
|
updates.brothers = syncSiblingArray(data.brothers, count);
|
|
fieldsToClear.push("brothers");
|
|
}
|
|
|
|
if (field === "sisterCount") {
|
|
const count = Number(value) || 0;
|
|
updates.sisterCount = count;
|
|
updates.sisters = syncSiblingArray(data.sisters, count);
|
|
fieldsToClear.push("sisters");
|
|
}
|
|
|
|
dispatch(updateFamilyDetails(updates));
|
|
if (onFieldChange) onFieldChange(fieldsToClear);
|
|
};
|
|
|
|
const handleSiblingChange = (type, index, field, value) => {
|
|
const list = [...(data[type] || [])];
|
|
if (!list[index]) list[index] = createSibling();
|
|
list[index] = { ...list[index], [field]: value };
|
|
dispatch(updateFamilyDetails({ [type]: list }));
|
|
if (onFieldChange) onFieldChange(type);
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
console.log("Submitting family details:", data);
|
|
onSubmitStep();
|
|
};
|
|
|
|
const countOptions = Array.from({ length: 11 }, (_, i) => i);
|
|
|
|
const renderSiblingCard = (type, index) => {
|
|
const sibling = (data[type] || [])[index] || createSibling();
|
|
const labelPrefix = type === "brothers" ? "Brother" : "Sister";
|
|
return (
|
|
<Box
|
|
key={`${type}-${index}`}
|
|
sx={{
|
|
border: "1px solid #e5e7eb",
|
|
borderRadius: 2,
|
|
padding: 2,
|
|
backgroundColor: "#fff",
|
|
}}
|
|
>
|
|
<div className="text-gray-900 text-[14px] font-semibold mb-3">
|
|
{labelPrefix} {index + 1}
|
|
</div>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4">
|
|
<TextField
|
|
fullWidth
|
|
label="Name"
|
|
value={sibling.name}
|
|
onChange={(e) =>
|
|
handleSiblingChange(type, index, "name", e.target.value)
|
|
}
|
|
variant="outlined"
|
|
/>
|
|
|
|
<FormControl fullWidth variant="outlined">
|
|
<InputLabel id={`${type}-${index}-occupation-label`}>
|
|
Occupation
|
|
</InputLabel>
|
|
<Select
|
|
labelId={`${type}-${index}-occupation-label`}
|
|
label="Occupation"
|
|
value={sibling.occupation}
|
|
onChange={(e) =>
|
|
handleSiblingChange(type, index, "occupation", e.target.value)
|
|
}
|
|
disabled={isFamilyMastersLoading}
|
|
sx={{
|
|
"& .MuiSelect-select.Mui-disabled": {
|
|
cursor: "not-allowed",
|
|
},
|
|
}}
|
|
>
|
|
{occupationOptions.map((opt) => (
|
|
<MenuItem key={opt} value={opt}>
|
|
{opt}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
|
|
<FormControl fullWidth variant="outlined">
|
|
<InputLabel id={`${type}-${index}-marital-label`}>
|
|
Marital Status
|
|
</InputLabel>
|
|
<Select
|
|
labelId={`${type}-${index}-marital-label`}
|
|
label="Marital Status"
|
|
value={sibling.maritalStatus}
|
|
onChange={(e) =>
|
|
handleSiblingChange(type, index, "maritalStatus", e.target.value)
|
|
}
|
|
disabled={isFamilyMastersLoading}
|
|
sx={{
|
|
"& .MuiSelect-select.Mui-disabled": {
|
|
cursor: "not-allowed",
|
|
},
|
|
}}
|
|
>
|
|
{maritalStatusOptions.map((opt) => (
|
|
<MenuItem key={opt} value={opt}>
|
|
{opt}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
|
|
<FormControl fullWidth variant="outlined">
|
|
<InputLabel id={`${type}-${index}-children-label`}>
|
|
Have Children
|
|
</InputLabel>
|
|
<Select
|
|
labelId={`${type}-${index}-children-label`}
|
|
label="Have Children"
|
|
value={sibling.haveChildrens}
|
|
onChange={(e) =>
|
|
handleSiblingChange(
|
|
type,
|
|
index,
|
|
"haveChildrens",
|
|
e.target.value
|
|
)
|
|
}
|
|
>
|
|
<MenuItem value={1}>Yes</MenuItem>
|
|
<MenuItem value={0}>No</MenuItem>
|
|
</Select>
|
|
</FormControl>
|
|
</div>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
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-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Father Name{requiredMark}
|
|
</label>
|
|
<TextField
|
|
fullWidth
|
|
inputRef={inputRef}
|
|
name="fatherName"
|
|
label="Father Name"
|
|
value={data.fatherName}
|
|
onChange={(e) => handleChange("fatherName", e.target.value)}
|
|
error={Boolean(errors.fatherName)}
|
|
helperText={errors.fatherName}
|
|
placeholder="Enter Father Name"
|
|
variant="outlined"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Father Occupation
|
|
</label>
|
|
<TextField
|
|
fullWidth
|
|
name="fatherOccupation"
|
|
label="Father Occupation"
|
|
value={data.fatherOccupation}
|
|
onChange={(e) => handleChange("fatherOccupation", e.target.value)}
|
|
error={Boolean(errors.fatherOccupation)}
|
|
helperText={errors.fatherOccupation}
|
|
placeholder="Enter Father Occupation"
|
|
variant="outlined"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Mother Name{requiredMark}
|
|
</label>
|
|
<TextField
|
|
fullWidth
|
|
name="motherName"
|
|
label="Mother Name"
|
|
value={data.motherName}
|
|
onChange={(e) => handleChange("motherName", e.target.value)}
|
|
error={Boolean(errors.motherName)}
|
|
helperText={errors.motherName}
|
|
placeholder="Enter Mother Name"
|
|
variant="outlined"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Mother Occupation
|
|
</label>
|
|
<TextField
|
|
fullWidth
|
|
name="motherOccupation"
|
|
label="Mother Occupation"
|
|
value={data.motherOccupation}
|
|
onChange={(e) => handleChange("motherOccupation", e.target.value)}
|
|
error={Boolean(errors.motherOccupation)}
|
|
helperText={errors.motherOccupation}
|
|
placeholder="Enter Mother Occupation"
|
|
variant="outlined"
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Brother Count
|
|
</label>
|
|
<FormControl fullWidth variant="outlined">
|
|
<InputLabel id="brotherCount-label">Select Brother Count</InputLabel>
|
|
<Select
|
|
labelId="brotherCount-label"
|
|
label="Select Brother Count"
|
|
name="brotherCount"
|
|
value={data.brotherCount}
|
|
onChange={(e) => handleChange("brotherCount", e.target.value)}
|
|
>
|
|
{countOptions.map((count) => (
|
|
<MenuItem key={count} value={count}>
|
|
{count}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Sister Count
|
|
</label>
|
|
<FormControl fullWidth variant="outlined">
|
|
<InputLabel id="sisterCount-label">Select Sister Count</InputLabel>
|
|
<Select
|
|
labelId="sisterCount-label"
|
|
label="Select Sister Count"
|
|
name="sisterCount"
|
|
value={data.sisterCount}
|
|
onChange={(e) => handleChange("sisterCount", e.target.value)}
|
|
>
|
|
{countOptions.map((count) => (
|
|
<MenuItem key={count} value={count}>
|
|
{count}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">
|
|
Family Status{requiredMark}
|
|
</label>
|
|
<FormControl
|
|
fullWidth
|
|
variant="outlined"
|
|
error={Boolean(errors.familyStatus)}
|
|
>
|
|
<InputLabel id="familyStatus-label">Select Family Status</InputLabel>
|
|
<Select
|
|
labelId="familyStatus-label"
|
|
label="Select Family Status"
|
|
name="familyStatus"
|
|
value={data.familyStatus}
|
|
onChange={(e) => handleChange("familyStatus", e.target.value)}
|
|
disabled={isFamilyMastersLoading}
|
|
sx={{
|
|
"& .MuiSelect-select.Mui-disabled": {
|
|
cursor: "not-allowed",
|
|
},
|
|
}}
|
|
>
|
|
{familyStatusOptions.map((item) => (
|
|
<MenuItem key={item.id ?? item} value={item.id ?? item}>
|
|
{item.family_type_name || item.name || item}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
{errors.familyStatus && (
|
|
<p
|
|
style={{
|
|
color: "#d32f2f",
|
|
margin: "3px 14px 0 14px",
|
|
fontSize: "0.75rem",
|
|
}}
|
|
>
|
|
{errors.familyStatus}
|
|
</p>
|
|
)}
|
|
</FormControl>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-4">
|
|
<label className="text-gray-900 text-[15px]">Native Place</label>
|
|
<TextField
|
|
fullWidth
|
|
name="nativePlace"
|
|
label="Native Place"
|
|
value={data.nativePlace}
|
|
onChange={(e) => handleChange("nativePlace", e.target.value)}
|
|
error={Boolean(errors.nativePlace)}
|
|
helperText={errors.nativePlace}
|
|
placeholder="Enter Native Place"
|
|
variant="outlined"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{Number(data.brotherCount) > 0 && (
|
|
<div className="mt-6">
|
|
<div className="text-gray-900 text-[16px] font-semibold mb-3">
|
|
Brother Details
|
|
</div>
|
|
<div className="grid grid-cols-1 gap-4">
|
|
{Array.from({ length: Number(data.brotherCount) }).map(
|
|
(_, index) => renderSiblingCard("brothers", index)
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{Number(data.sisterCount) > 0 && (
|
|
<div className="mt-6">
|
|
<div className="text-gray-900 text-[16px] font-semibold mb-3">
|
|
Sister Details
|
|
</div>
|
|
<div className="grid grid-cols-1 gap-4">
|
|
{Array.from({ length: Number(data.sisterCount) }).map(
|
|
(_, index) => renderSiblingCard("sisters", index)
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<Grid
|
|
item
|
|
xs={12}
|
|
sx={{ marginTop: 10, display: "flex", gap: 4, justifyContent: "center" }}
|
|
>
|
|
{onSkipStep && (
|
|
<Button variant="outlined" onClick={onSkipStep}>
|
|
Skip
|
|
</Button>
|
|
)}
|
|
<Button variant="contained" color="primary" onClick={handleSubmit}>
|
|
{onSkipStep ? "Next" : "Update"}
|
|
</Button>
|
|
</Grid>
|
|
</form>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default FamilyDetailsForm;
|