event.stopPropagation()}>
+
event.target.id === "client-help-overlay" && onClose()}>
+
event.stopPropagation()}>
-
{title}
+ Помощь по заявке
-
-
);
}
- function ServiceRequestList({ rows }) {
- const safeRows = Array.isArray(rows) ? rows : [];
- return (
-
- );
- }
-
function App() {
const [requestModal, setRequestModal] = useState(createRequestModalState());
const [requestsList, setRequestsList] = useState([]);
const [activeTrack, setActiveTrack] = useState("");
const [status, setStatus] = useState({ message: "", kind: "" });
const [serviceRequests, setServiceRequests] = useState([]);
- const [serviceRequestModal, setServiceRequestModal] = useState({ open: false, type: "", body: "", loading: false, status: { message: "", kind: "" } });
+ const [clientHelpModal, setClientHelpModal] = useState({
+ open: false,
+ loadingType: "",
+ lawyerChangeReason: "",
+ status: { message: "", kind: "" },
+ });
const setPageStatus = useCallback((message, kind) => {
setStatus({ message: String(message || ""), kind: kind || "" });
}, []);
- const setServiceStatus = useCallback((message, kind) => {
- setServiceRequestModal((prev) => ({ ...prev, status: { message: String(message || ""), kind: kind || "" } }));
- }, []);
-
const apiError = (data, fallback) => {
if (data && typeof data.detail === "string" && data.detail.trim()) return data.detail;
return fallback;
@@ -656,60 +656,103 @@ import { detectAttachmentPreviewKind, fmtShortDateTime } from "./admin/shared/ut
[activeTrack, apiJson]
);
- const openServiceRequestModal = useCallback((type) => {
- const normalized = String(type || "").trim().toUpperCase();
- if (!normalized) return;
- setServiceRequestModal({
+ const openClientHelpModal = useCallback(() => {
+ setClientHelpModal((prev) => ({
+ ...prev,
open: true,
- type: normalized,
- body: "",
- loading: false,
status: { message: "", kind: "" },
- });
+ }));
}, []);
- const closeServiceRequestModal = useCallback(() => {
- setServiceRequestModal({ open: false, type: "", body: "", loading: false, status: { message: "", kind: "" } });
+ const closeClientHelpModal = useCallback(() => {
+ setClientHelpModal((prev) => ({
+ ...prev,
+ open: false,
+ loadingType: "",
+ status: { message: "", kind: "" },
+ }));
}, []);
+ const normalizedCurrentLawyerId = String(requestModal.requestData?.assigned_lawyer_id || "")
+ .trim()
+ .toLowerCase();
+
+ const serviceRequestState = useMemo(() => {
+ const rows = Array.isArray(serviceRequests) ? serviceRequests : [];
+ const curatorRows = rows.filter((item) => String(item?.type || "").toUpperCase() === "CURATOR_CONTACT");
+ const lawyerRows = rows.filter((item) => String(item?.type || "").toUpperCase() === "LAWYER_CHANGE_REQUEST");
+ const latestLawyerChange = lawyerRows[0] || null;
+ const hasCuratorRequest = curatorRows.length > 0;
+
+ let lawyerChangeDisabledByState = false;
+ if (latestLawyerChange) {
+ const hasLawyerSnapshot = Object.prototype.hasOwnProperty.call(latestLawyerChange, "assigned_lawyer_id");
+ if (hasLawyerSnapshot) {
+ const requestedForLawyer = String(latestLawyerChange?.assigned_lawyer_id || "")
+ .trim()
+ .toLowerCase();
+ lawyerChangeDisabledByState = requestedForLawyer === normalizedCurrentLawyerId;
+ } else {
+ const statusCode = String(latestLawyerChange?.status || "").toUpperCase();
+ lawyerChangeDisabledByState = statusCode === "NEW" || statusCode === "IN_PROGRESS";
+ }
+ }
+
+ return {
+ hasCuratorRequest,
+ lawyerChangeDisabledByState,
+ };
+ }, [normalizedCurrentLawyerId, serviceRequests]);
+
+ const canInteract = Boolean(requestModal.requestData && !requestModal.loading);
+ const curatorBlocked = !canInteract || serviceRequestState.hasCuratorRequest;
+ const lawyerChangeBlocked = !canInteract || serviceRequestState.lawyerChangeDisabledByState;
+
const submitServiceRequest = useCallback(
- async (event) => {
- if (event && typeof event.preventDefault === "function") event.preventDefault();
+ async ({ type, body }) => {
const track = String(activeTrack || "").trim();
+ const requestType = String(type || "").trim().toUpperCase();
+ const message = String(body || "").trim();
if (!track) {
- setServiceStatus("Сначала выберите заявку.", "error");
+ setClientHelpModal((prev) => ({ ...prev, status: { message: "Сначала выберите заявку.", kind: "error" } }));
return;
}
- const requestType = String(serviceRequestModal.type || "").trim().toUpperCase();
- const body = String(serviceRequestModal.body || "").trim();
if (!requestType) {
- setServiceStatus("Выберите тип обращения.", "error");
+ setClientHelpModal((prev) => ({ ...prev, status: { message: "Не указан тип запроса.", kind: "error" } }));
return;
}
- if (body.length < 3) {
- setServiceStatus("Сообщение должно содержать минимум 3 символа.", "error");
+ if (message.length < 3) {
+ setClientHelpModal((prev) => ({ ...prev, status: { message: "Сообщение должно содержать минимум 3 символа.", kind: "error" } }));
return;
}
try {
- setServiceRequestModal((prev) => ({ ...prev, loading: true, status: { message: "", kind: "" } }));
+ setClientHelpModal((prev) => ({ ...prev, loadingType: requestType, status: { message: "", kind: "" } }));
await apiJson(
"/api/public/requests/" + encodeURIComponent(track) + "/service-requests",
{
method: "POST",
headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ type: requestType, body }),
+ body: JSON.stringify({ type: requestType, body: message }),
},
"Не удалось отправить обращение"
);
await loadRequestWorkspace(track, false);
setPageStatus("Обращение отправлено.", "ok");
- closeServiceRequestModal();
+ setClientHelpModal((prev) => ({
+ ...prev,
+ loadingType: "",
+ status: { message: "Обращение отправлено.", kind: "ok" },
+ lawyerChangeReason: requestType === "LAWYER_CHANGE_REQUEST" ? "" : prev.lawyerChangeReason,
+ }));
} catch (error) {
- setServiceRequestModal((prev) => ({ ...prev, loading: false }));
- setServiceStatus(error?.message || "Не удалось отправить обращение", "error");
+ setClientHelpModal((prev) => ({
+ ...prev,
+ loadingType: "",
+ status: { message: error?.message || "Не удалось отправить обращение", kind: "error" },
+ }));
}
},
- [activeTrack, apiJson, closeServiceRequestModal, loadRequestWorkspace, serviceRequestModal.body, serviceRequestModal.type, setPageStatus, setServiceStatus]
+ [activeTrack, apiJson, loadRequestWorkspace, setPageStatus]
);
useEffect(() => {
@@ -721,7 +764,6 @@ import { detectAttachmentPreviewKind, fmtShortDateTime } from "./admin/shared/ut
}, [loadMyRequests, setPageStatus]);
const summary = requestModal.requestData || null;
- const canInteract = Boolean(summary && !requestModal.loading);
return (
@@ -731,9 +773,17 @@ import { detectAttachmentPreviewKind, fmtShortDateTime } from "./admin/shared/ut
Кабинет клиента
Работа с заявками: статусы, чат, файлы и обращения.
-
+
+ ?
+