import React, { useState, useEffect } from 'react';
import {
Box, Container, Typography, Button, TextField,
InputAdornment, IconButton, AppBar, Toolbar, Avatar,
Tooltip, Dialog, DialogTitle, DialogContent,
DialogActions, CircularProgress, Paper, Chip,
Table, TableBody, TableCell, TableContainer, TableHead, TableRow,
Switch, FormControlLabel, Divider, List, ListItem, ListItemText, ListItemSecondaryAction,
Select, MenuItem, FormControl, InputLabel
} from '@mui/material';
import SearchIcon from '@mui/icons-material/Search';
import AddIcon from '@mui/icons-material/Add';
import SteamIcon from '@mui/icons-material/SportsEsports';
import DeleteIcon from '@mui/icons-material/Delete';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import SyncIcon from '@mui/icons-material/Sync';
import BoltIcon from '@mui/icons-material/Bolt';
import TimerIcon from '@mui/icons-material/Timer';
import LockResetIcon from '@mui/icons-material/LockReset';
import SettingsIcon from '@mui/icons-material/Settings';
import ShareIcon from '@mui/icons-material/Share';
import GroupAddIcon from '@mui/icons-material/GroupAdd';
import ShieldIcon from '@mui/icons-material/Shield';
import GppBadIcon from '@mui/icons-material/GppBad';
import PeopleIcon from '@mui/icons-material/People';
import VerifiedUserIcon from '@mui/icons-material/VerifiedUser';
import WorkspacePremiumIcon from '@mui/icons-material/WorkspacePremium';
import { useAccounts, type Account } from '../hooks/useAccounts';
import { useAppTheme } from '../theme/ThemeContext';
import type { ThemeType } from '../theme/SteamTheme';
import NebulaBanner from '../components/NebulaBanner';
const Dashboard: React.FC = () => {
const { currentTheme, setTheme } = useAppTheme();
const {
accounts, isLoading, isSyncing, serverConfig, deleteAccount,
switchAccount, openSteamAppLogin, openSteamLogin, updateServerConfig, loginToServer, syncNow
} = useAccounts();
const [searchTerm, setSearchTerm] = useState('');
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const [serverUrl, setServerUrl] = useState('');
useEffect(() => {
if (serverConfig?.url) setServerUrl(serverConfig.url);
}, [serverConfig?.url]);
const saveSettings = async () => {
await updateServerConfig({ url: serverUrl });
alert("Server URL updated!");
};
const safeAccounts = Array.isArray(accounts) ? accounts : [];
const filteredAccounts = safeAccounts.filter((acc) => {
if (!acc) return false;
const name = acc.personaName || 'Unknown';
const id = acc.steamId || '';
return name.toLowerCase().includes(searchTerm.toLowerCase()) || id.includes(searchTerm);
});
return (
ULTIMATE BAN TRACKER
{isSyncing ? (
) : (
syncNow()} disabled={!serverConfig?.enabled} sx={{ color: 'primary.main' }}>
)}
setSearchTerm(e.target.value)}
sx={{
backgroundColor: 'rgba(255, 255, 255, 0.05)',
borderRadius: 1,
width: 200,
'& .MuiOutlinedInput-root': { '& fieldset': { border: 'none' }, height: 32 }
}}
InputProps={{
startAdornment: (
),
}}
/>
}
onClick={() => openSteamAppLogin()}
sx={{ height: 32 }}
>
Add
setIsSettingsOpen(true)}>
{isLoading ? (
) : (
AVATAR
ACCOUNT
BAN STATUS
COOLDOWN
ACTIONS
{filteredAccounts.map((account) => (
openSteamLogin(account.steamId)}
/>
))}
)}
{!isLoading && filteredAccounts.length === 0 && (
No accounts tracked. Click "Add" to get started!
)}
{/* Settings Dialog */}
);
};
// --- Sub-Component: AccountRow ---
const AccountRow: React.FC<{
account: Account,
onDelete: (id: string) => void,
onSwitch: (login: string) => void,
onAuth: () => void
}> = ({ account, onDelete, onSwitch, onAuth }) => {
const { shareAccountWithUser, revokeAccountAccess, revokeAllAccountAccess, getServerUsers, serverConfig } = useAccounts();
const [timeLeft, setTimeLeft] = useState(null);
const [isShareOpen, setIsShareOpen] = useState(false);
const [targetUserId, setTargetUserId] = useState('');
const [isSharing, setIsSharing] = useState(false);
const [serverUsers, setServerUsers] = useState([]);
const cooldownDate = account?.cooldownExpiresAt ? new Date(account.cooldownExpiresAt) : null;
const isCooldownActive = cooldownDate && !isNaN(cooldownDate.getTime()) && cooldownDate.getTime() > Date.now();
useEffect(() => {
if (!isCooldownActive || !cooldownDate) { setTimeLeft(null); return; }
const targetTime = cooldownDate.getTime();
const timer = setInterval(() => {
const diff = targetTime - Date.now();
if (diff <= 0) { setTimeLeft(null); clearInterval(timer); return; }
const hours = Math.floor(diff / 3600000);
const mins = Math.floor((diff % 3600000) / 60000);
const secs = Math.floor((diff % 60000) / 1000);
setTimeLeft(`${hours}h ${mins}m ${secs}s`);
}, 1000);
return () => clearInterval(timer);
}, [account?.cooldownExpiresAt, isCooldownActive]);
const avatarSrc = account?.localAvatar ? `steam-resource://${account.localAvatar}` : (account?.avatar || '');
const [imgSrc, setImgSrc] = useState(avatarSrc);
useEffect(() => { setImgSrc(avatarSrc); }, [avatarSrc]);
const handleOpenShare = async () => {
setIsShareOpen(true);
try {
const [users, selfInfo] = await Promise.all([
getServerUsers(),
(window as any).electronAPI.getServerUserInfo()
]);
const filtered = (Array.isArray(users) ? users : []).filter(u =>
u.steamId !== selfInfo.steamId &&
u.steamId !== account.steamId
);
setServerUsers(filtered);
} catch (e) {}
};
const handleShare = async () => {
if (!targetUserId) return;
setIsSharing(true);
try {
await shareAccountWithUser(account.steamId, targetUserId);
setTargetUserId('');
} catch (e: any) { alert(e.message || "Failed to share account");
} finally { setIsSharing(false); }
};
const handleRevoke = async (targetSteamId: string) => {
if (!window.confirm("Revoke access for this user?")) return;
try { await revokeAccountAccess(account.steamId, targetSteamId);
} catch (e: any) { alert(e.message); }
};
const handleRevokeAll = async () => {
if (!window.confirm("Completely stop sharing this account?")) return;
try { await revokeAllAccountAccess(account.steamId); setIsShareOpen(false);
} catch (e: any) { alert(e.message); }
};
const isBanned = account?.vacBanned || (account?.gameBans && account.gameBans > 0);
// Primary account check
const isPrimaryAccount = serverConfig?.serverSteamId === account.steamId;
// Refined Shared Logic
const isSharedWithYou = account?._id.startsWith('shared_');
const hasSharedMembers = (account as any).sharedWith && (account as any).sharedWith.length > 0;
const showCommunityIcon = isSharedWithYou || hasSharedMembers;
return (
{isPrimaryAccount && (
)}
{showCommunityIcon && (
)}
{account?.personaName || 'Unknown'}
{account?.steamId}
{isBanned ? (
BANNED
{account?.vacBanned && }
{account?.gameBans ? account.gameBans > 0 && : null}
) : (
SECURE
)}
{account?.authError ? (
Needs Re-auth
) : isCooldownActive ? (
{timeLeft}
) : (
Available
)}
{account.loginName && (
)}
{account.steamLoginSecure && !account.authError ? : (account.authError ? : )}
{account.steamLoginSecure && !account.authError && (
TRACKING
)}
(window as any).electronAPI.openExternal(account?.profileUrl || '')}>
onDelete(account?._id || '')}>
);
};
export default Dashboard;