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
98 lines
3.7 KiB
TypeScript
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>
|
|
);
|
|
}
|