feat: UI cleanup and short GUIDs

This commit is contained in:
mattia
2025-01-06 17:46:10 +01:00
parent d4b12e8738
commit 50ecb39cce
7 changed files with 101 additions and 9 deletions

27
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "game-logger",
"version": "0.0.2",
"version": "0.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "game-logger",
"version": "0.0.2",
"version": "0.0.3",
"license": "ISC",
"dependencies": {
"@ts-rest/core": "^3.51.0",
@@ -41,6 +41,7 @@
"@vitejs/plugin-react": "^4.3.4",
"concurrently": "^9.1.2",
"date-fns": "^4.1.0",
"jotai": "^2.11.0",
"material-react-table": "^3.1.0",
"openapi3-ts": "^4.4.0",
"react": "^18.0.0",
@@ -3577,6 +3578,28 @@
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/jotai": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/jotai/-/jotai-2.11.0.tgz",
"integrity": "sha512-zKfoBBD1uDw3rljwHkt0fWuja1B76R7CjznuBO+mSX6jpsO1EBeWNRKpeaQho9yPI/pvCv4recGfgOXGxwPZvQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.20.0"
},
"peerDependencies": {
"@types/react": ">=17.0.0",
"react": ">=17.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"react": {
"optional": true
}
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

View File

@@ -37,6 +37,7 @@
"@vitejs/plugin-react": "^4.3.4",
"concurrently": "^9.1.2",
"date-fns": "^4.1.0",
"jotai": "^2.11.0",
"material-react-table": "^3.1.0",
"openapi3-ts": "^4.4.0",
"react": "^18.0.0",

View File

@@ -2,8 +2,10 @@ import {
AppBar,
Breadcrumbs,
Container,
FormControlLabel,
Link,
Stack,
Switch,
Toolbar,
Typography,
} from "@mui/material";
@@ -15,11 +17,23 @@ import {
} from "react-router";
import "./theme";
import { serverRoot } from "./client";
import { useAtom } from "jotai";
import { shortGuidsAtom } from "./configuration";
import { ChangeEvent, useCallback } from "react";
export function Root() {
const location = useLocation();
const params = useParams();
const [shortGuids, setShortGuids] = useAtom(shortGuidsAtom);
const handleShortGuidsOnChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
setShortGuids(e.target.checked);
},
[setShortGuids]
);
return (
<Container maxWidth="lg">
<Stack spacing={2}>
@@ -28,6 +42,17 @@ export function Root() {
<Typography variant="h6" component="h1" sx={{ flexGrow: 1 }}>
Game Logger
</Typography>
<FormControlLabel
control={
<Switch
checked={shortGuids}
onChange={handleShortGuidsOnChange}
aria-label="short guids switch"
color="secondary"
/>
}
label={"Use short GUIDs"}
/>
<Link
variant="appbar"
href={serverRoot + "/swagger-ui"}

View File

@@ -11,6 +11,10 @@ import { GetSessionsResponse } from "../common/contract";
import { format, formatDuration, interval, intervalToDuration } from "date-fns";
import { useMemo, useState } from "react";
import { useNavigate } from "react-router";
import { Typography } from "@mui/material";
import { useAtom } from "jotai";
import { shortGuidsAtom } from "./configuration";
import { formatGuid } from "./guid";
export function Sessions() {
const [paginationState, setPaginationState] = useState<MRT_PaginationState>({
@@ -73,27 +77,54 @@ function SessionsTable({
isRefetching: boolean;
columnFilters: MRT_ColumnFiltersState;
}) {
const [shortGuids] = useAtom(shortGuidsAtom);
const columns = useMemo<MRT_ColumnDef<GetSessionsResponse["sessions"][0]>[]>(
() => [
{
accessorKey: "save_id",
header: "Save ID",
grow: false,
Cell: ({
row: {
original: { save_id },
},
}) => <Typography variant="body2">{formatGuid(save_id, shortGuids)}</Typography>,
},
{
accessorKey: "id",
header: "ID",
grow: true,
Cell: ({
row: {
original: { id },
},
}) => <Typography variant="body2">{formatGuid(id, shortGuids)}</Typography>,
},
{
accessorKey: "game_name",
header: "Game Name",
grow: false,
Cell: ({
row: {
original: { game_name },
},
}) => <Typography variant="body1">{game_name}</Typography>,
},
{
accessorKey: "version",
header: "Version",
grow: false,
Cell: ({
row: {
original: { version },
},
}) => <Typography variant="body2">{version}</Typography>,
},
{
accessorKey: "time",
header: "Time",
grow: true,
Cell: ({ row }) => {
const rangeInterval = interval(
row.original.start_time,
@@ -104,19 +135,23 @@ function SessionsTable({
const formattedDuration = formatDuration(duration);
return (
<span>
{formattedStartTime}
<br />({formattedDuration || "very quick"})
<Typography variant="body2">{formattedStartTime}</Typography>
<Typography variant="body2" color="textSecondary">
{formattedDuration || "very quick"}, {row.original.num_events}{" "}
events
</Typography>
</span>
);
},
},
],
[]
[shortGuids]
);
const navigate = useNavigate();
const table = useMaterialReactTable({
layoutMode: "grid",
data: sessions,
columns,
muiTableBodyRowProps: ({ row }) => ({

View File

@@ -0,0 +1,3 @@
import {atom} from "jotai";
export const shortGuidsAtom = atom(true);

7
src/client/guid.ts Normal file
View File

@@ -0,0 +1,7 @@
export function formatGuid(guid: string, shortGuid: boolean) {
if (shortGuid) {
return guid.substring(0, 4) + "-" + guid.substring(guid.length - 4);
} else {
return guid;
}
}

View File

@@ -7,17 +7,15 @@ declare module "@mui/material/Typography" {
}
}
// const x: LinkPropsVariantOverrides;
// A custom theme for this app
const theme = createTheme({
cssVariables: true,
palette: {
primary: {
main: "#556cd6",
main: "#735DA5",
},
secondary: {
main: "#19857b",
main: "#D3C5E5",
},
error: {
main: red.A400,