WIPVOLONT

This commit is contained in:
fullofempt
2025-12-14 21:14:55 +05:00
parent 433b9e896c
commit 0df52352a8
12 changed files with 893 additions and 440 deletions

View File

@@ -1,9 +1,14 @@
"use client";
import React from "react";
import React, { useState } from "react";
import { FaTimesCircle } from "react-icons/fa";
const AcceptPopup = ({ request, isOpen, onClose, onAccept, loading, error }) => {
const API_BASE = process.env.NEXT_PUBLIC_API_BASE_URL;
const AcceptPopup = ({ request, isOpen, onClose }) => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
if (!isOpen || !request) return null;
const title = request.title;
@@ -15,14 +20,21 @@ const AcceptPopup = ({ request, isOpen, onClose, onAccept, loading, error }) =>
const city = request.city ? `, ${request.city}` : "";
const place = `${baseAddress}${city}`;
const deadline = request.desired_completion_date
? new Date(request.desired_completion_date).toLocaleString("ru-RU", {
let deadline = "Не указано";
if (request.desired_completion_date) {
const d = new Date(request.desired_completion_date);
if (!Number.isNaN(d.getTime())) {
const datePart = d.toLocaleDateString("ru-RU", {
day: "2-digit",
month: "2-digit",
});
const timePart = d.toLocaleTimeString("ru-RU", {
hour: "2-digit",
minute: "2-digit",
})
: "Не указано";
});
deadline = `${datePart}, ${timePart}`;
}
}
const phone = request.contact_phone || request.phone;
const contactNotes = request.contact_notes || request.contactNotes;
@@ -42,26 +54,79 @@ const AcceptPopup = ({ request, isOpen, onClose, onAccept, loading, error }) =>
}
})();
const handleClick = () => {
// здесь видно, с каким id ты стучишься в /requests/{id}/responses
console.log("Отклик на заявку из попапа:", {
id: request.id,
title: request.title,
raw: request,
});
onAccept(request);
const getAccessToken = () => {
if (typeof window === "undefined") return null;
const saved = localStorage.getItem("authUser");
const authUser = saved ? JSON.parse(saved) : null;
return authUser?.accessToken || null;
};
// тут полностью логика отклика
const handleClick = async () => {
if (!API_BASE || !request.id) {
setError("Некорректная заявка (нет id)");
return;
}
const accessToken = getAccessToken();
if (!accessToken) {
setError("Вы не авторизованы");
return;
}
try {
setLoading(true);
setError("");
console.log("POST отклик", {
url: `${API_BASE}/requests/${request.id}/responses`,
requestId: request.id,
});
const res = await fetch(`${API_BASE}/requests/${request.id}/responses`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `Bearer ${accessToken}`,
},
// по схеме тело обязательно, просто пустой объект допустим [file:598]
body: JSON.stringify({}),
});
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;
}
console.error("Ответ API /responses:", msg);
setError(msg);
setLoading(false);
return;
}
await res.json(); // VolunteerResponse [file:598]
setLoading(false);
onClose();
} catch (e) {
setError(e.message || "Ошибка сети");
setLoading(false);
}
};
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="fixed inset-0 z-50 flex items-center justify-center">
{/* затемнение */}
<div
className="absolute inset-0 bg-black/40"
onClick={onClose}
/>
{/* карточка на всю страницу */}
<div className="relative z-10 w-full h-250px bg-white rounded-2xl px-4 pt-4 pb-6 flex flex-col">
{/* карточка поверх всего */}
<div className="relative z-50 w-full max-w-[400px] bg-white rounded-2xl px-4 pt-4 pb-6 flex flex-col mt-50">
{/* крестик */}
<button
type="button"
@@ -80,9 +145,9 @@ const AcceptPopup = ({ request, isOpen, onClose, onAccept, loading, error }) =>
</p>
{/* Только время выполнить до */}
<div className="flex.items-center gap-3 mb-3">
<div className="flex items-center gap-3 mb-3">
<div className="w-full h-[40px] bg-[#90D2F9] rounded-full flex flex-col items-center justify-center">
<span className="text-[12px] leading-[11px] text-white font-semibold.mb-2">
<span className="text-[12px] leading-[11px] text-white font-semibold mb-1">
Выполнить до
</span>
<span className="text-[15px] leading-[13px] text-white font-semibold">