Browse Source
feat: update finding match page layout and styles
feat: update finding match page layout and styles
- Adjusted dimensions of the image container in FindingMatchPage. - Modified the submit path logic in Intro component to handle new case statuses. - Changed button to link in NewMatchPage for profile viewing and added a locked profile indicator. - Enhanced NewMatchProfilePage with mutation for responding to marriage cases and improved button states. - Updated QuestionsListPage to change text size for optional info prompt. - Refactored RequestAcceptedPage to include subscription handling and improved layout. - Added SubscriptionRequiredSheet for subscription prompts and payment handling. - Implemented useHabcoinPayment hook for managing Habcoin payments. - Introduced new RequestSentPage for displaying request status. - Added new SVG asset for request sent confirmation.master
15 changed files with 462 additions and 92 deletions
-
21public/assets/images/Group 15978804fdasf68.svg
-
1src/app/[lang]/request-sent/page.tsx
-
2src/app/finding-match/page.tsx
-
6src/app/intro/page.tsx
-
28src/app/new-match/page.tsx
-
56src/app/new-match/profile/page.tsx
-
2src/app/questions-list/page.tsx
-
113src/app/request-accepted/page.tsx
-
76src/app/request-sent/page.tsx
-
2src/components/ui/call-result-sheet.tsx
-
68src/components/ui/dismiss-reason-sheet.tsx
-
81src/components/ui/subscription-required-sheet.tsx
-
5src/hooks/marriage/types.ts
-
85src/hooks/marriage/use-habcoin-payment.ts
-
8src/hooks/marriage/use-profile-main.ts
21
public/assets/images/Group 15978804fdasf68.svg
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1 @@ |
|||||
|
export { default } from "@/app/request-sent/page"; |
||||
@ -0,0 +1,76 @@ |
|||||
|
"use client"; |
||||
|
|
||||
|
import Image from "next/image"; |
||||
|
import { useRouter } from "next/navigation"; |
||||
|
import Button from "@/components/ui/button"; |
||||
|
import NavigationButton from "@/components/ui/navigation-button"; |
||||
|
import { PageBackground } from "@/components/utils/page-background"; |
||||
|
import { localizePath } from "@/i18n/config"; |
||||
|
import { useI18n } from "@/i18n/provider"; |
||||
|
import Link from "next/link"; |
||||
|
|
||||
|
export default function RequestSentPage() { |
||||
|
const { locale } = useI18n(); |
||||
|
const router = useRouter(); |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<PageBackground /> |
||||
|
|
||||
|
<main className="-mx-[17px] flex min-h-screen flex-col px-[23px] pt-7 pb-10 text-center"> |
||||
|
<header className="-mx-[6px] flex items-center justify-between"> |
||||
|
<NavigationButton icon="back" /> |
||||
|
<h1 className="font-faminela">Habib Marriage</h1> |
||||
|
<NavigationButton icon="support" iconLabel="Support" /> |
||||
|
</header> |
||||
|
|
||||
|
<div className="flex flex-1 flex-col justify-between gap-20 pt-[109px]"> |
||||
|
<section className="flex flex-col items-center"> |
||||
|
<div className="relative isolate flex items-center justify-center"> |
||||
|
<Image |
||||
|
src="/assets/images/Group 15978804fdasf68.svg" |
||||
|
alt="Request sent" |
||||
|
width={131} |
||||
|
height={125} |
||||
|
priority |
||||
|
className="relative z-10" |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
<h1 className="mt-11 text-[22px] leading-none font-black tracking-[0.02em] text-[#171717] uppercase"> |
||||
|
Request Sent |
||||
|
</h1> |
||||
|
|
||||
|
<p className="mt-4 max-w-[315px] text-[16px] leading-[1.45] font-semibold text-[#777777]"> |
||||
|
We will propose marriage on your behalf. If they accept, their contact details will be shared with you. |
||||
|
</p> |
||||
|
|
||||
|
<Link href={"/new-match/profile"} className="mt-9 w-full max-w-[212px]"> |
||||
|
<div className="bg-[#F5F5F5] px-4 py-2 rounded-[15px] shadow text-sm text-center font-semibold text-[#36363C]"> |
||||
|
Match Profile |
||||
|
</div> |
||||
|
</Link > |
||||
|
</section> |
||||
|
|
||||
|
<div className="space-y-8"> |
||||
|
|
||||
|
<section className="flex flex-col items-center text-center"> |
||||
|
<div className="flex items-center justify-center py-3.5 rounded-[11px] gap-1 w-full bg-[#DBDBDB]"> |
||||
|
<Image |
||||
|
src={"/assets/images/material-symbols_lock.svg"} |
||||
|
width={24} |
||||
|
height={24} |
||||
|
alt="lock" |
||||
|
/> |
||||
|
|
||||
|
<h2 className="text-[17px] leading-none font-semibold text-[#747474]"> |
||||
|
Profile is locked |
||||
|
</h2> |
||||
|
</div> |
||||
|
</section> |
||||
|
</div> |
||||
|
</div> |
||||
|
</main> |
||||
|
</> |
||||
|
); |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
"use client"; |
||||
|
|
||||
|
import Image from "next/image"; |
||||
|
import InformationSheet from "@/components/ui/information-sheet"; |
||||
|
|
||||
|
type SubscriptionRequiredSheetProps = { |
||||
|
onClose: () => void; |
||||
|
onPayment: () => void; |
||||
|
isPaymentPending?: boolean; |
||||
|
}; |
||||
|
|
||||
|
export function SubscriptionRequiredSheet({ |
||||
|
onClose, |
||||
|
onPayment, |
||||
|
isPaymentPending = false, |
||||
|
}: SubscriptionRequiredSheetProps) { |
||||
|
return ( |
||||
|
<InformationSheet |
||||
|
icon="coin" |
||||
|
title="Subscription required" |
||||
|
description={ |
||||
|
<div className="space-y-4 text-left"> |
||||
|
<p className="text-sm text-center leading-[1.45] font-medium text-[#2B2B2B]"> |
||||
|
To view profiles, you need a subscription. Each subscription |
||||
|
includes up to{" "} |
||||
|
<span className="font-bold underline decoration-[1.5px] underline-offset-2"> |
||||
|
3 |
||||
|
</span>{" "} |
||||
|
matches. |
||||
|
</p> |
||||
|
|
||||
|
<div className="rounded-[12px] border border-[#FF4F67] bg-[#FFECEF] px-3.5 py-2.5 text-center"> |
||||
|
<p className="text-xs leading-[1.45] font-semibold text-[#FF4F67]"> |
||||
|
To view profiles, a subscription is required. This helps cover our |
||||
|
support and matching services and applies only to male users |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
onClose={onClose} |
||||
|
buttons={({ close }) => ( |
||||
|
<div className="grid w-full grid-cols-[1fr_2fr] gap-3"> |
||||
|
<button |
||||
|
type="button" |
||||
|
className="appearance-none border-0 bg-transparent p-0 text-left" |
||||
|
onClick={close} |
||||
|
> |
||||
|
<div className="inline-flex w-full items-center justify-center rounded-[18px] border border-[#9A9A9A] bg-[#F7F7F7] px-4 py-[18px] text-[16px] font-bold text-[#8B8B8B] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] transition-opacity active:opacity-90"> |
||||
|
Back |
||||
|
</div> |
||||
|
</button> |
||||
|
|
||||
|
<button |
||||
|
type="button" |
||||
|
disabled={isPaymentPending} |
||||
|
className="appearance-none border-0 bg-transparent p-0 text-left disabled:cursor-not-allowed disabled:opacity-70" |
||||
|
onClick={onPayment} |
||||
|
> |
||||
|
<div className="inline-flex w-full items-center justify-center gap-3 rounded-[18px] bg-[#F0445B] px-4 py-[16px] text-[16px] font-semibold text-white shadow-[0_10px_18px_rgba(240,68,91,0.28)] transition-opacity active:opacity-90"> |
||||
|
<span>Payment</span> |
||||
|
|
||||
|
<span className="inline-flex items-center gap-1 rounded-full bg-[#E43B51] p-1.5 text-xs font-semibold leading-none text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.12)]"> |
||||
|
<Image |
||||
|
src="/assets/images/Inner Plugdsain Iframe.svg" |
||||
|
alt="" |
||||
|
aria-hidden="true" |
||||
|
width={18} |
||||
|
height={18} |
||||
|
className="shrink-0" |
||||
|
/> |
||||
|
<span>50 Habib Coin</span> |
||||
|
</span> |
||||
|
</div> |
||||
|
</button> |
||||
|
</div> |
||||
|
)} |
||||
|
/> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
export default SubscriptionRequiredSheet; |
||||
@ -0,0 +1,85 @@ |
|||||
|
"use client"; |
||||
|
|
||||
|
import { useMutation, useQueryClient } from "@tanstack/react-query"; |
||||
|
import { http } from "@/lib/http"; |
||||
|
import type { MutationOptions } from "./options"; |
||||
|
import { marriageQueryKeys } from "./query-keys"; |
||||
|
|
||||
|
const HABCOIN_PAY_SERVICE = "marriagesubscriptionplan" as const; |
||||
|
|
||||
|
type HabcoinPaymentResponse = unknown; |
||||
|
|
||||
|
function getSecurityToken() { |
||||
|
const token = process.env.NEXT_PUBLIC_SECURITY_KEY; |
||||
|
|
||||
|
if (!token) { |
||||
|
throw new Error("NEXT_PUBLIC_SECURITY_KEY is required"); |
||||
|
} |
||||
|
|
||||
|
return token; |
||||
|
} |
||||
|
|
||||
|
export function extractHabcoinPaymentUrl(response: HabcoinPaymentResponse) { |
||||
|
if (typeof response === "string") { |
||||
|
const trimmed = response.trim(); |
||||
|
|
||||
|
return /^(https?:\/\/|\/)/i.test(trimmed) ? trimmed : null; |
||||
|
} |
||||
|
|
||||
|
if (!response || typeof response !== "object") { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
const record = response as Record<string, unknown>; |
||||
|
const candidates = [ |
||||
|
record.url, |
||||
|
record.payment_url, |
||||
|
record.redirect_url, |
||||
|
record.checkout_url, |
||||
|
record.payment_link, |
||||
|
record.link, |
||||
|
record.href, |
||||
|
]; |
||||
|
|
||||
|
for (const candidate of candidates) { |
||||
|
if (typeof candidate === "string" && candidate.trim()) { |
||||
|
return candidate.trim(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (record.data && typeof record.data === "object") { |
||||
|
return extractHabcoinPaymentUrl(record.data); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
export async function getHabcoinPayment(objectId: number) { |
||||
|
const { data } = await http.get<HabcoinPaymentResponse>("/habcoin/pay/", { |
||||
|
params: { |
||||
|
token: getSecurityToken(), |
||||
|
service: HABCOIN_PAY_SERVICE, |
||||
|
object_id: objectId, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
export function useHabcoinPaymentMutation( |
||||
|
options?: MutationOptions<HabcoinPaymentResponse, number>, |
||||
|
) { |
||||
|
const queryClient = useQueryClient(); |
||||
|
|
||||
|
return useMutation({ |
||||
|
...options, |
||||
|
mutationFn: getHabcoinPayment, |
||||
|
onSuccess: async (data, variables, onMutateResult, context) => { |
||||
|
await queryClient.invalidateQueries({ |
||||
|
queryKey: marriageQueryKeys.profile(), |
||||
|
}); |
||||
|
|
||||
|
await options?.onSuccess?.(data, variables, onMutateResult, context); |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue