"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}

{/* Карточка */}
{/* Статус + дата/время */}
{isDone ? "Выполнена" : request.status}

{request.date}

{request.time}

{/* Название */}

{request.title}

{/* Инфо по заявке */}
{loading && (

Загрузка информации о заявке...

)} {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}

)}
{/* Отклики волонтёров (как было) */} {!responsesLoading && !responsesError && responses.length > 0 && (

Отклики волонтёров

{responses.map((resp) => (

Волонтёр:{" "} {resp.volunteer_name || resp.volunteername || resp.volunteer?.name}

{resp.message && (

Сообщение:{" "} {resp.message}

)}
))} {acceptError && (

{acceptError}

)} {acceptSuccess && (

{acceptSuccess}

)}
)} {responsesLoading && !responsesError && (

Загрузка откликов волонтёров...

)} {responsesError && (

{responsesError}

)} {/* Отклонена */} {isRejected && ( <> {request.rejectReason && (

Причина отказа

{request.rejectReason}

)}

Ваш комментарий