mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-20 12:11:28 -07:00
5-tab React dashboard with Catppuccin Mocha theme: - Overview: hero stats, streak calendar, watch time chart, recent sessions - Anime: grid with cover art, episode list with completion %, detail view - Trends: 15 charts across Activity, Efficiency, Anime, and Patterns - Vocabulary: POS-filtered word/kanji lists with detail panels - Sessions: expandable session history with event timeline Features: - Cross-tab navigation (anime <-> vocabulary) - Global word detail panel overlay - Expandable episode detail with Anki card links (Expression field) - Per-anime multi-line trend charts - Watch time by day-of-week and hour-of-day - Collapsible sections with accessibility (aria-expanded) - Card size selector for anime grid - Cover art caching via AniList - HTTP API client with file:// protocol fallback for Electron overlay
81 lines
3.6 KiB
TypeScript
81 lines
3.6 KiB
TypeScript
import { useOverview } from '../../hooks/useOverview';
|
|
import { useStreakCalendar } from '../../hooks/useStreakCalendar';
|
|
import { HeroStats } from './HeroStats';
|
|
import { StreakCalendar } from './StreakCalendar';
|
|
import { RecentSessions } from './RecentSessions';
|
|
import { TrendChart } from '../trends/TrendChart';
|
|
import { buildOverviewSummary, buildStreakCalendar } from '../../lib/dashboard-data';
|
|
import { formatNumber } from '../../lib/formatters';
|
|
|
|
export function OverviewTab() {
|
|
const { data, sessions, loading, error } = useOverview();
|
|
const { calendar, loading: calLoading } = useStreakCalendar(90);
|
|
|
|
if (loading) return <div className="text-ctp-overlay2 p-4">Loading...</div>;
|
|
if (error) return <div className="text-ctp-red p-4">Error: {error}</div>;
|
|
if (!data) return null;
|
|
|
|
const summary = buildOverviewSummary(data);
|
|
const streakData = buildStreakCalendar(calendar);
|
|
const showTrackedCardNote = summary.totalTrackedCards === 0 && summary.totalSessions > 0;
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<HeroStats summary={summary} sessions={sessions} />
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<TrendChart
|
|
title="Last 14 Days Watch Time (min)"
|
|
data={summary.recentWatchTime}
|
|
color="#8aadf4"
|
|
type="bar"
|
|
/>
|
|
{!calLoading && <StreakCalendar data={streakData} />}
|
|
</div>
|
|
|
|
<div className="bg-ctp-surface0 border border-ctp-surface1 rounded-lg p-4">
|
|
<h3 className="text-sm font-semibold text-ctp-text mb-3">Tracking Snapshot</h3>
|
|
{showTrackedCardNote && (
|
|
<div className="mb-3 rounded-lg border border-ctp-surface2 bg-ctp-surface1/50 px-3 py-2 text-xs text-ctp-subtext0">
|
|
No tracked card-add events in the current immersion DB yet. New cards mined after this fix will show here.
|
|
</div>
|
|
)}
|
|
<div className="grid grid-cols-2 sm:grid-cols-5 gap-3 text-sm">
|
|
<div className="rounded-lg bg-ctp-surface1/60 p-3">
|
|
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">Total Sessions</div>
|
|
<div className="mt-1 text-xl font-semibold text-ctp-lavender">
|
|
{formatNumber(summary.totalSessions)}
|
|
</div>
|
|
</div>
|
|
<div className="rounded-lg bg-ctp-surface1/60 p-3">
|
|
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">Episodes Today</div>
|
|
<div className="mt-1 text-xl font-semibold text-ctp-teal">
|
|
{formatNumber(summary.episodesToday)}
|
|
</div>
|
|
</div>
|
|
<div className="rounded-lg bg-ctp-surface1/60 p-3">
|
|
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">All-Time Hours</div>
|
|
<div className="mt-1 text-xl font-semibold text-ctp-mauve">
|
|
{formatNumber(summary.allTimeHours)}
|
|
</div>
|
|
</div>
|
|
<div className="rounded-lg bg-ctp-surface1/60 p-3">
|
|
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">Active Days</div>
|
|
<div className="mt-1 text-xl font-semibold text-ctp-peach">
|
|
{formatNumber(summary.activeDays)}
|
|
</div>
|
|
</div>
|
|
<div className="rounded-lg bg-ctp-surface1/60 p-3">
|
|
<div className="text-xs uppercase tracking-wide text-ctp-overlay2">Cards Mined</div>
|
|
<div className="mt-1 text-xl font-semibold text-ctp-green">
|
|
{formatNumber(summary.totalTrackedCards)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<RecentSessions sessions={sessions} />
|
|
</div>
|
|
);
|
|
}
|