From 4c7fd501ce557246b87cec8ae803482fbb7d80bb Mon Sep 17 00:00:00 2001 From: "Muhammad A. Ghorbani" Date: Mon, 17 Aug 2026 12:28:05 +0330 Subject: [PATCH] feat: add marriage profile page with dynamic fields, consent sheets, and submission path handling --- src/app/new-match/profile/page.tsx | 3 + .../Componentes/question-answer-storage.tsx | 12 +- src/components/Componentes/token-switcher.tsx | 195 ++++-------------- src/lib/get-submit-path.ts | 6 + 4 files changed, 50 insertions(+), 166 deletions(-) diff --git a/src/app/new-match/profile/page.tsx b/src/app/new-match/profile/page.tsx index 157e643..14e785a 100644 --- a/src/app/new-match/profile/page.tsx +++ b/src/app/new-match/profile/page.tsx @@ -22,6 +22,7 @@ import type { import { useRespondToMarriageCaseMutation } from "@/hooks/marriage/use-case-respond"; import { useMarriageProfileQuery } from "@/hooks/marriage/use-profile-main"; import { getSubmitPath } from "@/lib/get-submit-path"; +import { markMatchStarted } from "@/lib/match-start-grace"; import { localizePath } from "@/translations/config"; import { useI18n } from "@/translations/provider"; @@ -454,6 +455,7 @@ export default function NewMatchProfilePage() { return; } + markMatchStarted(); await respondMutation.mutateAsync({ action: "accept" }); }} > @@ -497,6 +499,7 @@ export default function NewMatchProfilePage() { return; } + markMatchStarted(); await respondMutation.mutateAsync({ action: "accept" }); }} > diff --git a/src/components/Componentes/question-answer-storage.tsx b/src/components/Componentes/question-answer-storage.tsx index ac58692..7c6f8a7 100644 --- a/src/components/Componentes/question-answer-storage.tsx +++ b/src/components/Componentes/question-answer-storage.tsx @@ -482,10 +482,11 @@ export function QuestionAnswersProvider({ } const fullPayload = createPayload(answersRef.current, questionsRef.current, backendFieldsRef.current); - const nextDirtyKey = fullPayload.fields.find((field) => dirtyKeysRef.current.has(field.key))?.key; + const dirtyFields = fullPayload.fields.filter((field) => dirtyKeysRef.current.has(field.key)); + const fieldsToSend = dirtyFields.length > 0 ? dirtyFields : fullPayload.fields; const payload = { ...fullPayload, - fields: nextDirtyKey ? fullPayload.fields.filter((field) => field.key === nextDirtyKey) : [], + fields: fieldsToSend, version: schemaVersionRef.current, }; const revision = answersRevisionRef.current; @@ -518,12 +519,7 @@ export function QuestionAnswersProvider({ return; } - if (nextDirtyKey) dirtyKeysRef.current.delete(nextDirtyKey); - - if (dirtyKeysRef.current.size > 0) { - await flushAnswersRef.current(); - return; - } + dirtyKeysRef.current.clear(); hasPendingSyncRef.current = false; setHasPendingSync(false); diff --git a/src/components/Componentes/token-switcher.tsx b/src/components/Componentes/token-switcher.tsx index bdeba04..00add5b 100644 --- a/src/components/Componentes/token-switcher.tsx +++ b/src/components/Componentes/token-switcher.tsx @@ -2,42 +2,38 @@ import { useEffect, useState } from "react"; import { MdOutlineSwitchAccount } from "react-icons/md"; +import { + IoClose, + IoTrashOutline, + IoKeyOutline, +} from "react-icons/io5"; import { getClientCookie, setClientCookie } from "@/lib/cookies"; import { setCachedMarriageEntryPath } from "@/lib/entry-route-cache"; export const FEMALE_TOKEN = "545f61bb3e061ccb9b19f84715eb1b1ed4740331"; export const MALE_TOKEN = "f3a7543b44ef0a713d1ee0d4f7866b3825cf1308"; export const MALE_2_TOKEN = "56cd0fceb93f7cecf7ffa84c590135026cf54a1d"; -export const GUEST_MALE_1_TOKEN = "7490550734175c3935c54c808eba4933ee9c7633"; -export const GUEST_MALE_2_TOKEN = "88813b0434f2207582f515f2c38de0cafd517fb7"; -export const GUEST_FEMALE_1_TOKEN = "d9f0d61b2a7bbea89266eded6ad8d81a112f7ffe"; -export const GUEST_FEMALE_2_TOKEN = "da44906159958b3f071096160b509e1479ccbc1a"; export const FEMALE_EMAIL = "m.a.ghorbani01@gmail.com"; export const MALE_EMAIL = "muhammadamin.ghorbani@gmail.com"; export const MALE_2_EMAIL = "habibwabackup@gmail.com"; const TOKEN_COOKIE_NAME = "HABIB_TOKEN"; -const STORAGE_POS_KEY = "DEV_TOKEN_SWITCHER_POS"; type TokenSwitcherProps = { variant?: "default" | "transparent"; className?: string; - isFloating?: boolean; }; export function TokenSwitcher({ variant = "default", className, - isFloating = true, }: TokenSwitcherProps) { const [isOpen, setIsOpen] = useState(false); const [currentToken, setCurrentToken] = useState(""); const [customTokenInput, setCustomTokenInput] = useState(""); - const [isCustomInputOpen, setIsCustomInputOpen] = useState(false); useEffect(() => { - setMounted(true); if (typeof window !== "undefined") { const token = (window as any).HABIB_TOKEN ?? @@ -46,59 +42,15 @@ export function TokenSwitcher({ sessionStorage.getItem(TOKEN_COOKIE_NAME) ?? ""; setCurrentToken(token); - - if (isFloating) { - try { - const savedPos = localStorage.getItem(STORAGE_POS_KEY); - if (savedPos) { - const parsed = JSON.parse(savedPos); - if (typeof parsed.x === "number" && typeof parsed.y === "number") { - const clampedX = Math.max(10, Math.min(window.innerWidth - 180, parsed.x)); - const clampedY = Math.max(10, Math.min(window.innerHeight - 50, parsed.y)); - setPosition({ x: clampedX, y: clampedY }); - return; - } - } - } catch (e) { - console.warn("Failed to load dev token switcher position:", e); - } - // Default initial position (top-left) - setPosition({ x: 12, y: 12 }); - } } - }, [isFloating]); - - // Keep floating position bounded on window resize - useEffect(() => { - if (!isFloating) return; - const handleResize = () => { - setPosition((prev) => { - if (!prev) return null; - const width = containerRef.current?.offsetWidth || 180; - const height = containerRef.current?.offsetHeight || 50; - return { - x: Math.max(10, Math.min(window.innerWidth - width - 10, prev.x)), - y: Math.max(10, Math.min(window.innerHeight - height - 10, prev.y)), - }; - }); - }; - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, [isFloating]); + }, []); const isMale = currentToken === MALE_TOKEN; const isMale2 = currentToken === MALE_2_TOKEN; const isFemale = currentToken === FEMALE_TOKEN; const isNoToken = currentToken === "NO_TOKEN" || !currentToken; - const guestTokens = [ - GUEST_MALE_1_TOKEN, - GUEST_MALE_2_TOKEN, - GUEST_FEMALE_1_TOKEN, - GUEST_FEMALE_2_TOKEN, - ]; - const isGuestToken = guestTokens.includes(currentToken); const isCustomToken = - !isMale && !isMale2 && !isFemale && !isNoToken && !isGuestToken; + !isMale && !isMale2 && !isFemale && !isNoToken; const handleSelectToken = (newToken: string) => { const trimmed = newToken.trim(); @@ -221,67 +173,38 @@ export function TokenSwitcher({ }, ]; - const guestAccounts = [ - { - token: GUEST_MALE_1_TOKEN, - title: "حساب مهمان آقا ۱", - subtitle: "مهمان / بدون اطلاعات", - emoji: "👨", - isActive: currentToken === GUEST_MALE_1_TOKEN, - }, - { - token: GUEST_MALE_2_TOKEN, - title: "حساب مهمان آقا ۲", - subtitle: "مهمان / بدون اطلاعات", - emoji: "👨", - isActive: currentToken === GUEST_MALE_2_TOKEN, - }, - { - token: GUEST_FEMALE_1_TOKEN, - title: "حساب مهمان خانم ۱", - subtitle: "مهمان / بدون اطلاعات", - emoji: "👩", - isActive: currentToken === GUEST_FEMALE_1_TOKEN, - }, - { - token: GUEST_FEMALE_2_TOKEN, - title: "حساب مهمان خانم ۲", - subtitle: "مهمان / بدون اطلاعات", - emoji: "👩", - isActive: currentToken === GUEST_FEMALE_2_TOKEN, - }, - ]; - return ( <> - +
+ +
{isOpen && (
@@ -370,50 +293,6 @@ export function TokenSwitcher({
))} - {/* Guest Accounts */} - {guestAccounts.map((acc) => ( -
-
handleSelectToken(acc.token)} - className="flex-1 min-w-0 flex items-center gap-3 text-right cursor-pointer" - > -
- {acc.emoji} -
-
- - {acc.title} - - - {acc.subtitle} - - - {acc.token} - -
-
- -
- {acc.isActive && ( - - فعال - - )} -
-
- ))} - {/* Custom Active Token Card (if any custom token is set) */} {isCustomToken && (
diff --git a/src/lib/get-submit-path.ts b/src/lib/get-submit-path.ts index db76d16..ab47cb5 100644 --- a/src/lib/get-submit-path.ts +++ b/src/lib/get-submit-path.ts @@ -43,6 +43,9 @@ export function getSubmitPath( if (caseStatus === "male_accepted") { if (myAction === "pending") { + if (isWithinMatchStartGrace()) { + return "/request-accepted"; + } return "/new-match"; } return "/request-sent"; @@ -50,6 +53,9 @@ export function getSubmitPath( if (caseStatus === "introduced") { if (myAction === "pending") { + if (isWithinMatchStartGrace()) { + return "/request-sent"; + } return "/new-match"; } return "/finding-match";