"use client"; import React, { useState, useEffect } from "react"; import { FaStar } from "react-icons/fa"; const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL; const RequestDetailsModal = ({ request, onClose }) => { const [details, setDetails] = useState(null); const [loading, setLoading] = useState(true); const [loadError, setLoadError] = useState(""); const [locallyCompleted, setLocallyCompleted] = useState( request.status === "Выполнена" ); const isRejected = request.status === "Отклонена"; const isDone = request.status === "Выполнена" || locallyCompleted; const canComplete = !isRejected && !isDone; const [rating, setRating] = useState(0); const [review, setReview] = useState(""); const [rejectFeedback, setRejectFeedback] = useState(""); const [responses, setResponses] = useState([]); const [responsesLoading, setResponsesLoading] = useState(true); const [responsesError, setResponsesError] = useState(""); const [acceptLoading, setAcceptLoading] = useState(false); const [acceptError, setAcceptError] = useState(""); const [acceptSuccess, setAcceptSuccess] = useState(""); const [completeLoading, setCompleteLoading] = useState(false); const [completeError, setCompleteError] = useState(""); const [completeSuccess, setCompleteSuccess] = useState(""); const getAccessToken = () => { if (typeof window === "undefined") return null; const saved = localStorage.getItem("authUser"); const authUser = saved ? JSON.parse(saved) : null; return authUser?.accessToken || null; }; useEffect(() => { const fetchDetails = async () => { if (!API_BASE) { setLoadError("API_BASE_URL не задан"); setLoading(false); return; } const accessToken = getAccessToken(); if (!accessToken) { setLoadError("Вы не авторизованы"); setLoading(false); return; } try { const res = await fetch(`${API_BASE}/requests/${request.id}`, { headers: { Accept: "application/json", Authorization: `Bearer ${accessToken}`, }, }); if (!res.ok) { let msg = "Не удалось загрузить заявку"; try { const data = await res.json(); if (data.error) msg = data.error; } catch { const text = await res.text(); if (text) msg = text; } setLoadError(msg); setLoading(false); return; } const data = await res.json(); setDetails(data); setLoading(false); } catch (e) { setLoadError(e.message || "Ошибка сети"); setLoading(false); } }; fetchDetails(); }, [request.id]); useEffect(() => { const fetchResponses = async () => { if (!API_BASE) { setResponsesError("API_BASE_URL не задан"); setResponsesLoading(false); return; } const accessToken = getAccessToken(); if (!accessToken) { setResponsesError("Вы не авторизованы"); setResponsesLoading(false); return; } try { const res = await fetch( `${API_BASE}/requests/${request.id}/responses`, { headers: { Accept: "application/json", Authorization: `Bearer ${accessToken}`, }, } ); if (!res.ok) { let msg = "Не удалось загрузить отклики"; try { const data = await res.json(); if (data.error) msg = data.error; } catch { const text = await res.text(); if (text) msg = text; } setResponsesError(msg); setResponsesLoading(false); return; } const data = await res.json(); setResponses(data); setResponsesLoading(false); } catch (e) { setResponsesError(e.message || "Ошибка сети"); setResponsesLoading(false); } }; fetchResponses(); }, [request.id]); const handleStarClick = (value) => { setRating(value); }; // ЕДИНСТВЕННЫЙ вызов /complete: завершение + отзыв const handleCompleteRequest = async () => { if (!API_BASE) { setCompleteError("API_BASE_URL не задан"); return; } const accessToken = getAccessToken(); if (!accessToken) { setCompleteError("Вы не авторизованы"); return; } if (!canComplete) return; if (!rating) { setCompleteError("Поставьте оценку от 1 до 5"); return; } try { setCompleteLoading(true); setCompleteError(""); setCompleteSuccess(""); const res = await fetch(`${API_BASE}/requests/${request.id}/complete`, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${accessToken}`, }, body: JSON.stringify({ rating, comment: review || null, }), }); let data = null; const text = await res.text(); if (text) { try { data = JSON.parse(text); } catch { data = null; } } if (!res.ok) { let msg = "Не удалось завершить заявку"; if (data && typeof data === "object" && data.error) { msg = data.error; } else if (text) { msg = text; } setCompleteError(msg); setCompleteLoading(false); return; } setLocallyCompleted(true); setCompleteSuccess("Заявка завершена и отзыв отправлен"); setCompleteLoading(false); } catch (e) { setCompleteError(e.message || "Ошибка сети"); setCompleteLoading(false); } }; const handleAcceptResponse = async (responseId) => { if (!API_BASE || !request.id || !responseId) { setAcceptError("Некорректные данные для приёма отклика"); return; } const accessToken = getAccessToken(); if (!accessToken) { setAcceptError("Вы не авторизованы"); return; } try { setAcceptLoading(true); setAcceptError(""); setAcceptSuccess(""); const res = await fetch( `${API_BASE}/requests/${request.id}/responses/${responseId}/accept`, { method: "POST", headers: { Accept: "application/json", Authorization: `Bearer ${accessToken}`, }, } ); if (!res.ok) { let msg = "Не удалось принять отклик"; try { const data = await res.json(); if (data.error) msg = data.error; } catch { const text = await res.text(); if (text) msg = text; } setAcceptError(msg); setAcceptLoading(false); return; } await res.json(); setAcceptSuccess("Волонтёр принят на заявку"); setAcceptLoading(false); } catch (e) { setAcceptError(e.message || "Ошибка сети"); setAcceptLoading(false); } }; const fullDescription = details?.description || request.description || "Описание отсутствует"; const addressLine = details ? [details.address, details.city].filter(Boolean).join(", ") : null; const requesterName = details?.requester?.first_name ? `${details.requester.first_name} ${details.requester.last_name || ""}`.trim() : details?.requester?.email; const requestTypeName = details?.request_type?.name; return (
Заявка от {request.createdAt}
{request.date}
{request.time}
{request.title}
{/* Инфо по заявке */}Загрузка информации о заявке...
)} {loadError && !loading && ({loadError}
)} {!loading && !loadError && ( <> {requestTypeName && (Тип: {requestTypeName}
)} {addressLine && (Адрес: {addressLine}
)} {details?.urgency && (Срочность:{" "} {details.urgency}
)} {requesterName && (Заявитель:{" "} {requesterName}
)} {details?.contact_phone && (Телефон:{" "} {details.contact_phone}
)} {details?.contact_notes && (Комментарий к контакту:{" "} {details.contact_notes}
)}Описание:{" "} {fullDescription}
> )}Отклики волонтёров
{responses.map((resp) => (Волонтёр:{" "} {resp.volunteer_name || resp.volunteername || resp.volunteer?.name}
{resp.message && (Сообщение:{" "} {resp.message}
)}{acceptError}
)} {acceptSuccess && ({acceptSuccess}
)}Загрузка откликов волонтёров...
)} {responsesError && ({responsesError}
)} {/* Отклонена */} {isRejected && ( <> {request.rejectReason && (Причина отказа
{request.rejectReason}
Ваш комментарий
Отзыв о волонтёре
Оценить волонтера
{completeError}
)} {completeSuccess && ({completeSuccess}
)}