157 lines
5.1 KiB
JavaScript
157 lines
5.1 KiB
JavaScript
import { useState } from 'react';
|
|
import { FaStar } from 'react-icons/fa';
|
|
import RatingChart from './RatingChart';
|
|
|
|
function ReviewForm({ mediaId, mediaType, onSubmit }) {
|
|
const [ratings, setRatings] = useState({
|
|
story: 5,
|
|
visuals: 5,
|
|
performance: 5,
|
|
soundtrack: 5,
|
|
enjoyment: 5
|
|
});
|
|
|
|
const [content, setContent] = useState('');
|
|
const [hasSpoilers, setHasSpoilers] = useState(false);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
const labels = {
|
|
story: 'Story & Writing',
|
|
visuals: 'Visuals & Effects',
|
|
performance: 'Acting/Performance',
|
|
soundtrack: 'Sound & Music',
|
|
enjoyment: 'Overall Enjoyment'
|
|
};
|
|
|
|
const handleRatingChange = (category, value) => {
|
|
setRatings(prev => ({
|
|
...prev,
|
|
[category]: value
|
|
}));
|
|
};
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault();
|
|
setIsSubmitting(true);
|
|
|
|
try {
|
|
// Calculate overall rating
|
|
const overallRating = Object.values(ratings).reduce((sum, rating) => sum + rating, 0) / Object.keys(ratings).length;
|
|
|
|
// Prepare review data
|
|
const reviewData = {
|
|
mediaId,
|
|
mediaType,
|
|
content,
|
|
ratings,
|
|
overallRating,
|
|
hasSpoilers,
|
|
createdAt: new Date().toISOString()
|
|
};
|
|
|
|
await onSubmit(reviewData);
|
|
|
|
// Reset form
|
|
setContent('');
|
|
setRatings({
|
|
story: 5,
|
|
visuals: 5,
|
|
performance: 5,
|
|
soundtrack: 5,
|
|
enjoyment: 5
|
|
});
|
|
setHasSpoilers(false);
|
|
} catch (error) {
|
|
console.error('Error submitting review:', error);
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="bg-campfire-charcoal rounded-lg shadow-md p-6">
|
|
<h2 className="text-xl font-bold mb-6">Write Your Review</h2>
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-6">
|
|
<div className="md:col-span-2">
|
|
{/* Rating Sliders */}
|
|
<div className="space-y-6 mb-6">
|
|
{Object.keys(ratings).map(category => (
|
|
<div key={category} className="space-y-2">
|
|
<div className="flex justify-between">
|
|
<label className="text-campfire-light">{labels[category]}</label>
|
|
<span className="flex items-center text-campfire-amber">
|
|
<FaStar className="mr-1" />
|
|
{ratings[category]}
|
|
</span>
|
|
</div>
|
|
<input
|
|
type="range"
|
|
min="1"
|
|
max="10"
|
|
value={ratings[category]}
|
|
onChange={(e) => handleRatingChange(category, parseInt(e.target.value))}
|
|
className="w-full h-2 bg-campfire-dark rounded-lg appearance-none cursor-pointer"
|
|
style={{
|
|
background: `linear-gradient(to right, #FF9D00 0%, #FF9D00 ${(ratings[category] - 1) * 11.1}%, #2D3748 ${(ratings[category] - 1) * 11.1}%, #2D3748 100%)`
|
|
}}
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Review Text */}
|
|
<div className="mb-6">
|
|
<label htmlFor="review-content" className="block mb-2 text-campfire-light">
|
|
Your Review
|
|
</label>
|
|
<textarea
|
|
id="review-content"
|
|
rows="8"
|
|
placeholder="Share your thoughts on this title..."
|
|
value={content}
|
|
onChange={(e) => setContent(e.target.value)}
|
|
className="w-full p-3 bg-campfire-dark border border-campfire-ash rounded-md text-campfire-light focus:ring-2 focus:ring-campfire-amber focus:border-transparent"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
{/* Spoiler Checkbox */}
|
|
<div className="mb-6 flex items-center">
|
|
<input
|
|
type="checkbox"
|
|
id="spoiler-check"
|
|
checked={hasSpoilers}
|
|
onChange={(e) => setHasSpoilers(e.target.checked)}
|
|
className="w-4 h-4 text-campfire-amber bg-campfire-dark border-campfire-ash rounded focus:ring-campfire-amber focus:ring-2"
|
|
/>
|
|
<label htmlFor="spoiler-check" className="ml-2 text-campfire-light">
|
|
This review contains spoilers
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Rating Chart Preview */}
|
|
<div className="md:col-span-1">
|
|
<p className="text-center text-campfire-light mb-4">Your Rating Preview</p>
|
|
<RatingChart ratings={ratings} size="medium" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Submit Button */}
|
|
<div className="flex justify-end">
|
|
<button
|
|
type="submit"
|
|
disabled={isSubmitting}
|
|
className="btn-primary"
|
|
>
|
|
{isSubmitting ? 'Submitting...' : 'Submit Review'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default ReviewForm; |