import { useState, useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { useDropzone } from 'react-dropzone'; import { useUploadCat } from '@/hooks/useCats'; import { useAuth } from '@/hooks/useAuth'; import { useToast } from '@/components/Toast'; import { Button } from '@/components/ui/button'; import UserAvatar from '@/components/UserAvatar'; import { ArrowLeft, Upload, X, ImagePlus } from 'lucide-react'; const ACCEPTED_FORMATS = 'JPG, PNG, GIF, WebP, HEIC, AVIF'; export default function UploadPage() { const navigate = useNavigate(); const { user, updateUser } = useAuth(); const [file, setFile] = useState(null); const [preview, setPreview] = useState(null); const [caption, setCaption] = useState(''); const uploadMutation = useUploadCat(); const { toast } = useToast(); const onDrop = useCallback((accepted: File[]) => { const f = accepted[0]; if (f) { setFile(f); if (preview) URL.revokeObjectURL(preview); setPreview(URL.createObjectURL(f)); } }, [preview]); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'image/*': ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.heic', '.heif', '.avif'], }, maxFiles: 1, maxSize: 20 * 1024 * 1024, }); const handleUpload = async () => { if (!file) return; const fd = new FormData(); fd.append('image', file); fd.append('caption', caption); try { const result = await uploadMutation.mutateAsync(fd); if (user) updateUser({ ...user, points: (user.points || 0) + 1 }); toast('+1 балл 🎉'); navigate(`/cat/${result.cat.id}`); } catch (err: any) { toast(err?.response?.data?.error || 'Ошибка загрузки', 'error'); } }; const clearFile = () => { setFile(null); if (preview) URL.revokeObjectURL(preview); setPreview(null); }; return (

Новая публикация

{!preview ? (

{isDragActive ? 'Отпустите фото здесь' : 'Перетащите фото сюда'}

или нажмите, чтобы выбрать файл

{ACCEPTED_FORMATS} · до 20 МБ

) : (
{/* Превью */}
Preview {file && (
{file.name}
)}
{/* Подпись */}

@{user?.username}