import { Paperclip } from "lucide-react"; import { useRef } from "react"; import { ApiError } from "../api/client"; import { useToast } from "../context/ToastContext"; import type { AttachmentRead } from "../domain/types"; /** * Сетка фото партии. Переиспользуется на странице партии (игрок) и в админ-правке — * URL/хуки приходят снаружи (cookie игрока и админа доходят до своих путей). */ export function MatchMedia({ attachments, editable = false, onUpload, onDelete, pending = false, max = 10, }: { attachments: AttachmentRead[]; editable?: boolean; onUpload?: (file: File) => Promise; onDelete?: (id: number) => Promise; pending?: boolean; max?: number; }) { const toast = useToast(); const fileRef = useRef(null); const full = attachments.length >= max; const pick = async (e: React.ChangeEvent) => { const files = Array.from(e.target.files ?? []); e.target.value = ""; if (!onUpload) return; let slots = max - attachments.length; for (const f of files) { if (slots <= 0) { toast.show(`Максимум ${max} фото`); break; } try { await onUpload(f); slots--; } catch (err) { toast.show(err instanceof ApiError ? err.message : "Не удалось загрузить"); break; } } }; const remove = async (id: number) => { if (!onDelete) return; try { await onDelete(id); } catch (e) { toast.show(e instanceof ApiError ? e.message : "Не удалось удалить"); } }; if (!editable && attachments.length === 0) return null; return (
{attachments.length > 0 && (
{attachments.map((a) => (
фото партии {editable && ( )}
))}
)} {editable && !full && ( <> )}
); }