155 lines
5.1 KiB
JavaScript
155 lines
5.1 KiB
JavaScript
import React, { useEffect, useState } from "react";
|
|
import Card from "../../../components/ui/Card";
|
|
import { useSocket } from "../../../hooks/useSocket";
|
|
import playerManager from "../../../services/PlayerManager";
|
|
import "./styles/DashboardTab.css";
|
|
|
|
const DashboardTab = () => {
|
|
const { socket, isConnected } = useSocket();
|
|
const [playerData, setPlayerData] = useState(null);
|
|
const [earnedPopup, setEarnedPopup] = useState(false);
|
|
const [credits, setCredits] = useState(0);
|
|
const [onlineCount, setOnlineCount] = useState(
|
|
playerManager.onlinePlayers.length,
|
|
);
|
|
|
|
const savedUser = JSON.parse(localStorage.getItem("user"));
|
|
const localUsername = savedUser?.username || "Unknown Pilot";
|
|
|
|
useEffect(() => {
|
|
const unsubscribe = playerManager.subscribe(({ online }) => {
|
|
setOnlineCount(online.length);
|
|
});
|
|
|
|
if (!socket) return;
|
|
|
|
socket.emit("player:get_dashboard");
|
|
|
|
const handleData = (data) => {
|
|
setPlayerData(data);
|
|
setCredits(data.credits);
|
|
};
|
|
|
|
const handleCreditsUpdate = ({ totalCredits }) => {
|
|
setCredits(totalCredits);
|
|
setEarnedPopup(true);
|
|
setTimeout(() => setEarnedPopup(false), 2000);
|
|
};
|
|
|
|
const handleOfflineReport = () => {
|
|
socket.emit("player:get_dashboard");
|
|
};
|
|
|
|
socket.on("player:dashboard_data", handleData);
|
|
socket.on("player:credits_update", handleCreditsUpdate);
|
|
socket.on("player:offline_report", handleOfflineReport);
|
|
|
|
return () => {
|
|
unsubscribe();
|
|
socket.off("player:dashboard_data", handleData);
|
|
socket.off("player:credits_update", handleCreditsUpdate);
|
|
socket.off("player:offline_report", handleOfflineReport);
|
|
};
|
|
}, [socket]);
|
|
|
|
const stats = playerData || { experience: 0, level: 1 };
|
|
const nextLevelExp = 1000;
|
|
const expProgress = Math.min((stats.experience / nextLevelExp) * 100, 100);
|
|
|
|
return (
|
|
<div className="dash-container">
|
|
<div className="dash-scanline"></div>
|
|
|
|
<div className="dashboard-grid">
|
|
<Card className="dash-card pilot-card">
|
|
<div className="card-tag">ID_RECOGNITION</div>
|
|
<div className="pilot-info">
|
|
<div className="pilot-avatar">
|
|
<i className="fas fa-user-astronaut"></i>
|
|
<div className="level-badge">{stats.level}</div>
|
|
</div>
|
|
<div className="pilot-details">
|
|
<h3>{localUsername}</h3>
|
|
<p className="status-online">RANK: VETERAN</p>
|
|
</div>
|
|
</div>
|
|
<div className="exp-bar-container">
|
|
<div className="exp-labels">
|
|
<span>EXP: {stats.experience}</span>
|
|
<span>NEXT: {nextLevelExp}</span>
|
|
</div>
|
|
<div className="exp-track">
|
|
<div
|
|
className="exp-fill"
|
|
style={{ width: `${expProgress}%` }}
|
|
></div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
<Card className="dash-card resources-card">
|
|
<div className="card-tag">FINANCIAL_DATA</div>
|
|
<h3>VALUABLES</h3>
|
|
<div className="resource-list">
|
|
<div className="res-item gold">
|
|
<i className="fas fa-coins"></i>
|
|
<div className="res-content">
|
|
<span className="res-label">CREDITS</span>
|
|
<span className="res-val">
|
|
{credits.toLocaleString()}
|
|
{earnedPopup && <span className="credit-plus">+1</span>}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div className="res-item crystal">
|
|
<i className="fas fa-microchip"></i>
|
|
<div className="res-content">
|
|
<span className="res-label">DATA_CORES</span>
|
|
<span className="res-val">
|
|
{Math.floor(stats.experience / 10)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
<Card className="dash-card status-card">
|
|
<div className="card-tag">SYSTEM_DIAGNOSTICS</div>
|
|
<h3>SHIPS_LOG</h3>
|
|
<div className="diag-grid">
|
|
<div className="diag-item">
|
|
<span className="diag-label">ENGINE</span>
|
|
<span className="diag-status">OPTIMAL</span>
|
|
</div>
|
|
<div className="diag-item">
|
|
<span className="diag-label">SHIELDS</span>
|
|
<span className="diag-status">100%</span>
|
|
</div>
|
|
<div className="diag-item warning">
|
|
<span className="diag-label">CARGO</span>
|
|
<span className="diag-status">NEAR_FULL</span>
|
|
</div>
|
|
<div className="diag-item">
|
|
<span className="diag-label">NET</span>
|
|
<span
|
|
className={`diag-status ${isConnected ? "online" : "offline"}`}
|
|
>
|
|
{isConnected ? (
|
|
<span className="online-info">
|
|
<span className="online-dot"></span>
|
|
LIVE: {onlineCount}
|
|
</span>
|
|
) : (
|
|
"DISCONNECTED"
|
|
)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DashboardTab;
|