Files
GSM/temp_ServerCard.jsx
2026-01-07 02:41:37 +01:00

209 lines
6.9 KiB
JavaScript

const serverInfo = {
minecraft: {
address: 'minecraft.dimension47.de',
logo: '/minecraft.png',
links: [
{ label: 'ATM10 Modpack', url: 'https://www.curseforge.com/minecraft/modpacks/all-the-mods-10' }
]
},
factorio: {
hint: 'Serverpasswort: affe',
address: 'factorio.dimension47.de',
logo: '/factorio.png',
links: [
{ label: 'Steam', url: 'https://store.steampowered.com/app/427520/Factorio/' }
]
},
vrising: {
address: 'Zeasy Software Vampire',
logo: '/vrising.png',
links: [
{ label: 'Steam', url: 'https://store.steampowered.com/app/1604030/V_Rising/' }
]
},
zomboid: {
hint: 'Version 42.13',
address: 'pz.zeasy.dev:16261',
logo: '/zomboid.png',
links: [
{ label: 'Steam', url: 'https://store.steampowered.com/app/108600/Project_Zomboid/' }
]
}
}
const getServerInfo = (serverName) => {
const name = serverName.toLowerCase()
if (name.includes('minecraft') || name.includes('all the mods')) return serverInfo.minecraft
if (name.includes('factorio')) return serverInfo.factorio
if (name.includes('vrising') || name.includes('v rising')) return serverInfo.vrising
if (name.includes('zomboid')) return serverInfo.zomboid
return null
}
export default function ServerCard({ server, onClick, isAuthenticated }) {
const info = getServerInfo(server.name)
const formatUptime = (seconds) => {
const hours = Math.floor(seconds / 3600)
if (hours > 24) {
const days = Math.floor(hours / 24)
return days + 'd ' + (hours % 24) + 'h'
}
const minutes = Math.floor((seconds % 3600) / 60)
return hours + 'h ' + minutes + 'm'
}
const cpuPercent = Math.min(server.metrics.cpu, 100)
const memPercent = Math.min(server.metrics.memory, 100)
const getProgressColor = (percent) => {
if (percent > 80) return 'progress-bar-danger'
if (percent > 60) return 'progress-bar-warning'
return 'progress-bar-success'
}
const getStatusBadge = () => {
const status = server.status || (server.running ? 'online' : 'offline')
switch (status) {
case 'online':
return { class: 'badge badge-success', text: 'Online' }
case 'starting':
return { class: 'badge badge-warning', text: 'Startet...' }
case 'stopping':
return { class: 'badge badge-warning', text: 'Stoppt...' }
case 'unreachable':
return { class: 'badge badge-muted', text: 'Nicht erreichbar' }
default:
return { class: 'badge badge-destructive', text: 'Offline' }
}
}
const statusBadge = getStatusBadge()
return (
<div
className={`card ${server.status !== "unreachable" ? "card-clickable" : "cursor-not-allowed"} p-5 ${server.status === "unreachable" ? "opacity-50" : ""}`}
onClick={server.status !== "unreachable" ? onClick : undefined}
>
{/* Header */}
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-3">
{info && info.logo && <img src={info.logo} alt="" className="h-8 w-8 object-contain" />}
<h3 className="text-lg font-semibold text-white">{server.name}</h3>
</div>
<span className={statusBadge.class}>
{statusBadge.text}
</span>
</div>
{/* Server Address & Links */}
{info && (
<div className="mb-4 flex items-center gap-3 text-sm">
<code className="text-neutral-400 bg-neutral-800 px-2 py-0.5 rounded">
{info.address}
</code>
{info.links.map((link, i) => (
<a
key={i}
href={link.url}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
className="text-blue-400 hover:text-blue-300 hover:underline"
>
{link.label}
</a>
))}
</div>
)}
{/* Whitelist notice for Minecraft - only for authenticated users */}
{isAuthenticated && server.type === 'minecraft' && (
<div className="mb-4 text-xs text-neutral-500">
Whitelist erforderlich - im Whitelist-Tab freischalten
</div>
)}
{/* Factorio notice - only for authenticated users */}
{isAuthenticated && server.type === 'factorio' && (
<div className="mb-4 text-xs text-neutral-500">
Serverpasswort: affe
</div>
)}
{/* V Rising notice - only for authenticated users */}
{isAuthenticated && server.type === 'vrising' && (
<div className="mb-4 text-xs text-neutral-500">
In der Serverliste suchen - Passwort: affe
</div>
)}
{/* Project Zomboid notice - only for authenticated users */}
{isAuthenticated && server.type === 'zomboid' && (
<div className="mb-4 text-xs text-neutral-500">
Version 42.13
</div>
)}
{/* Metrics */}
<div className="space-y-3">
{/* CPU */}
<div>
<div className="flex justify-between text-sm mb-1">
<span className="text-neutral-400">CPU</span>
<span className="text-white">{server.metrics.cpu.toFixed(1)}%</span>
</div>
<div className="progress">
<div
className={'progress-bar ' + getProgressColor(cpuPercent)}
style={{ width: cpuPercent + '%' }}
/>
</div>
</div>
{/* RAM */}
<div>
<div className="flex justify-between text-sm mb-1">
<span className="text-neutral-400">Arbeitsspeicher</span>
<span className="text-white">
{server.metrics.memoryUsed?.toFixed(1) || 0} / {server.metrics.memoryTotal?.toFixed(1) || 0} {server.metrics.memoryUnit}
</span>
</div>
<div className="progress">
<div
className={'progress-bar ' + getProgressColor(memPercent)}
style={{ width: memPercent + '%' }}
/>
</div>
</div>
</div>
{/* Footer Stats */}
<div className="flex items-center justify-between mt-4 pt-4 border-t border-neutral-800 text-sm">
<div className="text-neutral-400">
<span className="text-white font-medium">{server.players.online}</span>
{server.players.max ? ' / ' + server.players.max : ''} Spieler
</div>
{server.running && (
<div className="text-neutral-400">
Laufzeit: <span className="text-white">{formatUptime(server.metrics.uptime)}</span>
</div>
)}
</div>
{/* Players List */}
{server.players?.list?.length > 0 && (
<div className="mt-3 pt-3 border-t border-neutral-800">
<div className="flex flex-wrap gap-1.5">
{server.players.list.map((player, i) => (
<span key={i} className="badge badge-secondary">
{player}
</span>
))}
</div>
</div>
)}
</div>
)
}