Game-Server/client/src/views/MainMenu/sections/ServerSection.jsx

153 lines
4.5 KiB
JavaScript

import React, { useState, useEffect } from "react";
import axios from "axios";
import Button from "../../../components/ui/Button";
import "./ServerSection.css";
const ServerSection = ({ onBack, onSelect }) => {
const [servers, setServers] = useState([]);
const [loading, setLoading] = useState(false);
const [joiningId, setJoiningId] = useState(null);
const [searchTerm, setSearchTerm] = useState("");
const fetchServers = async () => {
setLoading(true);
const startTime = Date.now();
const API_URL = import.meta.env.VITE_API_URL;
try {
const response = await axios.get(`${API_URL}/api/servers/list`);
const elapsedTime = Date.now() - startTime;
const remainingTime = Math.max(0, 2000 - elapsedTime);
await new Promise((resolve) => setTimeout(resolve, remainingTime));
setServers(response.data);
} catch (error) {
console.error("Error fetching servers:", error);
} finally {
setLoading(false);
}
};
const handleJoinServer = async (server) => {
setJoiningId(server._id);
const API_URL = import.meta.env.VITE_API_URL;
try {
const token = JSON.parse(localStorage.getItem("user")).token;
const response = await axios.post(
`${API_URL}/api/servers/join`,
{ serverId: server._id },
{ headers: { Authorization: `Bearer ${token}` } },
);
if (response.data.success) {
console.log(response.data);
onSelect(response.data);
}
} catch (error) {
console.error("Join request failed:", error);
} finally {
setJoiningId(null);
}
};
useEffect(() => {
fetchServers();
}, []);
const filteredServers = servers.filter((server) =>
searchTerm.length > 0
? server.name?.toLowerCase().includes(searchTerm.toLowerCase())
: true,
);
return (
<div id="serverSection" className="menu-section">
<h2 className="server-section-title">Galaxy Browser</h2>
<div className="server-controls">
<div className="search-wrapper">
<i className="fas fa-search search-icon"></i>
<input
type="text"
className="server-search-input"
placeholder="Search sector..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className="control-group">
<Button
variant="secondary"
icon="fa-sync"
onClick={fetchServers}
disabled={loading}
>
{loading ? "Scanning..." : "Refresh"}
</Button>
<div className="server-filters">
<select className="filter-select">
<option value="">All Regions</option>
<option value="europe">Europe</option>
<option value="ukraine">Ukraine</option>
</select>
</div>
</div>
</div>
<div className="server-list">
{loading ? (
<div className="server-loading">
<i className="fas fa-spinner fa-spin"></i>
<p>Synchronizing with Star-Net...</p>
</div>
) : filteredServers.length > 0 ? (
filteredServers.map((server) => (
<div key={server._id || server.serverName} className="server-card">
<div className="server-info">
<div
className={`status-indicator ${server.status === "online" ? "online" : "offline"}`}
></div>
<div className="server-details-text">
<span className="server-name">{server.name}</span>
<span className="server-players">
{server.playersOnline || 0} / {server.maxPlayers || 100}
</span>
</div>
</div>
<Button
variant="primary"
size="small"
onClick={() => handleJoinServer(server)}
>
SELECT
</Button>
</div>
))
) : (
<div className="server-empty">
<i className="fas fa-satellite-dish"></i>
<p>
{searchTerm
? "No sectors match your search."
: "No active universes found."}
</p>
</div>
)}
</div>
<div className="server-actions">
<Button variant="secondary" icon="fa-arrow-left" onClick={onBack}>
Back to Login
</Button>
</div>
</div>
);
};
export default ServerSection;