Updating
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { AppShell } from "@/components/AppShell";
|
||||
import { EmptyState } from "@/components/EmptyState";
|
||||
import { SectionCard } from "@/components/SectionCard";
|
||||
import { StatusBadge } from "@/components/StatusBadge";
|
||||
import { fetchJson } from "@/lib/client";
|
||||
import type { DashboardResponse } from "@/lib/types";
|
||||
|
||||
export function DashboardClient() {
|
||||
const [data, setData] = useState<DashboardResponse | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [message, setMessage] = useState<string | null>(null);
|
||||
|
||||
async function loadDashboard() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetchJson<DashboardResponse>("/api/dashboard");
|
||||
setData(response);
|
||||
} catch (loadError) {
|
||||
setError(loadError instanceof Error ? loadError.message : "Failed to load dashboard.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function seedSampleData() {
|
||||
try {
|
||||
const response = await fetchJson<{ seeded: boolean; reason?: string }>("/api/seed", { method: "POST" });
|
||||
setMessage(response.seeded ? "Sample team loaded." : response.reason ?? "Seed skipped.");
|
||||
await loadDashboard();
|
||||
} catch (seedError) {
|
||||
setError(seedError instanceof Error ? seedError.message : "Failed to seed data.");
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
void loadDashboard();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AppShell
|
||||
title="Game Day Snapshot"
|
||||
subtitle="Check roster health, pitcher rest, and lineup readiness before first pitch."
|
||||
actions={
|
||||
<button className="button button-secondary" onClick={() => void seedSampleData()}>
|
||||
Load Sample Team
|
||||
</button>
|
||||
}
|
||||
>
|
||||
{message ? <div className="banner banner-success">{message}</div> : null}
|
||||
{error ? <div className="banner banner-error">{error}</div> : null}
|
||||
|
||||
{loading ? (
|
||||
<SectionCard title="Loading" description="Pulling current roster and pitching data." />
|
||||
) : data && data.rosterCount > 0 ? (
|
||||
<>
|
||||
<section className="stats-grid">
|
||||
<article className="stat-card">
|
||||
<span>Rostered Players</span>
|
||||
<strong>{data.rosterCount}</strong>
|
||||
</article>
|
||||
<article className="stat-card">
|
||||
<span>Active Today</span>
|
||||
<strong>{data.activePlayers}</strong>
|
||||
</article>
|
||||
<article className="stat-card stat-card-success">
|
||||
<span>Pitchers Available</span>
|
||||
<strong>{data.availablePitchers}</strong>
|
||||
</article>
|
||||
<article className="stat-card stat-card-warning">
|
||||
<span>Need Rest</span>
|
||||
<strong>{data.needsRest}</strong>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<SectionCard
|
||||
title="Pitcher Availability"
|
||||
description="Availability is based on the latest appearance and your configured rest rules."
|
||||
>
|
||||
<div className="list-stack">
|
||||
{data.recentPitching.map((entry) => (
|
||||
<article key={entry.playerId} className="list-row">
|
||||
<div>
|
||||
<h3>{entry.playerName}</h3>
|
||||
<p>
|
||||
{entry.lastPitchedDate
|
||||
? `${entry.pitchCount} pitches on ${entry.lastPitchedDate}`
|
||||
: "No pitching history recorded yet."}
|
||||
</p>
|
||||
</div>
|
||||
<div className="list-meta">
|
||||
<StatusBadge status={entry.status} />
|
||||
<small>
|
||||
{entry.daysSinceLastAppearance === null
|
||||
? "No history"
|
||||
: `${entry.daysSinceLastAppearance} day(s) since last outing`}
|
||||
</small>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</SectionCard>
|
||||
</>
|
||||
) : (
|
||||
<SectionCard title="No Team Yet" description="Start with sample data or add players on the roster screen.">
|
||||
<EmptyState
|
||||
title="Roster is empty"
|
||||
description="Load the sample team to explore the app, then adjust players and pitching records as needed."
|
||||
action={
|
||||
<button className="button" onClick={() => void seedSampleData()}>
|
||||
Load Sample Team
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
</SectionCard>
|
||||
)}
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user