"use client"; import { useState, useRef } from "react"; import { FileFormatBadge } from "@/components/shared/file-format-badge"; interface LessonFile { id: string; name: string; url: string; size: number; } export function LessonFilesManager({ lessonId, initialFiles }: { lessonId: string; initialFiles: LessonFile[] }) { const [files, setFiles] = useState(initialFiles); const [uploading, setUploading] = useState(false); const [labelInput, setLabelInput] = useState(""); const [editingId, setEditingId] = useState(null); const [editingLabel, setEditingLabel] = useState(""); const fileInputRef = useRef(null); async function handleUpload(e: React.ChangeEvent) { const file = e.target.files?.[0]; if (!file) return; setUploading(true); const fd = new FormData(); fd.append("file", file); fd.append("lessonId", lessonId); if (labelInput.trim()) fd.append("label", labelInput.trim()); const res = await fetch("/api/admin/lesson-files", { method: "POST", body: fd }); const created = await res.json(); if (created.id) { setFiles((prev) => [...prev, created]); setLabelInput(""); } setUploading(false); e.target.value = ""; } async function handleDelete(fileId: string) { if (!confirm("Удалить файл?")) return; await fetch("/api/admin/lesson-files", { method: "DELETE", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ fileId }), }); setFiles((prev) => prev.filter((f) => f.id !== fileId)); } async function saveLabel(fileId: string) { const trimmed = editingLabel.trim(); if (!trimmed) return cancelEdit(); const res = await fetch("/api/admin/lesson-files", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ fileId, label: trimmed }), }); const updated = await res.json(); if (updated.id) { setFiles((prev) => prev.map((f) => (f.id === fileId ? { ...f, name: updated.name } : f))); } cancelEdit(); } function startEdit(file: LessonFile) { setEditingId(file.id); setEditingLabel(file.name); } function cancelEdit() { setEditingId(null); setEditingLabel(""); } function formatSize(bytes: number) { if (bytes < 1024) return `${bytes} Б`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} КБ`; return `${(bytes / 1024 / 1024).toFixed(1)} МБ`; } return (
{files.length > 0 && (
{files.map((f) => (
{editingId === f.id ? ( setEditingLabel(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") saveLabel(f.id); if (e.key === "Escape") cancelEdit(); }} onBlur={() => saveLabel(f.id)} className="flex-1 text-sm px-2 py-0.5" style={{ border: "1px solid var(--foreground)", background: "var(--background)", outline: "none", fontFamily: "inherit", }} /> ) : ( )} {formatSize(f.size)}
))}
)}
setLabelInput(e.target.value)} placeholder="Название (например, Презентация)" className="flex-1 text-sm px-3 py-2" style={{ border: "2px solid var(--border)", background: "var(--background)", outline: "none", fontFamily: "inherit", }} onFocus={(e) => (e.currentTarget.style.borderColor = "var(--foreground)")} onBlur={(e) => (e.currentTarget.style.borderColor = "var(--border)")} />

PDF, ZIP, DOCX, XLSX — до 100 МБ

); }