diff --git a/frontend/character-list/src/App.css b/frontend/character-list/src/App.css index a8d3235..e143290 100644 --- a/frontend/character-list/src/App.css +++ b/frontend/character-list/src/App.css @@ -104,4 +104,8 @@ .encounter-not-done { color: red; +} + +.reset-button { + margin: 1em!important; } \ No newline at end of file diff --git a/frontend/character-list/src/App.tsx b/frontend/character-list/src/App.tsx index 17efef2..b114f25 100644 --- a/frontend/character-list/src/App.tsx +++ b/frontend/character-list/src/App.tsx @@ -1,7 +1,8 @@ -import {useMemo} from 'react' +import {useCallback, useEffect, useMemo, useState} from 'react' import './App.css' import {Outlet, useLoaderData, useNavigate, useNavigation, useParams} from "react-router"; import { + Button, CircularProgress, Container, createTheme, @@ -10,7 +11,14 @@ import { ThemeProvider, Tooltip, useMediaQuery } from "@mui/material"; -import {DataGrid, GridColDef, GridFooter, GridFooterContainer, GridRowModel} from "@mui/x-data-grid"; +import { + DataGrid, + GridColDef, + GridFooter, + GridFooterContainer, + GridRowModel, + useGridApiRef +} from "@mui/x-data-grid"; import CheckIcon from '@mui/icons-material/Check'; import CloseIcon from '@mui/icons-material/Close'; import {createBrowserRouter, redirect, redirectDocument, RouterProvider} from "react-router-dom"; @@ -96,44 +104,73 @@ const columns: GridColDef[] = [ { field: 'race', headerName: 'Race', headerAlign: 'center', type: 'singleSelect', valueOptions: RACES}, { field: 'gender', headerName: 'Gender', headerAlign: 'center', type: 'singleSelect', valueOptions: GENDERS}, { field: 'account', headerName: 'Account', headerAlign: 'center', type: 'number'}, - { field: 'sort'}, { field: 'raids', headerName: 'Raid IDs', headerAlign: 'center', renderCell: (params) => }, ]; function CharacterList() { const data: any = useLoaderData(); + const apiRef = useGridApiRef(); + const [key, setKey] = useState(0); + + //Restore saved state + useEffect(() => { + const storedState = localStorage.getItem('gridState'); + + if(storedState) { + apiRef.current.restoreState(JSON.parse(storedState)); + } + }, []); - const rows: GridRowModel[] = []; - - data.profile.wow_accounts.forEach((account: any, accountIndex: number) => { - account.characters.forEach((character: any) => { - rows.push({ - id: character.id, - account: accountIndex+1, - name: character.name, - level: character.level, - classId: character.playable_class.id, - className: character.playable_class.name, - realm: character.realm.name, - factionName: character.faction.name, - factionType: character.faction.type, - race: character.playable_race.name, - gender: character.gender.name, - raids: data.raids[`${character.name.toLowerCase()}-${character.realm.slug}`], - sort: (data.raids[`${character.name.toLowerCase()}-${character.realm.slug}`]?.reduce((totalKills: any, instance: any) => { - instance.modes.forEach((mode: any) => { - mode.progress.encounters.forEach((encounter: any) => { - totalKills += encounter.completed_count; + //Save state on unload + const saveState = useCallback(() => { + localStorage.setItem('gridState', JSON.stringify(apiRef.current.exportState())); + }, []); + useEffect(() => { + window.addEventListener('beforeunload', saveState); + return () => { + window.removeEventListener('beforeunload', saveState); + }; + }, []); + + const rows: GridRowModel[] = useMemo(() => { + const r: GridRowModel[] = []; + + data.profile.wow_accounts.forEach((account: any, accountIndex: number) => { + account.characters.forEach((character: any) => { + r.push({ + id: character.id, + account: accountIndex+1, + name: character.name, + level: character.level, + classId: character.playable_class.id, + className: character.playable_class.name, + realm: character.realm.name, + factionName: character.faction.name, + factionType: character.faction.type, + race: character.playable_race.name, + gender: character.gender.name, + raids: data.raids[`${character.name.toLowerCase()}-${character.realm.slug}`], + sort: (data.raids[`${character.name.toLowerCase()}-${character.realm.slug}`]?.reduce((totalKills: any, instance: any) => { + instance.modes.forEach((mode: any) => { + mode.progress.encounters.forEach((encounter: any) => { + totalKills += encounter.completed_count; + }); }); - }); - return totalKills; - }, 0) || 0) + character.level*1000 + return totalKills; + }, 0) || 0) + character.level*1000 + }); }); }); - }); + + r.sort((a: any, b: any) => b.sort - a.sort); + + return r; + }, [data]); return ( ); } @@ -236,7 +270,7 @@ function RaidTooltip(props: any) { ); } -function Footer() { +function Footer(props: any) { const {region} = useParams(); const navigate = useNavigate(); @@ -244,6 +278,11 @@ function Footer() { navigate(`/${event.target.value}`); }; + const resetState = useCallback(() => { + localStorage.removeItem('gridState'); + props.setKey((prev: number) => prev+1); + }, []); + return ( @@ -252,6 +291,9 @@ function Footer() { {region.toUpperCase()} ))} +