import { useCallback, useEffect, useState } from "react"; import CloseIcon from "../components/icons/CloseIcon"; import RulesModal from "../components/RulesModal"; import { EMPTY_FORM, CATEGORY_KEYS } from "../config/feedConstants"; import { useTranslation } from 'react-i18next'; import { usePostMutation } from "../hooks/usePostMutation"; import { useImageUpload, ACCEPT, MAX_SIZE_MB } from "../hooks/useImageUpload"; import { validatePostForm } from "../utils/validatePostForm"; import { formatPhone } from "../utils/formatPhone"; import { useYandexMap } from "../hooks/useYandexMap"; import { isMobileDevice } from "../utils/isMobileDevice"; /** * CreateUpdatePost — модальная форма создания и редактирования объявления. * * @param {function} onClose — закрыть модалку без сохранения * @param {function} onSuccess — колбэк после успешного сохранения (перезагружает ленту) * @param {object} [initialData] — если передан, форма работает в режиме редактирования */ export default function CreateUpdatePost({ onClose, onSuccess, initialData }) { const isEdit = !!initialData; const { t } = useTranslation(); const [form, setForm] = useState( isEdit ? { type: (initialData.type || "loss").toLowerCase(), title: initialData.title || "", description: initialData.description || "", category: initialData.category || "", date: initialData.date || "", phone: initialData.phone || "", address: initialData.city || "", rulesAccepted: true, reward: initialData.reward ?? false } : EMPTY_FORM ); const [rulesModalOpen, setRulesModalOpen] = useState(false); const [errors, setErrors] = useState({}); const { images: uploadedImages, imgError, compressing, fileInputRef, handleFileChange, removeImage, getFilesForUpload, getExistingUrlsToKeep, } = useImageUpload(isEdit ? initialData.images : []); const { save, loading: saving, error: apiError } = usePostMutation(); const [resultModal, setResultModal] = useState(null); // null | "success" | "blocked" const initialCoords = isEdit && initialData.latitude && initialData.longitude ? { latitude: initialData.latitude, longitude: initialData.longitude } : null; const { mapRef, coords, address, addressRef } = useYandexMap( true, initialCoords, isEdit ? (initialData.location || "") : "" ); useEffect(() => { if (address) { setForm(prev => ({ ...prev, address })); // Адрес пришёл — очищаем и ошибку поля, и "карта грузится", // иначе последняя может остаться висеть на экране навсегда. setErrors(prev => ({ ...prev, address: "", map: "" })); } }, [address]); const loading = saving || compressing; /** Обновляет одно поле формы и сбрасывает его ошибку валидации. */ const set = useCallback((key, value) => { setForm(prev => ({ ...prev, [key]: value })); setErrors(prev => ({ ...prev, [key]: "" })); }, []); /** Собирает FormData и отправляет запрос на создание или обновление. */ const handleSubmit = async () => { const validationErrors = validatePostForm(form); if (Object.keys(validationErrors).length) { setErrors(validationErrors); return; } if (coords && !addressRef.current) { setErrors(prev => ({ ...prev, map: t('post.mapLoading') })); return; } const data = new FormData(); data.append("type", form.type.toUpperCase()); data.append("title", form.title.trim()); data.append("description", form.description.trim()); data.append("category", form.category); data.append("phone", form.phone.trim()); data.append("reward", form.reward ? "true" : "false"); if (form.date) data.append("date", form.date); const files = getFilesForUpload(); files.forEach(f => data.append("images", f)); if (isEdit) { const existing = getExistingUrlsToKeep(); if (existing.length > 0) { data.append("existingImages", JSON.stringify(existing)); } } if (coords) { data.append("latitude", coords.latitude); data.append("longitude", coords.longitude); data.append("address", form.address.trim()); } if (!coords && form.address.trim()) { data.append("address", form.address.trim()); } data.append("rulesAccepted", form.rulesAccepted ? "true" : "false"); const result = await save(isEdit ? initialData.id : null, data); if (!result) return; if (result.blocked) { setResultModal("blocked"); return; } if (result.data) { setResultModal("success"); } }; return ( <>
e.target === e.currentTarget && !loading && onClose()} >
{isEdit ? t('post.editTitle') : t('post.newTitle')}
{/* Тип: Потеря / Находка */}
{/* Название */}
set("title", e.target.value)} /> {errors.title &&

{errors.title}

}
{/* Описание */}