diff --git a/src/App.jsx b/src/App.jsx index ace1206..10f8d34 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -354,6 +354,7 @@ function App() { const [uptime, setUptime] = useState({ status: 'idle', checks: [], history: [], updatedAt: null }) const [viewers, setViewers] = useState({ status: 'idle', data: null, error: null, updatedAt: null }) const [analyticsPreferences, setAnalyticsPreferences] = useState(() => storedAnalyticsPreferences()) + const [showFloatingNav, setShowFloatingNav] = useState(() => window.scrollY > 40) const [teamQuery, setTeamQuery] = useState('') const [searchHint, setSearchHint] = useState({ status: 'idle', name: '' }) const [profile, setProfile] = useState({ @@ -379,6 +380,13 @@ function App() { return () => window.removeEventListener('popstate', onPopState) }, []) + useEffect(() => { + const onScroll = () => setShowFloatingNav(window.scrollY > 40) + onScroll() + window.addEventListener('scroll', onScroll, { passive: true }) + return () => window.removeEventListener('scroll', onScroll) + }, []) + useEffect(() => { const title = route.page === 'team' && route.teamName @@ -870,18 +878,27 @@ function App() { return (
-
-
- -
{route.page === 'home' ? ( - + ) : null} {route.page === 'teams' ? ( @@ -1263,15 +1268,24 @@ function PrivacySection({ children, title }) { ) } -function Landing({ live, matches, navigate }) { +function Landing({ + live, + matches, + navigate, + onTeamSearch, + searchPlaceholder, + setTeamQuery, + teams, + teamQuery, +}) { const treeRef = useRef(null) return (
-
+
-
+

BorisBot got nothin on THIS @@ -1282,21 +1296,47 @@ function Landing({ live, matches, navigate }) {

Powered by Spectra. TSS analytics.

-
- + + + Visit SREBOT + +
+ +
- Team leaderboard - - + setTeamQuery(event.target.value)} + /> + +
@@ -1306,14 +1346,179 @@ function Landing({ live, matches, navigate }) {
+ +
+ Scroll + + + +
+ + ) } +function LandingOverview({ teams, matches, navigate }) { + const activeTeams = teams.slice(0, 4) + const totalPlayers = matches.reduce((sum, match) => sum + Number(match.player_count || 0), 0) + const latestMatch = matches[0] + + return ( +
+
+
+

+ What it does +

+

A clean window into TSS activity

+

+ Track teams, inspect recent battles, and jump from a leaderboard name to a + profile without touching the god awful TSS website. +

+ +
+ + + +
+
+ +
+ navigate('/teams')} + title="Team discovery" + /> + navigate('/battle-logs')} + title="Battle context" + /> + navigate('/uptime')} + title="Operational status" + /> + navigate('/viewers')} + title="Viewer pulse" + /> +
+
+ +
+
+

+ Latest signal +

+

+ {latestMatch?.map_name || 'Waiting for the next battle'} +

+

+ {latestMatch + ? `${latestMatch.team_name || 'A TSS team'} played with ${formatNumber(latestMatch.player_count)} players.` + : 'Latest match data will appear here once the data proxy returns games.'} +

+
+ +
+

+ Teams to watch +

+
+ {activeTeams.length ? ( + activeTeams.map((team) => { + const name = bestTeamName(team) + return ( + + ) + }) + ) : ( +

Team data is still loading.

+ )} +
+
+
+
+ ) +} + +function LandingMetric({ label, value }) { + return ( +
+

{value}

+

{label}

+
+ ) +} + +function LandingFeature({ action, description, onClick, title }) { + return ( +
+

{title}

+

{description}

+ +
+ ) +} + +function LandingTrustSection({ navigate }) { + return ( +
+
+
+

+ Brought to you by... +

+

Built by the team behind SREBot

+

+ TSSBot is built alongside SREBot, both providing different views into different aspects of "competitive" War Thunder. +

+
+ +
+ + Visit SREBOT + + +
+
+
+ ) +} + function RecentGamesSection({ live, matches, navigate }) { const recentMatches = matches.slice(0, 6) @@ -1498,7 +1703,7 @@ function PixelMountains() { function TeamsPage({ leaderboard, navigate, teams }) { return ( -
+

Team leaderboard

@@ -1741,7 +1946,7 @@ function BattleResults({ games, status }) { function BattleLogsPage({ live, matches }) { return ( -

+

Battle Logs

@@ -1808,7 +2013,7 @@ function ViewersPage({ viewers }) { const generatedAt = data.generated_at ? dateFormat.format(new Date(data.generated_at)) : 'Waiting for data' return ( -

+
diff --git a/src/styles.css b/src/styles.css index aa7c3fc..1eafda3 100644 --- a/src/styles.css +++ b/src/styles.css @@ -130,3 +130,18 @@ body { z-index: 2; } +@keyframes scrollPulse { + 0% { + transform: translateY(-100%); + opacity: 0; + } + + 35% { + opacity: 1; + } + + 100% { + transform: translateY(250%); + opacity: 0; + } +}