filter master integrate

This commit is contained in:
Meenadeveloper 2026-03-10 18:03:17 +05:30
parent 5392a4211e
commit 9427677a72
16 changed files with 784 additions and 468 deletions

88
package-lock.json generated
View File

@ -31,6 +31,9 @@
"react-lazy-load-image-component": "^1.6.3", "react-lazy-load-image-component": "^1.6.3",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
"react-router-dom": "^7.9.6", "react-router-dom": "^7.9.6",
"react-select": "^5.10.2",
"react-window": "^2.2.7",
"redux-persist": "^6.0.0",
"swiper": "^12.0.3", "swiper": "^12.0.3",
"tailwindcss": "^4.1.17" "tailwindcss": "^4.1.17"
}, },
@ -1719,6 +1722,31 @@
"integrity": "sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw==", "integrity": "sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw==",
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/@floating-ui/core": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.11"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.6",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.7.5",
"@floating-ui/utils": "^0.2.11"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
"license": "MIT"
},
"node_modules/@grpc/grpc-js": { "node_modules/@grpc/grpc-js": {
"version": "1.9.15", "version": "1.9.15",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
@ -7139,6 +7167,12 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
"license": "MIT"
},
"node_modules/merge-stream": { "node_modules/merge-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -8053,6 +8087,27 @@
"react-dom": ">=18" "react-dom": ">=18"
} }
}, },
"node_modules/react-select": {
"version": "5.10.2",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz",
"integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.0",
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.8.1",
"@floating-ui/dom": "^1.0.1",
"@types/react-transition-group": "^4.4.0",
"memoize-one": "^6.0.0",
"prop-types": "^15.6.0",
"react-transition-group": "^4.3.0",
"use-isomorphic-layout-effect": "^1.2.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-smooth": { "node_modules/react-smooth": {
"version": "4.0.4", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
@ -8116,6 +8171,16 @@
} }
} }
}, },
"node_modules/react-window": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-2.2.7.tgz",
"integrity": "sha512-SH5nvfUQwGHYyriDUAOt7wfPsfG9Qxd6OdzQxl5oQ4dsSsUicqQvjV7dR+NqZ4coY0fUn3w1jnC5PwzIUWEg5w==",
"license": "MIT",
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
}
},
"node_modules/read-cache": { "node_modules/read-cache": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -8205,6 +8270,15 @@
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/redux-persist": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
"integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
"license": "MIT",
"peerDependencies": {
"redux": ">4.0.0"
}
},
"node_modules/redux-thunk": { "node_modules/redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
@ -9069,6 +9143,20 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-isomorphic-layout-effect": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz",
"integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-sync-external-store": { "node_modules/use-sync-external-store": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",

View File

@ -33,6 +33,9 @@
"react-lazy-load-image-component": "^1.6.3", "react-lazy-load-image-component": "^1.6.3",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
"react-router-dom": "^7.9.6", "react-router-dom": "^7.9.6",
"react-select": "^5.10.2",
"react-window": "^2.2.7",
"redux-persist": "^6.0.0",
"swiper": "^12.0.3", "swiper": "^12.0.3",
"tailwindcss": "^4.1.17" "tailwindcss": "^4.1.17"
}, },

View File

@ -53,5 +53,9 @@ BE_SAFE_ONLINE:"get_be_safe_online",
NOTIFICATION_LIST:"notification/lists", NOTIFICATION_LIST:"notification/lists",
NOTIFICATION_COUNT:"notification/un_read_count", NOTIFICATION_COUNT:"notification/un_read_count",
// filter with profiles list api's
PROFILES_FILTER_LIST:"profiles/lists",
PROFILES_FILTER_MASTER:"profiles/filter/masters",
}; };

View File

@ -63,3 +63,17 @@ export const getPartnerPreferenceMasters = async () => {
); );
return res.data; return res.data;
}; };
// profile filter masters
export const getProfilesFilterList = async (filters) => {
const res = await axiosInstance.get(API_ENDPOINTS.PROFILES_FILTER_LIST, {
params: filters,
});
return res.data;
};
export const getProfilesFilterMasters = async () => {
const res = await axiosInstance.get(API_ENDPOINTS.PROFILES_FILTER_MASTER);
return res.data;
};

View File

@ -0,0 +1,97 @@
import React from "react";
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
import ReactWindow from "react-window";
const FixedSizeList = ReactWindow?.FixedSizeList || ReactWindow?.default?.FixedSizeList;
const LISTBOX_PADDING = 8; // px
function renderRow(props) {
const { data, index, style } = props;
const dataSet = data[index];
const inlineStyle = {
...style,
top: style.top + LISTBOX_PADDING,
};
return (
<div style={inlineStyle}>
{dataSet}
</div>
);
}
const OuterElementContext = React.createContext({});
const OuterElementType = React.forwardRef((props, ref) => {
const outerProps = React.useContext(OuterElementContext);
return <div ref={ref} {...props} {...outerProps} />;
});
const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) {
const { children, ...other } = props;
if (!FixedSizeList) {
return <ul ref={ref} {...other}>{children}</ul>;
}
const itemData = [];
React.Children.forEach(children, (item) => {
itemData.push(item);
itemData.push(...(item.children || []));
});
const itemCount = itemData.length;
const itemSize = 48;
const getHeight = () => {
if (itemCount > 8) {
return 8 * itemSize;
}
return itemCount * itemSize;
};
return (
<div ref={ref}>
<OuterElementContext.Provider value={other}>
<FixedSizeList
itemData={itemData}
height={getHeight() + 2 * LISTBOX_PADDING}
width="100%"
outerElementType={OuterElementType}
innerElementType="ul"
itemSize={itemSize}
overscanCount={5}
itemCount={itemCount}
>
{renderRow}
</FixedSizeList>
</OuterElementContext.Provider>
</div>
);
});
const VirtualizedSelect = ({ options, value, onChange, label, placeholder, isMulti, ...props }) => {
return (
<Autocomplete
multiple={isMulti}
options={options}
value={value}
onChange={(event, newValue) => {
onChange(newValue);
}}
disableListWrap
ListboxComponent={ListboxComponent}
renderInput={(params) => (
<TextField {...params} label={label} placeholder={placeholder} variant="outlined" />
)}
isOptionEqualToValue={(option, value) => option.value === value.value}
getOptionLabel={(option) => option.label || ""}
{...props}>
</Autocomplete>
)
}
export default VirtualizedSelect

View File

