-
-
- {bot.candles && bot.candles.length > 0 ? (
-
- ) : null}
-
-
-
- {/* Bot Name - Always on its own line */}
-
- {bot.name}
-
-
- {/* Badge Container - Responsive */}
-
-
- {/* Action Badges - Only show for bot owners */}
- { (
-
- {getToggleBotStatusBadge(bot.status as BotStatus, bot.identifier)}
- {getUpdateBotBadge(bot)}
- {getManualPositionBadge(bot.identifier)}
- {getDeleteBadge(bot.identifier)}
-
- )}
-
-
-
-
-
-
-
-
-
- {
- const realized = p.ProfitAndLoss?.realized ?? 0
- return realized > 0 ? p : null
- })}
- >
- {
- const realized = p.ProfitAndLoss?.realized ?? 0
- return realized <= 0 ? p : null
- })}
- >
-
-
-
-
- WR {bot.winRate?.toFixed(2).toString()} %
-
-
- PNL {bot.profitAndLoss.toFixed(2).toString()} $
-
- {getTradesBadge(bot.name, bot.agentName, bot.identifier)}
-
-
+ // Table columns definition
+ const columns = React.useMemo(
+ () => [
+ {
+ Header: 'Name',
+ accessor: 'name',
+ Cell: ({ row }: any) => (
+
{row.original.name}
+ ),
+ },
+ {
+ Header: 'Status',
+ accessor: 'status',
+ Cell: ({ row }: any) => {
+ const status = row.original.status as BotStatus
+ let statusClass = 'badge '
+ switch (status) {
+ case BotStatus.Running:
+ statusClass += 'badge-success'
+ break
+ case BotStatus.Stopped:
+ statusClass += 'badge-warning'
+ break
+ case BotStatus.Saved:
+ statusClass += 'badge-info'
+ break
+ default:
+ statusClass += 'badge-neutral'
+ }
+ return
{BotStatus[status]}
+ },
+ },
+ {
+ Header: 'Ticker',
+ accessor: 'ticker',
+ },
+ {
+ Header: 'Agent',
+ accessor: 'agentName',
+ },
+ {
+ Header: 'Win Rate %',
+ accessor: 'winRate',
+ Cell: ({ value }: any) => value?.toFixed(2) || '0.00',
+ },
+ {
+ Header: 'PNL $',
+ accessor: 'profitAndLoss',
+ Cell: ({ value }: any) => value?.toFixed(2) || '0.00',
+ },
+ {
+ Header: 'Actions',
+ accessor: 'actions',
+ disableSortBy: true,
+ Cell: ({ row }: any) => {
+ const bot = row.original
+ return (
+
+ {getToggleBotStatusBadge(bot.status, bot.identifier)}
+ {getUpdateBotBadge(bot)}
+ {getManualPositionBadge(bot.identifier)}
+ {getCopyTradingBadge(bot.name, bot.identifier)}
+ {getTradesBadge(bot.name, bot.agentName, bot.identifier)}
+ {getDeleteBadge(bot.identifier)}
-
-
- ))}
+ )
+ },
+ },
+ ],
+ []
+ )
+ return (
+
+ {/* Filters */}
+
+
+
+
+
+
+
+
+ setAgentFilter(e.target.value || undefined)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Table */}
+ {isLoading ? (
+
+ ) : (
+
+ )}
+
+ {/* Modals */}
= ({ list }) => {
config: selectedBotForUpdate.config
} : undefined}
/>
+
+ {/* Copy Trading Modal */}
+ {showCopyTradingModal && selectedBotForCopy && (
+
+
+
Start Copy Trading
+
+ Copy trades from {selectedBotForCopy.name}
+
+
+
+ setCopyTradingBalance(Number(e.target.value))}
+ min="1"
+ step="0.01"
+ />
+
+
+
+
+
+
+
+ )}
)
}
diff --git a/src/Managing.WebApp/src/pages/botsPage/bots.tsx b/src/Managing.WebApp/src/pages/botsPage/bots.tsx
index 33e43f19..4259b9ef 100644
--- a/src/Managing.WebApp/src/pages/botsPage/bots.tsx
+++ b/src/Managing.WebApp/src/pages/botsPage/bots.tsx
@@ -1,92 +1,16 @@
-import {ViewGridAddIcon} from '@heroicons/react/solid'
import React, {useState} from 'react'
-import 'react-toastify/dist/ReactToastify.css'
-import useApiUrlStore from '../../app/store/apiStore'
-import {useCurrentAgentName} from '../../app/store/userStore'
import {UnifiedTradingModal} from '../../components/organism'
-import {BotClient, BotSortableColumn, BotStatus} from '../../generated/ManagingApi'
-import {useQuery} from '@tanstack/react-query'
import BotList from './botList'
const Bots: React.FC = () => {
- const [activeTab, setActiveTab] = useState(0)
const [showBotConfigModal, setShowBotConfigModal] = useState(false)
- const [pageNumber, setPageNumber] = useState(1)
- const [pageSize] = useState(50) // Fixed page size for now
-
- // Reset page number when tab changes
- const handleTabChange = (newTab: number) => {
- setActiveTab(newTab)
- setPageNumber(1) // Reset to first page when changing tabs
- }
- const { apiUrl } = useApiUrlStore()
- const botClient = new BotClient({}, apiUrl)
-
- // Use the new user store hook to get current agent name
- const currentAgentName = useCurrentAgentName()
-
- // Query for paginated bots using the new endpoint
- const { data: paginatedBots } = useQuery({
- queryFn: () => {
- switch (activeTab) {
- case 0: // All Active Bots
- return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Running, undefined, undefined, undefined, BotSortableColumn.Roi, 'Desc')
- case 1: // My Active Bots
- return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Running, undefined, undefined, currentAgentName, BotSortableColumn.Roi, 'Desc')
- case 2: // My Down Bots
- return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Stopped, undefined, undefined, currentAgentName, BotSortableColumn.Roi, 'Desc')
- case 3: // Saved Bots
- return botClient.bot_GetBotsPaginated(pageNumber, pageSize, BotStatus.Saved, undefined, undefined, currentAgentName, BotSortableColumn.Roi, 'Desc')
- default:
- return botClient.bot_GetBotsPaginated(pageNumber, pageSize, undefined, undefined, undefined, undefined, BotSortableColumn.Roi, 'Desc')
- }
- },
- queryKey: ['paginatedBots', activeTab, pageNumber, pageSize, currentAgentName],
- enabled: !!currentAgentName,
- })
-
- const filteredBots = paginatedBots?.items || []
-
- function openCreateBotModal() {
- setShowBotConfigModal(true)
- }
-
-
- const tabs = [
- { label: 'All Active Bots', index: 0 },
- { label: 'My Active Bots', index: 1 },
- { label: 'My Down Bots', index: 2 },
- { label: 'Saved Bots', index: 3 },
- ]
return (
- {/* Action Buttons */}
-
-
- {/* Tabs */}
-
- {tabs.map((tab) => (
-
- ))}
-
-
{/* Bot List */}
-
+
{/* Unified Trading Modal */}