mirror of
https://github.com/prdlk/leetcode.git
synced 2026-11-02 13:12:44 +00:00
docs: add /progress page with live stats cards and update navigation and component imports
This commit is contained in:
1 parent
cb4a03b6fa
commit
13734e2e27
11 files changed
+88
-57
No files matched your search
@@ -127,10 +127,11 @@ export default defineConfig({
|
||||
llmsTxt: true,
|
||||
mcp: { enabled: false },
|
||||
},
|
||||
// The only content source. `/changelog` and `/appendix` are custom pages
|
||||
// (pages/*.astro): `/changelog` reads the GitHub releases itself — one
|
||||
// timeline, no per-release pages — and `/appendix` is one glossary page
|
||||
// built from appendix.ts, so neither enters the sidebar tree or prev/next.
|
||||
// The only content source. `/changelog`, `/appendix` and `/progress` are
|
||||
// custom pages (pages/*.astro): `/changelog` reads the GitHub releases
|
||||
// itself — one timeline, no per-release pages — `/appendix` is one glossary
|
||||
// page built from appendix.ts, and `/progress` is the live stats cards, so
|
||||
// none enters the sidebar tree or prev/next.
|
||||
content: {
|
||||
sources: [filesystem({ root: "content" })],
|
||||
},
|
||||
@@ -142,10 +143,11 @@ export default defineConfig({
|
||||
sidebar: {
|
||||
display: "flat", // "flat" | "group" | "page"
|
||||
},
|
||||
// The two custom pages (pages/*.astro) as header tabs. Neither is a
|
||||
// content folder, so the tabs scope nothing out of the sidebar tree.
|
||||
// The custom pages (pages/*.astro) as header tabs. None is a content
|
||||
// folder, so the tabs scope nothing out of the sidebar tree.
|
||||
tabs: [
|
||||
{ label: "Changelog", path: "/changelog" },
|
||||
{ label: "Progress", path: "/progress" },
|
||||
{ label: "Appendix", path: "/appendix" },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
* hover. A row links to the problem's docs page when one exists: the
|
||||
* sync-generated short links (`redirects.ts`) are exactly the pages built.
|
||||
*/
|
||||
import { StatsPending } from "../components/progress/shared";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "../components/ui/card";
|
||||
import { useStats, utcDate } from "../lib/stats";
|
||||
import redirects from "../redirects";
|
||||
|
||||
export const client = "load";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
|
||||
import { useStats, utcDate } from "../../lib/stats";
|
||||
import redirects from "../../redirects";
|
||||
import { StatsPending } from "./shared";
|
||||
|
||||
const PAGES = new Map(redirects.map((r) => [r.from, r.to]));
|
||||
|
||||
@@ -8,13 +8,11 @@
|
||||
*/
|
||||
import { useState } from "react";
|
||||
import { Pie, PieChart } from "recharts";
|
||||
import { StatsPending } from "../components/progress/shared";
|
||||
import { Card, CardContent } from "../components/ui/card";
|
||||
import { type ChartConfig, ChartContainer } from "../components/ui/chart";
|
||||
import { DIFFICULTIES, type Difficulty, useStats } from "../lib/stats";
|
||||
import { cn } from "../lib/utils";
|
||||
|
||||
export const client = "load";
|
||||
import { Card, CardContent } from "../ui/card";
|
||||
import { type ChartConfig, ChartContainer } from "../ui/chart";
|
||||
import { DIFFICULTIES, type Difficulty, useStats } from "../../lib/stats";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { StatsPending } from "./shared";
|
||||
|
||||
const chartConfig = {
|
||||
easy: { label: "Easy", color: "var(--chart-1)" },
|
||||
+5
-7
@@ -9,13 +9,11 @@
|
||||
*/
|
||||
import { useState } from "react";
|
||||
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts";
|
||||
import { StatsPending } from "../components/progress/shared";
|
||||
import { Card, CardAction, CardContent, CardFooter, CardHeader } from "../components/ui/card";
|
||||
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from "../components/ui/chart";
|
||||
import { ToggleGroup, ToggleGroupItem } from "../components/ui/toggle-group";
|
||||
import { DIFFICULTIES, type Day, type Difficulty, useStats, utcDate } from "../lib/stats";
|
||||
|
||||
export const client = "load";
|
||||
import { Card, CardAction, CardContent, CardFooter, CardHeader } from "../ui/card";
|
||||
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from "../ui/chart";
|
||||
import { ToggleGroup, ToggleGroupItem } from "../ui/toggle-group";
|
||||
import { DIFFICULTIES, type Day, type Difficulty, useStats, utcDate } from "../../lib/stats";
|
||||
import { StatsPending } from "./shared";
|
||||
|
||||
const chartConfig = {
|
||||
easy: { label: "Easy", color: "var(--chart-1)" },
|
||||
+3
-5
@@ -8,11 +8,9 @@
|
||||
* 4) and rows start on Monday like it, so the three heatmaps read the same.
|
||||
* Drawn as SVG in a viewBox, so it scales to its column instead of scrolling.
|
||||
*/
|
||||
import { StatsPending, TipRow, useHoverTip } from "../components/progress/shared";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card";
|
||||
import { type Day, useStats, utcDate } from "../lib/stats";
|
||||
|
||||
export const client = "load";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card";
|
||||
import { type Day, useStats, utcDate } from "../../lib/stats";
|
||||
import { StatsPending, TipRow, useHoverTip } from "./shared";
|
||||
|
||||
const MONTHS = 6;
|
||||
const CELL = 10;
|
||||
@@ -9,12 +9,10 @@
|
||||
*/
|
||||
import { packEnclose, packSiblings } from "d3-hierarchy";
|
||||
import { useId } from "react";
|
||||
import { StatsPending, TipRow, useHoverTip } from "../components/progress/shared";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../components/ui/card";
|
||||
import { type Stats, useStats } from "../lib/stats";
|
||||
import { cn } from "../lib/utils";
|
||||
|
||||
export const client = "load";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card";
|
||||
import { type Stats, useStats } from "../../lib/stats";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { StatsPending, TipRow, useHoverTip } from "./shared";
|
||||
|
||||
const PAD = 2; // gap between bubbles, in layout units
|
||||
const UNIT = 12; // radius of a one-problem bubble
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* What the four progress islands share besides the data: the not-ready body
|
||||
* What the progress cards share besides the data: the not-ready body
|
||||
* (a skeleton while /api/stats loads, one muted line if it fails) and the
|
||||
* hover tooltip for the two charts drawn as plain SVG (the heatmap calendar
|
||||
* and the topic bubbles — Recharts has neither layout). The tooltip wears the
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
title: Progress
|
||||
description: Live campaign progress — solved by difficulty, recent attempts, the year by difficulty, topic coverage, and the most recently solved problems, fetched from the SRS Worker.
|
||||
icon: loader
|
||||
---
|
||||
|
||||
<div className="not-prose flex flex-col gap-6">
|
||||
<SolvedRing />
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
<SubmissionHeatmap />
|
||||
<SubmissionChart />
|
||||
</div>
|
||||
<TopicBubbles />
|
||||
<RecentSolves />
|
||||
</div>
|
||||
@@ -1,7 +1,9 @@
|
||||
---
|
||||
title: System Design
|
||||
description: "Notes on System Design Interview — An Insider's Guide (Volumes 1 and 2): how to scope a problem, size it, and pick the parts that carry the load."
|
||||
icon: network
|
||||
icon: play
|
||||
sidebar:
|
||||
label: 'Getting Started'
|
||||
---
|
||||
|
||||
These notes follow Alex Xu's [System Design Interview — An Insider's Guide](https://bytebytego.com/courses/system-design-interview), [Volumes 1 and 2](https://www.goodreads.com/book/show/54109255-system-design-interview-an-insider-s-guide).
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* browser so `blume build` never depends on the API being up. API_BASE is the
|
||||
* deployed Worker — do not inline it anywhere else.
|
||||
*
|
||||
* Four islands read this (SolvedRing, SubmissionHeatmap, RecentSolves,
|
||||
* TopicBubbles). Each hydrates on its own, but they share this module, so the
|
||||
* one in-flight request is shared too: the page asks the Worker once.
|
||||
* The five cards on pages/progress.astro read this (components/progress/).
|
||||
* Each hydrates on its own, but they share this module, so the one in-flight
|
||||
* request is shared too: the page asks the Worker once.
|
||||
*
|
||||
* Invariants: a malformed body is an error state, never a throw; the first
|
||||
* frame is always the loading state, so server and client render identically.
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
/**
|
||||
* `/progress`: the live campaign dashboard — five LeetCode-style React cards
|
||||
* over GET /api/stats (lib/stats.ts), hydrated on load. A custom page like
|
||||
* `/changelog` and `/appendix`, linked from the header's `navigation.tabs`,
|
||||
* so it enters neither the sidebar tree nor prev/next. The cards live in
|
||||
* components/progress/, not islands/: they are imported here, never used from
|
||||
* MDX, so Blume has no reason to register them as global MDX components.
|
||||
*/
|
||||
import PageLayout from "blume/components/layout/PageLayout.astro";
|
||||
import data from "blume:data";
|
||||
import RecentSolves from "../components/progress/RecentSolves";
|
||||
import SolvedRing from "../components/progress/SolvedRing";
|
||||
import SubmissionChart from "../components/progress/SubmissionChart";
|
||||
import SubmissionHeatmap from "../components/progress/SubmissionHeatmap";
|
||||
import TopicBubbles from "../components/progress/TopicBubbles";
|
||||
|
||||
const { config } = data;
|
||||
const description =
|
||||
"Live campaign progress — solved by difficulty, recent attempts, the year by difficulty, topic coverage, and the most recently solved problems, fetched from the SRS Worker.";
|
||||
---
|
||||
|
||||
<PageLayout
|
||||
site={{ title: config.title, description: config.description }}
|
||||
logo={config.logo}
|
||||
favicon={config.favicon}
|
||||
banner={config.banner}
|
||||
analytics={config.analytics}
|
||||
navigation={data.navigation}
|
||||
fontCssVars={data.fontCssVars}
|
||||
themeMode={config.theme.mode}
|
||||
searchEnabled={config.search.enabled}
|
||||
siteUrl={config.site}
|
||||
ogEnabled={config.og.enabled}
|
||||
structuredDataEnabled={config.structuredData}
|
||||
page={{ title: `Progress - ${config.title}`, description, route: "/progress" }}
|
||||
>
|
||||
<section class="mx-auto w-full max-w-5xl px-6 py-16">
|
||||
<h1 class="m-0 text-4xl font-semibold tracking-tight text-foreground">Progress</h1>
|
||||
<p class="mt-3 max-w-3xl text-lg text-muted-foreground">{description}</p>
|
||||
|
||||
<div class="mt-10 flex flex-col gap-6">
|
||||
<SolvedRing client:load />
|
||||
<div class="grid gap-6 md:grid-cols-2">
|
||||
<SubmissionHeatmap client:load />
|
||||
<SubmissionChart client:load />
|
||||
</div>
|
||||
<TopicBubbles client:load />
|
||||
<RecentSolves client:load />
|
||||
</div>
|
||||
</section>
|
||||
</PageLayout>
|
||||
Reference in new issue
Block a user