diff --git a/frontend/src/BillingManager.jsx b/frontend/src/BillingManager.jsx index 00a088a..88061d8 100644 --- a/frontend/src/BillingManager.jsx +++ b/frontend/src/BillingManager.jsx @@ -26,8 +26,13 @@ import { IconUpload, IconEye, IconEyeOff, - IconHistory + IconHistory, + IconChevronUp, + IconChevronDown, + IconX, + IconChecks } from '@tabler/icons-react'; +import BulkActionsBar from './components/BulkActionsBar.jsx'; function BillingManager() { const [billingData, setBillingData] = useState([]); @@ -63,6 +68,21 @@ function BillingManager() { const [editingPayment, setEditingPayment] = useState(null); // { serverId, index } const [showDeletePaymentModal, setShowDeletePaymentModal] = useState(false); const [paymentToDelete, setPaymentToDelete] = useState(null); // { serverId, index, data } + const [futureDateConfirm, setFutureDateConfirm] = useState(false); // Подтверждение будущей даты + + // Состояния для истории платежей: поиск, сортировка, фильтры + const [paymentSearchTerm, setPaymentSearchTerm] = useState(''); + const [paymentSortField, setPaymentSortField] = useState('date'); + const [paymentSortOrder, setPaymentSortOrder] = useState('desc'); + const [paymentFilterServer, setPaymentFilterServer] = useState(''); + const [paymentFilterDateFrom, setPaymentFilterDateFrom] = useState(''); + const [paymentFilterDateTo, setPaymentFilterDateTo] = useState(''); + const [paymentFilterAmountFrom, setPaymentFilterAmountFrom] = useState(''); + const [paymentFilterAmountTo, setPaymentFilterAmountTo] = useState(''); + const [showPaymentFilters, setShowPaymentFilters] = useState(false); + const [selectedPayments, setSelectedPayments] = useState(new Set()); + const [paymentPage, setPaymentPage] = useState(1); + const paymentPageSize = 20; // Состояние для курсов валют const [exchangeRates, setExchangeRates] = useState({ @@ -868,23 +888,272 @@ function BillingManager() { История платежей
| Имя хостера | -Дата | -Сумма | ++ 0 && (() => { + const allRows = billingData.flatMap(server => + (server.payments || []).map((p, idx) => ({ server, ...p, _key: `${server.id}-${idx}`, _index: idx })) + ); + return selectedPayments.size === allRows.length; + })()} + onChange={(e) => { + if (e.target.checked) { + const allRows = billingData.flatMap(server => + (server.payments || []).map((p, idx) => ({ server, ...p, _key: `${server.id}-${idx}`, _index: idx })) + ); + setSelectedPayments(new Set(allRows.map(r => r._key))); + } else { + setSelectedPayments(new Set()); + } + }} + /> + | + {
+ if (paymentSortField === 'hostName') {
+ setPaymentSortOrder(paymentSortOrder === 'asc' ? 'desc' : 'asc');
+ } else {
+ setPaymentSortField('hostName');
+ setPaymentSortOrder('asc');
+ }
+ }}
+ >
+
+ Имя хостера
+ {paymentSortField === 'hostName' && (
+ paymentSortOrder === 'asc' ?
+ |
+ {
+ if (paymentSortField === 'date') {
+ setPaymentSortOrder(paymentSortOrder === 'asc' ? 'desc' : 'asc');
+ } else {
+ setPaymentSortField('date');
+ setPaymentSortOrder('desc');
+ }
+ }}
+ >
+
+ Дата
+ {paymentSortField === 'date' && (
+ paymentSortOrder === 'asc' ?
+ |
+ {
+ if (paymentSortField === 'amount') {
+ setPaymentSortOrder(paymentSortOrder === 'asc' ? 'desc' : 'asc');
+ } else {
+ setPaymentSortField('amount');
+ setPaymentSortOrder('desc');
+ }
+ }}
+ >
+
+ Сумма
+ {paymentSortField === 'amount' && (
+ paymentSortOrder === 'asc' ?
+ |
Валюта | Комментарий | Действия | @@ -892,106 +1161,203 @@ function BillingManager() {||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
- {r.server.hostName}
-
- {r.server.loginUrl && (
-
+ |
+
+
+ Платежи не найдены
+ {allRows.length === 0 && billingData.every(i => !i.payments || i.payments.length === 0) && (
+ <>
+
+ Добавьте первый платеж, чтобы начать отслеживание
+
+
+ {
+ const newSet = new Set(selectedPayments);
+ if (e.target.checked) {
+ newSet.add(r._key);
+ } else {
+ newSet.delete(r._key);
+ }
+ setSelectedPayments(newSet);
+ }}
/>
- )}
- {r.server.provider}
-
- |
- {formatDate(r.date)} |
-
- |
- {formatCurrency(r.amount, r.currency)}
- {formatCurrencyInRUB(r.amount, r.currency)}
- {r.currency || 'USD'} |
- {r.note || ''} |
-
- |
-
-
- |
+
+ {r.server.hostName}
+
+ {r.server.loginUrl && (
+
+ |
+ {formatDate(r.date)} | +
+ {formatCurrency(r.amount, r.currency)}
+ {formatCurrencyInRUB(r.amount, r.currency)}
+ |
+ {r.currency || 'USD'} | +{r.note || ''} | +
+
+
+ |
+ ||||||
|
+ |
+ |||||||||||||||||||
|
-
-
- История платежей пуста
-
- Добавьте первый платеж, чтобы начать отслеживание
-
- |
- |||||||||||||||||||