From 30bea864e5b897011f622b22f2aa5c3a49cb7832 Mon Sep 17 00:00:00 2001 From: MAGESHWARAN Date: Wed, 29 Apr 2026 10:56:58 +0530 Subject: [PATCH] Refine profile interaction logic, synchronize UI components, and update API request formatting to use FormData --- src/components/common/ProfileCardUI.jsx | 56 +- src/components/common/ProfileHeader.jsx | 8 +- .../profiledashboard/DailyRecommendedCard.jsx | 14 +- .../profiledetail/MatrimonyProfile.jsx | 1254 +++++++++++++---- .../profiledetail/PartnerPreferences.jsx | 24 +- src/pages/ProfileDetailPage.jsx | 25 +- src/services/shortlistapi.js | 38 +- 7 files changed, 1114 insertions(+), 305 deletions(-) diff --git a/src/components/common/ProfileCardUI.jsx b/src/components/common/ProfileCardUI.jsx index 84c65c9..9ea84fb 100644 --- a/src/components/common/ProfileCardUI.jsx +++ b/src/components/common/ProfileCardUI.jsx @@ -26,6 +26,7 @@ import { getHeaderDetails } from "../../api/preview.api"; export default function ProfileCardUI({ profile }) { const [isLiked, setIsLiked] = useState(false); const [isShortlisted, setIsShortlisted] = useState(profile.is_shortlisted === 1); + const [isLimitModalOpen, setIsLimitModalOpen] = useState(false); const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false); const [isViewContactModalOpen, setIsViewContactModalOpen] = useState(false); const [isInterestStatusModalOpen, setIsInterestStatusModalOpen] = useState(false); @@ -60,14 +61,19 @@ export default function ProfileCardUI({ profile }) { return; } try { - await axiosInstance.post(`${API_ENDPOINTS.INTEREST_SEND}?profile_id=${profile.id}`); + await sendInterest(profile.id); setIsLiked(true); toast.success(`Interest sent to ${profile.name}!`, { icon: '❤️', style: { borderRadius: '10px', background: '#333', color: '#fff' } }); } catch (error) { - toast.error("Failed to send interest."); + const msg = error.message || ""; + if (msg.toLowerCase().includes("limit") || msg.toLowerCase().includes("reached")) { + setIsLimitModalOpen(true); + } else { + toast.error(msg || "Failed to send interest"); + } } }; @@ -227,8 +233,8 @@ export default function ProfileCardUI({ profile }) { const handleShortlistClick = async (e) => { e.stopPropagation(); try { - const res = await axiosInstance.post(`${API_ENDPOINTS.SHORTLIST_API}?profile_id=${profile.id}`); - if (res.data?.status === "success") { + const res = await shortlistProfile(profile.id); + if (res.status === "success") { setIsShortlisted(!isShortlisted); toast.success(res.data.message || "Updated shortlist status"); } @@ -401,10 +407,12 @@ export default function ProfileCardUI({ profile }) { - + setIsLimitModalOpen(false)} + />
navigate(`/profile-details/${profile.id}`)} className="w-full max-w-sm rounded-[10px] shadow-xl overflow-hidden border border-green-200 bg-white cursor-pointer hover:shadow-2xl transition-all duration-300" > @@ -572,13 +580,41 @@ export default function ProfileCardUI({ profile }) { )}
- - - - ); } +const LimitReachedModal = ({ isOpen, onClose }) => { + if (!isOpen) return null; + return ( +
+ + +
+ +
+

Limit Reached!

+

+ You've reached your daily limit for sending interests. Please try again tomorrow or upgrade your plan for more daily connections! +

+ +
+
+ ); +}; diff --git a/src/components/common/ProfileHeader.jsx b/src/components/common/ProfileHeader.jsx index f916a23..002c476 100644 --- a/src/components/common/ProfileHeader.jsx +++ b/src/components/common/ProfileHeader.jsx @@ -439,14 +439,13 @@ const ProfileHeader = () => { return ( <> - + navigate("/")} sx={{ display: { xs: "none", md: "flex" }, mr: 1 }}> @@ -462,8 +461,7 @@ const ProfileHeader = () => { > diff --git a/src/components/profiledashboard/DailyRecommendedCard.jsx b/src/components/profiledashboard/DailyRecommendedCard.jsx index 72b4dc9..79a3420 100644 --- a/src/components/profiledashboard/DailyRecommendedCard.jsx +++ b/src/components/profiledashboard/DailyRecommendedCard.jsx @@ -7,6 +7,7 @@ import { useNavigate } from 'react-router-dom'; import { toast } from 'react-hot-toast'; import axiosInstance from "../../api/axiosInstance"; import { API_ENDPOINTS } from "../../api/apiEndpoints"; +import { sendInterest, shortlistProfile } from '../../services/shortlistapi'; import UpgradeModal from '../common/UpgradeModal'; // Custom Icons @@ -137,14 +138,19 @@ const DailyRecommendedCard = ({ profiles: initialProfiles = [] }) => { return; } try { - await axiosInstance.post(`${API_ENDPOINTS.INTEREST_SEND}?profile_id=${profileId}`); + await sendInterest(profileId); toast.success(`Interest sent to ${name}!`, { icon: '❤️', style: { borderRadius: '10px', background: '#333', color: '#fff' } }); setActiveProfiles(prev => prev.filter(p => p.id !== profileId)); } catch (error) { - toast.error("Failed to send interest. Please try again."); + const msg = error.message || ""; + if (msg.toLowerCase().includes("limit") || msg.toLowerCase().includes("reached")) { + setIsUpgradeModalOpen(true); + } else { + toast.error(msg || "Failed to send interest. Please try again."); + } } }; @@ -173,8 +179,8 @@ const DailyRecommendedCard = ({ profiles: initialProfiles = [] }) => { const handleShortlistClick = async (e) => { e.stopPropagation(); try { - const res = await axiosInstance.post(`${API_ENDPOINTS.SHORTLIST_API}?profile_id=${profile.id}`); - if (res.data?.status === "success") { + const res = await shortlistProfile(profile.id); + if (res.status === "success") { setIsShortlisted(!isShortlisted); toast.success(res.data.message || "Updated shortlist status"); } diff --git a/src/components/profiledetail/MatrimonyProfile.jsx b/src/components/profiledetail/MatrimonyProfile.jsx index 48b736b..dcfb087 100644 --- a/src/components/profiledetail/MatrimonyProfile.jsx +++ b/src/components/profiledetail/MatrimonyProfile.jsx @@ -8,7 +8,16 @@ import { Ban, Flag, ChevronLeft, + MapPin, + Shield, + Clock, + Lock, + User as UserIcon, + BookOpen, + Info, + Phone, } from "lucide-react"; +import { motion, AnimatePresence } from "framer-motion"; // Import Swiper React components and styles import { Swiper, SwiperSlide } from "swiper/react"; @@ -20,8 +29,14 @@ import "swiper/css/thumbs"; import { useNavigate } from "react-router-dom"; import { sendInterest, shortlistProfile } from "../../services/shortlistapi"; import { toast } from "react-hot-toast"; +import UpgradeModal from "../common/UpgradeModal"; +import axiosInstance, { apiForFiles } from "../../api/axiosInstance"; +import { API_ENDPOINTS } from "../../api/apiEndpoints"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; +import { getHeaderDetails } from "../../api/preview.api"; +import { sendMessage } from "../../services/chatApi"; -const MatrimonyProfile = ({ data }) => { +const MatrimonyProfile = ({ data, onRefresh }) => { const navigate = useNavigate(); const [isModalOpen, setIsModalOpen] = useState(false); const [showMenu, setShowMenu] = useState(false); @@ -41,21 +56,252 @@ const MatrimonyProfile = ({ data }) => { ? personal.images : [profile.profile_picture || "https://www.thirukalyanam.amrithaa.net/backend/app-assets/images/portrait/small/no-image.png"]; + const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false); + const [isViewContactModalOpen, setIsViewContactModalOpen] = useState(false); + const [isInterestStatusModalOpen, setIsInterestStatusModalOpen] = useState(false); + const [isInterestRejectedModalOpen, setIsInterestRejectedModalOpen] = useState(false); + const [isProtectionModalOpen, setIsProtectionModalOpen] = useState(false); + const [isContactSuccessModalOpen, setIsContactSuccessModalOpen] = useState(false); + const [unlockedMobile, setUnlockedMobile] = useState(null); + const [unlockedEmail, setUnlockedEmail] = useState(null); + const [isProcessing, setIsProcessing] = useState(false); + const [isChatConfirmModalOpen, setIsChatConfirmModalOpen] = useState(false); + const [isCreatingChat, setIsCreatingChat] = useState(false); + const [modalTitle, setModalTitle] = useState(""); + const [modalMessage, setModalMessage] = useState(""); + + const queryClient = useQueryClient(); + + const { data: headerData } = useQuery({ + queryKey: ["headerDetails"], + queryFn: getHeaderDetails, + staleTime: 60000, + }); + + const isUserPaid = headerData?.myDetails?.is_paid_member === true; + const openModal = (index) => { setIsModalOpen(true); setTimeout(() => { if (modalSwiperRef.current) { - modalSwiperRef.current.slideTo(index); + modalSwiperRef.current.slideTo(index, 0); } }, 100); }; - const handleSendInterest = async () => { + const _handleContactInteraction = async (type) => { + const value = type === 'mobile' ? profile.mobile : profile.email; + if (!value) return; + + const lowerValue = value.toLowerCase(); + const isUpgradeToView = lowerValue.includes("upgrade"); + const isViewContact = lowerValue.includes("view contact"); + + if (isUpgradeToView) { + setIsUpgradeModalOpen(true); + return; + } + + if (!isViewContact) return; + + // Protection logic + const isCallProtectionEnabled = profile.call_protection === 1; + + if (isCallProtectionEnabled) { + if (!profile.is_send_interest) { + setIsProtectionModalOpen(true); + } else { + const status = (profile.is_send_interest_status || "").toLowerCase(); + if (status === 'pending') { + setIsInterestStatusModalOpen(true); + } else if (status === 'reject' || status === 'rejected') { + setIsInterestRejectedModalOpen(true); + } else if (status === 'accept' || status === 'accepted') { + setIsViewContactModalOpen(true); + } + } + } else { + setIsViewContactModalOpen(true); + } + }; + + const _handleViewContact = async () => { + setIsViewContactModalOpen(false); + setIsProcessing(true); + try { + const formData = new FormData(); + formData.append("profile_id", profile.id); + const response = await apiForFiles.post(API_ENDPOINTS.VIEW_CONTACT, formData); + if (response.data?.status === 'success') { + const newMobile = response.data?.mobile_number || response.data?.mobile; + const newEmail = response.data?.email; + setUnlockedMobile(newMobile); + setUnlockedEmail(newEmail); + setIsContactSuccessModalOpen(true); + toast.success("Contact details unlocked!"); + if (onRefresh) onRefresh(false); + } else { + setIsUpgradeModalOpen(true); + } + } catch (error) { + toast.error("Failed to view contact"); + } finally { + setIsProcessing(false); + } + }; + + const _handleSendInterest = async () => { + setIsProtectionModalOpen(false); + setIsProcessing(true); try { const res = await sendInterest(profile.id); toast.success(res.message || "Interest sent successfully"); + // Ideally trigger a refresh of the profile data here + if (onRefresh) onRefresh(false); } catch (error) { - toast.error(error.message || "Failed to send interest"); + const msg = error.message || ""; + if (msg.toLowerCase().includes("limit") || msg.toLowerCase().includes("reached")) { + setIsUpgradeModalOpen(true); + } else { + toast.error(msg || "Failed to send interest"); + } + } finally { + setIsProcessing(false); + } + }; + + const handleSendInterest = async () => { + if (!isUserPaid) { + setIsUpgradeModalOpen(true); + return; + } + try { + const res = await sendInterest(profile.id); + toast.success(res.message || "Interest sent successfully"); + if (onRefresh) onRefresh(false); + queryClient.invalidateQueries(); + } catch (error) { + const msg = error.message || ""; + if (msg.toLowerCase().includes("limit") || msg.toLowerCase().includes("reached")) { + setIsUpgradeModalOpen(true); + } else { + toast.error(msg || "Failed to send interest"); + } + } + }; + + const handleCall = (e) => { + if (e) e.stopPropagation(); + if (!isUserPaid) { + setIsUpgradeModalOpen(true); + return; + } + + const interestStatus = (profile.is_send_interest_status || "").toLowerCase(); + + if (profile.call_protection === 1) { + if (profile.is_send_interest) { + if (interestStatus === 'pending') { + setModalTitle("Note"); + setModalMessage("An interest request has already been sent for this profile. Please wait for their response"); + setIsInterestStatusModalOpen(true); + return; + } else if (interestStatus === 'reject' || interestStatus === 'rejected') { + setIsInterestRejectedModalOpen(true); + return; + } + } + } + + _handleCallTap(); + }; + + const _handleCallTap = () => { + const currentMobile = unlockedMobile || profile.mobile || ""; + const mobile = currentMobile.toLowerCase(); + if (mobile.includes("upgrade to view")) { + setIsUpgradeModalOpen(true); + } else if (mobile.includes("view contact")) { + setIsViewContactModalOpen(true); + } else { + setUnlockedMobile(currentMobile); + setIsContactSuccessModalOpen(true); + } + }; + + const handleMessage = (e) => { + if (e) e.stopPropagation(); + + if (profile.chat_id) { + navigate(`/chat/${profile.chat_id}`); + return; + } + + if (!isUserPaid) { + setIsUpgradeModalOpen(true); + return; + } + + const interestStatus = (profile.is_send_interest_status || "").toLowerCase(); + + if (profile.chat_protection === 1 || profile.call_protection === 1) { + if (profile.is_send_interest) { + if (interestStatus === 'pending') { + setModalTitle("Note"); + setModalMessage("An interest request has already been sent for this profile. Please wait for their response"); + setIsInterestStatusModalOpen(true); + return; + } else if (interestStatus === 'reject' || interestStatus === 'rejected') { + setIsInterestRejectedModalOpen(true); + return; + } + } + } + + setIsChatConfirmModalOpen(true); + }; + + const _handleCreateChat = async () => { + if (isCreatingChat) return; + + setIsChatConfirmModalOpen(false); + setIsCreatingChat(true); + + try { + const response = await axiosInstance.post(API_ENDPOINTS.CHAT_CREATE, { profile_id: profile.id }); + + if (response.data?.status === true || response.data?.status === 'success') { + const newChatId = response.data?.chat_id; + + try { + await sendMessage(newChatId, "This profile has initiated a chat with you"); + } catch (msgErr) { + console.error("Error sending initial message:", msgErr); + } + + toast.success("Chat initiated!"); + navigate(`/chat/${newChatId}`); + queryClient.invalidateQueries(); + } else { + toast.error(response.data?.message || "Could not create chat."); + } + } catch (error) { + console.error("Error creating chat", error); + toast.error("Failed to start conversation"); + } finally { + setIsCreatingChat(false); + } + }; + + const handleDecline = async (e) => { + if (e) e.stopPropagation(); + try { + await axiosInstance.post(`${API_ENDPOINTS.UPDATE_INTEREST_STATUS}?profile_id=${profile.id}&status=reject`); + toast.success("Profile declined"); + if (onRefresh) onRefresh(false); + queryClient.invalidateQueries(); + } catch (error) { + toast.error("Failed to decline profile."); } }; @@ -63,11 +309,27 @@ const MatrimonyProfile = ({ data }) => { try { const res = await shortlistProfile(profile.id); toast.success(res.message || "Profile shortlisted successfully"); + if (onRefresh) onRefresh(false); } catch (error) { toast.error(error.message || "Failed to shortlist"); } }; + const _renderValue = (value) => { + if (!value) return "N/A"; + const strValue = String(value); + const isUpgrade = strValue.toLowerCase().includes("upgrade"); + + return ( + isUpgrade && setIsUpgradeModalOpen(true)} + > + {strValue} + + ); + }; + const safeVal = (val, key) => { if (typeof val === 'object' && val !== null) { return val[key] || "N/A"; @@ -76,10 +338,10 @@ const MatrimonyProfile = ({ data }) => { }; return ( -
+
{/* Image Section with Swiper */} @@ -218,18 +480,45 @@ const MatrimonyProfile = ({ data }) => {
{/* Action Buttons */} -
- - +
+ {profile.is_send_interest_received && profile.statusReceived?.toLowerCase() === 'pending' ? ( + <> + + + + ) : (!profile.is_send_interest && !profile.is_send_interest_received) ? ( + + ) : ( + <> + + + + )}
@@ -336,13 +625,6 @@ const MatrimonyProfile = ({ data }) => {
-

Like this member?

-
@@ -350,6 +632,26 @@ const MatrimonyProfile = ({ data }) => { )} + {/* About Me Section */} + {profile.about_me && ( +
+
+
+
+ +
+

About Me

+
+
+

+ {profile.about_me} +

+
+
+
+ )} + +
{/* Personal Information Section */}
@@ -363,96 +665,198 @@ const MatrimonyProfile = ({ data }) => {
-
- Name - : - {profile.name} -
-
- Gender - : - {personal.gender || profile.type || "N/A"} -
-
- Date of Birth - : - {personal.dob || profile.dob || "N/A"} -
-
- Place of Birth - : - {lifestyle.place_of_birth || personal.place_of_birth || profile.place_of_birth || "N/A"} -
-
- Time of Birth - : - {lifestyle.time_of_birth || personal.time_of_birth || "N/A"} -
-
- Height - : - {profile.height ? `${profile.height} ft` : "N/A"} -
-
- Weight - : - {profile.weight ? `${profile.weight} Kg` : "N/A"} -
-
- Religion - : - {personal.religion || safeVal(profile.religion, 'religion_name')} -
-
- Profile Created By - : - {personal.profile_for || safeVal(profile.profile_for, 'profile_for_name')} -
-
- Caste - : - {personal.caste || safeVal(profile.caste, 'caste_name')} -
-
- Sub Caste - : - {personal.sub_caste || safeVal(profile.sub_caste, 'sub_caste_name')} -
-
- Gothram - : - {personal.gothram || safeVal(profile.gothram, 'gothram_name')} -
-
- Rasi - : - {personal.raasi || safeVal(profile.raasi, 'raasi_name')} -
-
- Birth Star - : - {personal.star || safeVal(profile.star, 'star_name')} -
-
- Known Languages - : - {personal.known_languages || "N/A"} -
-
- Speaks Telugu - : - {personal.do_you_speak_telugu === 1 ? "Yes" : personal.do_you_speak_telugu === 0 ? "No" : "N/A"} -
-
- City - : - {personal.district || safeVal(profile.district, 'district_name') || "N/A"} -
-
- Pin Code - : - {personal.pincode || profile.zip || "N/A"} -
+ {/* Part 1 */} + {(personal.profile_for || safeVal(profile.profile_for, 'profile_for_name')) && ( +
+ Created For + : + {personal.profile_for || safeVal(profile.profile_for, 'profile_for_name')} +
+ )} + {(personal.gender || profile.type) && ( +
+ Gender + : + {personal.gender || profile.type} +
+ )} + {profile.name && ( +
+ Name + : + {profile.name} +
+ )} + {(personal.dob || profile.dob) && ( +
+ Date of Birth + : + {_renderValue(personal.dob || profile.dob)} +
+ )} + {(personal.dob || profile.dob) && ( +
+ Day of Birth + : + {(() => { + const dob = personal.dob || profile.dob; + if (!dob || dob.toLowerCase().includes("upgrade")) return _renderValue("Upgrade to view"); + const date = new Date(dob); + return {isNaN(date.getTime()) ? "N/A" : date.toLocaleDateString('en-US', { weekday: 'long' })}; + })()} +
+ )} + {(personal.marital_status || safeVal(profile.marital_status, 'marital_status_name')) && ( +
+ Marital Status + : + {personal.marital_status || safeVal(profile.marital_status, 'marital_status_name')} +
+ )} + {profile.height && ( +
+ Height + : + {profile.height} ft +
+ )} + {profile.weight && ( +
+ Weight + : + {profile.weight} Kg +
+ )} + {(personal.complexion || safeVal(profile.complexion, 'complexion_name')) && ( +
+ Complexion + : + {personal.complexion || safeVal(profile.complexion, 'complexion_name')} +
+ )} + {(personal.physical_status || safeVal(profile.physical_status, 'physical_status_name')) && ( +
+ Physical Status + : + {personal.physical_status || safeVal(profile.physical_status, 'physical_status_name')} +
+ )} + {(personal.religion || safeVal(profile.religion, 'religion_name')) && ( +
+ Religion + : + {personal.religion || safeVal(profile.religion, 'religion_name')} +
+ )} + {(personal.caste || safeVal(profile.caste, 'caste_name')) && ( +
+ Caste / Community + : + {personal.caste || safeVal(profile.caste, 'caste_name')} +
+ )} + {(personal.sub_caste || safeVal(profile.sub_caste, 'sub_caste_name')) && ( +
+ Sub-Sect (optional) + : + {personal.sub_caste || safeVal(profile.sub_caste, 'sub_caste_name')} +
+ )} + {(lifestyle.time_of_birth_formated || lifestyle.time_of_birth) && ( +
+ Time of Birth + : + {_renderValue(lifestyle.time_of_birth_formated || lifestyle.time_of_birth)} +
+ )} + {(lifestyle.place_of_birth || personal.place_of_birth || profile.place_of_birth) && ( +
+ Place of Birth + : + {_renderValue(lifestyle.place_of_birth || personal.place_of_birth || profile.place_of_birth)} +
+ )} + {(lifestyle.star_name || personal.star || safeVal(profile.star, 'star_name')) && ( +
+ Birth Star + : + {_renderValue(lifestyle.star_name || personal.star || safeVal(profile.star, 'star_name'))} +
+ )} + {(lifestyle.patham || profile.patham) && ( +
+ Padham + : + {_renderValue(lifestyle.patham || profile.patham)} +
+ )} + {(lifestyle.raasi_name || personal.raasi || safeVal(profile.raasi, 'raasi_name')) && ( +
+ Rasi + : + {_renderValue(lifestyle.raasi_name || personal.raasi || safeVal(profile.raasi, 'raasi_name'))} +
+ )} + {(lifestyle.lagnam_name || safeVal(profile.lagnam, 'lagnam_name')) && ( +
+ Lagnam + : + {_renderValue(lifestyle.lagnam_name || safeVal(profile.lagnam, 'lagnam_name'))} +
+ )} + {profile.willing_to_marry && ( +
+ Willing to marry from + : + {profile.willing_to_marry} +
+ )} + {(profile.inter_caste_parents === 1 || profile.inter_caste_parents === 0) && ( +
+ Inter-Caste Parents + : + {profile.inter_caste_parents === 1 ? "Yes" : "No"} +
+ )} + {profile.inter_caste_parents_details && ( +
+ Parents Details + : + {profile.inter_caste_parents_details} +
+ )} + +
+ + {/* Part 2 */} + {(personal.gothram || safeVal(profile.gothram, 'gothram_name')) && ( +
+ Gothram (optional) + : + {personal.gothram || safeVal(profile.gothram, 'gothram_name')} +
+ )} + {(profile.do_you_speak_telugu === true || profile.do_you_speak_telugu === false || profile.do_you_speak_telugu === 1 || profile.do_you_speak_telugu === 0) && ( +
+ Do you speak Telugu + : + {(profile.do_you_speak_telugu === true || profile.do_you_speak_telugu === 1) ? "Yes" : "No"} +
+ )} + {personal.known_languages && ( +
+ Language Spoken + : + {personal.known_languages} +
+ )} + {(personal.mother_language || safeVal(profile.mother_language, 'mother_language_name')) && ( +
+ Mother Tongue + : + {personal.mother_language || safeVal(profile.mother_language, 'mother_language_name')} +
+ )}
@@ -468,163 +872,523 @@ const MatrimonyProfile = ({ data }) => {
-
- Father Name - : - {family.father_name || profile.father_name || "N/A"} -
-
- Father Occupation - : - {family.father_occupation || profile.father_occupation || "N/A"} -
-
- Mother Name - : - {family.mother_name || profile.mother_name || "N/A"} -
-
- Mother Occupation - : - {family.mother_occupation || profile.mother_occupation || "N/A"} -
-
- Siblings - : - {family.brother_count || profile.brother_count} Brothers, {family.sister_count || profile.sister_count} Sisters -
-
- Family Type - : - {family.family_status || safeVal(profile.family_type, 'family_type_name') || "N/A"} -
-
- Settled - : - {family.settled || "N/A"} -
-
- Native Place - : - {family.native_place || profile.native_place || "N/A"} -
+ {(family.father_name || profile.father_name) && ( +
+ Father name + : + {_renderValue(family.father_name || profile.father_name)} +
+ )} + {(family.father_occupation || profile.father_occupation) && ( +
+ Father Occupation + : + {_renderValue(family.father_occupation || profile.father_occupation)} +
+ )} + {(family.mother_name || profile.mother_name) && ( +
+ Mother name + : + {_renderValue(family.mother_name || profile.mother_name)} +
+ )} + {(family.mother_occupation || profile.mother_occupation) && ( +
+ Mother Occupation + : + {_renderValue(family.mother_occupation || profile.mother_occupation)} +
+ )} + {(() => { + const b = family.brother_count || profile.brother_count || 0; + const s = family.sister_count || profile.sister_count || 0; + if (b === 0 && s === 0) return null; + const parts = []; + if (b > 0) parts.push(`${b < 10 ? '0' : ''}${b} Brother${b > 1 ? 's' : ''}`); + if (s > 0) parts.push(`${s < 10 ? '0' : ''}${s} Sister${s > 1 ? 's' : ''}`); + return ( +
+ Brothers / Sisters + : + {parts.join(", ")} +
+ ); + })()} + {(family.family_status || safeVal(profile.family_type, 'family_type_name')) && ( +
+ Family Status + : + {_renderValue(family.family_status || safeVal(profile.family_type, 'family_type_name'))} +
+ )} + {(family.native_place || profile.native_place) && ( +
+ Native Place + : + {_renderValue(family.native_place || profile.native_place)} +
+ )}
- {/* Lifestyle Section */}
- - - +
-

Lifestyle

+

Location & Living

+
+ +
+ {family.family_country_name && ( +
+ Country Living + : + {family.family_country_name} +
+ )} + {family.family_state_name && ( +
+ Residing State + : + {family.family_state_name} +
+ )} + {(family.family_city || family.family_district_name) && ( +
+ Residing City + : + {family.family_city || family.family_district_name} +
+ )} + {(family.address || profile.address) && ( +
+ Address + : + {family.address || profile.address} +
+ )} + {family.expectation_details && ( +
+ Expectations Details + : + {_renderValue(family.expectation_details)} +
+ )} + {family.willing_to_go_abroad && ( +
+ Willing to go abroad + : + {_renderValue(family.willing_to_go_abroad)} +
+ )} +
+
+ + + +
+
+
+ +
+

Contact Details

- Diet + Phone Number : - {lifestyle.diet || safeVal(profile.diet, 'diet_name')} -
-
- Place of Birth - : - {lifestyle.place_of_birth || personal.place_of_birth || profile.place_of_birth || "N/A"} -
-
- Time of Birth - : - {lifestyle.time_of_birth || personal.time_of_birth || "N/A"} -
-
- Panjangam Type - : - {lifestyle.panjangam_type || "N/A"} -
-
- Dasa Balance - : - {lifestyle.dasa_balance || "N/A"} -
-
- Dasa Period - : - - {lifestyle.dasa_years || "0"} Years, {lifestyle.dasa_months || "0"} Months, {lifestyle.dasa_days || "0"} Days + _handleContactInteraction('mobile')} + > + {unlockedMobile || profile.mobile || "N/A"}
- Age + Email : - {(personal.age || profile.age || lifestyle.age) ? `${personal.age || profile.age || lifestyle.age} Years` : "N/A"} -
-
- Hobbies - : - - {lifestyle.hobbies && lifestyle.hobbies.length > 0 ? lifestyle.hobbies.join(", ") : "N/A"} + _handleContactInteraction('email')} + > + {unlockedEmail || profile.email || "N/A"}
- - {/* Educational Details Section */} -
-
-
- - - + {/* Educational & Professional Section */} +
+
+
+ +
+

Educational & Professional

+
+ +
+ {(education.education || safeVal(profile.education, 'education_name')) && ( +
+ Highest Qualification + : + {_renderValue(education.education || safeVal(profile.education, 'education_name'))} +
+ )} + {(education.study_field || safeVal(profile.study_field, 'study_field_name')) && ( +
+ Field of Study + : + {_renderValue(education.study_field || safeVal(profile.study_field, 'study_field_name'))} +
+ )} + {(profile.college_name || education.college_name) && ( +
+ College Name + : + {_renderValue(profile.college_name || education.college_name)} +
+ )} + {(education.employee_type || safeVal(profile.employee_type, 'employee_type_name')) && ( +
+ Employee type + : + {_renderValue(education.employee_type || safeVal(profile.employee_type, 'employee_type_name'))} +
+ )} + {(education.occupation || safeVal(profile.occupation, 'occupation_name')) && ( +
+ Occupation + : + {_renderValue(education.occupation || safeVal(profile.occupation, 'occupation_name'))} +
+ )} + {profile.occupation_details && ( +
+ Occupation Details + : + {profile.occupation_details} +
+ )} + {(education.company_name || profile.company_name) && ( +
+ Organization Name + : + {_renderValue(education.company_name || profile.company_name)} +
+ )} + {(profile.income_currency || education.income_currency) && ( +
+ Income Currency Type + : + {_renderValue(profile.income_currency || education.income_currency)} +
+ )} + {(education.annual_income || safeVal(profile.annual_income, 'annual_income_name')) && ( +
+ Annual Income + : + {_renderValue(education.annual_income || safeVal(profile.annual_income, 'annual_income_name'))} +
+ )}
-

Educational Details

-
-
- Highest Qualification - : - {education.education || safeVal(profile.education, 'education_name')} + {/* Work Location Section */} +
+
+
+ +
+

Work Location

-
- Field of Study - : - {education.study_field || safeVal(profile.study_field, 'study_field_name')} -
-
- College Name - : - {profile.college_name || education.college_name || "N/A"} -
-
- Occupation - : - {education.occupation || safeVal(profile.occupation, 'occupation_name')} -
-
- Organization Name - : - {education.company_name || profile.company_name || "N/A"} -
-
- Employee Type - : - {education.employee_type || safeVal(profile.employee_type, 'employee_type_name')} -
-
- Annual Income - : - {education.annual_income || safeVal(profile.annual_income, 'annual_income_name')} -
-
- Work Location - : - {profile.work_location || education.work_location || "N/A"} + +
+ {(education.work_country_name || profile.work_country_name) && ( +
+ Country + : + {education.work_country_name || profile.work_country_name} +
+ )} + {(education.work_state_name || profile.work_state_name) && ( +
+ State + : + {education.work_state_name || profile.work_state_name} +
+ )} + {(education.work_city || education.work_district_name || profile.work_city || profile.work_district_name) && ( +
+ City + : + {education.work_city || education.work_district_name || profile.work_city || profile.work_district_name} +
+ )} + {(education.work_location || profile.work_location) && ( +
+ Address + : + {education.work_location || profile.work_location} +
+ )}
-
+ {/* Modals */} + setIsUpgradeModalOpen(false)} + z={9999} + /> + + + {/* Protection Modal */} + {isProtectionModalOpen && ( +
+ +
+ +
+

Note

+

+ This user has enabled call protection. Please send a request to access their contact details. +

+
+ + +
+
+
+ )} + + {/* View Contact Confirmation Modal */} + {isViewContactModalOpen && ( +
+ + +

Note

+

+ You need to view this profile's contact details. If you choose to "Proceed" one count will be deducted from your subscription. +

+
+ + +
+
+
+ )} + + {/* Interest Status Modal (Pending) */} + {isInterestStatusModalOpen && ( +
+ +
+ +
+

Note

+

+ An interest request has already been sent for this profile. Please wait for their response. +

+ +
+
+ )} + + {/* Interest Rejected Modal */} + {isInterestRejectedModalOpen && ( +
+ +
+ +
+

Request Rejected

+

+ Your interest request was declined. You cannot view the contact details for this profile. +

+ +
+
+ )} + {/* Contact Success Modal */} + {isContactSuccessModalOpen && ( +
+ +
+ +
+

Success!

+

The contact details have been unlocked.

+ +
+ {(() => { + const mobile = unlockedMobile || (profile.mobile && !profile.mobile.toLowerCase().includes("view") ? profile.mobile : null); + if (!mobile) return null; + return ( +
+ Mobile + {mobile} +
+ ); + })()} + + {(() => { + const email = unlockedEmail || (profile.email && !profile.email.toLowerCase().includes("view") ? profile.email : null); + if (!email) return null; + return ( +
+ Email + {email} +
+ ); + })()} +
+ +
+ + {(() => { + const finalMobile = unlockedMobile || (profile.mobile && !profile.mobile.toLowerCase().includes("view") ? profile.mobile : null); + if (!finalMobile) return null; + return ( + + ); + })()} +
+
+
+ )} + {/* Chat Confirmation Modal */} + {isChatConfirmModalOpen && (() => { + const currentMobile = unlockedMobile || profile.mobile || ""; + const mobileLower = currentMobile.toLowerCase(); + const isMobileVisible = currentMobile !== "" && + !mobileLower.includes("upgrade") && + !mobileLower.includes("view contact"); + + return ( +
+ + +

+ {isMobileVisible ? "Ready to Chat?" : "Note"} +

+

+ {isMobileVisible + ? <>Are you ready to chat with {currentMobile}? + : <>Starting a conversation will use 1 chat count. Are you ready to proceed?} +

+
+ + +
+
+
+ ); + })()} +
+
); }; diff --git a/src/components/profiledetail/PartnerPreferences.jsx b/src/components/profiledetail/PartnerPreferences.jsx index 237d940..38691b0 100644 --- a/src/components/profiledetail/PartnerPreferences.jsx +++ b/src/components/profiledetail/PartnerPreferences.jsx @@ -81,26 +81,14 @@ const PartnerPreferences = ({ data }) => {
-
- {/* Basic Preferences Section */} -
-
-

Basic Preferences

-
-
- {basicPreferences.map((pref, index) => ( - - ))} -
-
- - {/* Other Preferences Section */} -
-
-

Professional & Location

+
+ {/* Partner Preferences Section */} +
+
+

Partner Preference Details

- {religiousPreferences.map((pref, index) => ( + {[...basicPreferences, ...religiousPreferences].map((pref, index) => ( ))}
diff --git a/src/pages/ProfileDetailPage.jsx b/src/pages/ProfileDetailPage.jsx index aa8c914..388c93b 100644 --- a/src/pages/ProfileDetailPage.jsx +++ b/src/pages/ProfileDetailPage.jsx @@ -11,18 +11,19 @@ const ProfileDetailPage = () => { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); + const fetchDetail = async (showLoading = true) => { + if (showLoading) setLoading(true); + try { + const res = await getProfileDetail(id); + setData(res); + } catch (error) { + console.error("Failed to fetch profile details:", error); + } finally { + if (showLoading) setLoading(false); + } + }; + useEffect(() => { - const fetchDetail = async () => { - setLoading(true); - try { - const res = await getProfileDetail(id); - setData(res); - } catch (error) { - console.error("Failed to fetch profile details:", error); - } finally { - setLoading(false); - } - }; if (id) { fetchDetail(); } @@ -47,7 +48,7 @@ const ProfileDetailPage = () => { return ( <>
- +
diff --git a/src/services/shortlistapi.js b/src/services/shortlistapi.js index 5351bc1..bf2af8f 100644 --- a/src/services/shortlistapi.js +++ b/src/services/shortlistapi.js @@ -1,22 +1,38 @@ -import axiosInstance from "../api/axiosInstance"; +import axiosInstance, { apiForFiles } from "../api/axiosInstance"; import { API_ENDPOINTS } from "../api/apiEndpoints"; export const shortlistProfile = async (profileId) => { - const response = await axiosInstance.post(`${API_ENDPOINTS.SHORTLIST_API}?profile_id=${profileId}`); - if (response.data?.status === "error") { - throw new Error(response.data.message || "Failed to shortlist"); + try { + const formData = new FormData(); + formData.append("profile_id", profileId); + const response = await apiForFiles.post(API_ENDPOINTS.SHORTLIST_API, formData); + if (response.data?.status === "error") { + throw new Error(response.data.message || "Failed to shortlist"); + } + return response.data; + } catch (error) { + const message = error.response?.data?.message || error.message || "Failed to shortlist"; + throw new Error(message); } - return response.data; }; export const sendInterest = async (profileId) => { - const response = await axiosInstance.post(`interest_send`, { - profile_id: profileId // ✅ sent in request body - }); - if (response.data?.status === "error") { - throw new Error(response.data.message || "Failed to send interest"); + try { + const formData = new FormData(); + formData.append("profile_id", profileId); + + // Using apiForFiles which is pre-configured for multipart/form-data + // This is more robust for PHP backends expecting form data + const response = await apiForFiles.post(API_ENDPOINTS.INTEREST_SEND, formData); + + if (response.data?.status === "error") { + throw new Error(response.data.message || "Failed to send interest"); + } + return response.data; + } catch (error) { + const message = error.response?.data?.message || error.message || "Failed to send interest"; + throw new Error(message); } - return response.data; }; export const declineProfile = async (profileId) => {