"use client"; import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { Cropper, CropperCropArea, CropperDescription, CropperImage } from "@/components/ui/cropper"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; type CropArea = { x: number; y: number; width: number; height: number }; export function ProfileImageInput({ id, disabled, onChange, onError }: { id: string; disabled?: boolean; onChange: (file: File) => void; onError: (message: string) => void; }) { const [pending, setPending] = useState<{ url: string } | null>(null); const [cropArea, setCropArea] = useState(null); const [cropping, setCropping] = useState(false); useEffect(() => () => { if (pending) URL.revokeObjectURL(pending.url); }, [pending]); function select(file: File | null) { if (!file) return; if (file.size > 6 * 1024 * 1024 || !["image/png", "image/jpeg", "image/webp"].includes(file.type)) { onError("ใช้รูป PNG, JPEG หรือ WebP ขนาดไม่เกิน 6 MB"); return; } onError(""); setCropArea(null); setPending({ url: URL.createObjectURL(file) }); } async function applyCrop() { if (!pending || !cropArea || cropping) return; setCropping(true); try { const image = await new Promise((resolve, reject) => { const candidate = new Image(); candidate.onload = () => resolve(candidate); candidate.onerror = reject; candidate.src = pending.url; }); const canvas = document.createElement("canvas"); canvas.width = 256; canvas.height = 256; const context = canvas.getContext("2d"); if (!context) throw new Error("Canvas unavailable"); context.imageSmoothingQuality = "high"; context.drawImage(image, cropArea.x, cropArea.y, cropArea.width, cropArea.height, 0, 0, 256, 256); const blob = await new Promise((resolve) => canvas.toBlob(resolve, "image/png")); if (!blob) throw new Error("Image encoding failed"); onChange(new File([blob], "profile.png", { type: "image/png" })); setPending(null); } catch { onError("ไม่สามารถครอปไฟล์ภาพนี้ได้"); } finally { setCropping(false); } } return <> { select(event.target.files?.[0] ?? null); event.target.value = ""; }} /> { if (!open && !cropping) setPending(null); }}> ครอปรูปโปรไฟล์ 1:1 ลากภาพเพื่อเลือกส่วนที่ต้องการใช้เป็นรูปโปรไฟล์ {pending && ลากภาพหรือใช้ปุ่มลูกศรเพื่อเลือกพื้นที่ครอปสี่เหลี่ยม } ; }