Skip to content

Commit

Permalink
Demos/Recent games: Add matchtag filter (#98)
Browse files Browse the repository at this point in the history
* Update dependencies.

* Reformat code.

* Add matchtag filter.
  • Loading branch information
vikpe authored Dec 4, 2024
1 parent 04ed41b commit e25f03a
Show file tree
Hide file tree
Showing 8 changed files with 574 additions and 417 deletions.
44 changes: 22 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,42 @@
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@types/react": "^18.3.12",
"@types/react": "^18.3.13",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"@vitest/coverage-v8": "^2.1.5",
"@vitejs/plugin-react": "^4.3.4",
"@vitest/coverage-v8": "^2.1.8",
"jsdom": "^25.0.1",
"npm-run-all": "^4.1.5",
"supabase": "^1.219.2",
"typescript": "^5.6.3",
"vitest": "^2.1.5"
"supabase": "^2.0.0",
"typescript": "^5.7.2",
"vitest": "^2.1.8"
},
"dependencies": {
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/core": "^6.3.0",
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/fontawesome-svg-core": "^6.7.1",
"@fortawesome/free-solid-svg-icons": "^6.7.1",
"@fortawesome/react-fontawesome": "^0.2.2",
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-slider": "^1.2.1",
"@radix-ui/react-switch": "^1.1.1",
"@reduxjs/toolkit": "^2.3.0",
"@sentry/react": "^8.38.0",
"@supabase/supabase-js": "2.46.1",
"@reduxjs/toolkit": "^2.4.0",
"@sentry/react": "^8.42.0",
"@supabase/supabase-js": "2.46.2",
"@uidotdev/usehooks": "^2.4.1",
"autoprefixer": "^10.4.20",
"class-variance-authority": "^0.7.0",
"class-variance-authority": "^0.7.1",
"classnames": "^2.5.1",
"clsx": "^2.1.1",
"copy-text-to-clipboard": "^3.2.0",
"dayjs": "^1.11.13",
"firebase-tools": "^13.25.0",
"firebase-tools": "^13.27.0",
"formik": "^2.4.6",
"lodash.groupby": "^4.6.0",
"lucide-react": "^0.460.0",
"lucide-react": "^0.465.0",
"postcss": "^8.4.49",
"query-string": "^8.1.0",
"react": "^18.3.1",
Expand All @@ -64,16 +64,16 @@
"react-redux": "^9.1.2",
"react-swipeable": "^7.0.2",
"react-toastify": "^9.1.3",
"remeda": "^2.17.3",
"sass": "^1.81.0",
"remeda": "^2.17.4",
"sass": "^1.82.0",
"screenfull": "^6.0.2",
"tailwind-merge": "^2.5.4",
"tailwindcss": "^3.4.15",
"tailwind-merge": "^2.5.5",
"tailwindcss": "^3.4.16",
"tailwindcss-animate": "^1.0.7",
"urlcat": "2.0.4",
"use-double-tap": "^1.3.6",
"use-long-press": "^3.2.0",
"usehooks-ts": "^2.12.1",
"vite": "^5.4.11"
"vite": "^6.0.2"
}
}
25 changes: 21 additions & 4 deletions src/pages/games/browser/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const GameContext = createContext<GameContextProps>({
});

export const GamesProvider = ({ children }: { children: ReactNode }) => {
const { setPage, playerQuery, teams, gameMode, map, maxAge, page } =
const { setPage, playerQuery, teams, gameMode, map, matchtag, maxAge, page } =
useGameSettings();
const [games, setGames] = useState<GameSearchEntry[]>([]);
const [count, setCount] = useState<number>(0);
Expand All @@ -42,13 +42,22 @@ export const GamesProvider = ({ children }: { children: ReactNode }) => {
gameMode,
map,
teams,
matchtag,
playerQuery,
maxAge,
});
let games: GameSearchEntry[] = [];

if (count > 0) {
const settings = { gameMode, map, playerQuery, teams, maxAge, page: 1 };
const settings = {
gameMode,
map,
playerQuery,
teams,
matchtag,
maxAge,
page: 1,
};
games = await searchGamesRows(settings);
}

Expand All @@ -59,7 +68,7 @@ export const GamesProvider = ({ children }: { children: ReactNode }) => {
}

run();
}, [playerQuery, teams, gameMode, map, maxAge]);
}, [playerQuery, teams, gameMode, map, matchtag, maxAge]);

