Browse Source
fix: update icon source and add new SVG assets; enhance localization and UI components
fix: update icon source and add new SVG assets; enhance localization and UI components
- Changed the icon source for the check icon in information-sheet.tsx. - Added new localization strings for decline and request proceed in dictionaries.ts. - Introduced new image assets: Group 1597880481.png and Icfdason.svg. - Created a new page for the new match profile with improved UI and functionality. - Implemented request and reject profile functionality with corresponding UI sheets.master
11 changed files with 567 additions and 174 deletions
-
9next.config.ts
-
BINpublic/assets/images/Group 1597880481.png
-
3public/assets/images/Icfdason.svg
-
3public/assets/images/Vectofdasr.svg
-
1src/app/[lang]/new-match/profile/page.tsx
-
2src/app/intro/page.tsx
-
414src/app/new-match/page.tsx
-
205src/app/new-match/profile/page.tsx
-
79src/components/ui/dismiss-reason-sheet.tsx
-
2src/components/ui/information-sheet.tsx
-
7src/i18n/dictionaries.ts
@ -1,7 +1,14 @@ |
|||||
import type { NextConfig } from "next"; |
import type { NextConfig } from "next"; |
||||
|
|
||||
const nextConfig: NextConfig = { |
const nextConfig: NextConfig = { |
||||
/* config options here */ |
|
||||
|
images: { |
||||
|
remotePatterns: [ |
||||
|
{ |
||||
|
protocol: "https", |
||||
|
hostname: "habibapp.com", |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
}; |
}; |
||||
|
|
||||
export default nextConfig; |
export default nextConfig; |
||||
|
After Width: 90 | Height: 91 | Size: 9.3 KiB |
@ -0,0 +1,3 @@ |
|||||
|
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg"> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.44429 7.24086C5.49445 6.19103 6.91857 5.60126 8.40349 5.60126C9.88841 5.60126 11.3125 6.19103 12.3627 7.24086L14.0035 8.88026L15.6443 7.24086C16.1609 6.70601 16.7788 6.27939 17.462 5.9859C18.1452 5.69241 18.8801 5.53792 19.6236 5.53146C20.3672 5.525 21.1046 5.66669 21.7928 5.94826C22.4811 6.22984 23.1063 6.64565 23.6321 7.17145C24.1579 7.69725 24.5737 8.3225 24.8553 9.01072C25.1369 9.69894 25.2786 10.4363 25.2721 11.1799C25.2656 11.9235 25.1112 12.6583 24.8177 13.3415C24.5242 14.0248 24.0975 14.6427 23.5627 15.1593L14.0035 24.7199L4.44429 15.1593C3.39445 14.1091 2.80469 12.685 2.80469 11.2001C2.80469 9.71515 3.39445 8.29102 4.44429 7.24086Z" fill="white"/> |
||||
|
</svg> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 18C0 13.2261 1.89642 8.64773 5.27208 5.27208C8.64773 1.89642 13.2261 0 18 0C22.7739 0 27.3523 1.89642 30.7279 5.27208C34.1036 8.64773 36 13.2261 36 18C36 22.7739 34.1036 27.3523 30.7279 30.7279C27.3523 34.1036 22.7739 36 18 36C13.2261 36 8.64773 34.1036 5.27208 30.7279C1.89642 27.3523 0 22.7739 0 18ZM16.9728 25.704L27.336 12.7488L25.464 11.2512L16.6272 22.2936L10.368 17.0784L8.832 18.9216L16.9728 25.704Z" fill="#F0445B"/> |
||||
|
</svg> |
||||
@ -0,0 +1 @@ |
|||||
|
export { default } from "@/app/new-match/profile/page"; |
||||
@ -0,0 +1,205 @@ |
|||||
|
"use client"; |
||||
|
|
||||
|
import Image from "next/image"; |
||||
|
import { useRouter } from "next/navigation"; |
||||
|
import { useState } from "react"; |
||||
|
import Button from "@/components/ui/button"; |
||||
|
import DismissReasonSheet from "@/components/ui/dismiss-reason-sheet"; |
||||
|
import InformationSheet from "@/components/ui/information-sheet"; |
||||
|
import NavigationButton from "@/components/ui/navigation-button"; |
||||
|
import StickyHeader from "@/components/ui/sticky-header"; |
||||
|
import { PageBackground } from "@/components/utils/page-background"; |
||||
|
import type { MarriageField, MarriageFieldValue } from "@/hooks/marriage/types"; |
||||
|
import { useMarriageProfileQuery } from "@/hooks/marriage/use-profile-main"; |
||||
|
import { localizePath } from "@/i18n/config"; |
||||
|
import { useI18n } from "@/i18n/provider"; |
||||
|
|
||||
|
function formatFieldValue(value: MarriageFieldValue) { |
||||
|
if (value === null || value === "") { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
if (typeof value === "boolean") { |
||||
|
return value ? "Yes" : "No"; |
||||
|
} |
||||
|
|
||||
|
return String(value); |
||||
|
} |
||||
|
|
||||
|
function titleFromKey(key: string) { |
||||
|
return key |
||||
|
.replace(/^q\d+[_-]?/i, "") |
||||
|
.replace(/[_-]+/g, " ") |
||||
|
.replace(/\s+/g, " ") |
||||
|
.trim() |
||||
|
.replace(/\b\w/g, (letter) => letter.toUpperCase()); |
||||
|
} |
||||
|
|
||||
|
function isImageField(field: MarriageField) { |
||||
|
return /(avatar|image|photo|picture|portrait|upload)/i.test( |
||||
|
`${field.key} ${field.label}`, |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
function MatchField({ field }: { field: MarriageField }) { |
||||
|
const value = formatFieldValue(field.value); |
||||
|
|
||||
|
if (!value || isImageField(field)) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
const label = field.label || titleFromKey(field.key); |
||||
|
|
||||
|
return ( |
||||
|
<div className="mb-3.5 space-y-2 border-b border-[#000000]/10 pb-2.5"> |
||||
|
<p className="text-xs font-semibold text-[#978787]">{label}</p> |
||||
|
<p className="font-semibold text-[#111111]">{value}</p> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
export default function NewMatchProfilePage() { |
||||
|
const { dictionary: t, locale } = useI18n(); |
||||
|
const router = useRouter(); |
||||
|
const [isRequestSheetOpen, setIsRequestSheetOpen] = useState(false); |
||||
|
const [isRejectSheetOpen, setIsRejectSheetOpen] = useState(false); |
||||
|
const [isDismissReasonSheetOpen, setIsDismissReasonSheetOpen] = |
||||
|
useState(false); |
||||
|
const { data: profile } = useMarriageProfileQuery(); |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<PageBackground /> |
||||
|
{isRequestSheetOpen ? ( |
||||
|
<InformationSheet |
||||
|
icon="check" |
||||
|
title="Request to Proceed" |
||||
|
description="With your approval, we will approach their family on your behalf to propose marriage. After their family agrees, you will be introduced to each other for further acquaintance." |
||||
|
buttons={({ close }) => ( |
||||
|
<div className="grid w-full grid-cols-2 gap-3"> |
||||
|
<Button variant="outlined" className="py-[18px]" onClick={close}> |
||||
|
{t.common.cancel} |
||||
|
</Button> |
||||
|
<Button |
||||
|
className="py-[18px]" |
||||
|
onClick={() => { |
||||
|
close(); |
||||
|
router.push(localizePath("/request-accepted", locale)); |
||||
|
}} |
||||
|
> |
||||
|
{t.common.confirm} |
||||
|
</Button> |
||||
|
</div> |
||||
|
)} |
||||
|
onClose={() => setIsRequestSheetOpen(false)} |
||||
|
/> |
||||
|
) : null} |
||||
|
{isRejectSheetOpen ? ( |
||||
|
<InformationSheet |
||||
|
icon="warning" |
||||
|
title="Reject Profile" |
||||
|
description="Are you sure you've fully reviewed the profile and want to reject this profile?" |
||||
|
buttons={({ close }) => ( |
||||
|
<div className="grid w-full grid-cols-2 gap-3"> |
||||
|
<Button variant="outlined" className="py-[18px]" onClick={close}> |
||||
|
{t.common.cancel} |
||||
|
</Button> |
||||
|
<Button |
||||
|
className="py-[18px]" |
||||
|
onClick={() => { |
||||
|
close(); |
||||
|
setIsDismissReasonSheetOpen(true); |
||||
|
}} |
||||
|
> |
||||
|
Reject |
||||
|
</Button> |
||||
|
</div> |
||||
|
)} |
||||
|
onClose={() => setIsRejectSheetOpen(false)} |
||||
|
/> |
||||
|
) : null} |
||||
|
{isDismissReasonSheetOpen ? ( |
||||
|
<DismissReasonSheet |
||||
|
onClose={() => setIsDismissReasonSheetOpen(false)} |
||||
|
onSubmit={() => { |
||||
|
router.push(localizePath("/candidate-contact", locale)); |
||||
|
}} |
||||
|
/> |
||||
|
) : null} |
||||
|
|
||||
|
<main className="-mx-[17px] flex min-h-screen flex-col bg-[linear-gradient(180deg,rgba(255,197,196,0.2)_0%,rgba(251,237,237,0.7)_100%)] pb-10"> |
||||
|
<StickyHeader className="rounded-b-[32px] px-[17px] pb-6 pt-7"> |
||||
|
<div className="flex items-center justify-between"> |
||||
|
<NavigationButton |
||||
|
variant="transparent" |
||||
|
icon="close" |
||||
|
iconLabel={t.match.goBack} |
||||
|
/> |
||||
|
<h1 className="text-[26px] text-white">{t.match.title}</h1> |
||||
|
<div className="w-[39px]" /> |
||||
|
</div> |
||||
|
</StickyHeader> |
||||
|
|
||||
|
<section className="px-[17px] pb-32 pt-5"> |
||||
|
<div> |
||||
|
<Image |
||||
|
src={"/assets/images/Group 1597880481.png"} |
||||
|
alt="" |
||||
|
width={90} |
||||
|
height={90} |
||||
|
className="rounded-full" |
||||
|
/> |
||||
|
<div className="relative inline-block mt-2"> |
||||
|
<p |
||||
|
className="text-[25px] leading-none text-white/80" |
||||
|
style={{ letterSpacing: "-2.3px", fontWeight: "1000" }} |
||||
|
> |
||||
|
{profile?.match_summary?.public_info.find( |
||||
|
(field) => field.key === "q1_full_name", |
||||
|
)?.value || "Name not available"} |
||||
|
</p> |
||||
|
<p className="absolute inset-0 whitespace-nowrap text-[22px] font-bold leading-none text-[#F0445B]"> |
||||
|
{profile?.match_summary?.public_info.find( |
||||
|
(field) => field.key === "q1_full_name", |
||||
|
)?.value || "Name not available"} |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div className="mt-6"> |
||||
|
{profile?.match_summary?.public_info.map((field) => ( |
||||
|
<MatchField key={field.key} field={field} /> |
||||
|
))} |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<div className="fixed inset-x-0 bottom-0 z-30 px-[17px]"> |
||||
|
<div className="mx-auto max-w-[375px] rounded-t-[24px] bg-white px-4 py-4 shadow-[0_12px_30px_rgba(0,0,0,0.14)]"> |
||||
|
<div className="flex gap-3"> |
||||
|
<button |
||||
|
type="button" |
||||
|
onClick={() => setIsRejectSheetOpen(true)} |
||||
|
className="inline-flex w-1/3 items-center justify-center rounded-[12px] border border-[#BFBFBF] bg-white px-4 py-[13px] text-[16px] font-semibold text-[#9A9A9A]" |
||||
|
> |
||||
|
Reject |
||||
|
</button> |
||||
|
<button |
||||
|
type="button" |
||||
|
onClick={() => setIsRequestSheetOpen(true)} |
||||
|
className="inline-flex w-2/3 whitespace-nowrap items-center justify-center gap-1 rounded-[12px] bg-[#F0445B] px-4 py-[13px] text-[16px] font-semibold text-white shadow-[0_8px_16px_rgba(240,68,91,0.24)]" |
||||
|
> |
||||
|
<Image |
||||
|
src="/assets/images/Icfdason.svg" |
||||
|
alt="" |
||||
|
width={28} |
||||
|
height={28} |
||||
|
/> |
||||
|
<span>{t.match.acceptProfile}</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</main> |
||||
|
</> |
||||
|
); |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue