/* Reviews */
function ReviewStars({ value, compact = false }) {
const rating = Math.max(0, Math.min(5, Number(value) || 0));
return (
{[1, 2, 3, 4, 5].map((star) => (
★
))}
);
}
function RatingInput({ value, onChange }) {
return (
{[1, 2, 3, 4, 5].map((star) => (
))}
);
}
function ReviewsPanel({ serviceSlug = '', serviceTitle = '' }) {
const data = window.__PUBLIC_DATA__ || {};
const services = data.services || [];
const allReviews = data.reviews || [];
const initialReviews = serviceSlug
? allReviews.filter((review) => review.service_slug === serviceSlug)
: allReviews;
const defaultService = serviceSlug || services[0]?.slug || '';
const [reviews, setReviews] = React.useState(initialReviews);
const [rating, setRating] = React.useState(5);
const [selectedService, setSelectedService] = React.useState(defaultService);
const [error, setError] = React.useState('');
const [sent, setSent] = React.useState(false);
const fileRef = React.useRef(null);
React.useEffect(() => {
setReviews(serviceSlug ? allReviews.filter((review) => review.service_slug === serviceSlug) : allReviews);
setSelectedService(serviceSlug || services[0]?.slug || '');
}, [serviceSlug]);
const handleSubmit = async (event) => {
event.preventDefault();
setError('');
setSent(false);
const form = event.currentTarget;
const payload = new FormData(form);
payload.set('rating', String(rating));
payload.set('service_slug', serviceSlug || selectedService);
try {
const response = await fetch('/reviews/', {
method: 'POST',
body: payload,
credentials: 'same-origin',
});
const body = await response.json();
if (!response.ok || !body.ok) {
const message = Object.values(body.errors || {}).join(' ') || 'Не получилось отправить отзыв.';
throw new Error(message);
}
if (body.review) {
setReviews((current) => [body.review, ...current]);
}
setSent(true);
setRating(5);
form.reset();
if (fileRef.current) fileRef.current.value = '';
window.setTimeout(() => setSent(false), 4000);
} catch (err) {
setError(err.message || 'Не получилось отправить отзыв.');
}
};
return (
// отзывы
{serviceSlug ? <>Отзывы по услуге> : <>Отзывы клиентов>}
{serviceSlug
? `Здесь показываются только отзывы по услуге «${serviceTitle || serviceSlug}».`
: 'Все отзывы по услугам на сайте.'}
{reviews.length || 0}
{serviceSlug ? 'отзывов по услуге' : 'отзывов всего'}
{reviews.length > 0 ? reviews.map((review) => (
{review.author_name}
{review.created_at_label && {review.created_at_label}}
{!serviceSlug && review.service_title && (
{review.service_title}
)}
{review.text}
{review.photo_path &&
}
{review.admin_reply && (
Ответ администратора
{review.admin_reply}
)}
)) : (
Отзывов пока нет
Можно оставить первый отзыв после выполненной задачи. Он появится в этом блоке с привязкой к услуге.
)}
$
winetlab review
● open
{serviceSlug ? (
Услуга
{serviceTitle || serviceSlug}
) : (
)}
{error && {error}
}
{sent && Спасибо, отзыв опубликован.
}
);
}
window.ReviewsPanel = ReviewsPanel;