diff --git a/frontend/src/components/Table/BreakdownTable.tsx b/frontend/src/components/Table/BreakdownTable.tsx index 9c13b7bd..0c50938f 100644 --- a/frontend/src/components/Table/BreakdownTable.tsx +++ b/frontend/src/components/Table/BreakdownTable.tsx @@ -124,12 +124,10 @@ const EPABreakdownTable = ({ year, yearData, data, - csvFilename, }: { year: number; yearData: APIYear; data: (APITeamYear | APITeamEvent)[]; - csvFilename: string; }) => { const [disableHighlight, setDisableHighlight] = useState(false); @@ -202,7 +200,6 @@ const EPABreakdownTable = ({ detailedData={yearInsightsData} detailedColumns={detailedColumns} searchCols={["num", "team"]} - csvFilename={csvFilename} toggleDisableHighlight={() => setDisableHighlight(!disableHighlight)} /> diff --git a/frontend/src/components/Table/InsightsTable.tsx b/frontend/src/components/Table/InsightsTable.tsx index aeb5d638..32c56e66 100644 --- a/frontend/src/components/Table/InsightsTable.tsx +++ b/frontend/src/components/Table/InsightsTable.tsx @@ -12,38 +12,40 @@ import Table from "./Table"; import { TableKey } from "./shared"; const InsightsTable = ({ - title, + title = null, data, columns, detailedData = [], detailedColumns = [], - searchCols, - csvFilename, - toggleDisableHighlight, - includeKey = true, + searchCols = [], + toggleDisableHighlight = undefined, }: { - title: string; + title?: string | null | undefined; data: any[]; columns: ColumnDef[]; detailedData?: any[]; detailedColumns?: ColumnDef[]; - searchCols: string[]; - csvFilename: string; + searchCols?: string[]; toggleDisableHighlight?: () => void; - includeKey?: boolean; }) => { const [showSearch, setShowSearch] = useState(false); const [search, setSearch] = useState(""); const [expanded, setExpanded] = useState(false); + const hasTitle = title !== undefined && title !== null && title !== ""; const expandable = detailedData?.length > 0; + const searchable = searchCols?.length > 0; const currData = expanded ? detailedData : data; const currColumns = expanded ? detailedColumns : columns; - const filteredData = currData.filter((row) => - searchCols.some((col) => row[col].toString().toLowerCase().includes(search.toLowerCase())) - ); + const filteredData = searchable + ? currData.filter((row) => + searchCols.some((col) => row[col].toString().toLowerCase().includes(search.toLowerCase())) + ) + : currData.filter((row) => + Object.values(row).some((value) => value.toString().toLowerCase().includes(search.toLowerCase())) + ); const headerClassName = () => "border-b-2 border-gray-800"; @@ -80,22 +82,20 @@ const InsightsTable = ({ /> ) : ( -
{title}
+ hasTitle && ( +
{title}
+ ) )} -
+ {searchable && (
setShowSearch(!showSearch)} /> -
+
) + } {toggleDisableHighlight && (
)} -
- - - -
{expandable && (
- {includeKey && } + {toggleDisableHighlight && } ); }; diff --git a/frontend/src/pagesContent/team/overview.tsx b/frontend/src/pagesContent/team/overview.tsx index d63a4329..6dbef92a 100644 --- a/frontend/src/pagesContent/team/overview.tsx +++ b/frontend/src/pagesContent/team/overview.tsx @@ -6,9 +6,63 @@ import Link from "next/link"; import MatchTable from "../../components/MatchTable"; import { canadaOptions, districtOptions, usaOptions } from "../../components/filterConstants"; import { CURR_YEAR, Category10Colors } from "../../constants"; -import { APITeam } from "../../types/api"; +import { APITeam, APITeamYear } from "../../types/api"; import { TeamYearData } from "../../types/data"; import { classnames, getMediaUrl } from "../../utils"; +import { MdAssessment } from "react-icons/md"; + + +type Config = { + points: { + [keyToName: string]: string; + }; + gamepieces: { + [keyToName: string]: string; + } | undefined; +}; + +const pre2016Keys: Config = { + points: { + total_points: "Total Points", + }, + gamepieces: undefined +} + +const post2015Keys: Config = { + points: { + auto_points: "Auto Points", + teleop_points: "Teleop Points", + endgame_points: "Endgame Points", + total_points: "Total Points", + }, + gamepieces: undefined +} + +const configs: { [key: number]: Config } = { + 2025: { + points: post2015Keys.points, + gamepieces: { + auto_coral: "Auto Coral", + coral_l1: "L1", + coral_l2: "L2", + coral_l3: "L3", + coral_l4: "L4", + processor_algae: "Processor", + net_algae: "Net", + total_game_pieces: "Total Game Pieces", + } + }, + 2024: { + points: post2015Keys.points, + gamepieces: { + auto_notes: "Auto Notes", + speaker_notes: "Speaker", + amplified_notes: "Amplified Speaker", + amp_notes: "Amp", + total_notes: "Total Game Pieces", + }, + }, +}; const epaCard = (epa: string, label: string, bg: string) => { if (!epa || !label || !bg) { @@ -40,8 +94,64 @@ const rankCard = (rank: number, count: number, label: string, filter: string) => ); }; +const epaCards = (year: number, breakdown: { [key: string]: number; }, gamepieces: boolean, gamepieceSettingCallback?: (v: boolean) => void, header: boolean = false) => { + + if (!gamepieceSettingCallback) { + gamepieceSettingCallback = (bool) => { }; + } + + const fallbackConfig = year < 2016 ? pre2016Keys : post2015Keys; + const config = configs[year] || fallbackConfig; + + const cardTemplates: [string, string][] = [] + if (gamepieces) { + Object.entries(config.gamepieces || {}).forEach(([key, label]) => { + const epa = breakdown?.[key]?.toFixed(1) || "0.0"; + cardTemplates.push([epa, label]); + }); + } else { + Object.entries(config.points).forEach(([key, label]) => { + const epa = breakdown?.[key]?.toFixed(1) || "0.0"; + cardTemplates.push([epa, label]); + }); + } + + var colorIndex = 0; + const cards = cardTemplates.map(([epa, label]) => { + const bg = Category10Colors[colorIndex % Category10Colors.length]; + colorIndex++; + return epaCard(epa, label, bg); + }); + + if (header) { + const text = gamepieces ? "GP Breakdown" : "EPA Breakdown"; + const swapText = gamepieces ? "Swap to EPA" : "Swap to Gamepieces"; + return ( +
+
+
+ gamepieceSettingCallback(!gamepieces)} + /> +
+ {text}: +
+
{cards}
+
+ ); + } else { + return ( +
+ {cards} +
+ ); + } +} + const OverviewSection = ({ teamYearData }: { teamYearData: TeamYearData | undefined }) => { const [alliance, setAlliance] = useState(true); + const [gamepieceEpa, setGamepieceEpa] = useState(true); const [media, setMedia] = useState(null); const teamNum = teamYearData?.team_year?.team; @@ -121,39 +231,7 @@ const OverviewSection = ({ teamYearData }: { teamYearData: TeamYearData | undefi {" "} in {year.year}. -
- EPA Breakdown: - {year.year >= 2016 ? ( - <> - {epaCard( - teamYear?.epa?.breakdown?.auto_points?.toFixed(1), - "Auto", - Category10Colors[0] - )} - {epaCard( - teamYear?.epa?.breakdown?.teleop_points?.toFixed(1), - "Teleop", - Category10Colors[1] - )} - {epaCard( - teamYear?.epa?.breakdown?.endgame_points?.toFixed(1), - "Endgame", - Category10Colors[2] - )} - {epaCard( - teamYear?.epa?.breakdown?.total_points?.toFixed(1), - "Total", - Category10Colors[3] - )} - - ) : ( - epaCard( - teamYear?.epa?.breakdown?.total_points?.toFixed(1), - "Total", - Category10Colors[0] - ) - )} -
+ {epaCards(teamYear?.year, teamYear?.epa?.breakdown, gamepieceEpa, setGamepieceEpa, true)}
{rankCard( teamYear?.epa?.ranks?.total?.rank, @@ -247,38 +325,7 @@ const OverviewSection = ({ teamYearData }: { teamYearData: TeamYearData | undefi
)} -
- {year.year >= 2016 ? ( - <> - {epaCard( - event?.epa?.breakdown?.auto_points?.toFixed(1), - "Auto", - Category10Colors[0] - )} - {epaCard( - event?.epa?.breakdown?.teleop_points?.toFixed(1), - "Teleop", - Category10Colors[1] - )} - {epaCard( - event?.epa?.breakdown?.endgame_points?.toFixed(1), - "Endgame", - Category10Colors[2] - )} - {epaCard( - event?.epa?.breakdown?.total_points?.toFixed(1), - "Total", - Category10Colors[3] - )} - - ) : ( - epaCard( - event?.epa?.breakdown?.total_points?.toFixed(1), - "Total", - Category10Colors[0] - ) - )} -
+ {epaCards(event?.year, event?.epa?.breakdown, gamepieceEpa)}
);