feat : able to rotate img for mat card
This commit is contained in:
@@ -6,6 +6,13 @@ import { DownloadIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { ExportLanguageDialog } from "@/components/public/export-language-dialog";
|
||||
import {
|
||||
ExportLanguageToggle,
|
||||
@@ -57,6 +64,7 @@ export function GuideImageExport({
|
||||
showLanguageSelector = true,
|
||||
promptForLanguage = false,
|
||||
localizeFileName = true,
|
||||
modeSelection = "dialog",
|
||||
}: {
|
||||
children: ReactNode;
|
||||
fileName: string;
|
||||
@@ -72,6 +80,7 @@ export function GuideImageExport({
|
||||
showLanguageSelector?: boolean;
|
||||
promptForLanguage?: boolean;
|
||||
localizeFileName?: boolean;
|
||||
modeSelection?: "dialog" | "inline";
|
||||
}) {
|
||||
const captureRef = useRef<HTMLDivElement>(null);
|
||||
const [captureMode, setCaptureMode] = useState<
|
||||
@@ -83,6 +92,13 @@ export function GuideImageExport({
|
||||
const [pendingCaptureMode, setPendingCaptureMode] = useState<
|
||||
"with-notes" | "without-notes" | null
|
||||
>(null);
|
||||
const [modeDialogOpen, setModeDialogOpen] = useState(false);
|
||||
|
||||
function requestCapture(mode: "with-notes" | "without-notes") {
|
||||
setModeDialogOpen(false);
|
||||
if (promptForLanguage) setPendingCaptureMode(mode);
|
||||
else setCaptureMode(mode);
|
||||
}
|
||||
|
||||
function selectLanguage(nextLanguage: ExportLanguage) {
|
||||
if (!pendingCaptureMode) return;
|
||||
@@ -91,6 +107,37 @@ export function GuideImageExport({
|
||||
setPendingCaptureMode(null);
|
||||
}
|
||||
|
||||
function exportButton(
|
||||
mode: "with-notes" | "without-notes" | null,
|
||||
label: string,
|
||||
) {
|
||||
const loading = capturing && (mode === null || captureMode === mode);
|
||||
return (
|
||||
<Button
|
||||
key={mode ?? "export"}
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className={mobileIconOnly ? "max-sm:size-7 max-sm:px-0 max-sm:has-data-[icon=inline-start]:pl-0" : undefined}
|
||||
disabled={capturing || disabled}
|
||||
onClick={() => {
|
||||
if (mode) requestCapture(mode);
|
||||
else if (allowWithoutNotes) setModeDialogOpen(true);
|
||||
else requestCapture("with-notes");
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<Spinner data-icon="inline-start" />
|
||||
) : (
|
||||
<DownloadIcon data-icon="inline-start" />
|
||||
)}
|
||||
<span className={mobileIconOnly ? "sr-only sm:not-sr-only" : undefined}>
|
||||
{loading ? "กำลังส่งออก…" : label}
|
||||
</span>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!capturing) return;
|
||||
|
||||
@@ -161,34 +208,41 @@ export function GuideImageExport({
|
||||
<ExportLanguageToggle language={language} onChange={setStoredLanguage} />
|
||||
) : null}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{(["with-notes", "without-notes"] as const).filter((mode) => allowWithoutNotes || mode === "with-notes").map((mode) => (
|
||||
<Button
|
||||
key={mode}
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className={mobileIconOnly ? "max-sm:size-7 max-sm:px-0 max-sm:has-data-[icon=inline-start]:pl-0" : undefined}
|
||||
disabled={capturing || disabled}
|
||||
onClick={() => {
|
||||
if (promptForLanguage) setPendingCaptureMode(mode);
|
||||
else setCaptureMode(mode);
|
||||
}}
|
||||
>
|
||||
{captureMode === mode ? (
|
||||
<Spinner data-icon="inline-start" />
|
||||
) : (
|
||||
<DownloadIcon data-icon="inline-start" />
|
||||
)}
|
||||
<span className={mobileIconOnly ? "sr-only sm:not-sr-only" : undefined}>
|
||||
{captureMode === mode
|
||||
? "กำลังส่งออก…"
|
||||
: mode === "without-notes"
|
||||
? "ส่งออกภาพโดยไม่รวมโน้ต"
|
||||
: buttonLabel}
|
||||
</span>
|
||||
</Button>
|
||||
))}
|
||||
{allowWithoutNotes && modeSelection === "inline"
|
||||
? [
|
||||
exportButton("with-notes", buttonLabel),
|
||||
exportButton("without-notes", "ส่งออกภาพโดยไม่รวมโน้ต"),
|
||||
]
|
||||
: exportButton(null, buttonLabel)}
|
||||
</div>
|
||||
{allowWithoutNotes && modeSelection === "dialog" ? (
|
||||
<Dialog open={modeDialogOpen} onOpenChange={setModeDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>เลือกรูปแบบการส่งออก</DialogTitle>
|
||||
<DialogDescription>เลือกว่าจะรวมโน้ตไว้ในภาพหรือไม่</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
className="flex-1"
|
||||
onClick={() => requestCapture("with-notes")}
|
||||
>
|
||||
ส่งออกพร้อมโน้ต
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
className="flex-1"
|
||||
onClick={() => requestCapture("without-notes")}
|
||||
>
|
||||
ส่งออกโดยไม่รวมโน้ต
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
) : null}
|
||||
<ExportLanguageDialog
|
||||
open={pendingCaptureMode !== null}
|
||||
onOpenChange={(open) => {
|
||||
|
||||
Reference in New Issue
Block a user