Browse Source

refactor: standardize profile opening flow using async refetching and replace deprecated useEffect-based logic across match modules

master
mortezaei 2 weeks ago
parent
commit
a99a66d801
  1. 63
      src/app/new-match/new-match-client.tsx
  2. 2
      src/app/new-match/profile/page.tsx
  3. 38
      src/app/request-accepted/request-accepted-client.tsx
  4. 33
      src/app/request-sent/request-sent-client.tsx

63
src/app/new-match/new-match-client.tsx

@ -488,9 +488,15 @@ export default function NewMatchClient() {
const { isAdvisorOpen, openAdvisors, closeAdvisors } = const { isAdvisorOpen, openAdvisors, closeAdvisors } =
useMarriageAdvisorsOverlay(); useMarriageAdvisorsOverlay();
const { isProfileOpen, openProfile, closeProfile } = useMatchProfileOverlay(); const { isProfileOpen, openProfile, closeProfile } = useMatchProfileOverlay();
const {
data: profile,
isError,
isLoading,
isFetched,
isFetching,
refetch: refetchProfile,
} = useMarriageProfileQuery();
const [isOpeningProfile, setIsOpeningProfile] = useState(false); const [isOpeningProfile, setIsOpeningProfile] = useState(false);
const { data: profile, isError, isLoading, isFetched } =
useMarriageProfileQuery();
const [isPaymentSheetOpen, setIsPaymentSheetOpen] = useState(false); const [isPaymentSheetOpen, setIsPaymentSheetOpen] = useState(false);
const [isDeclineConfirmOpen, setIsDeclineConfirmOpen] = useState(false); const [isDeclineConfirmOpen, setIsDeclineConfirmOpen] = useState(false);
const [paymentError, setPaymentError] = useState<string | null>(null); const [paymentError, setPaymentError] = useState<string | null>(null);
@ -608,20 +614,43 @@ export default function NewMatchClient() {
// Signal Flutter to lift its loading cover immediately with 0ms latency. // Signal Flutter to lift its loading cover immediately with 0ms latency.
useHabibWebReady(true); useHabibWebReady(true);
const handleOpenProfile = () => {
if (profile) {
openProfile();
} else {
const handleOpenProfile = async () => {
// If profile has not yet completed its initial server fetch or is in flight:
if (!isFetched || isFetching) {
setIsOpeningProfile(true); setIsOpeningProfile(true);
try {
const result = await refetchProfile();
const freshProfile = result.data ?? profile;
setIsOpeningProfile(false);
const isMaleUser = freshProfile?.gender === "male";
const hasActiveSubscription =
!!freshProfile?.active_subscription &&
freshProfile.active_subscription.is_active !== false &&
freshProfile.active_subscription.is_valid !== false;
if (isMaleUser && !hasActiveSubscription) {
setIsPaymentSheetOpen(true);
} else {
openProfile();
}
} catch (err) {
setIsOpeningProfile(false);
if (isMale && !hasActiveSub) {
setIsPaymentSheetOpen(true);
} else {
openProfile();
}
}
return;
} }
};
useEffect(() => {
if (isOpeningProfile && profile) {
setIsOpeningProfile(false);
if (isMale && !hasActiveSub) {
setIsPaymentSheetOpen(true);
} else {
openProfile(); openProfile();
} }
}, [isOpeningProfile, profile, openProfile]);
};
const isRedirecting = useMemo(() => { const isRedirecting = useMemo(() => {
if (!profile) return false; if (!profile) return false;
@ -835,14 +864,8 @@ export default function NewMatchClient() {
{/* Button */} {/* Button */}
<button <button
type="button" type="button"
disabled={isOpeningProfile && isLoading}
onClick={() => {
if (isMale && !hasActiveSub) {
setIsPaymentSheetOpen(true);
} else {
handleOpenProfile();
}
}}
disabled={isOpeningProfile}
onClick={handleOpenProfile}
className=" className="
mt-2.5 mt-2.5
flex flex
@ -863,7 +886,7 @@ export default function NewMatchClient() {
border-none border-none
" "
> >
{isOpeningProfile && isLoading ? (
{isOpeningProfile ? (
<LoadingThreeDot /> <LoadingThreeDot />
) : ( ) : (
<> <>

2
src/app/new-match/profile/page.tsx

@ -688,7 +688,7 @@ export default function NewMatchProfilePage({
<MatchPublicProfileFields <MatchPublicProfileFields
publicInfo={profile?.match_summary?.public_info} publicInfo={profile?.match_summary?.public_info}
isCandidateFemale={true}
isCandidateFemale={isCandidateFemale}
dictionary={t} dictionary={t}
/> />
</section> </section>

38
src/app/request-accepted/request-accepted-client.tsx

@ -241,9 +241,14 @@ export default function RequestAcceptedClient() {
useState(false); useState(false);
const [hasConfirmedFemaleContact, setHasConfirmedFemaleContact] = const [hasConfirmedFemaleContact, setHasConfirmedFemaleContact] =
useState(false); useState(false);
const [showPaymentSuccessToast, setShowPaymentSuccessToast] = useState(false);
const [isOpeningProfile, setIsOpeningProfile] = useState(false); const [isOpeningProfile, setIsOpeningProfile] = useState(false);
const { data: profile, isLoading, isFetched } = useMarriageProfileQuery();
const {
data: profile,
isLoading,
isFetched,
isFetching,
refetch: refetchProfile,
} = useMarriageProfileQuery();
const isFemaleProfile = profile?.gender === "female"; const isFemaleProfile = profile?.gender === "female";
const contactSharedAtStr = profile?.active_case?.contact_shared_at; const contactSharedAtStr = profile?.active_case?.contact_shared_at;
@ -264,21 +269,20 @@ export default function RequestAcceptedClient() {
// Signal Flutter to lift its loading cover immediately with 0ms latency. // Signal Flutter to lift its loading cover immediately with 0ms latency.
useHabibWebReady(true); useHabibWebReady(true);
const handleOpenProfile = () => {
if (profile) {
openProfile();
} else {
const handleOpenProfile = async () => {
if (!isFetched || isFetching) {
setIsOpeningProfile(true); setIsOpeningProfile(true);
try {
await refetchProfile();
} finally {
setIsOpeningProfile(false);
openProfile();
}
return;
} }
openProfile();
}; };
useEffect(() => {
if (isOpeningProfile && profile) {
setIsOpeningProfile(false);
openProfile();
}
}, [isOpeningProfile, profile, openProfile]);
const isRedirecting = useMemo(() => { const isRedirecting = useMemo(() => {
if (!profile) return false; if (!profile) return false;
return getSubmitPath(profile) !== "/request-accepted"; return getSubmitPath(profile) !== "/request-accepted";
@ -706,11 +710,11 @@ export default function RequestAcceptedClient() {
<> <>
<button <button
type="button" type="button"
disabled={isOpeningProfile && isLoading}
disabled={isOpeningProfile}
onClick={handleOpenProfile} onClick={handleOpenProfile}
className="flex-1 h-[50px] px-3 rounded-[14px] 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]" className="flex-1 h-[50px] px-3 rounded-[14px] 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]"
> >
{isOpeningProfile && isLoading ? (
{isOpeningProfile ? (
<LoadingThreeDot /> <LoadingThreeDot />
) : ( ) : (
t["View Profile"] t["View Profile"]
@ -753,11 +757,11 @@ export default function RequestAcceptedClient() {
) : ( ) : (
<button <button
type="button" type="button"
disabled={isOpeningProfile && isLoading}
disabled={isOpeningProfile}
onClick={handleOpenProfile} onClick={handleOpenProfile}
className="flex-1 min-h-[48px] px-3.5 py-2.5 rounded-[14px] 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] cursor-pointer" className="flex-1 min-h-[48px] px-3.5 py-2.5 rounded-[14px] 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] cursor-pointer"
> >
{isOpeningProfile && isLoading ? (
{isOpeningProfile ? (
<LoadingThreeDot /> <LoadingThreeDot />
) : ( ) : (
primaryActionText primaryActionText

33
src/app/request-sent/request-sent-client.tsx

@ -34,7 +34,13 @@ export default function RequestSentClient() {
const { isProfileOpen, openProfile, closeProfile } = const { isProfileOpen, openProfile, closeProfile } =
useMatchProfileOverlay(); useMatchProfileOverlay();
const [isOpeningProfile, setIsOpeningProfile] = useState(false); const [isOpeningProfile, setIsOpeningProfile] = useState(false);
const { data: profile, isLoading, isFetched } = useMarriageProfileQuery({
const {
data: profile,
isLoading,
isFetched,
isFetching,
refetch: refetchProfile,
} = useMarriageProfileQuery({
refetchInterval: 3000, refetchInterval: 3000,
}); });
@ -59,21 +65,20 @@ export default function RequestSentClient() {
return getSubmitPath(profile) !== "/request-sent"; return getSubmitPath(profile) !== "/request-sent";
}, [profile]); }, [profile]);
const handleOpenProfile = () => {
if (profile) {
openProfile();
} else {
const handleOpenProfile = async () => {
if (!isFetched || isFetching) {
setIsOpeningProfile(true); setIsOpeningProfile(true);
try {
await refetchProfile();
} finally {
setIsOpeningProfile(false);
openProfile();
}
return;
} }
openProfile();
}; };
useEffect(() => {
if (isOpeningProfile && profile) {
setIsOpeningProfile(false);
openProfile();
}
}, [isOpeningProfile, profile, openProfile]);
const copy = { const copy = {
advisorTitle: t["Get an advisor"], advisorTitle: t["Get an advisor"],
advisorDescription: advisorDescription:
@ -138,12 +143,12 @@ export default function RequestSentClient() {
{/* Button */} {/* Button */}
<button <button
type="button" type="button"
disabled={isOpeningProfile && isLoading}
disabled={isOpeningProfile}
onClick={handleOpenProfile} onClick={handleOpenProfile}
className="mt-12 w-full max-w-[300px] cursor-pointer transition-transform active:scale-[0.97]" className="mt-12 w-full max-w-[300px] cursor-pointer transition-transform active:scale-[0.97]"
> >
<div className="flex items-center justify-center min-h-[54px] rounded-[14px] bg-gradient-to-r from-[#FF6687] to-[#FF456C] px-6 py-4 text-[16px] font-bold text-white shadow-sm hover:opacity-95"> <div className="flex items-center justify-center min-h-[54px] rounded-[14px] bg-gradient-to-r from-[#FF6687] to-[#FF456C] px-6 py-4 text-[16px] font-bold text-white shadow-sm hover:opacity-95">
{isOpeningProfile && isLoading ? (
{isOpeningProfile ? (
<LoadingThreeDot /> <LoadingThreeDot />
) : ( ) : (
requestSentCopy.matchProfile requestSentCopy.matchProfile

Loading…
Cancel
Save