thirukalyanamweb/src/feature/FamilyDetailsForm.jsx
2026-03-07 17:09:56 +05:30

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;