import { useState, useEffect } from 'react'; import { FaFire, FaEdit, FaTrashAlt } from 'react-icons/fa'; // Changed FaStar to FaFire import RatingChart from './RatingChart'; import FlameRatingInput from './FlameRatingInput'; // Import the new component import ReactQuill from 'react-quill'; // Import ReactQuill import 'react-quill/dist/quill.snow.css'; // Import Quill styles (snow theme) // Default characteristics if none are provided (fallback) const defaultCharacteristics = { overall: 'Общая оценка' // Ensure a default 'overall' characteristic }; // Mapping for watched/completed status values const watchedStatusLabels = { not_watched: 'Не просмотрено', watched: 'Просмотрено', }; const completedStatusLabels = { not_completed: 'Не пройдено', completed: 'Пройдено', }; // ReviewForm now expects characteristics prop to be the media's characteristics { [key]: label } // Also expects mediaType, progressType, seasons, and selectedSeasonId function ReviewForm({ mediaId, seasonId, mediaType, progressType, onSubmit, onEdit, onDelete, characteristics = defaultCharacteristics, existingReview, seasons = [], selectedSeasonId }) { // Initial state for ratings, now storing just the number { [key]: number } // Initialize with a default value (e.g., 5) for each characteristic provided const initialRatings = Object.keys(characteristics).reduce((acc, key) => { acc[key] = 5; // Default rating of 5 return acc; }, {}); const [ratings, setRatings] = useState(initialRatings); // Use empty string for Quill content state initially const [content, setContent] = useState(''); const [hasSpoilers, setHasSpoilers] = useState(false); // Use 'progress' state instead of 'status' const [progress, setProgress] = useState(''); // State for progress (text field) const [isSubmitting, setIsSubmitting] = useState(false); const [isEditing, setIsEditing] = useState(false); // New state for selected season in the form (only relevant if media supports seasons) // Initialize with the selectedSeasonId passed from the parent const [formSeasonId, setFormSeasonId] = useState(selectedSeasonId); // Determine the correct progress options/label based *only* on progressType const getProgressOptions = () => { if (progressType === 'watched') { return watchedStatusLabels; } else if (progressType === 'completed') { return completedStatusLabels; } // If progressType is 'hours' or unknown, use text input return null; }; const progressOptions = getProgressOptions(); const isProgressSelect = progressOptions !== null; // Determine if we should show a select/segmented control // Determine if the media type supports seasons const supportsSeasons = mediaType === 'tv' || mediaType === 'anime'; // Reset ratings, content, progress, and formSeasonId when characteristics, existingReview, progressType, or selectedSeasonId change useEffect(() => { console.log('ReviewForm useEffect: existingReview changed', existingReview); // LOG console.log('ReviewForm useEffect: selectedSeasonId changed', selectedSeasonId); // LOG // Ensure characteristics is an object before processing const validCharacteristics = characteristics && typeof characteristics === 'object' ? characteristics : defaultCharacteristics; if (existingReview) { // If editing, pre-fill form with existing review data // Expect existingReview.ratings to be { [key]: number } const populatedRatings = Object.keys(validCharacteristics).reduce((acc, key) => { // Use existing rating if it's a number, otherwise default to 5 acc[key] = typeof existingReview.ratings?.[key] === 'number' ? existingReview.ratings[key] : 5; return acc; }, {}); setRatings(populatedRatings); // Set content from existing review (assuming it's HTML) setContent(existingReview.content || ''); setHasSpoilers(existingReview.has_spoilers ?? false); // Initialize progress from existing review setProgress(existingReview.progress || ''); // Initialize formSeasonId from existing review's season_id setFormSeasonId(existingReview.season_id || null); // Use null for overall review console.log('ReviewForm useEffect: Setting isEditing to false (existing review)'); // LOG setIsEditing(false); // Start in view mode } else { // If creating, reset form const newInitialRatings = Object.keys(validCharacteristics).reduce((acc, key) => { acc[key] = 5; // Default rating of 5 return acc; }, {}); setRatings(newInitialRatings); setContent(''); // Reset content to empty string for Quill setHasSpoilers(false); // Reset progress based on the type of input expected if (isProgressSelect) { // Set default for select based on options (e.g., 'completed' or 'not_watched') // Default to the first option key, which should be the 'not_' status setProgress(Object.keys(progressOptions)[0] || ''); } else { setProgress(''); // Default to empty string for text input (hours) } // Reset formSeasonId to the currently selected season on the page setFormSeasonId(selectedSeasonId); console.log('ReviewForm useEffect: Resetting form, setting isEditing to false (no existing review)'); // LOG setIsEditing(false); } }, [characteristics, existingReview, progressType, isProgressSelect, selectedSeasonId, seasons]); // Depend on selectedSeasonId and seasons too // Add a log to see when isEditing state changes useEffect(() => { console.log('ReviewForm: isEditing state changed to', isEditing); // LOG }, [isEditing]); const handleRatingChange = (category, value) => { const newRatings = { ...ratings, [category]: value }; // Рассчитываем overall_rating как среднее всех оценок const validRatings = Object.values(newRatings).filter(rating => typeof rating === 'number'); const overallRating = validRatings.length > 0 ? validRatings.reduce((sum, rating) => sum + rating, 0) / validRatings.length : 0; setRatings({ ...newRatings, overall: overallRating }); }; const handleProgressChange = (value) => { setProgress(value); }; const handleFormSeasonChange = (e) => { // Convert the value to null if it's the "Общее" option const value = e.target.value === '' ? null : e.target.value; setFormSeasonId(value); }; const handleSubmit = async (e) => { e.preventDefault(); setIsSubmitting(true); try { // Рассчитываем overall_rating перед отправкой const validRatings = Object.entries(ratings) .filter(([key, value]) => key !== 'overall' && typeof value === 'number'); const overallRating = validRatings.length > 0 ? validRatings.reduce((sum, [_, rating]) => sum + rating, 0) / validRatings.length : 0; const reviewData = { media_id: mediaId, season_id: formSeasonId, media_type: mediaType, content, ratings: { ...ratings, overall: overallRating }, has_spoilers: hasSpoilers, progress: progress, progress_type: progressType }; if (existingReview && isEditing) { await onEdit(existingReview.id, reviewData); setIsEditing(false); } else { await onSubmit(reviewData); } } catch (error) { console.error('Error submitting review:', error); } finally { setIsSubmitting(false); } }; const handleDelete = async () => { if (window.confirm('Вы уверены, что хотите удалить эту рецензию?')) { setIsSubmitting(true); try { await onDelete(existingReview.id, mediaId); // deleteReview only needs reviewId, mediaId is optional // Form reset is handled by the useEffect when existingReview becomes null } catch (error) { console.error('Error deleting review:', error); // Optionally set an error state } finally { setIsSubmitting(false); } } }; // Determine if the form is valid for submission // Content must not be empty, ALL characteristics must have a valid rating (1-10), and progress must be filled/selected const isFormValid = content.trim() !== '' && content !== '
Вы уже написали рецензию на это произведение.