diff --git a/src/app/finding-match/finding-match-client.test.tsx b/src/app/finding-match/finding-match-client.test.tsx
new file mode 100644
index 0000000..99b783e
--- /dev/null
+++ b/src/app/finding-match/finding-match-client.test.tsx
@@ -0,0 +1,181 @@
+import { act, cleanup, fireEvent, render, screen } from "@testing-library/react";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { I18nProvider } from "@/translations/provider";
+import FindingMatchClient from "./finding-match-client";
+
+const mockReplace = vi.fn();
+const mockPush = vi.fn();
+const mockBack = vi.fn();
+
+vi.mock("next/navigation", () => ({
+ useRouter: () => ({
+ push: mockPush,
+ replace: mockReplace,
+ back: mockBack,
+ prefetch: vi.fn(),
+ }),
+}));
+
+let mockProfileData: any = {
+ id: 1,
+ gender: "male",
+ status: "search_in_progress",
+ can_edit_profile: true,
+ unseen_rejection: null,
+};
+
+vi.mock("@/hooks/marriage/use-profile-main", () => ({
+ useMarriageProfileQuery: () => ({
+ data: mockProfileData,
+ isLoading: false,
+ isFetched: true,
+ refetch: vi.fn(),
+ }),
+}));
+
+vi.mock("@/hooks/marriage/use-form-schema", () => ({
+ useFormOverviewQuery: () => ({
+ data: {
+ sections: [
+ {
+ slug: "personal_identity",
+ title: "Personal Identity",
+ required: true,
+ estimated_time_min: 3,
+ is_completed: false,
+ progress: {
+ current_step: 0,
+ completion_percent: 0,
+ is_completed: false,
+ },
+ },
+ ],
+ },
+ isLoading: false,
+ isFetched: true,
+ isError: false,
+ refetch: vi.fn(),
+ }),
+ getFormSection: vi.fn(),
+}));
+
+vi.mock("@/hooks/marriage/use-cattell", () => ({
+ useCattellResultQuery: () => ({ data: null }),
+ getCattellQuestions: vi.fn(),
+}));
+
+vi.mock("@/hooks/marriage/use-glasser", () => ({
+ useGlasserResultQuery: () => ({ data: null }),
+ getGlasserQuestions: vi.fn(),
+}));
+
+vi.mock("@/hooks/marriage/use-match-start", () => ({
+ useStartMarriageMatchMutation: () => ({
+ mutate: vi.fn(),
+ isPending: false,
+ isError: false,
+ reset: vi.fn(),
+ }),
+}));
+
+vi.mock("@/hooks/marriage/use-rejection-seen", () => ({
+ useRejectionSeenMutation: () => ({
+ mutate: vi.fn(),
+ isPending: false,
+ }),
+}));
+
+vi.mock("@/hooks/marriage/use-marriage-advisors", () => ({
+ useMarriageAdvisorsQuery: () => ({
+ data: { results: [] },
+ isLoading: false,
+ isError: false,
+ refetch: vi.fn(),
+ }),
+}));
+
+function createWrapper() {
+ const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: { retry: false },
+ },
+ });
+
+ return function Wrapper({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+ };
+}
+
+describe("FindingMatchClient", () => {
+ beforeEach(() => {
+ vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
+ vi.stubGlobal("requestAnimationFrame", (cb: FrameRequestCallback) => {
+ return setTimeout(() => cb(Date.now()), 0);
+ });
+ vi.stubGlobal("cancelAnimationFrame", (id: number) => {
+ clearTimeout(id);
+ });
+ document.body.className = "";
+ mockProfileData = {
+ id: 1,
+ gender: "male",
+ status: "search_in_progress",
+ can_edit_profile: true,
+ unseen_rejection: null,
+ };
+ });
+
+ afterEach(() => {
+ cleanup();
+ vi.restoreAllMocks();
+ vi.useRealTimers();
+ document.body.className = "";
+ });
+
+ it("renders search in progress and Edit Profile button", () => {
+ const wrapper = createWrapper();
+ render(, { wrapper });
+
+ expect(screen.getByText("SEARCH IN PROGRESS")).toBeInTheDocument();
+ expect(screen.getByText("Edit Profile")).toBeInTheDocument();
+ });
+
+ it("opens questions list overlay when Edit Profile button is clicked", () => {
+ const wrapper = createWrapper();
+ const { container } = render(, { wrapper });
+
+ // Initial render - overlay is pre-mounted offscreen
+ const editBtn = screen.getByRole("button", { name: /edit profile/i });
+ expect(editBtn).toBeInTheDocument();
+
+ fireEvent.click(editBtn);
+
+ act(() => {
+ vi.advanceTimersByTime(16);
+ });
+
+ const overlay = container.querySelector('aside[data-slot="section-overlay"][data-state="open"]');
+ expect(overlay).toBeInTheDocument();
+ expect(document.body.classList.contains("section-overlay-open")).toBe(true);
+ });
+
+ it("renders locked state when can_edit_profile is false", () => {
+ mockProfileData = {
+ id: 1,
+ gender: "male",
+ status: "search_in_progress",
+ can_edit_profile: false,
+ };
+
+ const wrapper = createWrapper();
+ render(, { wrapper });
+
+ expect(screen.getByText("Profile is locked")).toBeInTheDocument();
+ expect(screen.queryByRole("button", { name: /edit profile/i })).not.toBeInTheDocument();
+ });
+});
diff --git a/src/app/finding-match/finding-match-client.tsx b/src/app/finding-match/finding-match-client.tsx
index 4b44acb..bbc7f6a 100644
--- a/src/app/finding-match/finding-match-client.tsx
+++ b/src/app/finding-match/finding-match-client.tsx
@@ -2,7 +2,7 @@
import Image from "next/image";
import { useRouter } from "next/navigation";
-import { useEffect, useMemo } from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
import { useHardwareBackHandler } from "@/hooks/use-hardware-back-handler";
import { useHabibWebReady } from "@/hooks/use-habib-web-ready";
import { Ic } from "@/icons";
@@ -10,6 +10,9 @@ import AdvisorActionsCard from "@/components/Componentes/advisor-actions-card";
import MarriageAdvisorsOverlay, {
useMarriageAdvisorsOverlay,
} from "@/components/Componentes/marriage-advisors-overlay";
+import QuestionsListOverlay, {
+ useQuestionsListOverlay,
+} from "@/components/Componentes/questions-list-overlay";
import Button from "@/components/Componentes/button";
import { FixToTheEnd } from "@/components/Componentes/fix-to-the-end";
import { PageBackground } from "@/components/Componentes/page-background";
@@ -31,6 +34,40 @@ export default function FindingMatchClient() {
const { dictionary: t, locale } = useI18n();
const { isAdvisorOpen, openAdvisors, closeAdvisors } =
useMarriageAdvisorsOverlay();
+ const { isQuestionsOpen, openQuestions, closeQuestions } =
+ useQuestionsListOverlay();
+ const [isQuestionsReady, setIsQuestionsReady] = useState(false);
+ const [isOpeningEditProfile, setIsOpeningEditProfile] = useState(false);
+
+ const handleQuestionsReady = useCallback(() => {
+ setIsQuestionsReady(true);
+ }, []);
+
+ useEffect(() => {
+ if (isQuestionsReady && isOpeningEditProfile) {
+ setIsOpeningEditProfile(false);
+ openQuestions();
+ }
+ }, [isQuestionsReady, isOpeningEditProfile, openQuestions]);
+
+ // Safety fallback if background preparation takes unexpectedly long
+ useEffect(() => {
+ if (!isOpeningEditProfile) return;
+ const timer = setTimeout(() => {
+ setIsOpeningEditProfile(false);
+ openQuestions();
+ }, 2000);
+ return () => clearTimeout(timer);
+ }, [isOpeningEditProfile, openQuestions]);
+
+ const handleEditProfileClick = useCallback(() => {
+ if (isQuestionsReady) {
+ openQuestions();
+ } else {
+ setIsOpeningEditProfile(true);
+ }
+ }, [isQuestionsReady, openQuestions]);
+
const { data: profile, isLoading, isFetched } = useMarriageProfileQuery({
refetchInterval: 3000,
});
@@ -43,6 +80,10 @@ export default function FindingMatchClient() {
closeAdvisors();
return true;
}
+ if (isQuestionsOpen) {
+ closeQuestions();
+ return true;
+ }
return false; // Hardware back closes the service in Flutter
});
@@ -211,7 +252,8 @@ export default function FindingMatchClient() {
) : (