From fb4de44cde022880e5eb91278eeeaf5bef73140a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D8=B1=D9=8A=D8=A7=D9=86?=
<112495059+ryanab00@users.noreply.github.com>
Date: Mon, 5 Oct 2026 10:38:58 -0500
Subject: [PATCH 1/4] Add grouped series tab for matches
Group match results by series_id and add a dedicated Series tab with expandable rows and per-match details. This keeps related games together, preserves the existing single-match behavior for ungrouped matches, and adds compact summary metadata like teams, match count, and last played time.
---
src/components/Matches/Matches.tsx | 296 ++++++++++++++++++++++++++++-
1 file changed, 294 insertions(+), 2 deletions(-)
diff --git a/src/components/Matches/Matches.tsx b/src/components/Matches/Matches.tsx
index 107cb554ae..99a3d32d8e 100644
--- a/src/components/Matches/Matches.tsx
+++ b/src/components/Matches/Matches.tsx
@@ -7,7 +7,6 @@ import { transformations, subTextStyle, rankTierToString } from "../../utility";
import { getProMatches, getPublicMatches } from "../../actions";
import Table from "../Table/Table";
import TableLink from "../Table/TableLink";
-// import Heading from '../Heading';
import { IconTrophy } from "../Icons";
import Match from "../Match/Match";
import TabBar from "../TabBar/TabBar";
@@ -97,6 +96,67 @@ const matchesColumns = (strings: Strings) => [
},
];
+// Columns used inside an expanded series. Same look as the pro tab but
+// without the league name (it now lives on the parent series row).
+const seriesMatchesColumns = (strings: Strings) => [
+ {
+ displayName: strings.th_match_id,
+ field: "match_id",
+ sortFn: true,
+ displayFn: (row: any, col: any, field: any) => (
+
+ ),
+ },
+ {
+ displayName: strings.th_duration,
+ tooltip: strings.tooltip_duration,
+ field: "duration",
+ sortFn: true,
+ displayFn: transformations.duration,
+ },
+ {
+ displayName: (
+
+ {strings.general_radiant}
+
+ ),
+ field: "radiant_name",
+ color: constants.colorGreen,
+ displayFn: (row: any, col: any, field: any) => (
+
+ {row.radiant_win && (
+
+
+
+ )}
+ {field}
+
+ ),
+ },
+ {
+ displayName: (
+ {strings.general_dire}
+ ),
+ field: "dire_name",
+ color: constants.colorRed,
+ displayFn: (row: any, col: any, field: any) => (
+
+ {!row.radiant_win && (
+
+
+
+ )}
+ {field}
+
+ ),
+ },
+];
+
const publicMatchesColumns = (strings: Strings) => [
{
displayName: strings.th_match_id,
@@ -160,6 +220,224 @@ const publicMatchesColumns = (strings: Strings) => [
},
];
+// ---------------------------------------------------------------------------
+// Series tab
+// ---------------------------------------------------------------------------
+
+// A series is identified by series_id. Matches without a series_id are each
+// treated as their own single-match "series" (matching the existing UI).
+const groupBySeries = (matches: any[]) => {
+ const map = new Map();
+ (matches || []).forEach((m) => {
+ const key =
+ m.series_id != null ? `s-${m.series_id}` : `m-${m.match_id}`;
+ if (!map.has(key)) map.set(key, []);
+ map.get(key)!.push(m);
+ });
+
+ // Insertion order follows the original (most-recent-first) array, so the
+ // series with the freshest game bubble to the top automatically.
+ return Array.from(map.entries()).map(([key, seriesMatches]) => ({
+ key,
+ seriesId: seriesMatches[0].series_id,
+ matches: seriesMatches, // already sorted newest -> oldest
+ latestMatch: seriesMatches[0],
+ }));
+};
+
+const SERIES_GRID = "40px minmax(180px, 1.3fr) 1fr 1fr 90px 140px";
+
+const SeriesWrapper = styled.div`
+ width: 100%;
+ background: #1b2330;
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ border-radius: 3px;
+ overflow: hidden;
+`;
+
+const SeriesGrid = styled.div`
+ display: grid;
+ grid-template-columns: ${SERIES_GRID};
+ align-items: center;
+ column-gap: 12px;
+ padding: 12px 14px;
+`;
+
+const SeriesHeaderGrid = styled(SeriesGrid)`
+ background: #1e2633;
+ color: #8fa3bd;
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 0.8px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+`;
+
+const SeriesRowGrid = styled(SeriesGrid)`
+ background: #1b2330;
+ color: #dfe6ee;
+ font-size: 14px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+ cursor: pointer;
+ transition: background 0.15s ease;
+
+ &:hover {
+ background: #222c3d;
+ }
+`;
+
+const Toggle = styled.span`
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 18px;
+ height: 18px;
+ border-radius: 3px;
+ background: rgba(255, 255, 255, 0.08);
+ color: #9fb0c7;
+ font-size: 13px;
+ line-height: 1;
+ user-select: none;
+`;
+
+const TeamOne = styled.span`
+ color: ${constants.colorGreen};
+`;
+
+const TeamTwo = styled.span`
+ color: ${constants.colorRed};
+`;
+
+// NOTE: `subTextStyle` is a plain CSSProperties object, so it can't be
+// interpolated directly into a styled-components template literal. We apply
+// it inline on the element instead.
+const SeriesSubText = styled.div`
+ margin-top: 3px;
+`;
+
+const SeriesMatchWrap = styled.div`
+ background: #161d28;
+
+ /* Kill the leftover spacing the Table component carries at its tail */
+ & > *:last-child {
+ margin-bottom: 0 !important;
+ padding-bottom: 0 !important;
+ border-bottom: none !important;
+ }
+
+ /* Remove the border on the very last match row so the expanded body
+ ends cleanly on the row itself */
+ table {
+ margin-bottom: 0;
+ }
+
+ tbody tr:last-child td,
+ tbody tr:last-child th {
+ border-bottom: none !important;
+ }
+`;
+
+const SeriesTab = ({
+ data,
+ loading,
+ strings,
+}: {
+ data: any[];
+ loading: boolean;
+ strings: Strings;
+}) => {
+ const [expandedKey, setExpandedKey] = React.useState(null);
+ const seriesList = React.useMemo(() => groupBySeries(data), [data]);
+
+ if (loading) {
+ return Loading series...
;
+ }
+
+ // `Strings` is a strict type from the app; the Series-specific keys below
+ // aren't part of it yet, so we cast to `any` to fall back to English.
+ const s = strings as any;
+
+ return (
+
+
+
+ {s.th_series || "Series"}
+ {s.th_team_1 || "Team 1"}
+ {s.th_team_2 || "Team 2"}
+ {s.th_matches || "Matches"}
+ {s.th_last_played || "Last Played"}
+
+
+ {seriesList.map((series) => {
+ const isExpanded = expandedKey === series.key;
+ const { latestMatch } = series;
+
+ return (
+
+
setExpandedKey(isExpanded ? null : series.key)}
+ >
+
+ {isExpanded ? "−" : "+"}
+
+
+
+ {series.seriesId != null ? (
+ // `TableLink` doesn't forward `onClick`, so we wrap it in a
+ // plain div that stops the click from toggling the row.
+
e.stopPropagation()}>
+
+ {series.seriesId}
+
+
+ ) : (
+
—
+ )}
+
+ {(latestMatch.league_name || "").trim()}
+
+
+
+
+ {latestMatch.radiant_name}
+
+
+
+ {latestMatch.dire_name}
+
+
+
+ {series.matches.length}{" "}
+ {series.matches.length === 1 ? "match" : "matches"}
+
+
+
+
+
+
+
+ {isExpanded && (
+
+
+
+ )}
+
+ );
+ })}
+
+ );
+};
+
+// ---------------------------------------------------------------------------
+// Tabs
+// ---------------------------------------------------------------------------
+
const matchTabs = (strings: Strings) => [
{
name: strings.hero_pro_tab,
@@ -176,6 +454,19 @@ const matchTabs = (strings: Strings) => [
),
route: "/matches/pro",
},
+ {
+ // `matches_series` isn't part of the strict `Strings` type yet.
+ name: (strings as any).matches_series || "Series",
+ key: "series",
+ content: (propsPar: MatchesProps) => (
+
+ ),
+ route: "/matches/series",
+ },
{
name: strings.matches_highest_mmr,
key: "highMmr",
@@ -221,6 +512,7 @@ class Matches extends React.Component {
getData(this.props);
}
}
+
render() {
const { strings } = this.props;
const route = this.props.match.params.matchId || "pro";
@@ -253,4 +545,4 @@ const mapDispatchToProps = (dispatch: any) => ({
dispatchPublicMatches: (options: any) => dispatch(getPublicMatches(options)),
});
-export default connect(mapStateToProps, mapDispatchToProps)(Matches);
+export default connect(mapStateToProps, mapDispatchToProps)(Matches);
\ No newline at end of file
From 5161d3713c2bed7ab37c710a37e202a81c9a5718 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D8=B1=D9=8A=D8=A7=D9=86?=
<112495059+ryanab00@users.noreply.github.com>
Date: Sat, 10 Oct 2026 08:53:27 -0500
Subject: [PATCH 2/4] Add series label to the US string collection
Update the matches tab to use the typed `matches_series` string instead of a temporary `any` fallback, and add the default English translation for the Series label.
---
src/components/Matches/Matches.tsx | 3 +--
src/lang/en-US.json | 1 +
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/Matches/Matches.tsx b/src/components/Matches/Matches.tsx
index 99a3d32d8e..d075f228ee 100644
--- a/src/components/Matches/Matches.tsx
+++ b/src/components/Matches/Matches.tsx
@@ -455,8 +455,7 @@ const matchTabs = (strings: Strings) => [
route: "/matches/pro",
},
{
- // `matches_series` isn't part of the strict `Strings` type yet.
- name: (strings as any).matches_series || "Series",
+ name: strings.matches_series,
key: "series",
content: (propsPar: MatchesProps) => (
Date: Sun, 11 Oct 2026 23:32:55 -0500
Subject: [PATCH 3/4] Removed fallback values
Removed fallback values, would be tedious to update if we ever needed to.
---
src/components/Matches/Matches.tsx | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/components/Matches/Matches.tsx b/src/components/Matches/Matches.tsx
index d075f228ee..af4d473c54 100644
--- a/src/components/Matches/Matches.tsx
+++ b/src/components/Matches/Matches.tsx
@@ -360,11 +360,11 @@ const SeriesTab = ({
- {s.th_series || "Series"}
- {s.th_team_1 || "Team 1"}
- {s.th_team_2 || "Team 2"}
- {s.th_matches || "Matches"}
- {s.th_last_played || "Last Played"}
+ {s.th_series}
+ {s.th_team_1}
+ {s.th_team_2}
+ {s.th_matches}
+ {s.th_last_played}
{seriesList.map((series) => {
From 6154868d6f8eeefedd8d842550bd2a1459e2e874 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D8=B1=D9=8A=D8=A7=D9=86?=
<112495059+ryanab00@users.noreply.github.com>
Date: Sun, 25 Oct 2026 15:21:56 -0500
Subject: [PATCH 4/4] Add localized series table headers
Add English labels for the series table and use typed localization keys instead of an `any` cast.
---
package-lock.json | 48 +++---------------------------
src/components/Matches/Matches.tsx | 14 ++++-----
src/lang/en-US.json | 3 ++
3 files changed, 12 insertions(+), 53 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 0681d76ac0..a1c8b5494f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,7 +15,6 @@
"@melloware/react-logviewer": "^6.6.0",
"@mui/icons-material": "^7.3.5",
"@mui/material": "^7.3.6",
- "abcolor": "^0.5.5",
"ace-builds": "^1.43.5",
"air-datepicker": "^3.6.0",
"dota2-emoticons": "^1.0.4",
@@ -112,7 +111,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz",
"integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==",
"dev": true,
- "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.23.5",
@@ -2175,7 +2173,6 @@
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@@ -2845,7 +2842,6 @@
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz",
"integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.28.4",
"@mui/core-downloads-tracker": "^7.3.6",
@@ -3651,7 +3647,6 @@
"version": "17.0.47",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.47.tgz",
"integrity": "sha512-mk0BL8zBinf2ozNr3qPnlu1oyVTYq+4V7WA76RgxUAtf0Em/Wbid38KN6n4abEkvO4xMTBWmnP1FtQzgkEiJoA==",
- "peer": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -3755,14 +3750,6 @@
"integrity": "sha512-UMKd/doXE3karDUd5l+2LqFKUU4SmuPWOT/VA22OrPOUGMlb8/qQvSf+DBLQf/sd8UphuBGxOK/jB/1BB5oQRw==",
"dev": true
},
- "node_modules/abcolor": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/abcolor/-/abcolor-0.5.5.tgz",
- "integrity": "sha512-xYDsPOWM2/n6Xvc9mwcJ1BIHdk6ahjWIqp5dwx9P+s0Ou/f6moythvJOdUNTdeRkB18e0yGin4DBZUksoaEQiw==",
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/ace-builds": {
"version": "1.43.5",
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.5.tgz",
@@ -4109,7 +4096,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751",
@@ -6924,7 +6910,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "peer": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -7028,7 +7013,6 @@
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
- "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@@ -7065,7 +7049,6 @@
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
- "peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
@@ -7387,7 +7370,6 @@
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.9.2"
}
@@ -7897,7 +7879,6 @@
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz",
"integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==",
"hasInstallScript": true,
- "peer": true,
"dependencies": {
"@babel/helper-module-imports": "^7.0.0",
"@babel/traverse": "^7.0.0",
@@ -7926,8 +7907,7 @@
"node_modules/stylis": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
- "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==",
- "peer": true
+ "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
},
"node_modules/stylis-rule-sheet": {
"version": "0.0.10",
@@ -8715,7 +8695,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -9324,7 +9303,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -9613,7 +9591,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz",
"integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==",
"dev": true,
- "peer": true,
"requires": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.23.5",
@@ -11035,7 +11012,6 @@
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
- "peer": true,
"requires": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@@ -11383,7 +11359,6 @@
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz",
"integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==",
- "peer": true,
"requires": {
"@babel/runtime": "^7.28.4",
"@mui/core-downloads-tracker": "^7.3.6",
@@ -11862,7 +11837,6 @@
"version": "17.0.47",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.47.tgz",
"integrity": "sha512-mk0BL8zBinf2ozNr3qPnlu1oyVTYq+4V7WA76RgxUAtf0Em/Wbid38KN6n4abEkvO4xMTBWmnP1FtQzgkEiJoA==",
- "peer": true,
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -11963,11 +11937,6 @@
"integrity": "sha512-UMKd/doXE3karDUd5l+2LqFKUU4SmuPWOT/VA22OrPOUGMlb8/qQvSf+DBLQf/sd8UphuBGxOK/jB/1BB5oQRw==",
"dev": true
},
- "abcolor": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/abcolor/-/abcolor-0.5.5.tgz",
- "integrity": "sha512-xYDsPOWM2/n6Xvc9mwcJ1BIHdk6ahjWIqp5dwx9P+s0Ou/f6moythvJOdUNTdeRkB18e0yGin4DBZUksoaEQiw=="
- },
"ace-builds": {
"version": "1.43.5",
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.43.5.tgz",
@@ -12221,7 +12190,6 @@
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz",
"integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==",
"dev": true,
- "peer": true,
"requires": {
"baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751",
@@ -14113,7 +14081,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "peer": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -14184,7 +14151,6 @@
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
- "peer": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@@ -14208,7 +14174,6 @@
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
- "peer": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
@@ -14462,7 +14427,6 @@
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
- "peer": true,
"requires": {
"@babel/runtime": "^7.9.2"
}
@@ -14834,7 +14798,6 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz",
"integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==",
- "peer": true,
"requires": {
"@babel/helper-module-imports": "^7.0.0",
"@babel/traverse": "^7.0.0",
@@ -14861,8 +14824,7 @@
"stylis": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
- "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==",
- "peer": true
+ "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q=="
},
"stylis-rule-sheet": {
"version": "0.0.10",
@@ -15453,8 +15415,7 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "dev": true,
- "peer": true
+ "dev": true
}
}
},
@@ -15804,8 +15765,7 @@
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "dev": true,
- "peer": true
+ "dev": true
}
}
},
diff --git a/src/components/Matches/Matches.tsx b/src/components/Matches/Matches.tsx
index af4d473c54..d7fbd7df95 100644
--- a/src/components/Matches/Matches.tsx
+++ b/src/components/Matches/Matches.tsx
@@ -352,19 +352,15 @@ const SeriesTab = ({
return Loading series...
;
}
- // `Strings` is a strict type from the app; the Series-specific keys below
- // aren't part of it yet, so we cast to `any` to fall back to English.
- const s = strings as any;
-
return (
- {s.th_series}
- {s.th_team_1}
- {s.th_team_2}
- {s.th_matches}
- {s.th_last_played}
+ {strings.th_series}
+ {strings.th_team_1}
+ {strings.th_team_2}
+ {strings.th_matches}
+ {strings.th_last_played}
{seriesList.map((series) => {
diff --git a/src/lang/en-US.json b/src/lang/en-US.json
index c6e5e7270a..5d27b815f3 100644
--- a/src/lang/en-US.json
+++ b/src/lang/en-US.json
@@ -781,6 +781,9 @@
"th_category": "Category",
"th_matches": "Matches",
"th_percentile": "Percentile",
+ "th_series": "Series",
+ "th_team_1": "Team 1",
+ "th_team_2": "Team 2",
"th_rank": "Rank",
"th_items": "Items",
"th_stacked": "Stacked",