Files
GuardDen/dashboard/frontend/src/pages/Servers.tsx
latte 574a07d127
Some checks failed
CI/CD Pipeline / Security Scanning (push) Has been cancelled
CI/CD Pipeline / Tests (3.11) (push) Has been cancelled
CI/CD Pipeline / Tests (3.12) (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
Update dashboard and Docker compose
2026-01-24 19:14:00 +01:00

98 lines
3.7 KiB
TypeScript

/**
* Servers overview page
*/
import { useQuery } from '@tanstack/react-query';
import { Link } from 'react-router-dom';
import { guildsApi } from '../services/api';
export function Servers() {
const { data: guilds, isLoading } = useQuery({
queryKey: ['guilds'],
queryFn: guildsApi.list,
});
const total = guilds?.length ?? 0;
const premiumCount = guilds?.filter((guild) => guild.premium).length ?? 0;
const standardCount = total - premiumCount;
return (
<div className="space-y-6">
{/* Header */}
<div className="flex justify-between items-center">
<div>
<h1 className="text-3xl font-bold text-gray-900">Servers</h1>
<p className="text-gray-600 mt-1">All servers that have added GuardDen</p>
</div>
</div>
{/* Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="stat-card">
<div className="stat-label">Total Servers</div>
<div className="stat-value">{total}</div>
</div>
<div className="stat-card">
<div className="stat-label">Premium Servers</div>
<div className="stat-value">{premiumCount}</div>
</div>
<div className="stat-card">
<div className="stat-label">Standard Servers</div>
<div className="stat-value">{standardCount}</div>
</div>
</div>
{/* Table */}
<div className="card">
{isLoading ? (
<div className="text-center py-12">Loading...</div>
) : guilds && guilds.length > 0 ? (
<div className="overflow-x-auto">
<table className="w-full">
<thead>
<tr className="border-b border-gray-200">
<th className="text-left py-3 px-4 font-semibold text-gray-700">Server</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Server ID</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Owner ID</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Plan</th>
<th className="text-left py-3 px-4 font-semibold text-gray-700">Actions</th>
</tr>
</thead>
<tbody>
{guilds.map((guild) => (
<tr key={guild.id} className="border-b border-gray-100 hover:bg-gray-50">
<td className="py-3 px-4 font-medium">{guild.name}</td>
<td className="py-3 px-4 text-sm text-gray-600">{guild.id}</td>
<td className="py-3 px-4 text-sm text-gray-600">{guild.owner_id}</td>
<td className="py-3 px-4">
<span
className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${
guild.premium
? 'bg-yellow-100 text-yellow-800'
: 'bg-gray-100 text-gray-700'
}`}
>
{guild.premium ? 'Premium' : 'Standard'}
</span>
</td>
<td className="py-3 px-4">
<Link
to={`/settings?guild=${guild.id}`}
className="text-sm text-primary-600 hover:text-primary-700 font-medium"
>
Configure
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
) : (
<div className="text-center py-12 text-gray-600">No servers found</div>
)}
</div>
</div>
);
}