"use client"; import { Loader2, Paperclip, X } from "lucide-react"; import { useRef, useState } from "react"; import { Button } from "@/components/ui/button"; import { tr } from "@/i18n/tr"; import type { ActionResult } from "@/lib/action-result"; import { cn } from "@/lib/utils"; import { acceptAttribute, MAX_ATTACHMENTS_PER_RECORD, type AttachmentKind, } from "@/shared/attachments"; import type { AttachmentInfo } from "../service"; import { AttachmentThumb } from "./attachment-strip"; import { AttachmentViewer } from "./attachment-viewer"; const t = tr.attachments; /** Tek dosyayı /api/files'a yükler. */ async function uploadFile(file: File): Promise> { const body = new FormData(); body.append("file", file); try { const res = await fetch("/api/files", { method: "POST", body }); return (await res.json()) as ActionResult; } catch { return { ok: false, error: t.errors.upload }; } } /** * Formdaki küçük "Ek ekle" alanı (Bölüm 6.3): seçilen dosyalar hemen yüklenir (bekleyen ek), * küçük önizleme ve sayaç gösterilir; kayıt kaydedilince ekler kayda bağlanır. */ export function AttachmentPicker({ value, onChange, allowedKinds, onBusyChange, }: { value: AttachmentInfo[]; onChange: (items: AttachmentInfo[]) => void; allowedKinds: readonly AttachmentKind[]; onBusyChange?: (busy: boolean) => void; }) { const inputRef = useRef(null); const [uploading, setUploading] = useState(0); const [errors, setErrors] = useState([]); const [viewer, setViewer] = useState(null); const invalid = value.filter((a) => !allowedKinds.includes(a.kind)); const room = MAX_ATTACHMENTS_PER_RECORD - value.length; async function onFiles(files: FileList | null) { if (!files?.length) return; const list = [...files]; const accepted = list.slice(0, Math.max(0, room)); const nextErrors: string[] = []; if (list.length > accepted.length) nextErrors.push(t.errors.tooMany(MAX_ATTACHMENTS_PER_RECORD)); setUploading(accepted.length); onBusyChange?.(true); let items = value; for (const file of accepted) { const result = await uploadFile(file); if (result.ok) { items = [...items, result.data]; onChange(items); } else { nextErrors.push(`${file.name}: ${result.error}`); } setUploading((n) => n - 1); } setErrors(nextErrors); onBusyChange?.(false); if (inputRef.current) inputRef.current.value = ""; } function remove(id: string) { onChange(value.filter((a) => a.id !== id)); } return (
{value.length ? t.count(value.length) : allowedKinds.includes("pdf") ? t.addHint.imagePdf : t.addHint.image} onFiles(e.target.files)} />
{value.length || uploading ? (
    {value.map((item, i) => (
  • setViewer(i)} />
  • ))} {Array.from({ length: uploading }, (_, i) => (
  • ))}
) : null} {invalid.length ? (

{t.errors.kindNotAllowed}

) : null} {errors.map((e) => (

{e}

))} !open && setViewer(null)} />
); }