@ -1,5 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Crown, Bookmark, CurrencyIcon, Currency, Wallet, Receipt, Sparkles, MoonStar, IdCard, RockingChair, LocateFixed, School, WorkflowIcon } from "lucide-react"; import { Crown, Bookmark, CurrencyIcon, Currency, Wallet, Receipt, Sparkles, MoonStar, IdCard, RockingChair, LocateFixed, School, WorkflowIcon, Lock } from "lucide-react";
import CakeIcon from "@mui/icons-material/Cake"; import CakeIcon from "@mui/icons-material/Cake";
import GroupsIcon from "@mui/icons-material/Groups"; import GroupsIcon from "@mui/icons-material/Groups";
import SchoolIcon from "@mui/icons-material/School"; import SchoolIcon from "@mui/icons-material/School";
@ -26,6 +26,9 @@ import { useNavigate } from "react-router-dom";
import { Button, Fab } from "@mui/material"; import { Button, Fab } from "@mui/material";
import MessageIcon from "@mui/icons-material/Message"; import MessageIcon from "@mui/icons-material/Message";
import PhoneIcon from "@mui/icons-material/Phone"; import PhoneIcon from "@mui/icons-material/Phone";
import toast from "react-hot-toast";
import { useSelector, useDispatch } from "react-redux";
import { updateFilter } from "../../redux/filterSlice";
// Profile Card Component // Profile Card Component
function ProfileCard({ profile }) { function ProfileCard({ profile }) {
const [isLiked, setIsLiked] = useState(false); const [isLiked, setIsLiked] = useState(false);
@ -216,67 +219,70 @@ function ProfileCard({ profile }) {
// Main Component // Main Component
export default function MatchesInterface() { export default function MatchesInterface() {
const navigate = useNavigate(); const navigate = useNavigate();
const [selectedTab, setSelectedTab] = useState("your-matches"); const dispatch = useDispatch();
const filterType = useSelector((state) => state.filters.filter_type);
const selectedTab = filterType || "all_matches";
const isPaidMember = useSelector((state) => state.filters.isPaidMember);
const tabs = [ const tabs = [
{ {
id: "your-matches", id: "all_matches",
icon: <PersonIcon className="w-6 h-6" />, icon: <PersonIcon className="w-6 h-6" />,
title: "Your Matches", title: "Your Matches",
description: "View all the profiles that match your preferences", description: "View all the profiles that match your preferences",
category: "All Matches", category: "All Matches",
}, },
{ {
id: "shortlisted-by-you", id: "shorlisted_by_you",
icon: <StarIcon className="w-6 h-6" />, icon: <StarIcon className="w-6 h-6" />,
title: "Shortlisted by you", title: "Shortlisted by you",
description: "Matches you have shortlisted", description: "Matches you have shortlisted",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "viewed-you", id: "viewed_you",
icon: <VisibilityIcon className="w-6 h-6" />, icon: <VisibilityIcon className="w-6 h-6" />,
title: "Viewed you", title: "Viewed you",
description: "Matches who have viewed your profile", description: "Matches who have viewed your profile",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "shortlisted-you", id: "shorlisted_you",
icon: <PersonAddIcon className="w-6 h-6" />, icon: <PersonAddIcon className="w-6 h-6" />,
title: "Shortlisted you", title: "Shortlisted you",
description: "Matches who have shortlisted your profile", description: "Matches who have shortlisted your profile",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "viewed-by-you", id: "viewed_by_you",
icon: <VisibilityIcon className="w-6 h-6" />, icon: <VisibilityIcon className="w-6 h-6" />,
title: "Viewed by you", title: "Viewed by you",
description: "Matches you have viewed", description: "Matches you have viewed",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "newly-joined", id: "newly_joined",
icon: <RockingChair className="w-6 h-6" />, icon: <RockingChair className="w-6 h-6" />,
title: "Newly Joined", title: "Newly Joined",
description: "Matches who Joined within the last 30 days", description: "Matches who Joined within the last 30 days",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "location", id: "location_matches",
icon: <LocateFixed className="w-6 h-6" />, icon: <LocateFixed className="w-6 h-6" />,
title: "Location matches", title: "Location matches",
description: "Matches near your location", description: "Matches near your location",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "education", id: "education_matches",
icon: <School className="w-6 h-6" />, icon: <School className="w-6 h-6" />,
title: "Education matches", title: "Education matches",
description: "Matches near your education match", description: "Matches near your education match",
category: "Based on activity", category: "Based on activity",
}, },
{ {
id: "job", id: "job_matches",
icon: <WorkflowIcon className="w-6 h-6" />, icon: <WorkflowIcon className="w-6 h-6" />,
title: "Job matches", title: "Job matches",
description: "Matches near your job", description: "Matches near your job",
@ -406,7 +412,9 @@ export default function MatchesInterface() {
</h2> </h2>
)} )}
<div <div
onClick={() => setSelectedTab(tab.id)} onClick={() => {
dispatch(updateFilter({ filter_type: tab.id }));
}}
className={`p-4 rounded-lg mb-3 cursor-pointer transition-all ${ className={`p-4 rounded-lg mb-3 cursor-pointer transition-all ${
selectedTab === tab.id selectedTab === tab.id
? "bg-green-50 border-l-4 border-green-600" ? "bg-green-50 border-l-4 border-green-600"
@ -472,12 +480,23 @@ export default function MatchesInterface() {
{tabs.find((t) => t.id === selectedTab)?.title} {tabs.find((t) => t.id === selectedTab)?.title}
</h1> </h1>
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<img <div className="relative cursor-pointer" onClick={() => {
src={horoscope} if (isPaidMember) {
onClick={() => {
navigate("/horoscoper-generate"); navigate("/horoscoper-generate");
}} } else {
/> toast.error("Star Matching is locked for free members");
}
}}>
<img
src={horoscope}
className={!isPaidMember ? "opacity-50 blur-[1px]" : ""}
/>
{!isPaidMember && (
<div className="absolute inset-0 flex items-center justify-center">
<Lock className="w-4 h-4 text-black" />
</div>
)}
</div>
<FilterModal /> <FilterModal />
</div> </div>
</div> </div>

View File

@ -107,14 +107,14 @@ const AdvancedDropzone = ({ value, onChange }) => {
<FileMosaic <FileMosaic
{...file} {...file}
onDelete={onDelete} onDelete={onDelete}
// onSee={handleSee} onSee={handleSee}
// onWatch={handleWatch} onWatch={handleWatch}
onAbort={handleAbort} onAbort={handleAbort}
onCancel={handleCancel} onCancel={handleCancel}
resultOnTooltip resultOnTooltip
alwaysActive alwaysActive
preview preview
// info={false} info={false}
/> />
{hoveredId === file.id && ( {hoveredId === file.id && (
<div <div

View File

@ -1,15 +1,12 @@
import React, { useState } from "react"; import React, { useState, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { import {
setAge, setAge,
setHeight, setHeight,
setMaritalStatus,
setMotherTongue,
setReligion,
setMatchesWithHoroscope,
setCaste, setCaste,
setSubCaste, setSubCaste,
updateFilter, updateFilter,
resetFilters,
} from "../redux/filterSlice"; } from "../redux/filterSlice";
import { import {
Slider, Slider,
@ -26,8 +23,12 @@ import {
Accordion, Accordion,
AccordionSummary, AccordionSummary,
AccordionDetails, AccordionDetails,
CircularProgress,
} from "@mui/material"; } from "@mui/material";
import { ChevronDown } from "lucide-react"; import { ChevronDown, Lock, Crown, RotateCcw, Check } from "lucide-react";
import { useProfilesFilterMasters } from "../hooks/useProfiles";
import { useCityMasters } from "../hooks/useDependentMasters";
import toast from "react-hot-toast";
const FilterForm = () => { const FilterForm = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -40,34 +41,61 @@ const FilterForm = () => {
location: false, location: false,
lifestyle: false, lifestyle: false,
family: false, family: false,
paidBenefit: false,
}); });
const { data: filterMasters, isLoading, isError } = useProfilesFilterMasters();
const { data: cityData } = useCityMasters(
filters.state && filters.state.length > 0 ? filters.state : null
);
const cityOptions = useMemo(() => {
const raw = cityData;
if (!raw) return [];
if (Array.isArray(raw)) return raw;
return raw.subCaste || raw.district || raw.data || [];
}, [cityData]);
const handleAccordionChange = (section) => (event, isExpanded) => { const handleAccordionChange = (section) => (event, isExpanded) => {
setExpandedSections((prev) => ({ ...prev, [section]: isExpanded })); setExpandedSections((prev) => ({ ...prev, [section]: isExpanded }));
}; };
const casteOptions = ["Agamudayar", "Pillai", "Vellalar"];
const motherTongueOptions = [
"Tamil",
"Telugu",
"Malayalam",
"Kannada",
"Hindi",
];
const handleSubmit = () => { const handleSubmit = () => {
console.log("Filter Values:", filters); console.log("Filter Values:", filters);
}; };
const handleClear = () => {
dispatch(resetFilters());
toast.success("Filters cleared");
};
const handleSelectionChange = (field, value) => { const handleSelectionChange = (field, value) => {
console.log(`${field} selected:`, value); console.log(`${field} selected:`, value);
}; };
if (isLoading) {
return (
<div className="flex justify-center items-center min-h-[300px]">
<CircularProgress />
</div>
);
}
if (isError) {
return (
<div className="flex justify-center items-center min-h-[300px]">
<Typography color="error">Failed to load filter options</Typography>
</div>
);
}
return ( return (
<div className="max-w-6xl mx-auto p-4 px-0 md:p-6 "> <div className="max-w-6xl mx-auto p-4 px-0 md:p-6 ">
<div className="bg-white rounded-lg shadow-sm"> <div className="bg-white rounded-lg shadow-sm">
{/* Header */} {/* Header */}
<div className="border-b border-pink-200 p-4 bg-[#fff5ed]"> <div className="border-b border-pink-200 p-4 bg-[#f2f2f2]">
<Typography variant="h5" className="font-semibold text-center"> <Typography variant="h5" className="font-semibold text-center">
Partner Filter preference Partner Filter preference
</Typography> </Typography>
@ -98,7 +126,7 @@ const FilterForm = () => {
<Typography gutterBottom sx={{marginBottom:"30px"}}>Age</Typography> <Typography gutterBottom sx={{marginBottom:"30px"}}>Age</Typography>
<div className="px-2"> <div className="px-2">
<Slider <Slider
value={filters.age} value={[filters.from_age, filters.to_age]}
onChange={(e, newValue) => { onChange={(e, newValue) => {
dispatch(setAge(newValue)); dispatch(setAge(newValue));
handleSelectionChange("Age", newValue); handleSelectionChange("Age", newValue);
@ -119,7 +147,7 @@ const FilterForm = () => {
<Typography gutterBottom sx={{marginBottom:"30px"}}>Height</Typography> <Typography gutterBottom sx={{marginBottom:"30px"}}>Height</Typography>
<div className="px-2"> <div className="px-2">
<Slider <Slider
value={filters.height} value={[filters.from_height, filters.to_height]}
onChange={(e, newValue) => { onChange={(e, newValue) => {
dispatch(setHeight(newValue)); dispatch(setHeight(newValue));
handleSelectionChange("Height", newValue); handleSelectionChange("Height", newValue);
@ -141,46 +169,40 @@ const FilterForm = () => {
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Marital Status</InputLabel> <InputLabel>Marital Status</InputLabel>
<Select <Select
value={filters.maritalStatus} multiple
value={filters.marital_status || []}
label="Marital Status" label="Marital Status"
onChange={(e) => { onChange={(e) => {
dispatch(setMaritalStatus(e.target.value)); dispatch(updateFilter({ marital_status: e.target.value }));
handleSelectionChange("Marital Status", e.target.value); handleSelectionChange("Marital Status", e.target.value);
}} }}
>
<MenuItem value="All Profile">All Profile</MenuItem>
<MenuItem value="Never Married">Never Married</MenuItem>
<MenuItem value="Divorced">Divorced</MenuItem>
<MenuItem value="Widowed">Widowed</MenuItem>
</Select>
</FormControl>
{/* Mother Tongue */}
<FormControl fullWidth>
<InputLabel>Mother Tongue</InputLabel>
<Select
multiple
value={filters.motherTongue}
label="Mother Tongue"
onChange={(e) => {
dispatch(setMotherTongue(e.target.value));
handleSelectionChange("Mother Tongue", e.target.value);
}}
renderValue={(selected) => ( renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}> <Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => ( {selected.map((value) => {
<Chip key={value} label={value} size="small" /> const label = filterMasters?.marital_statuses?.find((s) => s.id === value)?.marital_status_name || value;
))} return (
<Chip
key={value}
label={label}
size="small"
onDelete={() => dispatch(updateFilter({ marital_status: filters.marital_status.filter((v) => v !== value) }))}
onMouseDown={(e) => e.stopPropagation()}
/>
);
})}
</Box> </Box>
)} )}
> >
{motherTongueOptions.map((lang) => ( {filterMasters?.marital_statuses?.map((status) => (
<MenuItem key={lang} value={lang}> <MenuItem key={status.id} value={status.id}>
{lang} {status.marital_status_name}
</MenuItem> </MenuItem>
))} ))}
</Select> </Select>
</FormControl> </FormControl>
</div> </div>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
@ -207,61 +229,69 @@ const FilterForm = () => {
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Religion</InputLabel> <InputLabel>Religion</InputLabel>
<Select <Select
value={filters.religion} multiple
value={filters.religion || []}
label="Religion" label="Religion"
onChange={(e) => { onChange={(e) => {
dispatch(setReligion(e.target.value)); dispatch(updateFilter({ religion: e.target.value }));
handleSelectionChange("Religion", e.target.value); handleSelectionChange("Religion", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.religions?.find((r) => r.id === value)?.religion_name || value;
return (
<Chip
key={value}
label={label}
size="small"
onDelete={() => dispatch(updateFilter({ religion: filters.religion.filter((v) => v !== value) }))}
onMouseDown={(e) => e.stopPropagation()}
/>
);
})}
</Box>
)}
> >
<MenuItem value="Hindu">Hindu</MenuItem> {filterMasters?.religions?.map((rel) => (
<MenuItem value="Muslim">Muslim</MenuItem> <MenuItem key={rel.id} value={rel.id}>
<MenuItem value="Christian">Christian</MenuItem> {rel.religion_name}
<MenuItem value="Sikh">Sikh</MenuItem> </MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
{/* Matches with Horoscope */}
<FormControlLabel
control={
<Checkbox
checked={filters.matchesWithHoroscope}
onChange={(e) => {
dispatch(setMatchesWithHoroscope(e.target.checked));
handleSelectionChange(
"Matches with Horoscope",
e.target.checked
);
}}
/>
}
label="Matches with horoscope"
/>
{/* Caste */} {/* Caste */}
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Caste (Multi Select)</InputLabel> <InputLabel>Caste</InputLabel>
<Select <Select
multiple multiple
value={filters.caste} value={filters.caste}
label="Caste (Multi Select)" label="Caste"
onChange={(e) => { onChange={(e) => {
dispatch(setCaste(e.target.value)); dispatch(setCaste(e.target.value));
handleSelectionChange("Caste", e.target.value); handleSelectionChange("Caste", e.target.value);
}} }}
renderValue={(selected) => ( renderValue={(selected) => (
<Box <Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }} {selected.map((value) => {
> const label = filterMasters?.castes?.find((c) => c.id === value)?.caste_name || value;
{selected.map((value) => ( return (
<Chip key={value} label={value} size="small" /> <Chip
))} key={value}
label={label}
size="small"
onDelete={() => dispatch(setCaste(filters.caste.filter((v) => v !== value)))}
onMouseDown={(e) => e.stopPropagation()}
/>
);
})}
</Box> </Box>
)} )}
> >
{["Agamudayar", "Pillai", "Vellalar"].map((caste) => ( {filterMasters?.castes?.map((caste) => (
<MenuItem key={caste} value={caste}> <MenuItem key={caste.id} value={caste.id}>
{caste} {caste.caste_name}
</MenuItem> </MenuItem>
))} ))}
</Select> </Select>
@ -269,21 +299,19 @@ const FilterForm = () => {
{/* Sub-Caste */} {/* Sub-Caste */}
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Sub-Caste (Multi Select)</InputLabel> <InputLabel>Sub-Caste</InputLabel>
<Select <Select
multiple multiple
value={filters.subCaste} value={filters.sub_caste}
label="Sub-Caste (Multi Select)" label="Sub-Caste"
onChange={(e) => { onChange={(e) => {
dispatch(setSubCaste(e.target.value)); dispatch(setSubCaste(e.target.value));
handleSelectionChange("Sub-Caste", e.target.value); handleSelectionChange("Sub-Caste", e.target.value);
}} }}
renderValue={(selected) => ( renderValue={(selected) => (
<Box <Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}
>
{selected.map((value) => ( {selected.map((value) => (
<Chip key={value} label={value} size="small" /> <Chip key={value} label={value} size="small" onDelete={() => dispatch(setSubCaste(filters.sub_caste.filter((v) => v !== value)))} onMouseDown={(e) => e.stopPropagation()} />
))} ))}
</Box> </Box>
)} )}
@ -296,39 +324,7 @@ const FilterForm = () => {
</Select> </Select>
</FormControl> </FormControl>
{/* Star */}
<FormControl fullWidth>
<InputLabel>Star</InputLabel>
<Select
value={filters.star}
label="Star"
onChange={(e) => {
dispatch(updateFilter({ star: e.target.value }));
handleSelectionChange("Star", e.target.value);
}}
>
<MenuItem value="Any">Any</MenuItem>
<MenuItem value="Ashwini">Ashwini</MenuItem>
<MenuItem value="Bharani">Bharani</MenuItem>
</Select>
</FormControl>
{/* Dasham */}
<FormControl fullWidth>
<InputLabel>Dasham</InputLabel>
<Select
value={filters.dasham}
label="Dasham"
onChange={(e) => {
dispatch(updateFilter({ dasham: e.target.value }));
handleSelectionChange("Dasham", e.target.value);
}}
>
<MenuItem value="Doesn't matter">Doesn't matter</MenuItem>
<MenuItem value="Yes">Yes</MenuItem>
<MenuItem value="No">No</MenuItem>
</Select>
</FormControl>
</div> </div>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
@ -356,66 +352,108 @@ const FilterForm = () => {
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Occupation</InputLabel> <InputLabel>Occupation</InputLabel>
<Select <Select
value={filters.occupation} multiple
value={filters.occupation || []}
label="Occupation" label="Occupation"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ occupation: e.target.value })); dispatch(updateFilter({ occupation: e.target.value }));
handleSelectionChange("Occupation", e.target.value); handleSelectionChange("Occupation", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.occupations?.find((o) => o.id === value)?.occupation_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ occupation: filters.occupation.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.occupations?.map((occ) => (
<MenuItem value="Software Engineer"> <MenuItem key={occ.id} value={occ.id}>
Software Engineer {occ.occupation_name}
</MenuItem> </MenuItem>
<MenuItem value="Doctor">Doctor</MenuItem> ))}
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Annual Income</InputLabel> <InputLabel>Annual Income</InputLabel>
<Select <Select
value={filters.annualIncome} multiple
value={filters.annual_income || []}
label="Annual Income" label="Annual Income"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ annualIncome: e.target.value })); dispatch(updateFilter({ annual_income: e.target.value }));
handleSelectionChange("Annual Income", e.target.value); handleSelectionChange("Annual Income", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.annual_incomes?.find((i) => i.id === value)?.annual_income_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ annual_income: filters.annual_income.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.annual_incomes?.map((inc) => (
<MenuItem value="0-5 Lakhs">0-5 Lakhs</MenuItem> <MenuItem key={inc.id} value={inc.id}>
<MenuItem value="5-10 Lakhs">5-10 Lakhs</MenuItem> {inc.annual_income_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Employee Type</InputLabel> <InputLabel>Employee Type</InputLabel>
<Select <Select
value={filters.employeeType} multiple
value={filters.employee_type || []}
label="Employee Type" label="Employee Type"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ employeeType: e.target.value })); dispatch(updateFilter({ employee_type: e.target.value }));
handleSelectionChange("Employee Type", e.target.value); handleSelectionChange("Employee Type", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.employee_types?.find((et) => et.id === value)?.employee_type_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ employee_type: filters.employee_type.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.employee_types?.map((emp) => (
<MenuItem value="Government">Government</MenuItem> <MenuItem key={emp.id} value={emp.id}>
<MenuItem value="Private">Private</MenuItem> {emp.employee_type_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Education</InputLabel> <InputLabel>Education</InputLabel>
<Select <Select
value={filters.education} multiple
value={filters.education || []}
label="Education" label="Education"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ education: e.target.value })); dispatch(updateFilter({ education: e.target.value }));
handleSelectionChange("Education", e.target.value); handleSelectionChange("Education", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.educations?.find((ed) => ed.id === value)?.education_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ education: filters.education.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.educations?.map((edu) => (
<MenuItem value="Bachelor">Bachelor</MenuItem> <MenuItem key={edu.id} value={edu.id}>
<MenuItem value="Master">Master</MenuItem> {edu.education_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
</div> </div>
@ -443,50 +481,59 @@ const FilterForm = () => {
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>State</InputLabel> <InputLabel>State</InputLabel>
<Select <Select
value={filters.state} multiple
value={filters.state || []}
label="State" label="State"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ state: e.target.value })); dispatch(updateFilter({ state: e.target.value, district: [] }));
handleSelectionChange("State", e.target.value); handleSelectionChange("State", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.states?.find((s) => s.id === value)?.state_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ state: filters.state.filter((v) => v !== value), district: [] }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.states?.map((state) => (
<MenuItem value="Tamil Nadu">Tamil Nadu</MenuItem> <MenuItem key={state.id} value={state.id}>
<MenuItem value="Karnataka">Karnataka</MenuItem> {state.state_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Country</InputLabel> <InputLabel>City</InputLabel>
<Select <Select
value={filters.country} multiple
label="Country" value={filters.district || []}
label="City"
disabled={!filters.state || filters.state.length === 0}
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ country: e.target.value })); dispatch(updateFilter({ district: e.target.value }));
handleSelectionChange("Country", e.target.value); handleSelectionChange("City", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = cityOptions.find((c) => c.id === value)?.district_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ district: filters.district.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {cityOptions.map((city) => (
<MenuItem value="India">India</MenuItem> <MenuItem key={city.id} value={city.id}>
<MenuItem value="USA">USA</MenuItem> {city.district_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth>
<InputLabel>Citizenship</InputLabel>
<Select
value={filters.citizenship}
label="Citizenship"
onChange={(e) => {
dispatch(updateFilter({ citizenship: e.target.value }));
handleSelectionChange("Citizenship", e.target.value);
}}
>
<MenuItem value="Any">Any</MenuItem>
<MenuItem value="Indian">Indian</MenuItem>
<MenuItem value="US Citizen">US Citizen</MenuItem>
</Select>
</FormControl>
</div> </div>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
@ -512,54 +559,22 @@ const FilterForm = () => {
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Eating Habits</InputLabel> <InputLabel>Eating Habits</InputLabel>
<Select <Select
value={filters.eatingHabits} value={filters.diet}
label="Eating Habits" label="Eating Habits"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ eatingHabits: e.target.value })); dispatch(updateFilter({ diet: e.target.value }));
handleSelectionChange("Eating Habits", e.target.value); handleSelectionChange("Eating Habits", e.target.value);
}} }}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.diets?.map((diet) => (
<MenuItem value="Vegetarian">Vegetarian</MenuItem> <MenuItem key={diet.id} value={diet.id}>
<MenuItem value="Non-Vegetarian">Non-Vegetarian</MenuItem> {diet.diet_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
{/* <FormControl fullWidth>
<InputLabel>Smoking Habits</InputLabel>
<Select
value={filters.smokingHabits}
label="Smoking Habits"
onChange={(e) => {
dispatch(
updateFilter({ smokingHabits: e.target.value })
);
handleSelectionChange("Smoking Habits", e.target.value);
}}
>
<MenuItem value="Doesn't matter">Doesn't matter</MenuItem>
<MenuItem value="Non-Smoker">Non-Smoker</MenuItem>
<MenuItem value="Smoker">Smoker</MenuItem>
</Select>
</FormControl>
<FormControl fullWidth>
<InputLabel>Drinking Habits</InputLabel>
<Select
value={filters.drinkingHabits}
label="Drinking Habits"
onChange={(e) => {
dispatch(
updateFilter({ drinkingHabits: e.target.value })
);
handleSelectionChange("Drinking Habits", e.target.value);
}}
>
<MenuItem value="Doesn't matter">Doesn't matter</MenuItem>
<MenuItem value="Non-Drinker">Non-Drinker</MenuItem>
<MenuItem value="Social Drinker">Social Drinker</MenuItem>
</Select>
</FormControl> */}
</div> </div>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
@ -585,64 +600,116 @@ const FilterForm = () => {
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Family Type</InputLabel> <InputLabel>Family Type</InputLabel>
<Select <Select
value={filters.familyType} multiple
value={filters.family_type || []}
label="Family Type" label="Family Type"
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ familyType: e.target.value })); dispatch(updateFilter({ family_type: e.target.value }));
handleSelectionChange("Family Type", e.target.value); handleSelectionChange("Family Type", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.family_types?.find((t) => t.id === value)?.family_type_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ family_type: filters.family_type.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.family_types?.map((type) => (
<MenuItem value="Nuclear">Nuclear</MenuItem> <MenuItem key={type.id} value={type.id}>
<MenuItem value="Joint">Joint</MenuItem> {type.family_type_name}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
<FormControl fullWidth> </div>
<InputLabel>Family Status</InputLabel> </AccordionDetails>
<Select </Accordion>
value={filters.familyStatus}
label="Family Status"
onChange={(e) => {
dispatch(updateFilter({ familyStatus: e.target.value }));
handleSelectionChange("Family Status", e.target.value);
}}
>
<MenuItem value="Any">Any</MenuItem>
<MenuItem value="Middle Class">Middle Class</MenuItem>
<MenuItem value="Upper Middle Class">
Upper Middle Class
</MenuItem>
</Select>
</FormControl>
{/* Paid Membership Benefit Section */}
<Accordion
expanded={expandedSections.paidBenefit && filters.isPaidMember}
onChange={(e, isExpanded) => {
if (!filters.isPaidMember) {
toast.error("This feature is locked for paid members only", {
icon: "🔒",
});
return;
}
handleAccordionChange("paidBenefit")(e, isExpanded);
}}
className="mb-4"
>
<AccordionSummary
expandIcon={filters.isPaidMember ? <ChevronDown /> : <Lock size={18} className="text-gray-400" />}
sx={{
backgroundColor: "#f5fbff",
"&:hover": {
backgroundColor: "#fff6f0",
},
}}
>
<div className="flex items-center gap-2 -mx-4 -my-2 px-4 py-2 w-full">
<Crown size={20} className="text-yellow-600" />
<Typography className="font-semibold">
Paid Membership Benefit
</Typography>
</div>
</AccordionSummary>
<AccordionDetails>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4">
{/* Star Filter */}
<FormControl fullWidth> <FormControl fullWidth>
<InputLabel>Family Value</InputLabel> <InputLabel>Star</InputLabel>
<Select <Select
value={filters.familyValue} multiple
label="Family Value" value={filters.star || []}
label="Star"
disabled={!filters.isPaidMember}
onChange={(e) => { onChange={(e) => {
dispatch(updateFilter({ familyValue: e.target.value })); dispatch(updateFilter({ star: e.target.value }));
handleSelectionChange("Family Value", e.target.value); handleSelectionChange("Star", e.target.value);
}} }}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => {
const label = filterMasters?.stars?.find((s) => s.id === value)?.star_name || value;
return <Chip key={value} label={label} size="small" onDelete={() => dispatch(updateFilter({ star: filters.star.filter((v) => v !== value) }))} onMouseDown={(e) => e.stopPropagation()} />;
})}
</Box>
)}
> >
<MenuItem value="Any">Any</MenuItem> {filterMasters?.stars?.map((star) => (
<MenuItem value="Traditional">Traditional</MenuItem> <MenuItem key={star.id} value={star.id}>
<MenuItem value="Moderate">Moderate</MenuItem> {star.star_name}
<MenuItem value="Liberal">Liberal</MenuItem> </MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
</div> </div>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
{/* Submit Button */} {/* Sticky Footer Actions */}
<div className="mt-6 flex justify-center"> <div className="sticky bottom-0 bg-white p-4 border-t border-gray-200 flex justify-between gap-4 mt-4 z-10 shadow-[0_-4px_6px_-1px_rgba(0,0,0,0.1)]">
<Button
variant="outlined"
size="large"
onClick={handleClear}
className="px-8"
color="inherit"
startIcon={<RotateCcw size={20} />}
>
Clear Filters
</Button>
<Button <Button
variant="contained" variant="contained"
size="large" size="large"
onClick={handleSubmit} onClick={handleSubmit}
className="px-12" className="px-12"
startIcon={<Check size={20} />}
> >
Apply Filters Apply Filters
</Button> </Button>

View File

@ -27,7 +27,7 @@ const FilterModal = () => {
open={open} open={open}
onClose={handleClose} onClose={handleClose}
fullWidth fullWidth
maxWidth="lg" // adjust: "sm" | "md" | "lg" maxWidth="md" // adjust: "sm" | "md" | "lg"
> >
<DialogTitle sx={{background:"#f5fbff"}}> <DialogTitle sx={{background:"#f5fbff"}}>
<Box display="flex" alignItems="center" justifyContent="space-between"> <Box display="flex" alignItems="center" justifyContent="space-between">

View File

@ -16,6 +16,7 @@ import {
DialogContent, DialogContent,
DialogContentText, DialogContentText,
DialogActions, DialogActions,
Tooltip,
} from "@mui/material"; } from "@mui/material";
import { LocalizationProvider } from "@mui/x-date-pickers"; import { LocalizationProvider } from "@mui/x-date-pickers";
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { DatePicker } from "@mui/x-date-pickers/DatePicker";
@ -184,6 +185,7 @@ const LifestyleDetailsForm = ({
}; };
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]"> <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"> <span className="text-[10px] font-medium text-gray-700 text-center">
{label} {label}
@ -196,7 +198,17 @@ const LifestyleDetailsForm = ({
onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}
renderValue={(selected) => { renderValue={(selected) => {
if (!selected || selected.length === 0) return `+ Add ${label}`; if (!selected || selected.length === 0) return `+ Add ${label}`;
return selected.join(", "); return (
<div style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
maxWidth: "60px",
fontSize: "11px"
}}>
{selected.join(", ")}
</div>
);
}} }}
MenuProps={{ MenuProps={{
PaperProps: { style: { maxHeight: 280 } }, PaperProps: { style: { maxHeight: 280 } },
@ -211,6 +223,7 @@ const LifestyleDetailsForm = ({
</Select> </Select>
</FormControl> </FormControl>
</div> </div>
</Tooltip>
); );
const renderChartGrid = (type) => { const renderChartGrid = (type) => {

View File

@ -39,6 +39,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
const dispatch = useDispatch(); const dispatch = useDispatch();
const data = useSelector((state) => state.registerform.personalDetails); const data = useSelector((state) => state.registerform.personalDetails);
const nameInputRef = useRef(null); const nameInputRef = useRef(null);
const mobileInputRef = useRef(null);
const requiredMark = <span style={{ color: "#d32f2f" }}> *</span>; const requiredMark = <span style={{ color: "#d32f2f" }}> *</span>;
const [showOtp, setShowOtp] = useState(false); const [showOtp, setShowOtp] = useState(false);
@ -56,15 +57,23 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
if (isStep1Update && data.mobileNumber && !data.verifiedMobileNumber) { if (isStep1Update && data.mobileNumber && !data.verifiedMobileNumber) {
dispatch(updatePersonalDetails({ verifiedMobileNumber: data.mobileNumber })); dispatch(updatePersonalDetails({ verifiedMobileNumber: data.mobileNumber }));
setMobileOtpVerified(true); setMobileOtpVerified(true);
setMobileNumberError("");
} }
}, [isStep1Update, data.mobileNumber, data.verifiedMobileNumber, dispatch]); }, [isStep1Update, data.mobileNumber, data.verifiedMobileNumber, dispatch]);
useEffect(() => { useEffect(() => {
if (data.verifiedMobileNumber && data.mobileNumber === data.verifiedMobileNumber) { if (data.verifiedMobileNumber && data.mobileNumber === data.verifiedMobileNumber) {
setMobileOtpVerified(true); setMobileOtpVerified(true);
setMobileNumberError("");
} }
}, [data.verifiedMobileNumber, data.mobileNumber]); }, [data.verifiedMobileNumber, data.mobileNumber]);
useEffect(() => {
if (!isStep1Update && !data.religion) {
dispatch(updatePersonalDetails({ religion: 1 }));
}
}, [isStep1Update, data.religion, dispatch]);
const { data: personalMasters, isLoading: isPersonalMastersLoading } = const { data: personalMasters, isLoading: isPersonalMastersLoading } =
usePersonalDetailsMasters(); usePersonalDetailsMasters();
@ -120,7 +129,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
const raw = cityQuery.data; const raw = cityQuery.data;
if (!raw) return []; if (!raw) return [];
if (Array.isArray(raw)) return raw; if (Array.isArray(raw)) return raw;
return raw.subCaste || raw.district || raw.data || []; return raw.subCaste || raw.sub_caste || raw.district || raw.data || [];
}, [cityQuery.data]); }, [cityQuery.data]);
const starOptions = useMemo(() => { const starOptions = useMemo(() => {
@ -384,12 +393,6 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
} }
}; };
useEffect(() => {
if (showOtp && !mobileOtpVerified && isOtpComplete) {
handleOtpSubmit();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [otp]);
// file upload // file upload
@ -426,32 +429,31 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
const handleSubmit = async () => { const handleSubmit = async () => {
if (showOtp && !isOtpComplete) { // For new registrations, mobile verification is mandatory.
setOtpError("OTP is required and must be complete"); // For updates, it's also mandatory if the number was changed.
return; // The `mobileOtpVerified` state covers both scenarios.
} if (!mobileOtpVerified) {
// Provide a more specific error message.
if (showOtp && !mobileOtpVerified) { if (showOtp) {
try { if (!isOtpComplete) {
await verifyOtp.mutateAsync({ setOtpError("OTP is required and must be complete");
mobile: data.mobileNumber, } else {
otp: otp.join(""), setOtpError("Please submit the OTP to verify your number.");
}); }
setMobileOtpVerified(true); const firstOtpInput = document.getElementById("otp-0");
setOtpError(""); if (firstOtpInput) {
console.log("Submitting personal details:", data); // log here firstOtpInput.focus();
onSubmitStep(); }
console.log("OTP verified on submit"); } else {
} catch (err) { setMobileNumberError("Please verify your mobile number to proceed.");
setOtpError(err || "OTP verification failed"); if (mobileInputRef.current) {
mobileInputRef.current.focus();
}
}
return;
} }
return; onSubmitStep();
} };
// no OTP or already verified
console.log("Submitting personal details:", data); // log here
onSubmitStep();
};
const formatTimer = (sec) => { const formatTimer = (sec) => {
@ -532,6 +534,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
<Box sx={{ display: "flex", alignItems: "start", gap: 2 }}> <Box sx={{ display: "flex", alignItems: "start", gap: 2 }}>
<TextField <TextField
fullWidth fullWidth
inputRef={mobileInputRef}
name="mobileNumber" name="mobileNumber"
label="Mobile Number" label="Mobile Number"
type="tel" type="tel"
@ -629,15 +632,15 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
</Button> </Button>
</Box> </Box>
<Typography sx={{ ml: 2, minWidth: 56 }}> <Typography sx={{ ml: 0, minWidth: 56 }}>
{otpTimer > 0 ? ( {otpTimer > 0 ? (
` ${formatTimer(otpTimer) } Seconds` ` ${formatTimer(otpTimer) } Seconds`
) : ( ) : (
<button <button
component="button" type="button"
variant="body2"
onClick={handleMobileSubmit} onClick={handleMobileSubmit}
disabled={otpTimer > 0} disabled={otpTimer > 0}
style={{ background: "none", border: "none", padding: 0, textDecoration: "underline", cursor: "pointer", color: "inherit", font: "inherit" }}
> >
Resend OTP Resend OTP
</button> </button>
@ -712,6 +715,8 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
fullWidth fullWidth
name="height" name="height"
label="Enter Height" label="Enter Height"
max={3}
type="number" type="number"
value={data.height} value={data.height}
onChange={(e) => handleChange("height", e.target.value)} onChange={(e) => handleChange("height", e.target.value)}

View File

@ -233,8 +233,7 @@ const StepperForm = () => {
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const hideStepperRoutes = ["/profile-edit"]; const hideStepperRoutes = ["/profile-edit"];
const shouldHideStepper = hideStepperRoutes.some((route) => location.pathname.startsWith(route));
const shouldHideStepper = hideStepperRoutes.includes(location.pathname);
const personalDetails = useSelector( const personalDetails = useSelector(
(state) => state.registerform.personalDetails (state) => state.registerform.personalDetails
); );
@ -421,78 +420,84 @@ const [completedSteps, setCompletedSteps] = useState([]);
} }
}, [location.state, navigate, location.pathname]); }, [location.state, navigate, location.pathname]);
const { data: personalDetailsData } = useQuery({
queryKey: ["personalDetails"],
queryFn: async () => {
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_PERSONAL_DETAILS);
return response.data;
},
enabled: isAuth || shouldHideStepper,
retry: false,
refetchOnWindowFocus: false,
});
useEffect(() => { useEffect(() => {
if (!isAuth) return; const processData = async () => {
const fetchPersonalDetails = async () => { if (personalDetailsData?.status === "success" && personalDetailsData?.personal_details) {
try { const pd = personalDetailsData.personal_details;
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_PERSONAL_DETAILS); setIsStep1Update(true);
const data = response.data;
if (data.status === "success" && data.personal_details) {
const pd = data.personal_details;
setIsStep1Update(true);
const rawImages = pd.profile_images || pd.images || []; const rawImages = pd.profile_images || pd.images || [];
const mappedImages = await Promise.all( const mappedImages = await Promise.all(
rawImages.map(async (url, index) => { rawImages.map(async (url, index) => {
const imageUrl = typeof url === "string" ? url : url?.url; const imageUrl = typeof url === "string" ? url : url?.url;
let file = null; let file = null;
let mimeType = "image/jpeg"; let mimeType = "image/jpeg";
let fileName = `image-${index}.jpg`; let fileName = `image-${index}.jpg`;
try { try {
if (imageUrl) {
const response = await fetch(imageUrl); const response = await fetch(imageUrl);
const blob = await response.blob(); const blob = await response.blob();
if (blob.type) mimeType = blob.type; if (blob.type) mimeType = blob.type;
const ext = mimeType.split("/")[1] || "jpg"; const ext = mimeType.split("/")[1] || "jpg";
fileName = `image-${index}.${ext}`; fileName = `image-${index}.${ext}`;
file = new File([blob], fileName, { type: mimeType }); file = new File([blob], fileName, { type: mimeType });
} catch (error) {
console.error("Error converting image URL to File:", error);
} }
return { } catch (error) {
id: `server-${index}`, console.error("Error converting image URL to File:", error);
preview: imageUrl, }
imageUrl: imageUrl, return {
file: file, id: `server-${index}`,
name: fileName, preview: imageUrl,
type: mimeType, imageUrl: imageUrl,
valid: true, file: file,
}; name: fileName,
}) type: mimeType,
); valid: true,
};
})
);
const formattedDob = pd.dob ? pd.dob.split("T")[0] : ""; const formattedDob = pd.dob ? pd.dob.split("T")[0] : "";
dispatch( dispatch(
updatePersonalDetails({ updatePersonalDetails({
name: pd.name || "", name: pd.name || "",
mobileNumber: pd.mobile || "", mobileNumber: pd.mobile || "",
email: pd.email || "", email: pd.email || "",
gender: pd.gender || "", gender: pd.gender || "",
dob: formattedDob, dob: formattedDob,
height: pd.height || "", height: pd.height || "",
weight: pd.weight || "", weight: pd.weight || "",
maritalStatus: pd.marital_status_id || "", maritalStatus: pd.marital_status_id || "",
religion: pd.religion_id || "", religion: pd.religion_id || "",
profileFor: pd.profile_for_id || "", profileFor: pd.profile_for_id || "",
caste: pd.caste_id || "", caste: pd.caste_id || "",
subCaste: pd.sub_caste_id || "", subCaste: pd.sub_caste_id || "",
gothram: pd.gothram_id || "", gothram: pd.gothram_id || "",
raasi: pd.raasi_id || "", raasi: pd.raasi_id || "",
star: pd.star_id || "", star: pd.star_id || "",
state: pd.state_id || "", state: pd.state_id || "",
city: pd.district_id || "", city: pd.district_id || "",
pincode: pd.pincode || "", pincode: pd.pincode || "",
profiles: mappedImages, profiles: mappedImages,
}) })
); );
}
} catch (error) {
console.error("Error fetching personal details:", error);
} }
}; };
fetchPersonalDetails(); processData();
}, [dispatch, isAuth]); }, [personalDetailsData, dispatch]);
// Fetch Educational Details // Fetch Educational Details
@ -502,7 +507,7 @@ const [completedSteps, setCompletedSteps] = useState([]);
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_EDUCATION_DETAILS); const response = await axiosInstance.get(API_ENDPOINTS.EDIT_EDUCATION_DETAILS);
return response.data; return response.data;
}, },
enabled: isAuth, enabled: isAuth || shouldHideStepper,
retry: false, retry: false,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
}); });
@ -535,7 +540,7 @@ const {data:familyData} = useQuery({
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_FAMILY_DETAILS); const response = await axiosInstance.get(API_ENDPOINTS.EDIT_FAMILY_DETAILS);
return response.data; return response.data;
}, },
enabled: isAuth, enabled: isAuth || shouldHideStepper,
retry:false, retry:false,
refetchOnWindowFocus:false, refetchOnWindowFocus:false,
}); });
@ -584,9 +589,10 @@ useEffect(()=>{
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_LIFESTYLE_DETAILS); const response = await axiosInstance.get(API_ENDPOINTS.EDIT_LIFESTYLE_DETAILS);
return response.data; return response.data;
}, },
enabled: isAuth, enabled: isAuth || shouldHideStepper,
retry: false, retry: false,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchOnMount: true,
}); });
useEffect(() => { useEffect(() => {
@ -608,8 +614,8 @@ useEffect(()=>{
updateLifestyleDetails({ updateLifestyleDetails({
diets: ld.diet_id || "", diets: ld.diet_id || "",
hobbies: ld.hobbies_ids || [], hobbies: ld.hobbies_ids || [],
dob: ld.time_of_birth || "", dob: ld.time_of_birth ? ld.time_of_birth.split("T")[0] : "",
tob: ld.date_of_birth ? ld.date_of_birth.substring(0, 5) : "", tob: ld.time_of_birth_formated ? ld.time_of_birth_formated.substring(0, 5) : "",
placeOfBirth: ld.place_of_birth || "", placeOfBirth: ld.place_of_birth || "",
graha: mapChart("graha"), graha: mapChart("graha"),
amsam: mapChart("amsam"), amsam: mapChart("amsam"),
@ -626,7 +632,7 @@ useEffect(()=>{
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_PREFERED_PARTNER_DETAILS); const response = await axiosInstance.get(API_ENDPOINTS.EDIT_PREFERED_PARTNER_DETAILS);
return response.data; return response.data;
}, },
enabled: isAuth, enabled: isAuth || shouldHideStepper,
retry: false, retry: false,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
}); });
@ -878,6 +884,8 @@ useEffect(()=>{
if (fileToAppend) { if (fileToAppend) {
formData.append(`profile_images[${index}]`, fileToAppend); formData.append(`profile_images[${index}]`, fileToAppend);
} else if (item.preview && typeof item.preview === "string") {
formData.append(`profile_images[${index}]`, item.preview);
} }
}) })
); );
@ -932,7 +940,7 @@ useEffect(()=>{
formData.append("tob", lifestyleDetails.tob || ""); formData.append("tob", lifestyleDetails.tob || "");
formData.append("place_of_birth", lifestyleDetails.placeOfBirth || ""); formData.append("place_of_birth", lifestyleDetails.placeOfBirth || "");
formData.append("diet", lifestyleDetails.diets || ""); formData.append("diets", lifestyleDetails.diets || "");
(lifestyleDetails.hobbies || []).forEach((id, index) => { (lifestyleDetails.hobbies || []).forEach((id, index) => {
formData.append(`hobbies[${index}]`, id); formData.append(`hobbies[${index}]`, id);
@ -1022,6 +1030,9 @@ useEffect(()=>{
try { try {
const previewData = await getPreviewDetails(); const previewData = await getPreviewDetails();
queryClient.invalidateQueries({
queryKey: ["preview-details"]
});
if (previewData?.personal_details) { if (previewData?.personal_details) {
const pd = previewData.personal_details; const pd = previewData.personal_details;
const images = pd.images || pd.profile_images; const images = pd.images || pd.profile_images;
@ -1032,7 +1043,7 @@ useEffect(()=>{
dispatch(updatePersonalDetails({ profiles: formattedImages })); dispatch(updatePersonalDetails({ profiles: formattedImages }));
} }
} }
queryClient.invalidateQueries({ queryKey: ["previewDetails"] }); queryClient.invalidateQueries({ queryKey: ["personalDetails"] });
} catch (error) { } catch (error) {
console.error("Error refreshing preview details:", error); console.error("Error refreshing preview details:", error);
} }
@ -1047,21 +1058,29 @@ useEffect(()=>{
case 2: case 2:
payload = buildRegisterStep2Payload(); payload = buildRegisterStep2Payload();
await registerStep2.mutateAsync(payload); await registerStep2.mutateAsync(payload);
queryClient.invalidateQueries({ queryKey: ["educationalDetails"] });
queryClient.invalidateQueries({ queryKey: ["preview-details"] });
break; break;
case 3: case 3:
payload = buildRegisterStep3Payload(); payload = buildRegisterStep3Payload();
await registerStep3.mutateAsync(payload); await registerStep3.mutateAsync(payload);
queryClient.invalidateQueries({ queryKey: ["familyDetails"] })
queryClient.invalidateQueries({ queryKey: ["preview-details"] });
break; break;
case 4: case 4:
payload = buildRegisterStep4Payload(); payload = buildRegisterStep4Payload();
await registerStep4.mutateAsync(payload); await registerStep4.mutateAsync(payload);
queryClient.invalidateQueries({ queryKey: ["lifestyleDetails"] });
queryClient.invalidateQueries({ queryKey: ["preview-details"] });
break; break;
case 5: case 5:
payload = buildRegisterStep5Payload(); payload = buildRegisterStep5Payload();
await registerStep5.mutateAsync(payload); await registerStep5.mutateAsync(payload);
queryClient.invalidateQueries({ queryKey: ["partnerPreferences"] });
queryClient.invalidateQueries({ queryKey: ["preview-details"] });
break; break;
default: default:

15
src/hooks/useProfiles.js Normal file
View File

@ -0,0 +1,15 @@
import { useQuery } from "@tanstack/react-query";
import { getProfilesFilterList, getProfilesFilterMasters } from "../api/masters.api";
export const useProfiles = (filters) => {
return useQuery({
queryKey: ["profiles-filter-list", filters],
queryFn: () => getProfilesFilterList(filters),
});
};
export const useProfilesFilterMasters = () =>
useQuery({
queryKey: ["profiles-filter-masters"],
queryFn: getProfilesFilterMasters,
});

View File

@ -7,8 +7,9 @@ import { ThemeProvider } from "@mui/material/styles";
import theme from "./theme"; import theme from "./theme";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { store } from "./redux/store.js"; import { persistor, store } from "./redux/store.js";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { PersistGate } from "redux-persist/integration/react";
// Disable noisy logs in production while keeping warnings/errors. // Disable noisy logs in production while keeping warnings/errors.
if (import.meta.env.PROD) { if (import.meta.env.PROD) {
console.log = () => {}; console.log = () => {};
@ -29,12 +30,14 @@ const queryClient = new QueryClient({
ReactDOM.createRoot(document.getElementById("root")).render( ReactDOM.createRoot(document.getElementById("root")).render(
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<Provider store={store}> <Provider store={store}>
<QueryClientProvider client={queryClient}> <PersistGate loading={null} persistor={persistor}>
<App /> <QueryClientProvider client={queryClient}>
</QueryClientProvider> <App />
</QueryClientProvider>
</PersistGate>
</Provider> </Provider>
</ThemeProvider> </ThemeProvider>
); );

View File

@ -1,29 +1,26 @@
import { createSlice } from "@reduxjs/toolkit"; import { createSlice } from "@reduxjs/toolkit";
const initialState = { const initialState = {
age: [18, 70], from_age: 18,
height: [4.0, 7.11], to_age: 70,
maritalStatus: "All Profile", from_height: 4.0,
motherTongue: [], to_height: 7.11,
religion: "Hindu", marital_status: [],
matchesWithHoroscope: false, religion: [],
caste: [], caste: [],
subCaste: [], sub_caste: [],
star: "Any", star: [],
dasham: "Doesn't matter", occupation: [],
occupation: "Any", annual_income: [],
annualIncome: "Any", employee_type: [],
employeeType: "Any", education: [],
education: "Any", state: [],
state: "Any", district: [],
country: "Any", diet: "",
citizenship: "Any", family_type: [],
eatingHabits: "Any", filter_type: "all_matches",
smokingHabits: "Doesn't matter", page: 1,
drinkingHabits: "Doesn't matter", isPaidMember: false,
familyType: "Any",
familyStatus: "Any",
familyValue: "Any",
}; };
const filterSlice = createSlice({ const filterSlice = createSlice({
@ -31,73 +28,24 @@ const filterSlice = createSlice({
initialState, initialState,
reducers: { reducers: {
setAge: (state, action) => { setAge: (state, action) => {
state.age = action.payload; state.from_age = action.payload[0];
state.to_age = action.payload[1];
}, },
setHeight: (state, action) => { setHeight: (state, action) => {
state.height = action.payload; state.from_height = action.payload[0];
state.to_height = action.payload[1];
}, },
setMaritalStatus: (state, action) => { setMaritalStatus: (state, action) => {
state.maritalStatus = action.payload; state.marital_status = Array.isArray(action.payload) ? action.payload : [action.payload];
},
setMotherTongue: (state, action) => {
state.motherTongue = action.payload;
}, },
setReligion: (state, action) => { setReligion: (state, action) => {
state.religion = action.payload; state.religion = Array.isArray(action.payload) ? action.payload : [action.payload];
},
setMatchesWithHoroscope: (state, action) => {
state.matchesWithHoroscope = action.payload;
}, },
setCaste: (state, action) => { setCaste: (state, action) => {
state.caste = action.payload; state.caste = action.payload;
}, },
setSubCaste: (state, action) => { setSubCaste: (state, action) => {
state.subCaste = action.payload; state.sub_caste = action.payload;
},
setStar: (state, action) => {
state.star = action.payload;
},
setDasham: (state, action) => {
state.dasham = action.payload;
},
setOccupation: (state, action) => {
state.occupation = action.payload;
},
setAnnualIncome: (state, action) => {
state.annualIncome = action.payload;
},
setEmployeeType: (state, action) => {
state.employeeType = action.payload;
},
setEducation: (state, action) => {
state.education = action.payload;
},
setState: (state, action) => {
state.state = action.payload;
},
setCountry: (state, action) => {
state.country = action.payload;
},
setCitizenship: (state, action) => {
state.citizenship = action.payload;
},
setEatingHabits: (state, action) => {
state.eatingHabits = action.payload;
},
setSmokingHabits: (state, action) => {
state.smokingHabits = action.payload;
},
setDrinkingHabits: (state, action) => {
state.drinkingHabits = action.payload;
},
setFamilyType: (state, action) => {
state.familyType = action.payload;
},
setFamilyStatus: (state, action) => {
state.familyStatus = action.payload;
},
setFamilyValue: (state, action) => {
state.familyValue = action.payload;
}, },
// universal update // universal update
@ -105,7 +53,16 @@ const filterSlice = createSlice({
return { ...state, ...action.payload }; return { ...state, ...action.payload };
}, },
resetFilters: () => initialState, resetFilters: (state) => {
// Reset all filters but preserve the paid member status
return { ...initialState, isPaidMember: state.isPaidMember };
},
setPage: (state, action) => {
state.page = action.payload;
},
setPaidMemberStatus: (state, action) => {
state.isPaidMember = action.payload;
},
}, },
}); });
@ -113,28 +70,13 @@ export const {
setAge, setAge,
setHeight, setHeight,
setMaritalStatus, setMaritalStatus,
setMotherTongue,
setReligion, setReligion,
setMatchesWithHoroscope,
setCaste, setCaste,
setSubCaste, setSubCaste,
setStar,
setDasham,
setOccupation,
setAnnualIncome,
setEmployeeType,
setEducation,
setState,
setCountry,
setCitizenship,
setEatingHabits,
setSmokingHabits,
setDrinkingHabits,
setFamilyType,
setFamilyStatus,
setFamilyValue,
updateFilter, updateFilter,
resetFilters, resetFilters,
setPage,
setPaidMemberStatus,
} = filterSlice.actions; } = filterSlice.actions;
export default filterSlice.reducer; export default filterSlice.reducer;

View File

@ -1,9 +1,36 @@
import { configureStore } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit";
import registerformReducer from "./registrationFormSlice"; import registerformReducer from "./registrationFormSlice";
import filtersReducer from "./filterSlice"; import filtersReducer from "./filterSlice";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import storage from "redux-persist/lib/storage"; // defaults to localStorage for web
const persistConfig = {
key: "filters",
storage,
};
const persistedFiltersReducer = persistReducer(persistConfig, filtersReducer);
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
registerform:registerformReducer, registerform: registerformReducer,
filters:filtersReducer, filters: persistedFiltersReducer,
}, },
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
}); });
export const persistor = persistStore(store);