Add star-player matches tab and watchlist-driven fetch.

Ship top-level #/matches with pro watchlist defaults, bump site to 0.5.71, and document the flow in AGENTS/README.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
voson
2026-07-29 16:03:45 +08:00
co-authored by Cursor
parent 09bd5aabb3
commit d9c7b4b7b1
11 changed files with 1073 additions and 130 deletions
+13 -2
View File
@@ -4,11 +4,13 @@
* Hash-based router for the Climperor web site (web/relations).
*
* Synchronizes the browser URL with app state across these dimensions:
* - page: heroes | rankings | streamers | trends | mechanics | items | patches (top-level tab)
* - page: heroes | rankings | matches | streamers | trends | mechanics | items | patches (top-level tab)
* - hero: selected hero key + detail sub-tab
* (skills|core|fears|trends|matchups|matches|streamers|patches; legacy stats → trends)
* - rankings: Immortal leaderboard region
* #/rankings[/region] (legacy #/rankings/meta[/bracket] → players / china)
* - matches: star-player recent matches (pro_matches)
* #/matches[/account_id]
* - streamers: curated Douyin streamer directory
* #/streamers
* - trends: medal bracket for the 8-week win/pick board
@@ -30,7 +32,7 @@
*/
const ROUTE_DEFAULT = "#/heroes";
const VALID_PAGES = ["heroes", "rankings", "streamers", "trends", "mechanics", "items", "patches"];
const VALID_PAGES = ["heroes", "rankings", "matches", "streamers", "trends", "mechanics", "items", "patches"];
const VALID_DETAIL_TABS = [
"skills",
"core",
@@ -92,6 +94,7 @@ function parseHash(hash) {
itemKey: null,
patchVersion: null,
rankingRegion: null,
matchesPlayerId: null,
trendsBracket: null,
trendsSort: null,
mechanicEffect: null,
@@ -118,6 +121,10 @@ function parseHash(hash) {
if (segs[1] && segs[1] !== "meta") {
out.rankingRegion = safeDecode(segs[1]);
}
} else if (page === "matches") {
if (segs[1] && /^\d+$/.test(segs[1])) {
out.matchesPlayerId = segs[1];
}
} else if (page === "trends") {
if (segs[1]) out.trendsBracket = safeDecode(segs[1]);
} else if (page === "mechanics") {
@@ -175,6 +182,10 @@ function serializeHash(state) {
if (region && region !== DEFAULT_RANKING_REGION) {
hash += "/" + encodeURIComponent(region);
}
} else if (state.page === "matches") {
if (state.matchesPlayerId) {
hash += "/" + encodeURIComponent(String(state.matchesPlayerId));
}
} else if (state.page === "trends") {
// Omit bracket when it is the default (legend) — bare #/trends means legend.
const bracket = state.trendsBracket || DEFAULT_TRENDS_BRACKET;