Browse Source

fix sheet

master
mortezaei 1 day ago
parent
commit
478d277c0a
  1. 4
      src/components/Componentes/currency-sheet.tsx
  2. 11
      src/components/Componentes/question-birthplace.tsx
  3. 78
      src/components/Componentes/question-checkbox.tsx
  4. 4
      src/components/Componentes/question-date-sheet.tsx
  5. 22
      src/components/Componentes/question-date.test.tsx
  6. 4
      src/components/Componentes/question-phone.tsx
  7. 16
      src/components/Componentes/question-renderer.tsx
  8. 48
      src/components/Componentes/question-sheet.test.tsx
  9. 4
      src/components/Componentes/question-sheet.tsx

4
src/components/Componentes/currency-sheet.tsx

@ -148,8 +148,8 @@ export function CurrencySheet({
].join(" ")}
>
{/* Header */}
<div className="flex items-center justify-between px-5 pt-3 pb-3 border-b border-[#F2F4F7]">
<h3 className="text-[17px] font-bold text-[#181818] truncate pr-2">
<div className="flex items-center justify-between gap-3 px-5 pt-3 pb-3 border-b border-[#F2F4F7]">
<h3 className="flex-1 min-w-0 text-[17px] font-bold leading-snug text-[#181818] line-clamp-2 break-words text-start">
{sheetTitle}
</h3>
<button

11
src/components/Componentes/question-birthplace.tsx