useEffect(() => {
if (isFirstRender) {
Expand All @@ -68,7 +77,15 @@ export const GamesProvider = ({ children }: { children: ReactNode }) => {

async function run() {
setIsLoading(true);
const settings = { playerQuery, teams, gameMode, map, maxAge, page };
const settings = {
playerQuery,
teams,
gameMode,
map,
matchtag,
maxAge,
page,
};
setGames(await searchGamesRows(settings));
setIsLoading(false);
}
Expand Down
35 changes: 35 additions & 0 deletions src/pages/games/browser/settings/Matchtag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { faTag } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { type ChangeEvent, useEffect } from "react";
import { useDebounceValue } from "usehooks-ts";
import { formInput } from "../../ui/theme.ts";
import { useGameSettings } from "./context.tsx";

export const Matchtag = () => {
const { matchtag, setMatchtag } = useGameSettings();
const [value, setValue] = useDebounceValue<string>(matchtag, 400);

function handleChange(e: ChangeEvent<HTMLInputElement>) {
setValue(e.target.value.toLowerCase().trim());
}

useEffect(() => {
setMatchtag(value);
}, [value]);

return (
<label className="flex items-center ml-2" title="Matchtag">
<FontAwesomeIcon
icon={faTag}
className="z-10 text-slate-500 pointer-events-none"
size="xs"
/>
<input
type="search"
defaultValue={matchtag}
className={`${formInput} -ml-6 pl-8 w-24`}
onChange={handleChange}
/>
</label>
);
};
2 changes: 2 additions & 0 deletions src/pages/games/browser/settings/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { DisplayModeBar } from "./DisplayModeBar.tsx";
import { GameModeBar } from "./GameModeBar.tsx";
import { GlobalShowScoresToggle } from "./GlobalShowScoresToggle.tsx";
import { MapName } from "./MapName.tsx";
import { Matchtag } from "./Matchtag.tsx";
import { Pagination } from "./Pagination.tsx";
import { PlayerQuery } from "./PlayerQuery.tsx";
import { Teams } from "./Teams.tsx";
Expand All @@ -24,6 +25,7 @@ export const Toolbar = () => {
<PlayerQuery />
<Teams />
<MapName />
<Matchtag />
<Timeframe />
<Pagination />
</div>
Expand Down
14 changes: 12 additions & 2 deletions src/pages/games/browser/settings/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type GameBrowserSettingsProps = {
setPlayerQuery: (query: string) => void;
teams: string;
setTeams: (query: string) => void;
matchtag: string;
setMatchtag: (query: string) => void;
maxAge: number;
setMaxAge: (maxAge: number) => void;
page: number;
Expand All @@ -33,6 +35,7 @@ const defaultSettings: GameBrowserSettings = {
map: "",
playerQuery: "",
teams: "",
matchtag: "",
maxAge: 30,
page: 1,
};
Expand All @@ -44,6 +47,7 @@ const GameSettingsContext = createContext<GameBrowserSettingsProps>({
setMap: () => {},
setPlayerQuery: () => {},
setTeams: () => {},
setMatchtag: () => {},
setMaxAge: () => {},
setPage: () => {},
nextPage: () => {},
Expand All @@ -68,7 +72,10 @@ export const GameSettingsProvider = ({
const [map, setMap] = useState<string>(settings.map);
const [playerQuery, setPlayerQuery] = useState<string>(settings.playerQuery);
const [teams, setTeams] = useState<string>(settings.teams);
const [maxAge, setMaxAge] = useState<number>(settings.maxAge ?? defaultSettings.maxAge);
const [matchtag, setMatchtag] = useState<string>(settings.matchtag ?? "");
const [maxAge, setMaxAge] = useState<number>(
settings.maxAge ?? defaultSettings.maxAge,
);
const [page, setPage] = useState<number>(settings.page);

useEffect(() => {
Expand All @@ -78,10 +85,11 @@ export const GameSettingsProvider = ({
map,
playerQuery,
teams,
matchtag,
maxAge,
page,
});
}, [displayMode, gameMode, map, playerQuery, teams, maxAge, page]);
}, [displayMode, gameMode, map, playerQuery, teams, matchtag, maxAge, page]);

function nextPage() {
setPage(page + 1);
Expand All @@ -102,6 +110,8 @@ export const GameSettingsProvider = ({
setPlayerQuery,
teams,
setTeams,
matchtag,
setMatchtag,
maxAge,
setMaxAge,
page,
Expand Down
1 change: 1 addition & 0 deletions src/pages/games/browser/settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type GameBrowserSettings = {
map: string;
playerQuery: string;
teams: string;
matchtag: string;
maxAge: number;
page: number;
};
22 changes: 16 additions & 6 deletions src/pages/games/services/supabase/supabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ export async function searchGamesCount(settings: {
gameMode: GameMode;
playerQuery: string;
teams: string;
matchtag: string;
maxAge: number;
}): Promise<number> {
let qb = supabase
.from("games")
.select("count", { head: true, count: "estimated" });
const { playerQuery, teams, map, gameMode } = settings;
const { playerQuery, teams, map, gameMode, matchtag, maxAge } = settings;

if (gameMode !== "All") {
qb = qb.eq("mode", gameMode.toLowerCase());
Expand All @@ -64,8 +65,12 @@ export async function searchGamesCount(settings: {
qb = qb.textSearch("players_fts", players_fts);
}

if (settings.maxAge > 0) {
const minTimestamp = new Date(Date.now() - settings.maxAge * MS_PER_DAY);
if (matchtag.length > 0) {
qb = qb.ilike("matchtag", `%${matchtag}%`);
}

if (maxAge > 0) {
const minTimestamp = new Date(Date.now() - maxAge * MS_PER_DAY);
qb = qb.gte("timestamp", minTimestamp.toISOString());
}

Expand All @@ -90,14 +95,15 @@ export async function searchGamesRows(settings: {
map: string;
playerQuery: string;
teams: string;
matchtag: string;
maxAge: number;
page: number;
}): Promise<GameSearchEntry[]> {
let qb = supabase
.from("games")
.select("id,timestamp,mode,matchtag,map,teams,players,demo_sha256");

const { gameMode, map, playerQuery, teams } = settings;
const { gameMode, map, playerQuery, teams, matchtag, maxAge } = settings;

if (gameMode !== "All") {
qb = qb.eq("mode", gameMode.toLowerCase());
Expand All @@ -116,8 +122,12 @@ export async function searchGamesRows(settings: {
qb = qb.textSearch("players_fts", fts);
}

if (settings.maxAge > 0) {
const minTimestamp = new Date(Date.now() - settings.maxAge * MS_PER_DAY);
if (matchtag.length > 0) {
qb = qb.ilike("matchtag", `%${matchtag}%`);
}

if (maxAge > 0) {
const minTimestamp = new Date(Date.now() - maxAge * MS_PER_DAY);
qb = qb.gte("timestamp", minTimestamp.toISOString());
}

Expand Down
Loading

0 comments on commit e25f03a

Please sign in to comment.