mirror of https://github.com/cocosolos/ixion.git
Add more filters
This commit is contained in:
parent
814092a9f0
commit
52908764ed
|
|
@ -3,7 +3,7 @@ import { useState } from 'react';
|
||||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||||
import AlertComponent from './components/Alert';
|
import AlertComponent from './components/Alert';
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
import Header from './components/Header';
|
import Header from './components/Header/Header';
|
||||||
import { SearchState, SearchStateDefaults } from './data/SearchState';
|
import { SearchState, SearchStateDefaults } from './data/SearchState';
|
||||||
import { ServerData } from './data/ServerData';
|
import { ServerData } from './data/ServerData';
|
||||||
import About from './pages/About';
|
import About from './pages/About';
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ import {
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { postData } from '../apiUtil';
|
import { postData } from '../../apiUtil';
|
||||||
import { useLoadingContext } from '../context/LoadingContext';
|
import { useLoadingContext } from '../../context/LoadingContext';
|
||||||
import { ServerData } from '../data/ServerData';
|
import { ServerData } from '../../data/ServerData';
|
||||||
|
|
||||||
const AddServerInput = styled('div')(({ theme }) => ({
|
const AddServerInput = styled('div')(({ theme }) => ({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
|
@ -10,10 +10,11 @@ import {
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { fetchDataFromBackend } from '../apiUtil';
|
import { fetchDataFromBackend } from '../../apiUtil';
|
||||||
import { useLoadingContext } from '../context/LoadingContext';
|
import { useLoadingContext } from '../../context/LoadingContext';
|
||||||
import { SearchState } from '../data/SearchState';
|
import { useThemeModeContext } from '../../context/ThemeContext';
|
||||||
import { ServerData } from '../data/ServerData';
|
import { SearchState } from '../../data/SearchState';
|
||||||
|
import { ServerData } from '../../data/ServerData';
|
||||||
import AddServer from './AddServer';
|
import AddServer from './AddServer';
|
||||||
import SearchServers from './SearchServers';
|
import SearchServers from './SearchServers';
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ export default function Header({
|
||||||
searchState,
|
searchState,
|
||||||
setSearchState,
|
setSearchState,
|
||||||
}: HeaderProps) {
|
}: HeaderProps) {
|
||||||
|
const { themeMode } = useThemeModeContext();
|
||||||
const { progress, setProgress, showAlert } = useLoadingContext();
|
const { progress, setProgress, showAlert } = useLoadingContext();
|
||||||
const [showSearchServer, setShowSearchServer] = useState(false);
|
const [showSearchServer, setShowSearchServer] = useState(false);
|
||||||
const toggleShowSearchServer = () => {
|
const toggleShowSearchServer = () => {
|
||||||
|
|
@ -67,7 +69,7 @@ export default function Header({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<AppBar position="static">
|
<AppBar position="static" elevation={themeMode === 'light' ? 8 : 3}>
|
||||||
<Toolbar className="min-h-min py-1">
|
<Toolbar className="min-h-min py-1">
|
||||||
<Typography
|
<Typography
|
||||||
component={Link}
|
component={Link}
|
||||||
|
|
@ -0,0 +1,640 @@
|
||||||
|
import { RestartAlt } from '@mui/icons-material';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
Slider,
|
||||||
|
TextField,
|
||||||
|
ToggleButton,
|
||||||
|
ToggleButtonGroup,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { SearchState, SearchStateDefaults } from '../../data/SearchState';
|
||||||
|
|
||||||
|
type SearchServersProps = {
|
||||||
|
showSearchServer: boolean;
|
||||||
|
searchState: SearchState;
|
||||||
|
setSearchState: React.Dispatch<React.SetStateAction<SearchState>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SearchServers({
|
||||||
|
showSearchServer,
|
||||||
|
searchState,
|
||||||
|
setSearchState,
|
||||||
|
}: SearchServersProps) {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [contentHeight, setContentHeight] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showSearchServer && containerRef.current) {
|
||||||
|
setContentHeight(containerRef.current.scrollHeight);
|
||||||
|
} else {
|
||||||
|
setContentHeight(0);
|
||||||
|
}
|
||||||
|
}, [showSearchServer]);
|
||||||
|
|
||||||
|
const handleChange = (
|
||||||
|
name: string,
|
||||||
|
value: string | string[] | number | number[],
|
||||||
|
activeThumb?: number
|
||||||
|
) => {
|
||||||
|
let newValue = value;
|
||||||
|
if (name === 'maxLevel') {
|
||||||
|
if (
|
||||||
|
!Array.isArray(value) ||
|
||||||
|
!value.every((item) => typeof item === 'number')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newValue = [
|
||||||
|
activeThumb === 0
|
||||||
|
? Math.min((newValue as number[])[0], searchState.maxLevel[1])
|
||||||
|
: searchState.maxLevel[0],
|
||||||
|
activeThumb === 0
|
||||||
|
? searchState.maxLevel[1]
|
||||||
|
: Math.max((newValue as number[])[1], searchState.maxLevel[0]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
setSearchState({ ...searchState, [name]: newValue });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearchExpansions = (
|
||||||
|
_event: React.MouseEvent<HTMLElement>,
|
||||||
|
newSearchExpansions: string[]
|
||||||
|
) => {
|
||||||
|
if (newSearchExpansions.length === 0) {
|
||||||
|
setSearchState({ ...searchState, expansions: null });
|
||||||
|
} else if (
|
||||||
|
searchState.expansions &&
|
||||||
|
searchState.expansions.includes('none') &&
|
||||||
|
newSearchExpansions.length > 1
|
||||||
|
) {
|
||||||
|
setSearchState({
|
||||||
|
...searchState,
|
||||||
|
expansions: newSearchExpansions.filter((item) => item !== 'none'),
|
||||||
|
});
|
||||||
|
} else if (
|
||||||
|
searchState.expansions &&
|
||||||
|
!searchState.expansions.includes('none') &&
|
||||||
|
newSearchExpansions.includes('none')
|
||||||
|
) {
|
||||||
|
setSearchState({ ...searchState, expansions: ['none'] });
|
||||||
|
} else {
|
||||||
|
setSearchState({ ...searchState, expansions: newSearchExpansions });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container
|
||||||
|
ref={containerRef}
|
||||||
|
className="overflow-hidden"
|
||||||
|
sx={{
|
||||||
|
transition: 'all 0.3s ease',
|
||||||
|
maxHeight: showSearchServer ? contentHeight : 0,
|
||||||
|
borderBottom: showSearchServer
|
||||||
|
? (theme) =>
|
||||||
|
theme.palette.mode === 'dark'
|
||||||
|
? '1px solid rgba(255, 255, 255, .12)'
|
||||||
|
: '1px solid rgba(0, 0, 0, .12)'
|
||||||
|
: 'none',
|
||||||
|
backgroundColor: (theme) =>
|
||||||
|
theme.palette.mode === 'dark'
|
||||||
|
? 'rgba(255, 255, 255, .06)'
|
||||||
|
: 'rgba(0, 0, 0, .06)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Grid container spacing={2} className="py-2">
|
||||||
|
{/* Name */}
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<TextField
|
||||||
|
value={searchState.name}
|
||||||
|
onChange={(event) => {
|
||||||
|
handleChange('name', event.target.value);
|
||||||
|
}}
|
||||||
|
variant="standard"
|
||||||
|
autoComplete="false"
|
||||||
|
fullWidth
|
||||||
|
label="Name"
|
||||||
|
size="small"
|
||||||
|
className="pb-2"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{/* Max Level */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
className="pt-0"
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="max-level" variant="caption">
|
||||||
|
Max Level
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} className="flex pt-0">
|
||||||
|
<Input
|
||||||
|
value={searchState.maxLevel[0]}
|
||||||
|
size="small"
|
||||||
|
onChange={(event) => {
|
||||||
|
let value = parseInt(event.target.value, 10);
|
||||||
|
if (Number.isNaN(value) || value < 1) {
|
||||||
|
value = 1;
|
||||||
|
} else if (value > 99) {
|
||||||
|
value = 99;
|
||||||
|
}
|
||||||
|
handleChange('maxLevel', [value, searchState.maxLevel[1]], 0);
|
||||||
|
}}
|
||||||
|
// onBlur={handleBlur}
|
||||||
|
inputProps={{
|
||||||
|
name: 'max-level-min',
|
||||||
|
step: 1,
|
||||||
|
min: 1,
|
||||||
|
max: 99,
|
||||||
|
type: 'number',
|
||||||
|
'aria-labelledby': 'max-level',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Slider
|
||||||
|
aria-labelledby="max-level"
|
||||||
|
value={searchState.maxLevel}
|
||||||
|
onChange={(_event, value, activeThumb) => {
|
||||||
|
handleChange('maxLevel', value, activeThumb);
|
||||||
|
}}
|
||||||
|
valueLabelDisplay="auto"
|
||||||
|
disableSwap
|
||||||
|
className="mx-4"
|
||||||
|
size="small"
|
||||||
|
min={1}
|
||||||
|
max={99}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={searchState.maxLevel[1]}
|
||||||
|
size="small"
|
||||||
|
onChange={(event) => {
|
||||||
|
let value = parseInt(event.target.value, 10);
|
||||||
|
if (Number.isNaN(value) || value < 1) {
|
||||||
|
value = 1;
|
||||||
|
} else if (value > 99) {
|
||||||
|
value = 99;
|
||||||
|
}
|
||||||
|
handleChange('maxLevel', [searchState.maxLevel[0], value], 1);
|
||||||
|
}}
|
||||||
|
// onBlur={handleBlur}
|
||||||
|
inputProps={{
|
||||||
|
name: 'max-level-max',
|
||||||
|
step: 1,
|
||||||
|
min: 1,
|
||||||
|
max: 99,
|
||||||
|
type: 'number',
|
||||||
|
'aria-labelledby': 'max-level',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{/* Expansion */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title="Enabled expansions, exact match."
|
||||||
|
arrow
|
||||||
|
disableInteractive
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Typography id="expansions-button-group" variant="caption">
|
||||||
|
Expansions
|
||||||
|
</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.expansions}
|
||||||
|
onChange={handleSearchExpansions}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="expansions-button-group"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
key="none"
|
||||||
|
value="none"
|
||||||
|
aria-label="none-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '20%' }}
|
||||||
|
>
|
||||||
|
None
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
key="rotz"
|
||||||
|
value="rotz"
|
||||||
|
aria-label="rotz-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '20%' }}
|
||||||
|
>
|
||||||
|
RotZ
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
key="cop"
|
||||||
|
value="cop"
|
||||||
|
aria-label="cop-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '20%' }}
|
||||||
|
>
|
||||||
|
CoP
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
key="toau"
|
||||||
|
value="toau"
|
||||||
|
aria-label="toau-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '20%' }}
|
||||||
|
>
|
||||||
|
ToAU
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
key="wotg"
|
||||||
|
value="wotg"
|
||||||
|
aria-label="wotg-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '20%' }}
|
||||||
|
>
|
||||||
|
WotG
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
key="soa"
|
||||||
|
value="soa"
|
||||||
|
aria-label="soa-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '20%' }}
|
||||||
|
>
|
||||||
|
SoA
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Multiboxing */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="multibox-button-group" variant="caption">
|
||||||
|
Multiboxing
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.multibox}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('multibox', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="multibox-button-group"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
exclusive
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="none"
|
||||||
|
aria-label="no-multiboxing"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '33.33%' }}
|
||||||
|
>
|
||||||
|
None
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="limited"
|
||||||
|
aria-label="limited-multiboxing"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '33.33%' }}
|
||||||
|
>
|
||||||
|
Limited
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="unlimited"
|
||||||
|
aria-label="unlimited-multiboxing"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '33.33%' }}
|
||||||
|
>
|
||||||
|
Unlimited
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Trusts */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={6}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="trust-button-group" variant="caption">
|
||||||
|
Trusts
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.trusts}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('trusts', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="trust-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="trust-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="trust-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Level Sync */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={6}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="level-sync-button-group" variant="caption">
|
||||||
|
Level Sync
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.levelSync}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('levelSync', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="level-sync-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="level-sync-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="level-sync-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Home Point Teleport */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={6}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="home-point-button-group" variant="caption">
|
||||||
|
Home Point Teleport
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.homePoint}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('homePoint', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="home-point-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="home-point-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="home-point-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Survival Guide Teleport */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={6}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="survival-guide-button-group" variant="caption">
|
||||||
|
Survival Guides
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.survivalGuide}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('survivalGuide', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="survival-guide-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="survival-guide-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="survival-guide-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Records of Eminence */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={4}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="roe-button-group" variant="caption">
|
||||||
|
Records of Eminence
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.recordsOfEminence}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('recordsOfEminence', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="records-of-eminence-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="records-of-eminence-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="records-of-eminence-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Fields of Valor */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={4}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="fields-of-valor-button-group" variant="caption">
|
||||||
|
Fields of Valor
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.fieldsOfValor}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('fieldsOfValor', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="fields-of-valor-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="fields-of-valor-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="fields-of-valor-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
{/* Grounds of Valor */}
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={4}
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Typography id="grounds-of-valor-button-group" variant="caption">
|
||||||
|
Grounds of Valor
|
||||||
|
</Typography>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={searchState.groundsOfValor}
|
||||||
|
onChange={(_event, value) => {
|
||||||
|
handleChange('groundsOfValor', value);
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
aria-labelledby="grounds-of-valor-button-group"
|
||||||
|
exclusive
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value="disabled"
|
||||||
|
aria-label="grounds-of-valor-disabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Disabled
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
value="enabled"
|
||||||
|
aria-label="grounds-of-valor-enabled"
|
||||||
|
className="py-0"
|
||||||
|
sx={{ width: '50%' }}
|
||||||
|
>
|
||||||
|
Enabled
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Grid>
|
||||||
|
<Box className="flex min-w-full justify-end pt-2">
|
||||||
|
<Tooltip title="Reset filters." arrow disableInteractive>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
setSearchState(SearchStateDefaults);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RestartAlt />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,452 +0,0 @@
|
||||||
import {
|
|
||||||
Container,
|
|
||||||
Divider,
|
|
||||||
Grid,
|
|
||||||
Input,
|
|
||||||
Slider,
|
|
||||||
TextField,
|
|
||||||
ToggleButton,
|
|
||||||
ToggleButtonGroup,
|
|
||||||
Tooltip,
|
|
||||||
Typography,
|
|
||||||
} from '@mui/material';
|
|
||||||
import { useEffect, useRef, useState } from 'react';
|
|
||||||
import { SearchState } from '../data/SearchState';
|
|
||||||
|
|
||||||
type SearchServersProps = {
|
|
||||||
showSearchServer: boolean;
|
|
||||||
searchState: SearchState;
|
|
||||||
setSearchState: React.Dispatch<React.SetStateAction<SearchState>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function SearchServers({
|
|
||||||
showSearchServer,
|
|
||||||
searchState,
|
|
||||||
setSearchState,
|
|
||||||
}: SearchServersProps) {
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
|
||||||
const [contentHeight, setContentHeight] = useState(0);
|
|
||||||
const minDistance = 0;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (showSearchServer && containerRef.current) {
|
|
||||||
setContentHeight(containerRef.current.scrollHeight);
|
|
||||||
} else {
|
|
||||||
setContentHeight(0);
|
|
||||||
}
|
|
||||||
}, [showSearchServer]);
|
|
||||||
|
|
||||||
const handleSearchName = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setSearchState({ ...searchState, name: event.target.value });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchMultibox = (
|
|
||||||
_event: React.MouseEvent<HTMLElement>,
|
|
||||||
newSearchMultibox: string[]
|
|
||||||
) => {
|
|
||||||
setSearchState({ ...searchState, multibox: newSearchMultibox });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchTrusts = (
|
|
||||||
_event: React.MouseEvent<HTMLElement>,
|
|
||||||
newSearchTrusts: string[]
|
|
||||||
) => {
|
|
||||||
setSearchState({ ...searchState, trusts: newSearchTrusts });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchLevelSync = (
|
|
||||||
_event: React.MouseEvent<HTMLElement>,
|
|
||||||
newSearchLevelSync: string[]
|
|
||||||
) => {
|
|
||||||
setSearchState({ ...searchState, levelSync: newSearchLevelSync });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchMaxLevelMin = (
|
|
||||||
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
|
||||||
) => {
|
|
||||||
let newValue = parseInt(event.target.value, 10);
|
|
||||||
if (Number.isNaN(newValue) || newValue < 1) {
|
|
||||||
newValue = 1;
|
|
||||||
} else if (newValue > 99) {
|
|
||||||
newValue = 99;
|
|
||||||
}
|
|
||||||
setSearchState({
|
|
||||||
...searchState,
|
|
||||||
maxLevel: [
|
|
||||||
Math.min(newValue, searchState.maxLevel[1] - minDistance),
|
|
||||||
searchState.maxLevel[1],
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchMaxLevelMax = (
|
|
||||||
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
|
||||||
) => {
|
|
||||||
let newValue = parseInt(event.target.value, 10);
|
|
||||||
if (Number.isNaN(newValue) || newValue < 1) {
|
|
||||||
newValue = 1;
|
|
||||||
} else if (newValue > 99) {
|
|
||||||
newValue = 99;
|
|
||||||
}
|
|
||||||
setSearchState({
|
|
||||||
...searchState,
|
|
||||||
maxLevel: [
|
|
||||||
searchState.maxLevel[0],
|
|
||||||
Math.max(newValue, searchState.maxLevel[0] + minDistance),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchMaxLevel = (
|
|
||||||
_event: Event,
|
|
||||||
newValue: number | number[],
|
|
||||||
activeThumb: number
|
|
||||||
) => {
|
|
||||||
if (!Array.isArray(newValue)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (activeThumb === 0) {
|
|
||||||
setSearchState({
|
|
||||||
...searchState,
|
|
||||||
maxLevel: [
|
|
||||||
Math.min(newValue[0], searchState.maxLevel[1] - minDistance),
|
|
||||||
searchState.maxLevel[1],
|
|
||||||
],
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setSearchState({
|
|
||||||
...searchState,
|
|
||||||
maxLevel: [
|
|
||||||
searchState.maxLevel[0],
|
|
||||||
Math.max(newValue[1], searchState.maxLevel[0] + minDistance),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSearchExpansions = (
|
|
||||||
_event: React.MouseEvent<HTMLElement>,
|
|
||||||
newSearchExpansions: string[]
|
|
||||||
) => {
|
|
||||||
if (newSearchExpansions.length === 0) {
|
|
||||||
setSearchState({ ...searchState, expansions: null });
|
|
||||||
} else if (
|
|
||||||
searchState.expansions &&
|
|
||||||
searchState.expansions.includes('none') &&
|
|
||||||
newSearchExpansions.length > 1
|
|
||||||
) {
|
|
||||||
setSearchState({
|
|
||||||
...searchState,
|
|
||||||
expansions: newSearchExpansions.filter((item) => item !== 'none'),
|
|
||||||
});
|
|
||||||
} else if (
|
|
||||||
searchState.expansions &&
|
|
||||||
!searchState.expansions.includes('none') &&
|
|
||||||
newSearchExpansions.includes('none')
|
|
||||||
) {
|
|
||||||
setSearchState({ ...searchState, expansions: ['none'] });
|
|
||||||
} else {
|
|
||||||
setSearchState({ ...searchState, expansions: newSearchExpansions });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Container
|
|
||||||
ref={containerRef}
|
|
||||||
className="overflow-hidden"
|
|
||||||
sx={{
|
|
||||||
transition: 'all 0.3s ease',
|
|
||||||
maxHeight: showSearchServer ? contentHeight : 0,
|
|
||||||
backgroundColor: (theme) =>
|
|
||||||
theme.palette.mode === 'dark'
|
|
||||||
? 'rgba(255, 255, 255, .06)'
|
|
||||||
: 'rgba(0, 0, 0, .06)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Grid container spacing={2} className="py-2">
|
|
||||||
{/* Name */}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<TextField
|
|
||||||
value={searchState.name}
|
|
||||||
onChange={handleSearchName}
|
|
||||||
variant="standard"
|
|
||||||
autoComplete="false"
|
|
||||||
fullWidth
|
|
||||||
label="Name"
|
|
||||||
size="small"
|
|
||||||
className="pb-2"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
{/* Max Level */}
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={12}
|
|
||||||
className="pt-0"
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Typography id="max-level" variant="caption">
|
|
||||||
Max Level
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} className="flex pt-0">
|
|
||||||
<Input
|
|
||||||
value={searchState.maxLevel[0]}
|
|
||||||
size="small"
|
|
||||||
onChange={handleSearchMaxLevelMin}
|
|
||||||
// onBlur={handleBlur}
|
|
||||||
inputProps={{
|
|
||||||
name: 'max-level-min',
|
|
||||||
step: 1,
|
|
||||||
min: 1,
|
|
||||||
max: 99,
|
|
||||||
type: 'number',
|
|
||||||
'aria-labelledby': 'max-level',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Slider
|
|
||||||
aria-labelledby="max-level"
|
|
||||||
value={searchState.maxLevel}
|
|
||||||
onChange={handleSearchMaxLevel}
|
|
||||||
valueLabelDisplay="auto"
|
|
||||||
disableSwap
|
|
||||||
className="mx-4"
|
|
||||||
size="small"
|
|
||||||
min={1}
|
|
||||||
max={99}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
value={searchState.maxLevel[1]}
|
|
||||||
size="small"
|
|
||||||
onChange={handleSearchMaxLevelMax}
|
|
||||||
// onBlur={handleBlur}
|
|
||||||
inputProps={{
|
|
||||||
name: 'max-level-max',
|
|
||||||
step: 1,
|
|
||||||
min: 1,
|
|
||||||
max: 99,
|
|
||||||
type: 'number',
|
|
||||||
'aria-labelledby': 'max-level',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
{/* Expansion */}
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={12}
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Tooltip
|
|
||||||
title="Enabled expansions, exact match."
|
|
||||||
arrow
|
|
||||||
disableInteractive
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<Typography id="expansions-button-group" variant="caption">
|
|
||||||
Expansions
|
|
||||||
</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
<ToggleButtonGroup
|
|
||||||
value={searchState.expansions}
|
|
||||||
onChange={handleSearchExpansions}
|
|
||||||
size="small"
|
|
||||||
aria-labelledby="expansions-button-group"
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleButton
|
|
||||||
key="none"
|
|
||||||
value="none"
|
|
||||||
aria-label="none-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '20%' }}
|
|
||||||
>
|
|
||||||
None
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
key="rotz"
|
|
||||||
value="rotz"
|
|
||||||
aria-label="rotz-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '20%' }}
|
|
||||||
>
|
|
||||||
RotZ
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
key="cop"
|
|
||||||
value="cop"
|
|
||||||
aria-label="cop-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '20%' }}
|
|
||||||
>
|
|
||||||
CoP
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
key="toau"
|
|
||||||
value="toau"
|
|
||||||
aria-label="toau-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '20%' }}
|
|
||||||
>
|
|
||||||
ToAU
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
key="wotg"
|
|
||||||
value="wotg"
|
|
||||||
aria-label="wotg-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '20%' }}
|
|
||||||
>
|
|
||||||
WotG
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
key="soa"
|
|
||||||
value="soa"
|
|
||||||
aria-label="soa-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '20%' }}
|
|
||||||
>
|
|
||||||
SoA
|
|
||||||
</ToggleButton>
|
|
||||||
</ToggleButtonGroup>
|
|
||||||
</Grid>
|
|
||||||
{/* Multiboxing */}
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={12}
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Typography id="multibox-button-group" variant="caption">
|
|
||||||
Multiboxing
|
|
||||||
</Typography>
|
|
||||||
<ToggleButtonGroup
|
|
||||||
value={searchState.multibox}
|
|
||||||
onChange={handleSearchMultibox}
|
|
||||||
size="small"
|
|
||||||
aria-labelledby="multibox-button-group"
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
exclusive
|
|
||||||
>
|
|
||||||
<ToggleButton
|
|
||||||
value="none"
|
|
||||||
aria-label="no multiboxing"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '33.33%' }}
|
|
||||||
>
|
|
||||||
None
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
value="limited"
|
|
||||||
aria-label="limited multiboxing"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '33.33%' }}
|
|
||||||
>
|
|
||||||
Limited
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
value="unlimited"
|
|
||||||
aria-label="unlimited multiboxing"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '33.33%' }}
|
|
||||||
>
|
|
||||||
Unlimited
|
|
||||||
</ToggleButton>
|
|
||||||
</ToggleButtonGroup>
|
|
||||||
</Grid>
|
|
||||||
{/* Trusts */}
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={6}
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Typography id="trust-button-group" variant="caption">
|
|
||||||
Trusts
|
|
||||||
</Typography>
|
|
||||||
<ToggleButtonGroup
|
|
||||||
value={searchState.trusts}
|
|
||||||
onChange={handleSearchTrusts}
|
|
||||||
size="small"
|
|
||||||
aria-labelledby="trust-button-group"
|
|
||||||
exclusive
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleButton
|
|
||||||
value="disabled"
|
|
||||||
aria-label="trust disabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '50%' }}
|
|
||||||
>
|
|
||||||
Disabled
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
value="enabled"
|
|
||||||
aria-label="trust enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '50%' }}
|
|
||||||
>
|
|
||||||
Enabled
|
|
||||||
</ToggleButton>
|
|
||||||
</ToggleButtonGroup>
|
|
||||||
</Grid>
|
|
||||||
{/* Level Sync */}
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={6}
|
|
||||||
display="flex"
|
|
||||||
flexDirection="column"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Typography id="level-sync-button-group" variant="caption">
|
|
||||||
Level Sync
|
|
||||||
</Typography>
|
|
||||||
<ToggleButtonGroup
|
|
||||||
value={searchState.levelSync}
|
|
||||||
onChange={handleSearchLevelSync}
|
|
||||||
size="small"
|
|
||||||
aria-labelledby="level-sync-button-group"
|
|
||||||
exclusive
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ToggleButton
|
|
||||||
value="disabled"
|
|
||||||
aria-label="level-sync-disabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '50%' }}
|
|
||||||
>
|
|
||||||
Disabled
|
|
||||||
</ToggleButton>
|
|
||||||
<ToggleButton
|
|
||||||
value="enabled"
|
|
||||||
aria-label="level-sync-enabled"
|
|
||||||
className="py-0"
|
|
||||||
sx={{ width: '50%' }}
|
|
||||||
>
|
|
||||||
Enabled
|
|
||||||
</ToggleButton>
|
|
||||||
</ToggleButtonGroup>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Container>
|
|
||||||
{contentHeight > 0 && <Divider />}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -26,16 +26,16 @@ import {
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useThemeModeContext } from '../context/ThemeContext';
|
import { useThemeModeContext } from '../../context/ThemeContext';
|
||||||
import { ServerData } from '../data/ServerData';
|
import { ServerData } from '../../data/ServerData';
|
||||||
import CopyImageIcon from '../images/copy-image.png';
|
import CopyImageIcon from '../../images/copy-image.png';
|
||||||
import ExpansionBar from './Server/ExpansionsBar';
|
|
||||||
import SettingsDataGrid from './Server/SettingsDataGrid';
|
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
} from './Themed/Accordion';
|
} from '../Themed/Accordion';
|
||||||
|
import ExpansionBar from './ExpansionsBar';
|
||||||
|
import SettingsDataGrid from './SettingsDataGrid';
|
||||||
|
|
||||||
function scrollToTop() {
|
function scrollToTop() {
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
|
|
@ -3,6 +3,11 @@ export type SearchState = {
|
||||||
multibox: string[] | null;
|
multibox: string[] | null;
|
||||||
trusts: string[] | null;
|
trusts: string[] | null;
|
||||||
levelSync: string[] | null;
|
levelSync: string[] | null;
|
||||||
|
homePoint: string[] | null;
|
||||||
|
survivalGuide: string[] | null;
|
||||||
|
recordsOfEminence: string[] | null;
|
||||||
|
fieldsOfValor: string[] | null;
|
||||||
|
groundsOfValor: string[] | null;
|
||||||
maxLevel: number[];
|
maxLevel: number[];
|
||||||
expansions: string[] | null;
|
expansions: string[] | null;
|
||||||
};
|
};
|
||||||
|
|
@ -12,6 +17,11 @@ export const SearchStateDefaults: SearchState = {
|
||||||
multibox: null,
|
multibox: null,
|
||||||
trusts: null,
|
trusts: null,
|
||||||
levelSync: null,
|
levelSync: null,
|
||||||
|
homePoint: null,
|
||||||
|
recordsOfEminence: null,
|
||||||
|
fieldsOfValor: null,
|
||||||
|
groundsOfValor: null,
|
||||||
|
survivalGuide: null,
|
||||||
maxLevel: [1, 99],
|
maxLevel: [1, 99],
|
||||||
expansions: null,
|
expansions: null,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import ErrorCard from '../components/ErrorCard';
|
import ErrorCard from '../components/ErrorCard';
|
||||||
|
import ServerCard from '../components/Server/ServerCard';
|
||||||
import SettingsChipCloud from '../components/Server/SettingsChipCloud';
|
import SettingsChipCloud from '../components/Server/SettingsChipCloud';
|
||||||
import ServerCard from '../components/ServerCard';
|
|
||||||
import { SearchState } from '../data/SearchState';
|
import { SearchState } from '../data/SearchState';
|
||||||
import { ServerData } from '../data/ServerData';
|
import { ServerData } from '../data/ServerData';
|
||||||
|
|
||||||
|
|
@ -13,51 +13,131 @@ export default function Home({
|
||||||
searchState: SearchState;
|
searchState: SearchState;
|
||||||
}) {
|
}) {
|
||||||
const filterServers = (server: ServerData): boolean => {
|
const filterServers = (server: ServerData): boolean => {
|
||||||
|
// Name
|
||||||
if (searchState.name.length > 0) {
|
if (searchState.name.length > 0) {
|
||||||
const serverName = server.name.toLowerCase();
|
const serverName = server.name.toLowerCase();
|
||||||
if (!serverName.includes(searchState.name.toLowerCase())) {
|
if (!serverName.includes(searchState.name.toLowerCase())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Max Level
|
||||||
if (server.max_level < searchState.maxLevel[0]) {
|
if (server.max_level < searchState.maxLevel[0]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (server.max_level > searchState.maxLevel[1]) {
|
if (server.max_level > searchState.maxLevel[1]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Trusts
|
||||||
if (
|
if (
|
||||||
searchState.trusts &&
|
searchState.trusts &&
|
||||||
typeof server.settings_summary['MAIN.ENABLE_TRUST_CASTING'] === 'number'
|
typeof server.settings_summary['MAIN.ENABLE_TRUST_CASTING'] === 'number'
|
||||||
) {
|
) {
|
||||||
const serverTrusts =
|
const serverEnabled =
|
||||||
server.settings_summary['MAIN.ENABLE_TRUST_CASTING'] === 1;
|
server.settings_summary['MAIN.ENABLE_TRUST_CASTING'] === 1;
|
||||||
const searchEnabled = searchState.trusts.includes('enabled');
|
const searchEnabled = searchState.trusts.includes('enabled');
|
||||||
const searchDisabled = searchState.trusts.includes('disabled');
|
const searchDisabled = searchState.trusts.includes('disabled');
|
||||||
if (serverTrusts && searchDisabled && !searchEnabled) {
|
if (
|
||||||
return false;
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
}
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
if (!serverTrusts && searchEnabled && !searchDisabled) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Level Sync
|
||||||
if (
|
if (
|
||||||
searchState.levelSync &&
|
searchState.levelSync &&
|
||||||
typeof server.settings_summary['MAP.LEVEL_SYNC_ENABLE'] === 'boolean'
|
typeof server.settings_summary['MAP.LEVEL_SYNC_ENABLE'] === 'boolean'
|
||||||
) {
|
) {
|
||||||
const serverLevelSync = server.settings_summary['MAP.LEVEL_SYNC_ENABLE'];
|
const serverEnabled = server.settings_summary['MAP.LEVEL_SYNC_ENABLE'];
|
||||||
const searchEnabled = searchState.levelSync.includes('enabled');
|
const searchEnabled = searchState.levelSync.includes('enabled');
|
||||||
const searchDisabled = searchState.levelSync.includes('disabled');
|
const searchDisabled = searchState.levelSync.includes('disabled');
|
||||||
if (serverLevelSync && searchDisabled && !searchEnabled) {
|
if (
|
||||||
return false;
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
}
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
if (!serverLevelSync && searchEnabled && !searchDisabled) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Home Point Teleport
|
||||||
|
if (
|
||||||
|
searchState.homePoint &&
|
||||||
|
typeof server.settings_summary['MAIN.HOMEPOINT_TELEPORT'] === 'number'
|
||||||
|
) {
|
||||||
|
const serverEnabled =
|
||||||
|
server.settings_summary['MAIN.HOMEPOINT_TELEPORT'] === 1;
|
||||||
|
const searchEnabled = searchState.homePoint.includes('enabled');
|
||||||
|
const searchDisabled = searchState.homePoint.includes('disabled');
|
||||||
|
if (
|
||||||
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Survival Guides
|
||||||
|
if (
|
||||||
|
searchState.survivalGuide &&
|
||||||
|
typeof server.settings_summary['MAIN.ENABLE_SURVIVAL_GUIDE'] === 'number'
|
||||||
|
) {
|
||||||
|
const serverEnabled =
|
||||||
|
server.settings_summary['MAIN.ENABLE_SURVIVAL_GUIDE'] === 1;
|
||||||
|
const searchEnabled = searchState.survivalGuide.includes('enabled');
|
||||||
|
const searchDisabled = searchState.survivalGuide.includes('disabled');
|
||||||
|
if (
|
||||||
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Records of Eminence
|
||||||
|
if (
|
||||||
|
searchState.recordsOfEminence &&
|
||||||
|
typeof server.settings_summary['MAIN.ENABLE_ROE'] === 'number'
|
||||||
|
) {
|
||||||
|
const serverEnabled = server.settings_summary['MAIN.ENABLE_ROE'] === 1;
|
||||||
|
const searchEnabled = searchState.recordsOfEminence.includes('enabled');
|
||||||
|
const searchDisabled = searchState.recordsOfEminence.includes('disabled');
|
||||||
|
if (
|
||||||
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fields of Valor
|
||||||
|
if (
|
||||||
|
searchState.fieldsOfValor &&
|
||||||
|
typeof server.settings_summary['MAIN.ENABLE_FIELD_MANUALS'] === 'number'
|
||||||
|
) {
|
||||||
|
const serverEnabled =
|
||||||
|
server.settings_summary['MAIN.ENABLE_FIELD_MANUALS'] === 1;
|
||||||
|
const searchEnabled = searchState.fieldsOfValor.includes('enabled');
|
||||||
|
const searchDisabled = searchState.fieldsOfValor.includes('disabled');
|
||||||
|
if (
|
||||||
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Grounds of Valor
|
||||||
|
if (
|
||||||
|
searchState.groundsOfValor &&
|
||||||
|
typeof server.settings_summary['MAIN.ENABLE_GROUNDS_TOMES'] === 'number'
|
||||||
|
) {
|
||||||
|
const serverEnabled =
|
||||||
|
server.settings_summary['MAIN.ENABLE_GROUNDS_TOMES'] === 1;
|
||||||
|
const searchEnabled = searchState.groundsOfValor.includes('enabled');
|
||||||
|
const searchDisabled = searchState.groundsOfValor.includes('disabled');
|
||||||
|
if (
|
||||||
|
(serverEnabled && searchDisabled && !searchEnabled) ||
|
||||||
|
(!serverEnabled && searchEnabled && !searchDisabled)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Expansions
|
||||||
if (searchState.expansions) {
|
if (searchState.expansions) {
|
||||||
if (!server.expansions) {
|
if (!server.expansions) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -72,23 +152,23 @@ export default function Home({
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (searchState.expansions.includes('rotz') && server.expansions.rotz) {
|
if (searchState.expansions.includes('rotz') !== server.expansions.rotz) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (searchState.expansions.includes('cop') && server.expansions.cop) {
|
if (searchState.expansions.includes('cop') !== server.expansions.cop) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (searchState.expansions.includes('toau') && server.expansions.toau) {
|
if (searchState.expansions.includes('toau') !== server.expansions.toau) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (searchState.expansions.includes('wotg') && server.expansions.wotg) {
|
if (searchState.expansions.includes('wotg') !== server.expansions.wotg) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (searchState.expansions.includes('soa') && server.expansions.soa) {
|
if (searchState.expansions.includes('soa') !== server.expansions.soa) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Multibox
|
||||||
if (searchState.multibox) {
|
if (searchState.multibox) {
|
||||||
const serverMultibox = server.login_limit;
|
const serverMultibox = server.login_limit;
|
||||||
if (searchState.multibox.includes('none') && serverMultibox !== 1) {
|
if (searchState.multibox.includes('none') && serverMultibox !== 1) {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { useEffect, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { fetchDataFromBackend, fetchDemo } from '../apiUtil';
|
import { fetchDataFromBackend, fetchDemo } from '../apiUtil';
|
||||||
import ErrorCard from '../components/ErrorCard';
|
import ErrorCard from '../components/ErrorCard';
|
||||||
|
import ServerCard from '../components/Server/ServerCard';
|
||||||
import SettingsDataGrid from '../components/Server/SettingsDataGrid';
|
import SettingsDataGrid from '../components/Server/SettingsDataGrid';
|
||||||
import ServerCard from '../components/ServerCard';
|
|
||||||
import { useLoadingContext } from '../context/LoadingContext';
|
import { useLoadingContext } from '../context/LoadingContext';
|
||||||
import { ServerData } from '../data/ServerData';
|
import { ServerData } from '../data/ServerData';
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue