From d345b72b2651a6fb3db731a657990f0b7a1846a6 Mon Sep 17 00:00:00 2001 From: gunshiz Date: Tue, 15 Sep 2026 18:31:41 +0700 Subject: [PATCH] feat : adding dialog to choose language --- components/public/export-language-dialog.tsx | 53 +++++++++++++ components/public/export-language.tsx | 79 +++++++++++++++++++- components/public/guide-image-export.tsx | 25 ++++++- components/public/structured-guide.tsx | 2 + components/public/team-search.tsx | 9 ++- lib/guides/image-export.test.tsx | 18 +++++ package.json | 2 +- 7 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 components/public/export-language-dialog.tsx diff --git a/components/public/export-language-dialog.tsx b/components/public/export-language-dialog.tsx new file mode 100644 index 0000000..b65721d --- /dev/null +++ b/components/public/export-language-dialog.tsx @@ -0,0 +1,53 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { + ExportLanguageOption, + type ExportLanguage, +} from "@/components/public/export-language"; + +export function ExportLanguageDialog({ + open, + onOpenChange, + onSelect, +}: { + open: boolean; + onOpenChange: (open: boolean) => void; + onSelect: (language: ExportLanguage) => void; +}) { + return ( + + + + เลือกภาษาในภาพ + What language do you want? + +
+ + +
+
+
+ ); +} diff --git a/components/public/export-language.tsx b/components/public/export-language.tsx index bc987a9..dae314d 100644 --- a/components/public/export-language.tsx +++ b/components/public/export-language.tsx @@ -6,6 +6,11 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; export type ExportLanguage = "th" | "en"; +const LANGUAGE_OPTIONS = { + th: { label: "ไทย" }, + en: { label: "English" }, +} satisfies Record; + const STORAGE_KEY = "buzz-sheet:export-language"; const LANGUAGE_EVENT = "buzz-sheet:export-language-change"; let memoryLanguage: ExportLanguage = "th"; @@ -21,7 +26,7 @@ function storedLanguage(): ExportLanguage { } export function useExportLanguage() { - const language = useSyncExternalStore( + const language = useSyncExternalStore( (onStoreChange) => { window.addEventListener(LANGUAGE_EVENT, onStoreChange); window.addEventListener("storage", onStoreChange); @@ -69,17 +74,85 @@ export function ExportLanguageToggle({ - ไทย + - English + ); } +export function ExportLanguageOption({ + language, +}: { + language: ExportLanguage; +}) { + const option = LANGUAGE_OPTIONS[language]; + + return ( + <> + + {option.label} + + ); +} + +function LanguageFlag({ language }: { language: ExportLanguage }) { + if (language === "th") { + return ( + + ); + } + + return ( + + ); +} + export function ExportText({ th, en }: { th: string; en: string }) { return ( <> diff --git a/components/public/guide-image-export.tsx b/components/public/guide-image-export.tsx index e2729e3..ffd1c40 100644 --- a/components/public/guide-image-export.tsx +++ b/components/public/guide-image-export.tsx @@ -6,6 +6,7 @@ import { DownloadIcon } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; +import { ExportLanguageDialog } from "@/components/public/export-language-dialog"; import { ExportLanguageToggle, useExportLanguage, @@ -53,6 +54,7 @@ export function GuideImageExport({ buttonLabel = "ส่งออกภาพ", language: controlledLanguage, showLanguageSelector = true, + promptForLanguage = false, localizeFileName = true, }: { children: ReactNode; @@ -66,6 +68,7 @@ export function GuideImageExport({ buttonLabel?: string; language?: ExportLanguage; showLanguageSelector?: boolean; + promptForLanguage?: boolean; localizeFileName?: boolean; }) { const captureRef = useRef(null); @@ -75,6 +78,16 @@ export function GuideImageExport({ const capturing = captureMode !== null; const [storedLanguage, setStoredLanguage] = useExportLanguage(); const language = controlledLanguage ?? storedLanguage; + const [pendingCaptureMode, setPendingCaptureMode] = useState< + "with-notes" | "without-notes" | null + >(null); + + function selectLanguage(nextLanguage: ExportLanguage) { + if (!pendingCaptureMode) return; + setStoredLanguage(nextLanguage); + setCaptureMode(pendingCaptureMode); + setPendingCaptureMode(null); + } useEffect(() => { if (!capturing) return; @@ -153,7 +166,10 @@ export function GuideImageExport({ variant="outline" size="sm" disabled={capturing || disabled} - onClick={() => setCaptureMode(mode)} + onClick={() => { + if (promptForLanguage) setPendingCaptureMode(mode); + else setCaptureMode(mode); + }} > {captureMode === mode ? ( @@ -168,6 +184,13 @@ export function GuideImageExport({ ))} + { + if (!open) setPendingCaptureMode(null); + }} + onSelect={selectLanguage} + /> {capturing ? createPortal(
+ } diff --git a/lib/guides/image-export.test.tsx b/lib/guides/image-export.test.tsx index 8dd0d77..e8a1348 100644 --- a/lib/guides/image-export.test.tsx +++ b/lib/guides/image-export.test.tsx @@ -17,6 +17,8 @@ describe("image export controls", () => { expect(html).toContain("ส่งออกภาพโดยไม่รวมโน้ต"); expect(html).toContain("ไทย"); expect(html).toContain("English"); + expect(html).toContain('data-language-flag="th"'); + expect(html).toContain('data-language-flag="en"'); expect(html.match(/ { expect(html.match(/ { + const html = renderToStaticMarkup( + + Content + , + ); + expect(html).not.toContain("ภาษาในภาพส่งออก"); + expect(html).not.toContain("English"); + expect(html.match(/ { const html = renderToStaticMarkup(No sections); expect(html.match(/\sdisabled=""/gu)).toHaveLength(2); diff --git a/package.json b/package.json index da1f1d3..54005c1 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "ioredis": "^6.0.0", "lucide-react": "^1.35.0", "modern-screenshot": "^4.7.0", - "next": "16.3.3", + "next": "^16.3.5", "postgres": "^3.4.9", "radix-ui": "^1.6.7", "react": "19.2.8",