@ -155,7 +155,12 @@ export function QuestionBirthplace({
const { getAnswerValue, setAnswerValue, isLoading } = useQuestionAnswers();
const rawValue = getAnswerValue(question);
const isResidence = question.ui_config?.enable_geoip === true;
const isResidence =
question.ui_config?.enable_geoip === true ||
question.ui_config?.location_kind === "residence" ||
question.id?.includes("residence") ||
question.id?.includes("living_area") ||
question.id?.includes("location");
const storedRegion = isResidence ? getStoredUserGeoRegion() : null;
const initial = parseValue(rawValue);
@ -707,8 +712,8 @@ export function QuestionBirthplace({
</div>
{/* Header with Title and Close Button */}
<div className="flex items-center justify-between px-5 pt-2 pb-3 border-b border-[#F2F4F7]">
<h3 className="text-[17px] font-bold text-[#181818] truncate pr-2">
<div className="flex items-center justify-between gap-3 px-5 pt-2.5 pb-3 border-b border-[#F2F4F7]">
<h3 className="flex-1 min-w-0 text-[17px] font-bold leading-snug text-[#181818] line-clamp-2 break-words text-start">
{selectCountryPlaceholder}
</h3>
<button

78
src/components/Componentes/question-checkbox.tsx

@ -23,8 +23,82 @@ export function QuestionCheckbox({
? [String(rawValue)]
: [];
if (options.length === 0) {
return null;
const isSingleCheckbox = options.length === 0;
if (isSingleCheckbox) {
const isChecked = Boolean(
rawValue === true ||
rawValue === "true" ||
rawValue === "confirmed" ||
(Array.isArray(rawValue) && rawValue.length > 0),
);
const toggleSingle = () => {
setAnswerValue(question, isChecked ? null : ["confirmed"]);
};
const labelText =
question.description ||
question.title ||
"تأیید می‌کنم که نام، سن، تصویر و اطلاعات هویتی من با مدارک بارگذاری‌شده مطابقت دارد.";
return (
<div
className={[
"flex w-full flex-col gap-3.5 transition-opacity duration-200",
disabled ? "pointer-events-none opacity-30" : "",
].join(" ")}
>
<QuestionTitle question={question} />
<div className="flex flex-col gap-3.5 pt-1">
<label
htmlFor={`checkbox-${question.id}`}
onClick={toggleSingle}
className={[
"cursor-pointer rounded-[16px] font-medium text-[14px] transition-all duration-200 active:scale-[0.99] flex items-center gap-3.5 w-full px-5 py-4 text-start leading-relaxed",
isChecked
? "bg-[#F0445B] text-white shadow-[0_8px_20px_rgba(240,68,91,0.25)]"
: "bg-[#FAFAFA] text-[#181818] hover:bg-white shadow-[0_2px_6px_rgba(0,0,0,0.03)] border border-[#F0EDED]",
].join(" ")}
>
<input
type="checkbox"
id={`checkbox-${question.id}`}
checked={isChecked}
disabled={disabled}
onChange={toggleSingle}
className="sr-only"
/>
<div
className={[
"size-[20px] shrink-0 rounded-[6px] border-[2px] transition-all flex items-center justify-center",
isChecked
? "border-white bg-white text-[#F0445B]"
: "border-[#D0D5DD] bg-white text-transparent",
].join(" ")}
>
{isChecked && (
<svg
width="12"
height="10"
viewBox="0 0 10 8"
fill="none"
className="stroke-current stroke-[2.5]"
>
<path
d="M1 4L3.5 6.5L9 1"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)}
</div>
<span className="flex-1">{labelText}</span>
</label>
</div>
</div>
);
}
const toggleOption = (optionId: string) => {

4
src/components/Componentes/question-date-sheet.tsx

@ -294,8 +294,8 @@ export function QuestionDateSheet({
isClosing ? "flutter-sheet-surface-exit" : "flutter-sheet-surface",
].join(" ")}
>
<div className="flex items-center justify-between border-b border-[#F2F4F7] px-5 pb-3 pt-2">
<h3 className="truncate pr-2 text-[17px] font-bold text-[#181818]">
<div className="flex items-center justify-between gap-3 border-b border-[#F2F4F7] px-5 pb-3 pt-2.5">
<h3 className="flex-1 min-w-0 text-[17px] font-bold leading-snug text-[#181818] line-clamp-2 break-words text-start">
{question.title}
</h3>
<button

22
src/components/Componentes/question-date.test.tsx

@ -70,4 +70,26 @@ describe("QuestionDate", () => {
expect(screen.queryByText("Age")).toBeNull();
expect(screen.getByText("Select date")).toBeDefined();
});
it("renders long date question title in sheet header with line-clamp-2 and without truncate", () => {
const longTitle =
"تاریخ دقیق تولد شما بر اساس مدارک شناسایی رسمی و شناسنامه معتبر";
const longDateQ = {
...question,
title: longTitle,
};
render(<QuestionDate question={longDateQ} />);
fireEvent.click(screen.getByRole("button", { name: /select date/i }));
const dialog = screen.getByRole("dialog");
expect(dialog).toBeDefined();
const heading = dialog.querySelector("h3");
expect(heading).toBeDefined();
expect(heading?.textContent?.trim()).toBe(longTitle);
expect(heading).toHaveClass("line-clamp-2");
expect(heading).toHaveClass("flex-1");
expect(heading).not.toHaveClass("truncate");
});
});

4
src/components/Componentes/question-phone.tsx

@ -816,8 +816,8 @@ export function QuestionPhone({
].join(" ")}
>
{/* Header with Title and Close Button */}
<div className="flex items-center justify-between px-5 pt-2 pb-3 border-b border-[#F2F4F7]">
<h3 className="text-[17px] font-bold text-[#181818] truncate pr-2">
<div className="flex items-center justify-between gap-3 px-5 pt-2.5 pb-3 border-b border-[#F2F4F7]">
<h3 className="flex-1 min-w-0 text-[17px] font-bold leading-snug text-[#181818] line-clamp-2 break-words text-start">
{selectCountryTitle}
</h3>
<button

16
src/components/Componentes/question-renderer.tsx

@ -33,6 +33,8 @@ export function QuestionRenderer({
switch (question.type) {
case "birthplace":
case "location":
case "residence":
return (
<QuestionBirthplace
question={question}
@ -125,6 +127,20 @@ export function QuestionRenderer({
/>
);
case "text":
if (
question.ui_config?.enable_geoip === true ||
question.ui_config?.location_kind === "residence" ||
question.id?.includes("approximate_location_of_current_living_area") ||
question.id?.includes("current_residence") ||
question.id?.includes("living_area")
) {
return (
<QuestionBirthplace
question={question}
disabled={disabled}
/>
);
}
return (
<QuestionText
question={question}

48
src/components/Componentes/question-sheet.test.tsx

@ -433,4 +433,52 @@ describe("QuestionSheet component", () => {
expect(screen.queryByText("Antigua and Barbuda")).toBeNull();
expect(screen.queryByText("افغانستان")).toBeNull();
});
it("renders long question title with line-clamp-2 and flex-1 classes in sheet header", () => {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
const longTitle =
"میزان پایبندی شما به مناسک و تکالیف شرعی و اعتقادات مذهبی در زندگی روزمره خانوادگی و اجتماعی";
const qLong = {
id: "religious_commitment_details",
title: longTitle,
type: "dropdown",
order: 1,
required: true,
isVisible: true,
description: "",
tooltip: "",
extras: { placeHolder: "انتخاب کنید" },
options: [
{ id: "high", value: "high", label: "بسیار زیاد", order: 1 },
{ id: "medium", value: "medium", label: "متوسط", order: 2 },
],
ui_config: {},
} as QuestionField;
render(
<QueryClientProvider client={queryClient}>
<QuestionAnswersProvider slug="test" questions={[qLong]}>
<QuestionSheet question={qLong} />
</QuestionAnswersProvider>
</QueryClientProvider>,
);
const trigger = screen.getByRole("button", { name: "انتخاب کنید" });
fireEvent.click(trigger);
const dialog = screen.getByRole("dialog");
expect(dialog).toBeDefined();
const heading = dialog.querySelector("h3");
expect(heading).toBeDefined();
expect(heading?.textContent?.trim()).toBe(longTitle);
expect(heading).toHaveClass("line-clamp-2");
expect(heading).toHaveClass("flex-1");
expect(heading).not.toHaveClass("truncate");
});
});

4
src/components/Componentes/question-sheet.tsx

@ -436,8 +436,8 @@ export function QuestionSheet({ question, disabled }: QuestionSheetProps) {
isClosing ? "flutter-sheet-surface-exit" : "flutter-sheet-surface",
].join(" ")}
>
<div className="flex items-center justify-between px-5 pt-2 pb-3 border-b border-[#F2F4F7]">
<h3 className="text-[17px] font-bold text-[#181818] truncate pr-2">
<div className="flex items-center justify-between gap-3 px-5 pt-2.5 pb-3 border-b border-[#F2F4F7]">
<h3 className="flex-1 min-w-0 text-[17px] font-bold leading-snug text-[#181818] line-clamp-2 break-words text-start">
{question.title}
</h3>
<button

Loading…
Cancel
Save