|
{r.session.name}
diff --git a/client/src/components/sessions/SessionOverview.tsx b/client/src/components/sessions/SessionOverview.tsx
new file mode 100644
index 000000000..e3f172a81
--- /dev/null
+++ b/client/src/components/sessions/SessionOverview.tsx
@@ -0,0 +1,165 @@
+import { ResponsiveLine } from "@nivo/line";
+import ChartTooltip from "components/charts/ChartTooltip";
+import Card from "components/layout/page/Card";
+import ScoreTable from "components/tables/scores/ScoreTable";
+import DebugContent from "components/util/DebugContent";
+import Divider from "components/util/Divider";
+import { UserContext } from "context/UserContext";
+import { ColourConfig } from "lib/config";
+import React, { useContext, useMemo } from "react";
+import { Col } from "react-bootstrap";
+import { ChartDocument, GetGamePTConfig, ScoreDocument, SongDocument } from "tachi-common";
+import { SessionReturns } from "types/api-returns";
+import { GamePT } from "types/react";
+import { ScoreDataset } from "types/tables";
+import { TACHI_CHART_THEME } from "util/constants/chart-theme";
+import { UppercaseFirst } from "util/misc";
+import { NumericSOV } from "util/sorts";
+import { FormatDuration } from "util/time";
+
+export default function SessionOverview({
+ sessionData,
+ scoreDataset,
+}: {
+ sessionData: SessionReturns;
+ scoreDataset: ScoreDataset;
+}) {
+ const { scores, session } = sessionData;
+ const { user } = useContext(UserContext);
+
+ // const performanceDataset = useMemo(() => {
+ // const d = [];
+
+ // for (const scoreInfo of session.scoreInfo) {
+ // const score = scoreMap.get(scoreInfo.scoreID);
+
+ // if (!score) {
+ // console.error(`Score ${scoreInfo.scoreID} doesn't exist?`);
+ // continue;
+ // }
+
+ // const chart = chartMap.get(score.chartID);
+ // const song = songMap.get(score.songID);
+
+ // if (!chart || !song) {
+ // console.error(`Chart ${score.chartID} (${score.songID}) has no chart?`);
+ // continue;
+ // }
+
+ // d.push({
+ // ...score,
+ // __related: {
+ // song,
+ // chart,
+ // },
+ // });
+ // }
+
+ // return d;
+ // }, [sessionData]);
+
+ return (
+ <>
+
+
+ e.highlight).length} />
+
+
+
+ e.highlight)}
+ />
+
+
+ >
+ );
+}
+
+function StatThing({
+ value,
+ name,
+ md12,
+}: {
+ value: string | number;
+ name: string;
+ md12?: boolean;
+}) {
+ return (
+
+
+
+ );
+}
+
+type PerformanceData = ScoreDocument & {
+ __related: {
+ chart: ChartDocument;
+ song: SongDocument;
+ };
+};
+
+function PerformanceComponent({
+ dataset,
+ timeStart,
+ game,
+ playtype,
+}: {
+ dataset: PerformanceData[];
+ timeStart: number;
+} & GamePT) {
+ const gptConfig = GetGamePTConfig(game, playtype);
+
+ const data = useMemo(() => {
+ const data = [];
+
+ for (const alg of gptConfig.scoreRatingAlgs) {
+ data.push({
+ id: UppercaseFirst(alg),
+ data: dataset
+ .map(e => ({
+ x: e.timeAchieved!,
+ y: (e.calculatedData[alg] ?? 0) < 0 ? null : e.calculatedData[alg] ?? 0,
+ }))
+ .sort(NumericSOV(e => e.x, true)),
+ });
+ }
+ return data;
+ }, [dataset]);
+
+ return (
+
+
+ FormatDuration(timeStart - x.valueOf()),
+ }}
+ gridXValues={3}
+ motionConfig="stiff"
+ crosshairType="x"
+ yScale={{ type: "linear", min: "auto", max: "auto" }}
+ colors={[ColourConfig.primary]}
+ useMesh={true}
+ theme={TACHI_CHART_THEME}
+ tooltip={d => (
+ } />
+ )}
+ // legends={[]}
+ enableArea
+ />
+
+
+ );
+}
diff --git a/client/src/components/sessions/SessionRaiseBreakdown.tsx b/client/src/components/sessions/SessionRaiseBreakdown.tsx
new file mode 100644
index 000000000..ed36c3e65
--- /dev/null
+++ b/client/src/components/sessions/SessionRaiseBreakdown.tsx
@@ -0,0 +1,476 @@
+import DifficultyCell from "components/tables/cells/DifficultyCell";
+import LampCell from "components/tables/cells/LampCell";
+import ScoreCell from "components/tables/cells/ScoreCell";
+import TitleCell from "components/tables/cells/TitleCell";
+import MiniTable from "components/tables/components/MiniTable";
+import Loading from "components/util/Loading";
+import SelectButton from "components/util/SelectButton";
+import deepmerge from "deepmerge";
+import { nanoid } from "nanoid";
+import React, { useState, useEffect, useMemo } from "react";
+import { useQuery } from "react-query";
+import Divider from "components/util/Divider";
+import Icon from "components/util/Icon";
+import {
+ FolderDocument,
+ TableDocument,
+ Lamps,
+ IDStrings,
+ ScoreDocument,
+ SessionScoreInfo,
+ Grades,
+ GetGamePTConfig,
+ GamePTConfig,
+ integer,
+ SongDocument,
+ Game,
+ ChartDocument,
+} from "tachi-common";
+import { SessionReturns } from "types/api-returns";
+import { APIFetchV1 } from "util/api";
+import { CreateSongMap, CreateChartMap, CreateScoreIDMap } from "util/data";
+import { PartialArrayRecordAssign } from "util/misc";
+import { ChangeOpacity } from "util/color-opacity";
+
+export default function SessionRaiseBreakdown({ sessionData }: { sessionData: SessionReturns }) {
+ const game = sessionData.session.game;
+ const playtype = sessionData.session.playtype;
+
+ // todo infer default table
+ // const gptConfig = GetGamePTConfig(game, playtype);
+
+ const [chartIDs, setChartIDs] = useState([]);
+ const [tableID, setTableID] = useState(null);
+ const [tableFolders, setTableFolders] = useState([]);
+ const [folder, setFolder] = useState(null);
+ const [filter, setFilter] = useState<"folder" | "all" | "highlighted">("all");
+
+ useEffect(() => {
+ if (!tableID) {
+ return;
+ }
+
+ APIFetchV1(`/games/${game}/${playtype}/tables/${tableID}`).then(r => {
+ if (!r.success) {
+ throw new Error(r.description);
+ }
+
+ // @ts-expect-error todo
+ setTableFolders(r.body.folders);
+ // @ts-expect-error todo
+ setFolder(r.body.folders[r.body.folders.length - 1]);
+ });
+ }, [tableID]);
+
+ useEffect(() => {
+ if (filter !== "folder" || !folder) {
+ setChartIDs(null);
+ return;
+ }
+
+ APIFetchV1(`/games/${game}/${playtype}/folders/${folder.folderID}`).then(r => {
+ if (!r.success) {
+ throw new Error(r.description);
+ }
+
+ // @ts-expect-error todo
+ setChartIDs(r.body.charts.map(e => e.chartID));
+ });
+ }, [folder, tableID, filter]);
+
+ const { isLoading, error, data } = useQuery(`/games/${game}/${playtype}/tables`, async () => {
+ const res = await APIFetchV1(`/games/${game}/${playtype}/tables`);
+
+ if (!res.success) {
+ throw new Error(res.description);
+ }
+
+ return res.body;
+ });
+ const [view, setView] = useState<"lamps" | "both" | "grades">("both");
+
+ useEffect(() => {
+ if (tableID === null && (data?.length ?? 0) > 0) {
+ setTableID(data![0].tableID);
+ }
+ }, [data]);
+
+ if (error) {
+ return <>{(error as Error).message}>;
+ }
+
+ if (isLoading || !data) {
+ return ;
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+ New Lamps
+
+
+
+
+ Both
+
+
+
+ New Grades
+
+
+
+
+
+
+
+
+ {filter === "folder" && (
+ <>
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+ >
+ );
+}
+
+function SessionScoreStatBreakdown({
+ sessionData,
+ chartIDs,
+ filter,
+ view,
+}: {
+ sessionData: SessionReturns;
+ chartIDs: string[] | null;
+ filter: "folder" | "all" | "highlighted";
+ view: "lamps" | "both" | "grades";
+}) {
+ const songMap = CreateSongMap(sessionData.songs);
+ const chartMap = CreateChartMap(sessionData.charts);
+ const scoreMap = CreateScoreIDMap(sessionData.scores);
+
+ const [newLamps, newGrades] = useMemo(() => {
+ const newLamps: Partial> = {};
+ const newGrades: Partial> = {};
+
+ for (const scoreInfo of sessionData.session.scoreInfo) {
+ const score = scoreMap.get(scoreInfo.scoreID);
+
+ if (!score) {
+ console.error(
+ `Session score info contains scoreID ${scoreInfo.scoreID}, but no score exists?`
+ );
+ continue;
+ }
+
+ if (filter === "folder" && chartIDs && !chartIDs.includes(score.chartID)) {
+ continue;
+ } else if (filter === "highlighted" && !score.highlight) {
+ continue;
+ }
+
+ if (scoreInfo.isNewScore) {
+ PartialArrayRecordAssign(newLamps, score.scoreData.lamp, { score, scoreInfo });
+ PartialArrayRecordAssign(newGrades, score.scoreData.grade, { score, scoreInfo });
+ } else {
+ if (scoreInfo.lampDelta > 0) {
+ PartialArrayRecordAssign(newLamps, score.scoreData.lamp, { score, scoreInfo });
+ }
+
+ if (scoreInfo.gradeDelta > 0) {
+ PartialArrayRecordAssign(newGrades, score.scoreData.grade, {
+ score,
+ scoreInfo,
+ });
+ }
+ }
+ }
+
+ return [newLamps, newGrades];
+ }, [chartIDs, filter, view]);
+
+ const gptConfig = GetGamePTConfig(sessionData.session.game, sessionData.session.playtype);
+
+ return (
+ <>
+ {view === "both" ? (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ ) : view === "grades" ? (
+
+
+
+
+
+ ) : (
+
+
+
+
+
+ )}
+ >
+ );
+}
+
+function ElementStatTable({
+ type,
+ counts,
+ gptConfig,
+ songMap,
+ chartMap,
+ game,
+ fullSize = false,
+}: {
+ type: "lamp" | "grade";
+ counts: Record;
+ gptConfig: GamePTConfig;
+ songMap: Map>;
+ chartMap: Map>;
+ game: Game;
+ fullSize?: boolean;
+}) {
+ const tableContents = useMemo(() => {
+ // relements.. haha
+ const relevantElements =
+ type === "lamp"
+ ? gptConfig.lamps.slice(gptConfig.lamps.indexOf(gptConfig.clearLamp) - 1).reverse()
+ : gptConfig.grades
+ .slice(gptConfig.grades.indexOf(gptConfig.clearGrade) - 1)
+ .reverse();
+
+ const colours = type === "lamp" ? gptConfig.lampColours : gptConfig.gradeColours;
+
+ const tableContents = [];
+ for (const element of relevantElements) {
+ if (!counts[element] || !counts[element].length) {
+ continue;
+ }
+
+ const firstData = counts[element][0];
+
+ tableContents.push(
+
+ |
+ {element}
+ |
+
+
+ );
+
+ for (const data of counts[element]!.slice(1)) {
+ tableContents.push(
+
+
+
+ );
+ }
+ }
+
+ return tableContents;
+ }, [type, counts, fullSize, game]);
+
+ if (tableContents.length === 0) {
+ return (
+
+ | Nothing... |
+
+ );
+ }
+
+ return <>{tableContents}>;
+}
+
+function BreakdownChartContents({
+ score,
+ scoreInfo,
+ game,
+ songMap,
+ chartMap,
+ fullSize,
+ gptConfig,
+ type,
+}: {
+ score: ScoreDocument;
+ scoreInfo: SessionScoreInfo;
+ fullSize: boolean;
+ game: Game;
+ songMap: Map;
+ chartMap: Map;
+ gptConfig: GamePTConfig;
+ type: "lamp" | "grade";
+}) {
+ const chart = chartMap.get(score.chartID)!;
+ const song = songMap.get(score.songID)!;
+
+ if (!chart || !song) {
+ console.error(`No chart for ${score.chartID}/${score.songID}???`);
+ return null;
+ }
+
+ if (fullSize) {
+ let preScoreCell = No Play | ;
+
+ if (!scoreInfo.isNewScore) {
+ const oldGradeIndex = score.scoreData.gradeIndex - scoreInfo.gradeDelta;
+ const oldLampIndex = score.scoreData.lampIndex - scoreInfo.lampDelta;
+
+ const mockScore = deepmerge(score, {
+ scoreData: {
+ score: score.scoreData.score - scoreInfo.scoreDelta,
+ percent: score.scoreData.percent - scoreInfo.percentDelta,
+ grade: gptConfig.grades[oldGradeIndex],
+ gradeIndex: oldGradeIndex,
+ lamp: gptConfig.lamps[oldLampIndex],
+ lampIndex: oldLampIndex,
+ },
+ }) as ScoreDocument;
+
+ if (type === "grade") {
+ preScoreCell = ;
+ } else {
+ preScoreCell = ;
+ }
+ }
+
+ console.log(game);
+
+ if (score) {
+ return (
+ <>
+
+
+ {preScoreCell}
+ ⟶ |
+ {type === "grade" ? (
+
+ ) : (
+
+ )}
+ >
+ );
+ }
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/client/src/components/tables/dropdowns/GenericSessionDropdown.tsx b/client/src/components/tables/dropdowns/GenericSessionDropdown.tsx
index 260cdce42..fe5e73146 100644
--- a/client/src/components/tables/dropdowns/GenericSessionDropdown.tsx
+++ b/client/src/components/tables/dropdowns/GenericSessionDropdown.tsx
@@ -1,38 +1,13 @@
+import SessionRaiseBreakdown from "components/sessions/SessionRaiseBreakdown";
import DebugContent from "components/util/DebugContent";
-import Divider from "components/util/Divider";
import HasDevModeOn from "components/util/HasDevModeOn";
import Icon from "components/util/Icon";
import Loading from "components/util/Loading";
import SelectButton from "components/util/SelectButton";
-import deepmerge from "deepmerge";
-import { nanoid } from "nanoid";
-import React, { useEffect, useMemo, useState } from "react";
+import React, { useState } from "react";
import { useQuery } from "react-query";
-import {
- ChartDocument,
- FolderDocument,
- Game,
- GamePTConfig,
- GetGamePTConfig,
- Grades,
- IDStrings,
- integer,
- Lamps,
- ScoreDocument,
- SessionScoreInfo,
- SongDocument,
- TableDocument,
-} from "tachi-common";
-import { SpecificSessionReturns } from "types/api-returns";
+import { SessionReturns } from "types/api-returns";
import { APIFetchV1 } from "util/api";
-import { ChangeOpacity } from "util/color-opacity";
-import { CreateChartMap, CreateScoreIDMap, CreateSongMap } from "util/data";
-import { PartialArrayRecordAssign } from "util/misc";
-import DifficultyCell from "../cells/DifficultyCell";
-import LampCell from "../cells/LampCell";
-import ScoreCell from "../cells/ScoreCell";
-import TitleCell from "../cells/TitleCell";
-import MiniTable from "../components/MiniTable";
import { SessionDataset } from "../sessions/GenericSessionTable";
import DropdownStructure from "./components/DropdownStructure";
@@ -40,7 +15,7 @@ export default function GenericSessionDropdown({ data }: { data: SessionDataset[
const { isLoading, error, data: sessionData } = useQuery(
`/sessions/${data.sessionID}`,
async () => {
- const res = await APIFetchV1(`/sessions/${data.sessionID}`);
+ const res = await APIFetchV1(`/sessions/${data.sessionID}`);
if (!res.success) {
throw new Error(res.description);
@@ -89,448 +64,3 @@ export default function GenericSessionDropdown({ data }: { data: SessionDataset[
);
}
-
-function SessionRaiseBreakdown({ sessionData }: { sessionData: SpecificSessionReturns }) {
- const game = sessionData.session.game;
- const playtype = sessionData.session.playtype;
-
- // todo infer default table
- // const gptConfig = GetGamePTConfig(game, playtype);
-
- const [chartIDs, setChartIDs] = useState([]);
- const [tableID, setTableID] = useState(null);
- const [tableFolders, setTableFolders] = useState([]);
- const [folder, setFolder] = useState(null);
- const [filter, setFilter] = useState<"folder" | "all" | "highlighted">("all");
-
- useEffect(() => {
- if (!tableID) {
- return;
- }
-
- APIFetchV1(`/games/${game}/${playtype}/tables/${tableID}`).then(r => {
- if (!r.success) {
- throw new Error(r.description);
- }
-
- // @ts-expect-error todo
- setTableFolders(r.body.folders);
- // @ts-expect-error todo
- setFolder(r.body.folders[r.body.folders.length - 1]);
- });
- }, [tableID]);
-
- useEffect(() => {
- if (filter !== "folder" || !folder) {
- setChartIDs(null);
- return;
- }
-
- APIFetchV1(`/games/${game}/${playtype}/folders/${folder.folderID}`).then(r => {
- if (!r.success) {
- throw new Error(r.description);
- }
-
- // @ts-expect-error todo
- setChartIDs(r.body.charts.map(e => e.chartID));
- });
- }, [folder, tableID, filter]);
-
- const { isLoading, error, data } = useQuery(`/games/${game}/${playtype}/tables`, async () => {
- const res = await APIFetchV1(`/games/${game}/${playtype}/tables`);
-
- if (!res.success) {
- throw new Error(res.description);
- }
-
- return res.body;
- });
-
- useEffect(() => {
- if (tableID === null && (data?.length ?? 0) > 0) {
- setTableID(data![0].tableID);
- }
- }, [data]);
-
- if (error) {
- return <>{(error as Error).message}>;
- }
-
- if (isLoading || !data) {
- return ;
- }
-
- return (
- <>
-
-
-
-
-
-
- Folder Filter
-
-
-
- No Filter
-
-
-
- Highlights Only
-
-
-
- {filter === "folder" && (
- <>
-
-
-
-
-
-
-
- >
- )}
-
-
-
-
-
- >
- );
-}
-
-function SessionScoreStatBreakdown({
- sessionData,
- chartIDs,
- filter,
-}: {
- sessionData: SpecificSessionReturns;
- chartIDs: string[] | null;
- filter: "folder" | "all" | "highlighted";
-}) {
- const [view, setView] = useState<"lamps" | "both" | "grades">("both");
-
- const songMap = CreateSongMap(sessionData.songs);
- const chartMap = CreateChartMap(sessionData.charts);
- const scoreMap = CreateScoreIDMap(sessionData.scores);
-
- const [newLamps, newGrades] = useMemo(() => {
- const newLamps: Partial> = {};
- const newGrades: Partial> = {};
-
- for (const scoreInfo of sessionData.session.scoreInfo) {
- const score = scoreMap.get(scoreInfo.scoreID);
-
- if (!score) {
- console.error(
- `Session score info contains scoreID ${scoreInfo.scoreID}, but no score exists?`
- );
- continue;
- }
-
- if (filter === "folder" && chartIDs && !chartIDs.includes(score.chartID)) {
- continue;
- } else if (filter === "highlighted" && !score.highlight) {
- continue;
- }
-
- if (scoreInfo.isNewScore) {
- PartialArrayRecordAssign(newLamps, score.scoreData.lamp, { score, scoreInfo });
- PartialArrayRecordAssign(newGrades, score.scoreData.grade, { score, scoreInfo });
- } else {
- if (scoreInfo.lampDelta > 0) {
- PartialArrayRecordAssign(newLamps, score.scoreData.lamp, { score, scoreInfo });
- }
-
- if (scoreInfo.gradeDelta > 0) {
- PartialArrayRecordAssign(newGrades, score.scoreData.grade, {
- score,
- scoreInfo,
- });
- }
- }
- }
-
- return [newLamps, newGrades];
- }, [chartIDs, filter, view]);
-
- const gptConfig = GetGamePTConfig(sessionData.session.game, sessionData.session.playtype);
-
- return (
- <>
-
-
-
-
- New Lamps
-
-
-
-
- Both
-
-
-
- New Grades
-
-
-
-
- {view === "both" ? (
- <>
-
-
-
-
-
-
-
-
-
-
- >
- ) : view === "grades" ? (
-
-
-
-
-
- ) : (
-
-
-
-
-
- )}
- >
- );
-}
-
-function ElementStatTable({
- type,
- counts,
- gptConfig,
- songMap,
- chartMap,
- game,
- fullSize = false,
-}: {
- type: "lamp" | "grade";
- counts: Record;
- gptConfig: GamePTConfig;
- songMap: Map>;
- chartMap: Map>;
- game: Game;
- fullSize?: boolean;
-}) {
- const tableContents = useMemo(() => {
- // relements.. haha
- const relevantElements =
- type === "lamp"
- ? gptConfig.lamps.slice(gptConfig.lamps.indexOf(gptConfig.clearLamp) - 1).reverse()
- : gptConfig.grades
- .slice(gptConfig.grades.indexOf(gptConfig.clearGrade) - 1)
- .reverse();
-
- const colours = type === "lamp" ? gptConfig.lampColours : gptConfig.gradeColours;
-
- const tableContents = [];
- for (const element of relevantElements) {
- if (!counts[element] || !counts[element].length) {
- continue;
- }
-
- const firstData = counts[element][0];
-
- tableContents.push(
-
- |
- {element}
- |
-
-
- );
-
- for (const data of counts[element]!.slice(1)) {
- tableContents.push(
-
-
-
- );
- }
- }
-
- return tableContents;
- }, [type, counts, fullSize, game]);
-
- if (tableContents.length === 0) {
- return (
-
- | Nothing... |
-
- );
- }
-
- return <>{tableContents}>;
-}
-
-function BreakdownChartContents({
- score,
- scoreInfo,
- game,
- songMap,
- chartMap,
- fullSize,
- gptConfig,
- type,
-}: {
- score: ScoreDocument;
- scoreInfo: SessionScoreInfo;
- fullSize: boolean;
- game: Game;
- songMap: Map;
- chartMap: Map;
- gptConfig: GamePTConfig;
- type: "lamp" | "grade";
-}) {
- const chart = chartMap.get(score.chartID)!;
- const song = songMap.get(score.songID)!;
-
- if (!chart || !song) {
- console.error(`No chart for ${score.chartID}/${score.songID}???`);
- return null;
- }
-
- if (fullSize) {
- let preScoreCell = No Play | ;
-
- if (!scoreInfo.isNewScore) {
- const oldGradeIndex = score.scoreData.gradeIndex - scoreInfo.gradeDelta;
- const oldLampIndex = score.scoreData.lampIndex - scoreInfo.lampDelta;
-
- const mockScore = deepmerge(score, {
- scoreData: {
- score: score.scoreData.score - scoreInfo.scoreDelta,
- percent: score.scoreData.percent - scoreInfo.percentDelta,
- grade: gptConfig.grades[oldGradeIndex],
- gradeIndex: oldGradeIndex,
- lamp: gptConfig.lamps[oldLampIndex],
- lampIndex: oldLampIndex,
- },
- }) as ScoreDocument;
-
- if (type === "grade") {
- preScoreCell = ;
- } else {
- preScoreCell = ;
- }
- }
-
- console.log(game);
-
- if (score) {
- return (
- <>
-
-
- {preScoreCell}
- ⟶ |
- {type === "grade" ? (
-
- ) : (
-
- )}
- >
- );
- }
- }
-
- return (
- <>
-
-
- >
- );
-}
diff --git a/client/src/components/tables/sessions/GenericSessionTable.tsx b/client/src/components/tables/sessions/GenericSessionTable.tsx
index a36d0b2a0..963f99f73 100644
--- a/client/src/components/tables/sessions/GenericSessionTable.tsx
+++ b/client/src/components/tables/sessions/GenericSessionTable.tsx
@@ -1,11 +1,13 @@
import { useSessionRatingAlg } from "components/util/useScoreRatingAlg";
import { nanoid } from "nanoid";
import React, { useState } from "react";
+import { Link } from "react-router-dom";
import {
Game,
GetGamePTConfig,
IDStrings,
integer,
+ PublicUserDocument,
SessionCalculatedDataLookup,
SessionDocument,
} from "tachi-common";
@@ -25,11 +27,13 @@ export type SessionDataset = (SessionDocument & { __related: { index: integer }
export default function GenericSessionTable({
dataset,
indexCol = false,
+ reqUser,
game,
playtype,
}: {
dataset: SessionDataset;
indexCol?: boolean;
+ reqUser: PublicUserDocument;
game: Game;
playtype: Playtype;
}) {
@@ -84,7 +88,15 @@ export default function GenericSessionTable({
timestamp: x => x.timeStarted,
[alg]: x => x.calculatedData[alg] ?? 0,
}}
- rowFunction={s => }
+ rowFunction={s => (
+
+ )}
/>
);
}
@@ -92,12 +104,14 @@ export default function GenericSessionTable({
function Row({
data,
rating,
+ reqUser,
indexCol = false,
}: // reqUser,
{
data: SessionDataset[0];
// reqUser: PublicUserDocument;
rating: SessionCalculatedDataLookup[IDStrings];
+ reqUser: PublicUserDocument;
indexCol?: boolean;
}) {
const [highlight, setHighlight] = useState(data.highlight);
@@ -106,13 +120,18 @@ function Row({
const sessionState = { highlight, desc, setHighlight, setDesc };
return (
- }
+ // dropdown={}
>
{indexCol && }
- {data.name}
+
+ {data.name}
+
{desc}
|
@@ -130,6 +149,6 @@ function Row({
{FormatTime(data.timeStarted)}
|
-
+
);
}
diff --git a/client/src/components/util/Icon.tsx b/client/src/components/util/Icon.tsx
index 04e2a0cdb..6644f4a8d 100644
--- a/client/src/components/util/Icon.tsx
+++ b/client/src/components/util/Icon.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { CSSProperties } from "react";
export default function Icon({
type,
@@ -6,12 +6,14 @@ export default function Icon({
brand,
onClick,
colour,
+ style,
}: {
type: string;
noPad?: boolean;
brand?: boolean;
onClick?: () => void;
colour?: "info" | "primary" | "danger" | "warning";
+ style?: CSSProperties;
}) {
return (