From 4b17da42e88e5231e81eb614c2d6b405106e8457 Mon Sep 17 00:00:00 2001 From: Redsandyg Date: Sat, 7 Jun 2025 12:25:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D1=82=D0=B2=D0=B5=D1=80=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8=D0=B9=20?= =?UTF-8?q?=D0=B2=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=20AccountAgentTransactionSection.=20=D0=A0=D0=B5=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=20=D0=B0=D1=81=D0=B8?= =?UTF-8?q?=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=81=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=BE?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BA=20=D0=B0=D0=B2=D1=82?= =?UTF-8?q?=D0=BE=D0=BF=D0=BE=D0=B4=D1=82=D0=B2=D0=B5=D1=80=D0=B6=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=D0=BC=20?= =?UTF-8?q?=D1=82=D0=BE=D0=BA=D0=B5=D0=BD=D0=B0=20=D0=B0=D0=B2=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8.=20=D0=9E=D0=B1?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BA=D0=BE=D0=BC=D0=BF?= =?UTF-8?q?=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=20AccountAgentTransactionTable?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=BA=D0=B8=20=D0=BD=D0=BE=D0=B2=D1=8B=D1=85=20=D1=84?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B9=20=D0=B8=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B8=20=D1=83=D1=82=D0=B2=D0=B5=D1=80=D0=B6=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA?= =?UTF-8?q?=D1=86=D0=B8=D0=B9.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=81=D1=82=D0=B8=D0=BB=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=81=D1=82=D0=B0=D1=82=D1=83=D1=81?= =?UTF-8?q?=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=82=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D1=86=D0=B0=D1=85.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AccountAgentTransactionSection.tsx | 101 +++++++++++++++--- .../AccountAgentTransactionTable.tsx | 57 ++++++++-- src/components/BillingPieChart.tsx | 1 + src/components/BillingStatChart.tsx | 1 + src/components/PayoutsTransactionsTable.tsx | 1 + 5 files changed, 143 insertions(+), 18 deletions(-) diff --git a/src/components/AccountAgentTransactionSection.tsx b/src/components/AccountAgentTransactionSection.tsx index 795ec27..f1b22ff 100644 --- a/src/components/AccountAgentTransactionSection.tsx +++ b/src/components/AccountAgentTransactionSection.tsx @@ -1,7 +1,8 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import DateFilters from "./DateFilters"; import AccountAgentTransactionTable from "./AccountAgentTransactionTable"; import styles from "../styles/account.module.css"; +import Cookies from 'js-cookie'; export default function AccountAgentTransactionSection() { const [filters, setFilters] = useState({ @@ -12,6 +13,33 @@ export default function AccountAgentTransactionSection() { const [autoConfirmEnabled, setAutoConfirmEnabled] = useState(false); const [showConfirmationUI, setShowConfirmationUI] = useState(false); + useEffect(() => { + const fetchAutoApproveSettings = async () => { + const token = Cookies.get("access_token"); + if (!token) { + console.warn("Токен авторизации не найден при загрузке настроек автоподтверждения."); + return; + } + try { + const res = await fetch("/api/account/auto-approve", { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + if (!res.ok) { + console.error('Ошибка при загрузке настроек автоподтверждения:', res.status, res.statusText); + return; + } + const data = await res.json(); + setAutoConfirmEnabled(data.auto_approve_transactions); + } catch (error) { + console.error('Ошибка при загрузке настроек автоподтверждения:', error); + } + }; + + fetchAutoApproveSettings(); + }, []); + function handleApply() { setReloadKey(k => k + 1); } @@ -25,24 +53,72 @@ export default function AccountAgentTransactionSection() { if (isChecked) { setShowConfirmationUI(true); } else { + updateAutoApproveSettings(false, false); setAutoConfirmEnabled(false); setShowConfirmationUI(false); console.log("Автоматическое подтверждение выключено."); } }; - const handleConfirmYes = () => { - setAutoConfirmEnabled(true); - setShowConfirmationUI(false); - console.log("Автоматическое подтверждение включено и текущие транзакции будут подтверждены."); - // TODO: Добавить логику автоматического подтверждения текущих транзакций + const updateAutoApproveSettings = async (auto_approve: boolean, apply_to_current: boolean = false) => { + const token = Cookies.get("access_token"); + if (!token) { + console.warn("Токен авторизации не найден при попытке обновить настройки автоподтверждения."); + return; + } + try { + const res = await fetch("/api/account/auto-approve", { + method: "POST", + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ + auto_approve: auto_approve, + apply_to_current: apply_to_current, + }) + }); + if (!res.ok) { + const errorData = await res.json(); + console.error('Ошибка при обновлении настроек автоподтверждения:', res.status, res.statusText, errorData); + return false; + } + const responseData = await res.json(); + console.log('Настройка автоподтверждения успешно обновлена:', responseData); + if (apply_to_current) { + setReloadKey(k => k + 1); + } + return true; + } catch (error) { + console.error('Ошибка при отправке запроса на обновление настроек автоподтверждения:', error); + return false; + } }; - const handleConfirmNo = () => { - setAutoConfirmEnabled(true); - setShowConfirmationUI(false); - console.log("Автоматическое подтверждение включено для новых транзакций. Текущие остаются неподтвержденными."); - // Текущие транзакции остаются в статусе waiting, ничего дополнительно делать не нужно + const handleConfirmYes = async () => { + const success = await updateAutoApproveSettings(true, true); + if (success) { + setAutoConfirmEnabled(true); + setShowConfirmationUI(false); + console.log("Автоматическое подтверждение включено и текущие транзакции будут подтверждены."); + } else { + setAutoConfirmEnabled(false); + setShowConfirmationUI(false); + console.log("Включение автоматического подтверждения не удалось."); + } + }; + + const handleConfirmNo = async () => { + const success = await updateAutoApproveSettings(true, false); + if (success) { + setAutoConfirmEnabled(true); + setShowConfirmationUI(false); + console.log("Автоматическое подтверждение включено для новых транзакций. Текущие остаются неподтвержденными."); + } else { + setAutoConfirmEnabled(false); + setShowConfirmationUI(false); + console.log("Включение автоматического подтверждения не удалось."); + } }; const handleConfirmCancel = () => { @@ -67,6 +143,7 @@ export default function AccountAgentTransactionSection() { checked={autoConfirmEnabled} onChange={handleToggleChange} className={styles.notificationsSwitchInput} + disabled={showConfirmationUI} /> - + ); } \ No newline at end of file diff --git a/src/components/AccountAgentTransactionTable.tsx b/src/components/AccountAgentTransactionTable.tsx index 1268d99..93f096a 100644 --- a/src/components/AccountAgentTransactionTable.tsx +++ b/src/components/AccountAgentTransactionTable.tsx @@ -13,6 +13,7 @@ const STATUS_COLORS: Record = { "error": "#EF4444", // Красный "process": "#3B82F6", // Синий "reject": "#800080", // Фиолетовый + "new": "#E30B5C", // Малиновый }; function formatCurrency(amount: number) { @@ -23,13 +24,15 @@ function formatCurrency(amount: number) { }) ?? ""; } -export default function AccountAgentTransactionTable({ filters, reloadKey }: { filters: { dateStart: string, dateEnd: string }, reloadKey: number }) { +export default function AccountAgentTransactionTable({ filters, reloadKey, setReloadKey }: { filters: { dateStart: string, dateEnd: string }, reloadKey: number, setReloadKey: React.Dispatch> }) { const [data, setData] = useState([]); + const [isLoading, setIsLoading] = useState(false); useEffect(() => { const token = Cookies.get("access_token"); if (token) { + setIsLoading(true); const params = new URLSearchParams(); if (filters.dateStart) params.append('date_start', filters.dateStart); if (filters.dateEnd) params.append('date_end', filters.dateEnd); @@ -57,6 +60,9 @@ export default function AccountAgentTransactionTable({ filters, reloadKey }: { f .catch(error => { console.error('Ошибка при загрузке данных транзакций агентов:', error); setData([]); + }) + .finally(() => { + setIsLoading(false); }); } else { console.warn('Токен авторизации не найден в куках.'); @@ -74,7 +80,7 @@ export default function AccountAgentTransactionTable({ filters, reloadKey }: { f Cell: ({ cell }) => { const status = cell.getValue() as string; const color = STATUS_COLORS[status] || '#A3A3A3'; - return {status}; + return {status}; } }, { accessorKey: 'create_dttm', header: 'Дата создания', Cell: ({ cell }) => new Date(cell.getValue() as string).toLocaleDateString() }, @@ -93,16 +99,55 @@ export default function AccountAgentTransactionTable({ filters, reloadKey }: { f columns, data, enableRowSelection: true, + state: { + isLoading: isLoading, + }, renderTopToolbarCustomActions: ({ table }) => (