'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 { useT, useLocale } from '@/i18n/I18nProvider'; import type { Cluster, ClusterPool } from '@/types'; import { Scale, BarChart3, RotateCw, CheckCircle, XCircle, Pencil, Clock, X } from 'lucide-react'; import { useConfirm } from '@/components/confirm-modal'; import { Select } from '@/components/ui/select'; export default function AdminPoolsPage() { const t = useT(); const p = t.dashboard.pools; const locale = useLocale(); const strategyOption = (s: string) => (p.strategyOptions as Record)[s] ?? s; const strategyShort = (s: string) => (p.strategyShort as Record)[s] ?? s; const clusterStatusLabel = (s?: string) => (s && (p.clusterStatus as Record)[s]) || s || ''; const clusterHealthLabel = (h?: string) => (h && (p.clusterHealth as Record)[h]) || h || p.clusterHealth.unknown; 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-round-robin' | 'least-loaded' | 'weighted-resource' | 'region-based', 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(p.poolCreated); resetForm(); }, onError: (err: any) => { toast.error(err?.response?.data?.message || p.createFailed); }, }); 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(p.poolUpdated); resetForm(); }, onError: (err: any) => { toast.error(err?.response?.data?.message || p.updateFailed); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => api.delete(`/clusters/pools/${id}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin-pools'] }); toast.success(p.poolDeleted); }, }); 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], })); }; const strategyIcon = (strategy: string) => strategy === 'weighted-round-robin' || strategy === 'round-robin' ? ( ) : ( ); return (

{p.title}

{p.subtitle}

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

{editingPool ? p.editTitle.replace('{name}', editingPool.name) : p.createNewPool}

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 ? (

{p.noClustersRegistered}

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

{p.noPools}

{p.noPoolsHint}

) : (
{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 ? p.active : p.inactive} {strategyIcon(pool.strategy)} {strategyShort(pool.strategy)} {pool.isDefault && {p.defaultPool}} {p.priorityBadge.replace('{n}', String(pool.priority || 100))}
{pool.description && (

{pool.description}

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

{p.noClustersInPool}

)}

{p.clustersActive .replace('{active}', String(activeClusters.length)) .replace('{total}', String(poolClusters.length)) .replace('{date}', new Date(pool.createdAt).toLocaleDateString(locale))}

); })}
)}
); }