filter master integrate
This commit is contained in:
parent
5392a4211e
commit
9427677a72
88
package-lock.json
generated
88
package-lock.json
generated
@ -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",
|
||||||
|
|||||||
@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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",
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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;
|
||||||
|
};
|
||||||
97
src/components/common/VirtualizedSelect.jsx
Normal file
97
src/components/common/VirtualizedSelect.jsx
Normal 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
|
||||||
@ -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">
|
||||||
|
<div className="relative cursor-pointer" onClick={() => {
|
||||||
|
if (isPaidMember) {
|
||||||
|
navigate("/horoscoper-generate");
|
||||||
|
} else {
|
||||||
|
toast.error("Star Matching is locked for free members");
|
||||||
|
}
|
||||||
|
}}>
|
||||||
<img
|
<img
|
||||||
src={horoscope}
|
src={horoscope}
|
||||||
onClick={() => {
|
className={!isPaidMember ? "opacity-50 blur-[1px]" : ""}
|
||||||
navigate("/horoscoper-generate");
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
{!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>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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}
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl fullWidth>
|
|
||||||
<InputLabel>Family Status</InputLabel>
|
|
||||||
<Select
|
|
||||||
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>
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl fullWidth>
|
</div>
|
||||||
<InputLabel>Family Value</InputLabel>
|
</AccordionDetails>
|
||||||
<Select
|
</Accordion>
|
||||||
value={filters.familyValue}
|
|
||||||
label="Family Value"
|
{/* Paid Membership Benefit Section */}
|
||||||
onChange={(e) => {
|
<Accordion
|
||||||
dispatch(updateFilter({ familyValue: e.target.value }));
|
expanded={expandedSections.paidBenefit && filters.isPaidMember}
|
||||||
handleSelectionChange("Family Value", e.target.value);
|
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",
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value="Any">Any</MenuItem>
|
<div className="flex items-center gap-2 -mx-4 -my-2 px-4 py-2 w-full">
|
||||||
<MenuItem value="Traditional">Traditional</MenuItem>
|
<Crown size={20} className="text-yellow-600" />
|
||||||
<MenuItem value="Moderate">Moderate</MenuItem>
|
<Typography className="font-semibold">
|
||||||
<MenuItem value="Liberal">Liberal</MenuItem>
|
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>
|
||||||
|
<InputLabel>Star</InputLabel>
|
||||||
|
<Select
|
||||||
|
multiple
|
||||||
|
value={filters.star || []}
|
||||||
|
label="Star"
|
||||||
|
disabled={!filters.isPaidMember}
|
||||||
|
onChange={(e) => {
|
||||||
|
dispatch(updateFilter({ star: 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>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{filterMasters?.stars?.map((star) => (
|
||||||
|
<MenuItem key={star.id} value={star.id}>
|
||||||
|
{star.star_name}
|
||||||
|
</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>
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -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) => {
|
||||||
|
|||||||
@ -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,30 +429,29 @@ const PersonalDetailsForm = ({ onSubmitStep, errors, onFieldChange, isStep1Updat
|
|||||||
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (showOtp && !isOtpComplete) {
|
// For new registrations, mobile verification is mandatory.
|
||||||
|
// For updates, it's also mandatory if the number was changed.
|
||||||
|
// The `mobileOtpVerified` state covers both scenarios.
|
||||||
|
if (!mobileOtpVerified) {
|
||||||
|
// Provide a more specific error message.
|
||||||
|
if (showOtp) {
|
||||||
|
if (!isOtpComplete) {
|
||||||
setOtpError("OTP is required and must be complete");
|
setOtpError("OTP is required and must be complete");
|
||||||
return;
|
} else {
|
||||||
|
setOtpError("Please submit the OTP to verify your number.");
|
||||||
|
}
|
||||||
|
const firstOtpInput = document.getElementById("otp-0");
|
||||||
|
if (firstOtpInput) {
|
||||||
|
firstOtpInput.focus();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setMobileNumberError("Please verify your mobile number to proceed.");
|
||||||
|
if (mobileInputRef.current) {
|
||||||
|
mobileInputRef.current.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showOtp && !mobileOtpVerified) {
|
|
||||||
try {
|
|
||||||
await verifyOtp.mutateAsync({
|
|
||||||
mobile: data.mobileNumber,
|
|
||||||
otp: otp.join(""),
|
|
||||||
});
|
|
||||||
setMobileOtpVerified(true);
|
|
||||||
setOtpError("");
|
|
||||||
console.log("Submitting personal details:", data); // log here
|
|
||||||
onSubmitStep();
|
|
||||||
console.log("OTP verified on submit");
|
|
||||||
} catch (err) {
|
|
||||||
setOtpError(err || "OTP verification failed");
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no OTP or already verified
|
|
||||||
console.log("Submitting personal details:", data); // log here
|
|
||||||
onSubmitStep();
|
onSubmitStep();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -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)}
|
||||||
|
|||||||
@ -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,14 +420,21 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
|||||||
}
|
}
|
||||||
}, [location.state, navigate, location.pathname]);
|
}, [location.state, navigate, location.pathname]);
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: personalDetailsData } = useQuery({
|
||||||
if (!isAuth) return;
|
queryKey: ["personalDetails"],
|
||||||
const fetchPersonalDetails = async () => {
|
queryFn: async () => {
|
||||||
try {
|
|
||||||
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_PERSONAL_DETAILS);
|
const response = await axiosInstance.get(API_ENDPOINTS.EDIT_PERSONAL_DETAILS);
|
||||||
const data = response.data;
|
return response.data;
|
||||||
if (data.status === "success" && data.personal_details) {
|
},
|
||||||
const pd = data.personal_details;
|
enabled: isAuth || shouldHideStepper,
|
||||||
|
retry: false,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const processData = async () => {
|
||||||
|
if (personalDetailsData?.status === "success" && personalDetailsData?.personal_details) {
|
||||||
|
const pd = personalDetailsData.personal_details;
|
||||||
setIsStep1Update(true);
|
setIsStep1Update(true);
|
||||||
|
|
||||||
const rawImages = pd.profile_images || pd.images || [];
|
const rawImages = pd.profile_images || pd.images || [];
|
||||||
@ -440,12 +446,14 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
|||||||
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) {
|
} catch (error) {
|
||||||
console.error("Error converting image URL to File:", error);
|
console.error("Error converting image URL to File:", error);
|
||||||
}
|
}
|
||||||
@ -487,12 +495,9 @@ const [completedSteps, setCompletedSteps] = useState([]);
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} 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
15
src/hooks/useProfiles.js
Normal 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,
|
||||||
|
});
|
||||||
@ -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 = () => {};
|
||||||
@ -31,9 +32,11 @@ ReactDOM.createRoot(document.getElementById("root")).render(
|
|||||||
|
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
|
<PersistGate loading={null} persistor={persistor}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<App />
|
<App />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
</PersistGate>
|
||||||
</Provider>
|
</Provider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user