'use client'; import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import api from '@/lib/api'; import { toast } from 'react-toastify'; import type { Cluster, ClusterPool } from '@/types'; import { Scale, BarChart3, RotateCw, CheckCircle, XCircle, Pencil, Clock, X } from 'lucide-react'; import { useConfirm } from '@/components/confirm-modal'; export default function AdminPoolsPage() { const queryClient = useQueryClient(); const confirm = useConfirm(); const [showForm, setShowForm] = useState(false); const [editingPool, setEditingPool] = useState(null); const [form, setForm] = useState({ name: '', description: '', strategy: 'weighted-resource' as 'least-apps' | 'round-robin' | 'weighted-resource', clusterIds: [] as string[], isDefault: false, priority: 100, }); const { data: pools = [], isLoading } = useQuery({ queryKey: ['admin-pools'], queryFn: () => api.get('/clusters/pools').then((r) => r.data), }); const { data: clusters = [] } = useQuery({ queryKey: ['admin-clusters'], queryFn: () => api.get('/clusters').then((r) => r.data), }); const createMutation = useMutation({ mutationFn: (data: typeof form) => api.post('/clusters/pools', data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin-pools'] }); toast.success('Cluster pool created!'); resetForm(); }, onError: (err: any) => { toast.error(err?.response?.data?.message || 'Failed to create pool'); }, }); const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: typeof form }) => api.patch(`/clusters/pools/${id}`, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin-pools'] }); toast.success('Cluster pool updated!'); resetForm(); }, onError: (err: any) => { toast.error(err?.response?.data?.message || 'Failed to update pool'); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => api.delete(`/clusters/pools/${id}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin-pools'] }); toast.success('Cluster pool deleted'); }, }); const resetForm = () => { setShowForm(false); setEditingPool(null); setForm({ name: '', description: '', strategy: 'weighted-resource', clusterIds: [], isDefault: false, priority: 100 }); }; const startEdit = (pool: ClusterPool) => { setEditingPool(pool); setForm({ name: pool.name, description: pool.description || '', strategy: pool.strategy, clusterIds: pool.clusterIds, isDefault: pool.isDefault || false, priority: pool.priority || 100, }); setShowForm(true); }; const handleSubmit = () => { if (editingPool) { updateMutation.mutate({ id: editingPool.id, data: form }); } else { createMutation.mutate(form); } }; const toggleCluster = (clusterId: string) => { setForm((prev) => ({ ...prev, clusterIds: prev.clusterIds.includes(clusterId) ? prev.clusterIds.filter((id) => id !== clusterId) : [...prev.clusterIds, clusterId], })); }; return (

Cluster Pools

Load-balanced groups of clusters for automatic app distribution

{/* Create/Edit Form */} {showForm && (

{editingPool ? `Edit "${editingPool.name}"` : 'Create New Cluster Pool'}

setForm({ ...form, name: e.target.value })} />
setForm({ ...form, priority: Number(e.target.value) || 100 })} />
setForm({ ...form, description: e.target.value })} />
{/* Cluster selection */}
{clusters.length === 0 ? (

No clusters registered. Add clusters first.

) : (
{clusters.map((cluster) => { const isSelected = form.clusterIds.includes(cluster.id); return ( ); })}
)}
)} {/* Pool List */} {isLoading ? (
{[1,2].map(i => (
))}
) : pools.length === 0 ? (

No cluster pools created yet

Create a pool to enable load-balanced deployment across multiple clusters

) : (
{pools.map((pool) => { const poolClusters = clusters.filter((c) => pool.clusterIds.includes(c.id)); const activeClusters = poolClusters.filter((c) => c.status === 'active'); return (

{pool.name}

{pool.isActive ? 'Active' : 'Inactive'} {pool.strategy === 'weighted-resource' ? <> Weighted Resource : pool.strategy === 'least-apps' ? <> Least Apps : <> Round Robin} {pool.isDefault && Default Pool} Priority {pool.priority || 100}
{pool.description && (

{pool.description}

)} {/* Cluster chips */}
{poolClusters.length > 0 ? poolClusters.map((cluster) => (
{cluster.status === 'active' ? : } {cluster.name} ({cluster.provider || 'N/A'} · {cluster.region || 'N/A'} · weight {cluster.weight || 1} · {cluster.healthStatus || 'unknown'})
)) : (

No clusters in this pool (they may have been deleted)

)}

{activeClusters.length}/{poolClusters.length} clusters active · Created {new Date(pool.createdAt).toLocaleDateString()}

); })}
)}
); }