You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

778 lines
30 KiB

"use client";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { useHabibWebReady } from "@/hooks/use-habib-web-ready";
import AdvisorActionsCard from "@/components/Componentes/advisor-actions-card";
import MarriageAdvisorsOverlay, {
useMarriageAdvisorsOverlay,
} from "@/components/Componentes/marriage-advisors-overlay";
import MatchProfileOverlay, {
useMatchProfileOverlay,
} from "@/components/Componentes/match-profile-overlay";
import CallResultSheet from "@/components/Componentes/call-result-sheet";
import DismissReasonSheet from "@/components/Componentes/dismiss-reason-sheet";
import FemaleConsentSheet from "@/components/Componentes/female-consent-sheet";
import FemaleOutcomeSheet from "@/components/Componentes/female-outcome-sheet";
import { LoadingThreeDot } from "@/components/Componentes/loading-three-dot";
import OutcomeSelectionSheet from "@/components/Componentes/outcome-selection-sheet";
import { PageBackground } from "@/components/Componentes/page-background";
import PageHeader from "@/components/Componentes/page-header";
import { PageLoadingSkeleton } from "@/components/Componentes/page-loading-skeleton";
import SubscriptionRequiredSheet from "@/components/Componentes/subscription-required-sheet";
import SwipeButton from "@/components/Componentes/swipe-button";
import type {
MarriageField,
MarriagePhoneFieldValue,
} from "@/hooks/marriage/types";
import { useMarriageContactInfoQuery } from "@/hooks/marriage/use-contact-info";
import {
useSubmitMarriageContactStatusMutation,
useSubmitMarriageOutcomeMutation,
} from "@/hooks/marriage/use-contact-status";
import {
extractHabcoinPaymentUrl,
useHabcoinPaymentMutation,
} from "@/hooks/marriage/use-habcoin-payment";
import { useMarriageProfileQuery } from "@/hooks/marriage/use-profile-main";
import { getSubmitPath } from "@/lib/get-submit-path";
import { localizePath } from "@/translations/config";
import { useI18n } from "@/translations/provider";
const advisorAvatars = [
{ id: "advisor-primary", src: "/assets/images/Avatar Image.png" },
{ id: "advisor-secondary", src: "/assets/images/Ellipse 370.png" },
{ id: "advisor-tertiary", src: "/assets/images/Avatar Image.png" },
];
type ContactInfoPhoneItem = {
key: string;
label: string;
phoneNumber: string;
};
function sanitizePhoneNumber(value: MarriageField["value"]) {
if (value === null || value === "") {
return null;
}
if (isMarriagePhoneFieldValue(value)) {
const digits = value.phoneNumber.replace(/\D/g, "");
return digits ? `+${value.countryCode}${digits}` : null;
}
const trimmedValue = String(value).trim();
if (!trimmedValue) {
return null;
}
const digits = trimmedValue.replace(/\D/g, "");
if (!digits) {
return null;
}
return trimmedValue.startsWith("+") ? `+${digits}` : digits;
}
function isMarriagePhoneFieldValue(
value: unknown,
): value is MarriagePhoneFieldValue {
if (!value || typeof value !== "object") {
return false;
}
const phoneValue = value as Partial<MarriagePhoneFieldValue>;
return (
typeof phoneValue.countryCode === "string" &&
typeof phoneValue.phoneNumber === "string"
);
}
function getContactInfoPhoneItems(
contactInfoFields: MarriageField[] | null | undefined,
): ContactInfoPhoneItem[] {
if (!contactInfoFields) {
return [];
}
return contactInfoFields
.map((field) => {
const phoneNumber = sanitizePhoneNumber(field.value);
if (!phoneNumber) {
return null;
}
const rawLabel = field.label || field.key;
const label = rawLabel
.replace(/\s+with\s+Country\s+Code/gi, "")
.replace(/\s+با\s+کد\s+کشور/g, "")
.trim();
return {
key: field.key,
label,
phoneNumber,
};
})
.filter((item): item is ContactInfoPhoneItem => item !== null);
}
function ContactInfoPhoneCard({ item }: { item: ContactInfoPhoneItem }) {
return (
<div className="flex items-center justify-between rounded-[15px] border border-[#E4E4E4] bg-[#FBFBFB] px-4 py-3.5 shadow-[0_4px_12px_rgba(0,0,0,0.03)] gap-4">
<div className="text-left min-w-0">
<p className="text-xs font-semibold text-[#8F8F8F] break-words">
{item.label}
</p>
<p className="text-base font-bold text-[#1F1F1F] dir-ltr">
{item.phoneNumber}
</p>
</div>
<div className="flex items-center gap-2 shrink-0">
<a
href={`tel:${item.phoneNumber}`}
onClick={(e) => {
if (typeof window !== "undefined" && "HabibApp" in window) {
e.preventDefault();
try {
const app = (
window as Window & {
HabibApp?: { postMessage: (msg: string) => void };
}
).HabibApp;
app?.postMessage(
JSON.stringify({
action: "open_external_url",
data: {
url: `tel:${item.phoneNumber}`,
mode: "externalApplication",
title: "phone_call",
},
}),
);
} catch (err) {
console.error("Error calling HabibApp bridge", err);
}
}
}}
className="inline-flex p-3 items-center justify-center rounded-[10px] bg-[#F0445B] text-white shrink-0"
>
<Image
src={"/assets/images/Vecfdastor.svg"}
width={16}
height={16}
alt="call"
/>
</a>
</div>
</div>
);
}
export default function RequestAcceptedClient() {
const { dictionary: t, locale } = useI18n();
const router = useRouter();
const { isAdvisorOpen, openAdvisors, closeAdvisors } =
useMarriageAdvisorsOverlay();
const { isProfileOpen, openProfile, closeProfile } =
useMatchProfileOverlay();
const [isCallResultSheetOpen, setIsCallResultSheetOpen] = useState(false);
const [isDismissReasonSheetOpen, setIsDismissReasonSheetOpen] =
useState(false);
const [isContactInfoSheetOpen, setIsContactInfoSheetOpen] = useState(false);
const [isSubscriptionSheetOpen, setIsSubscriptionSheetOpen] = useState(false);
const [paymentError, setPaymentError] = useState<string | null>(null);
const [isInsufficientCoins, setIsInsufficientCoins] = useState(false);
const [isOutcomeSheetOpen, setIsOutcomeSheetOpen] = useState(false);
const [isNoContactConfirmOpen, setIsNoContactConfirmOpen] = useState(false);
const [isContactReceivedConfirmOpen, setIsContactReceivedConfirmOpen] =
useState(false);
const [noContactReportedSuccess, setNoContactReportedSuccess] =
useState(false);
const [hasConfirmedFemaleContact, setHasConfirmedFemaleContact] =
useState(false);
const profileHref = localizePath("/new-match/profile", locale);
const { data: profile, isLoading } = useMarriageProfileQuery({
refetchInterval: 3000,
});
const isFemaleProfile = profile?.gender === "female";
const contactSharedAtStr = profile?.active_case?.contact_shared_at;
useEffect(() => {
if (!profile || noContactReportedSuccess) {
return;
}
const targetPath = getSubmitPath(profile);
if (targetPath !== "/request-accepted") {
router.replace(localizePath(targetPath, locale));
}
}, [profile, router, locale, noContactReportedSuccess]);
// Signal Flutter to lift its loading cover once the profile is available.
useHabibWebReady(!!profile && !isLoading);
const isRedirecting = useMemo(() => {
if (!profile) return false;
return getSubmitPath(profile) !== "/request-accepted";
}, [profile]);
const caseId = profile?.active_case?.case_id;
const caseStatus = profile?.active_case?.status;
const isFemaleContactConfirmed =
isFemaleProfile &&
(caseStatus === "contacted" || hasConfirmedFemaleContact);
const recommendedPlanId = profile?.recommended_plan?.id;
const paymentMutation = useHabcoinPaymentMutation();
const outcomeMutation = useSubmitMarriageOutcomeMutation(caseId ?? "");
const contactStatusMutation = useSubmitMarriageContactStatusMutation(
caseId ?? "",
{
onSuccess: (_data, variables) => {
if (variables?.action === "no_contact") {
setNoContactReportedSuccess(true);
} else {
if (!isFemaleProfile) {
router.push(localizePath("/finding-match", locale));
}
}
},
},
);
const contactInfoQuery = useMarriageContactInfoQuery(caseId, {
enabled: false,
});
if (isLoading || isRedirecting) {
return <PageLoadingSkeleton />;
}
const titleText = isFemaleProfile
? t["Request Approved"]
: caseStatus === "payment_done" || caseStatus === "contacted"
? t["Contact info released"]
: t["Request approved!"];
const primaryActionText = isFemaleProfile
? t["No Contact Received"]
: t["View profile"];
const secondaryActionText = isFemaleProfile
? t["Contact Received"]
: caseStatus === "payment_done" || caseStatus === "contacted"
? t["Contact"]
: t["Pay and get contact"];
const contactInfoPhoneItems = getContactInfoPhoneItems(
contactInfoQuery.data?.contact_info,
);
const handleSecondaryAction = async () => {
if (isFemaleProfile) {
setIsContactReceivedConfirmOpen(true);
return;
}
if (caseStatus === "female_accepted" || caseStatus === "payment_pending") {
setIsSubscriptionSheetOpen(true);
return;
}
if (caseStatus === "payment_done" || caseStatus === "contacted") {
if (!caseId) {
return;
}
if (!contactInfoQuery.data) {
await contactInfoQuery.refetch();
}
setIsContactInfoSheetOpen(true);
}
};
const handlePayment = async () => {
if (!recommendedPlanId || paymentMutation.isPending) {
return;
}
try {
setPaymentError(null);
setIsInsufficientCoins(false);
const paymentResponse =
await paymentMutation.mutateAsync(recommendedPlanId);
const paymentUrl = extractHabcoinPaymentUrl(paymentResponse);
if (paymentUrl) {
window.location.assign(paymentUrl);
return;
}
setIsSubscriptionSheetOpen(false);
if (caseId) {
await contactInfoQuery.refetch();
setIsContactInfoSheetOpen(true);
}
} catch (err: any) {
console.error("Habcoin payment request failed", err);
const msg =
err?.response?.data?.error || err?.message || "Payment failed";
if (msg === "Not enough coins") {
setIsInsufficientCoins(true);
setPaymentError(
t["Insufficient coin balance. Please recharge your account."] ||
"Insufficient coin balance. Please recharge your account.",
);
} else {
setPaymentError(msg);
}
}
};
const handleNoContactReport = async () => {
if (!caseId || contactStatusMutation.isPending) return;
await contactStatusMutation.mutateAsync({
action: "no_contact",
custom_note:
"No contact reported by female candidate after decision window",
});
};
const isFinalized =
caseStatus === "finalized" || profile?.status === "matched";
return (
<>
<PageBackground />
{isCallResultSheetOpen ? (
<CallResultSheet
onClose={() => setIsCallResultSheetOpen(false)}
onOtherReasonsClick={() => setIsDismissReasonSheetOpen(true)}
onSubmit={async (value) => {
if (caseId) {
await contactStatusMutation.mutateAsync({
action: "contacted",
custom_note: value,
});
}
}}
/>
) : null}
{isContactReceivedConfirmOpen ? (
<FemaleConsentSheet
title={t.Confirm}
description={
<p className="font-bold text-[#00AC78] text-center my-4 text-base">
{t["Are you sure contact has been made?"]}
</p>
}
buttons={
<SwipeButton
theme="green"
text={t["Confirm"]}
onCancel={() => setIsContactReceivedConfirmOpen(false)}
onSuccess={async () => {
setIsContactReceivedConfirmOpen(false);
setHasConfirmedFemaleContact(true);
if (!caseId) {
return;
}
try {
await contactStatusMutation.mutateAsync({
action: "contacted",
custom_note:
"Contact received confirmed by female candidate",
});
} catch (error) {
// The confirmation screen must advance immediately after a swipe.
// Keep the local state visible while the profile query retries.
console.error("Unable to persist received contact", error);
}
}}
/>
}
onClose={() => setIsContactReceivedConfirmOpen(false)}
closeOnOutside={true}
/>
) : null}
{isDismissReasonSheetOpen ? (
<DismissReasonSheet
onClose={() => setIsDismissReasonSheetOpen(false)}
onSubmit={async (value) => {
if (caseId) {
await outcomeMutation.mutateAsync({
status: "failure",
custom_note: value,
});
}
}}
/>
) : null}
{isOutcomeSheetOpen ? (
isFemaleProfile ? (
<FemaleOutcomeSheet
onClose={() => setIsOutcomeSheetOpen(false)}
onSubmit={async (status, reason) => {
if (status === "success") {
// If they confirm they are in the acquaintance/proposal process and nothing is finalized yet:
// No change is made to the profile, we just close the sheet.
setIsOutcomeSheetOpen(false);
} else {
// If they cancel:
if (caseId) {
await outcomeMutation.mutateAsync({
status: "failure",
custom_note: reason,
});
}
}
}}
/>
) : (
<OutcomeSelectionSheet
onClose={() => setIsOutcomeSheetOpen(false)}
onSubmit={async (status) => {
if (status === "success") {
if (caseId) {
await outcomeMutation.mutateAsync({
status: "success",
});
}
} else {
setIsDismissReasonSheetOpen(true);
}
}}
/>
)
) : null}
{isContactInfoSheetOpen ? (
<FemaleConsentSheet
title={t["Contact Detail"]}
description={
t[
"Please mention during the call that you were introduced by the Habib Marriage app."
]
}
buttons={
contactInfoPhoneItems.length ? (
<div className="space-y-4">
{contactInfoPhoneItems.map((item) => (
<ContactInfoPhoneCard key={item.key} item={item} />
))}
</div>
) : (
<div className="rounded-[12px] bg-[#ECECEC] px-4 py-3 group-12 font-semibold text-[#555]">
{t["Contact information is not available yet."]}
</div>
)
}
onClose={() => setIsContactInfoSheetOpen(false)}
/>
) : null}
{isSubscriptionSheetOpen ? (
<SubscriptionRequiredSheet
onClose={() => {
setIsSubscriptionSheetOpen(false);
setPaymentError(null);
setIsInsufficientCoins(false);
}}
onPayment={handlePayment}
isPaymentPending={!recommendedPlanId || paymentMutation.isPending}
errorMessage={paymentError}
showBuyCoins={isInsufficientCoins}
/>
) : null}
{isNoContactConfirmOpen ? (
<FemaleConsentSheet
title={t.Confirm}
description={
<p className="font-bold text-[#E03950] text-center my-4 text-base">
{
t[
"No contact has been made with you in any way or by any party."
]
}
</p>
}
buttons={
<button
type="button"
onClick={async () => {
setIsNoContactConfirmOpen(false);
await handleNoContactReport();
}}
className="w-full h-[48px] rounded-[15px] bg-[#E03950] text-white font-semibold group-14 flex items-center justify-center transition-transform active:scale-[0.98] cursor-pointer hover:opacity-95"
>
{t.Confirm}
</button>
}
onClose={() => setIsNoContactConfirmOpen(false)}
closeOnOutside={true}
/>
) : null}
<main className="-mx-[17px] flex min-h-screen flex-col px-[23px] pt-[max(12px,calc(var(--safe-top)+4px))] pb-[calc(20px+var(--safe-bottom))] text-center">
<PageHeader className="-mx-[6px]" profile={profile} />
<div className="flex flex-1 flex-col justify-between gap-6 pt-4">
<section className="flex flex-col items-center">
{isFinalized ? (
<div className="flex flex-col items-center max-w-[320px] text-center my-auto py-12">
<div className="relative flex items-center justify-center text-[70px] animate-bounce">
🎉
</div>
<h1 className="mt-8 text-center text-[24px] leading-[1.25] font-bold text-[#E03950]">
{t["Congratulations! 🎉"]}
</h1>
<p className="mt-6 text-[#4A4A4A] group-14 font-medium leading-relaxed">
{
t[
"Wishing you a lifetime of love, joy, and happiness. Your profile has been successfully closed."
]
}
</p>
</div>
) : (
<>
{/* Illustration */}
<div className="relative mt-6 flex items-center justify-center">
{/* soft glow */}
<div className="absolute h-[115px] w-[115px] rounded-full bg-[#FF5C7D]/10 blur-xl" />
<div className="relative z-10">
<Image
src="/assets/images/Group 15978804fdasf68.svg"
alt={t["Request accepted"]}
width={131}
height={125}
priority
/>
</div>
</div>
<h1 className="mt-8 text-[20px] leading-none font-black tracking-[0.03em] text-[#171717] uppercase">
{titleText}
</h1>
{caseStatus === "contacted" ||
isFemaleContactConfirmed ||
(isFemaleProfile && contactStatusMutation.isPending) ? (
<div className="w-full border border-[#E2E8F0] bg-white/90 backdrop-blur-sm rounded-[20px] mt-6 px-5 py-4 text-center shadow-sm max-w-[340px] flex flex-col items-center justify-center min-h-[90px]">
{isFemaleProfile && contactStatusMutation.isPending ? (
<LoadingThreeDot className="text-[#E03950]" />
) : (
<p className="text-[#475569] text-[14px] font-medium leading-relaxed">
{isFemaleProfile
? t[
"Thank you for your feedback. To complete the process, please submit the final outcome of this introduction/contact so that the final status can be determined. If the final status is not yet determined, you can stay in this state until it is finalized."
]
: t[
"Thank you for giving us feedback, we would be very happy if you also let us know the final result."
]}
</p>
)}
</div>
) : (
<p className="mt-5 max-w-[340px] text-[15px] leading-[1.6] font-medium text-[#777777]">
{noContactReportedSuccess
? t[
"Thank you for your feedback. Our support team will investigate the matter and notify you of the result. Please wait patiently during the review; our support will contact you."
]
: isFemaleProfile
? t[
"The selected candidate will contact your family shortly."
]
: t[
"You can now view their family's contact details and arrange further steps."
]}
</p>
)}
<>
{caseStatus === "contacted" ||
isFemaleContactConfirmed ||
(isFemaleProfile && contactStatusMutation.isPending) ? (
<div className="flex mt-8 w-full gap-3 justify-center max-w-[350px] mx-auto">
{isFemaleProfile &&
contactStatusMutation.isPending ? null : isFemaleProfile ? (
<button
type="button"
onClick={() => setIsOutcomeSheetOpen(true)}
disabled={outcomeMutation.isPending}
className="w-full h-[50px] px-6 rounded-full bg-gradient-to-r from-[#FF6687] to-[#FF456C] text-white font-bold text-[15px] flex items-center justify-center shadow-sm transition-transform active:scale-[0.98] cursor-pointer hover:opacity-95 disabled:opacity-50"
>
{outcomeMutation.isPending ? (
<LoadingThreeDot className="text-white" />
) : (
t["Share Result"]
)}
</button>
) : (
<>
<button
type="button"
onClick={() => openProfile()}
className="flex-1 h-[50px] px-3 rounded-full border border-[#E2E8F0] bg-white/95 backdrop-blur-sm text-[#334155] font-bold text-[14px] shadow-sm flex items-center justify-center transition-transform active:scale-[0.98] cursor-pointer hover:bg-[#F8FAFC]"
>
{t["View Profile"]}
</button>
<button
type="button"
onClick={() => setIsOutcomeSheetOpen(true)}
disabled={outcomeMutation.isPending}
className="flex-1 h-[50px] px-3 rounded-full bg-gradient-to-r from-[#FF6687] to-[#FF456C] text-white font-bold text-[14px] flex items-center justify-center shadow-sm transition-transform active:scale-[0.98] cursor-pointer hover:opacity-95 disabled:opacity-50"
>
{outcomeMutation.isPending ? (
<LoadingThreeDot className="text-white" />
) : (
t["Submit Final Outcome"]
)}
</button>
</>
)}
</div>
) : (
<div className="flex mt-8 w-full justify-center gap-3.5 max-w-[360px] mx-auto">
{isFemaleProfile ? (
<button
type="button"
onClick={() => setIsNoContactConfirmOpen(true)}
disabled={
contactStatusMutation.isPending ||
noContactReportedSuccess
}
className="flex-1 min-h-[48px] px-3.5 py-2.5 rounded-full border border-[#E2E8F0] bg-white/95 backdrop-blur-sm text-[#475569] font-bold text-[13.5px] leading-tight shadow-sm flex items-center justify-center text-center transition-all cursor-pointer hover:bg-[#F8FAFC] active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed"
>
{contactStatusMutation.isPending ? (
<LoadingThreeDot />
) : (
primaryActionText
)}
</button>
) : (
<Link
href={profileHref}
className="flex-1 max-w-[170px]"
>
<div className="w-full min-h-[48px] px-3.5 py-2.5 rounded-full border border-[#E2E8F0] bg-white/95 backdrop-blur-sm text-[#475569] font-bold text-[14px] leading-tight shadow-sm flex items-center justify-center text-center whitespace-nowrap transition-all hover:bg-[#F8FAFC] active:scale-[0.98]">
{primaryActionText}
</div>
</Link>
)}
<button
type="button"
onClick={() => {
void handleSecondaryAction();
}}
disabled={paymentMutation.isPending}
className={
isFemaleProfile
? "flex-1 min-h-[48px] px-3.5 py-2.5 rounded-full bg-gradient-to-r from-[#FF6687] to-[#FF456C] text-white font-bold text-[13.5px] leading-tight flex items-center justify-center text-center whitespace-nowrap shadow-sm transition-all cursor-pointer hover:opacity-95 active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed"
: "flex-1 max-w-[170px] min-h-[48px] appearance-none border-0 bg-transparent p-0 text-center cursor-pointer transition-transform active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed"
}
>
{isFemaleProfile ? (
paymentMutation.isPending ? (
<LoadingThreeDot className="text-white" />
) : (
secondaryActionText
)
) : (
<div className="w-full h-full min-h-[48px] px-3.5 py-2.5 rounded-full bg-gradient-to-r from-[#FF6687] to-[#FF456C] text-white font-bold text-[14px] leading-tight flex items-center justify-center text-center whitespace-nowrap shadow-sm hover:opacity-95">
{paymentMutation.isPending ? (
<LoadingThreeDot className="text-white" />
) : (
secondaryActionText
)}
</div>
)}
</button>
</div>
)}
{caseStatus !== "contacted" &&
!isFemaleContactConfirmed &&
!noContactReportedSuccess &&
!(isFemaleProfile && contactStatusMutation.isPending) ? (
<div className="border border-[#FDA4AF]/60 bg-[#FFF1F2]/80 backdrop-blur-sm rounded-[16px] mt-6 p-4 max-w-[360px] shadow-sm">
<p className="text-[#BE123C] text-[12px] font-medium leading-[1.65] whitespace-pre-line text-justify">
{
t[
"Please be informed that from the time of this introduction, you have 48 hours (2 days) to contact the person or their respected family to declare your readiness and begin the acquaintance process. At this stage, merely an initial call to announce your presence is sufficient, and planning for further steps (such as an in-person meeting) depends entirely on your subsequent mutual agreements. Since failing to make contact within the specified time might be considered socially disrespectful, if no action is taken within these 2 days, the introduced match will be removed according to the platform's rules. We also remind you that this issue may lead to restrictions such as delays in future introductions and financial penalties."
]
}
</p>
</div>
) : null}
</>
</>
)}
</section>
<div className="space-y-8 pb-20">
{/* Advisor section */}
<AdvisorActionsCard
title={t["Get an advisor"]}
description={
t[
"Not sure what to do next? Our psychology section is here to guide you at every step."
]
}
avatars={advisorAvatars}
extraCount={7}
getAdvisorLabel={t["Get Advisor"]}
onGetAdvisor={openAdvisors}
/>
<section className="pointer-events-none fixed bottom-0 left-1/2 z-20 w-full sm:max-w-[375px] -translate-x-1/2 bg-[#F5F5F5]">
<div
style={{ paddingBottom: "calc(20px + var(--safe-bottom))" }}
className="pointer-events-auto px-[17px] pt-3"
>
<div className="flex items-center justify-center w-full gap-1 rounded-[11px] bg-[#DBDBDB] py-3.5">
<Image
src="/assets/images/material-symbols_lock.svg"
width={24}
height={24}
alt="lock"
/>
<h2 className="group-14 leading-none font-semibold text-[#747474]">
{t["Profile is locked"]}
</h2>
</div>
</div>
</section>
</div>
</div>
</main>
<MarriageAdvisorsOverlay
open={isAdvisorOpen}
onClose={closeAdvisors}
/>
<MatchProfileOverlay
open={isProfileOpen}
onClose={closeProfile}
/>
</>
);
}