205 lines
5.6 KiB
TypeScript
205 lines
5.6 KiB
TypeScript
import "./App.css";
|
|
import names from "./players.json";
|
|
import * as React from "react";
|
|
import { Theme, useTheme } from "@mui/material/styles";
|
|
import Box from "@mui/material/Box";
|
|
import OutlinedInput from "@mui/material/OutlinedInput";
|
|
import InputLabel from "@mui/material/InputLabel";
|
|
import MenuItem from "@mui/material/MenuItem";
|
|
import FormControl from "@mui/material/FormControl";
|
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
|
import Chip from "@mui/material/Chip";
|
|
import {
|
|
Alert,
|
|
Button,
|
|
Dialog,
|
|
DialogTitle,
|
|
FormHelperText,
|
|
Stack,
|
|
} from "@mui/material";
|
|
|
|
function getStyles(name: string, players: readonly string[], theme: Theme) {
|
|
return {
|
|
fontWeight: players.includes(name)
|
|
? theme.typography.fontWeightMedium
|
|
: theme.typography.fontWeightRegular,
|
|
};
|
|
}
|
|
|
|
async function submit(
|
|
person: string,
|
|
players: string[],
|
|
setResponseStatus: (value: number) => void
|
|
) {
|
|
// console.log(JSON.stringify({ person: person, players: players }));
|
|
const response = await fetch("https://0124816.xyz/team/submit/", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ person: person, players: players }),
|
|
});
|
|
setResponseStatus(response.status);
|
|
}
|
|
|
|
type SubmitButtonProps = {
|
|
person: string;
|
|
players: string[];
|
|
};
|
|
|
|
function SubmitButton(props: SubmitButtonProps) {
|
|
const [responseStatus, setResponseStatus] = React.useState(0);
|
|
|
|
return (
|
|
<div>
|
|
<Button
|
|
variant="contained"
|
|
color={responseStatus === 200 ? "success" : "primary"}
|
|
onClick={() => submit(props.person, props.players, setResponseStatus)}
|
|
>
|
|
submit
|
|
</Button>
|
|
<Dialog open={responseStatus === 200}>
|
|
<DialogTitle>thank you. please leave now.</DialogTitle>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
type MultiSelectProps = {
|
|
person: string;
|
|
setPerson: (value: string) => void;
|
|
players: string[];
|
|
setPlayers: (value: string[]) => void;
|
|
};
|
|
|
|
function MultipleSelectChip(props: MultiSelectProps) {
|
|
const ITEM_HEIGHT = 48;
|
|
const ITEM_PADDING_TOP = 8;
|
|
const MenuProps = {
|
|
PaperProps: {
|
|
style: {
|
|
maxHeight: ITEM_HEIGHT * 6.5 + ITEM_PADDING_TOP,
|
|
width: 250,
|
|
},
|
|
},
|
|
};
|
|
const [alert, setAlert] = React.useState<string>("none");
|
|
const maxLimit = 9;
|
|
const theme = useTheme();
|
|
|
|
const handlePersonChange = (
|
|
event: SelectChangeEvent<typeof props.person>
|
|
) => {
|
|
const {
|
|
target: { value },
|
|
} = event;
|
|
props.setPerson(value);
|
|
const index = props.players.indexOf(value);
|
|
if (index > -1) {
|
|
props.players.splice(index, 1);
|
|
}
|
|
props.setPlayers(props.players);
|
|
};
|
|
|
|
const handleChange = (event: SelectChangeEvent<typeof props.players>) => {
|
|
const {
|
|
target: { value },
|
|
} = event;
|
|
if (value.length <= maxLimit) {
|
|
setAlert("none");
|
|
props.setPlayers(
|
|
// On autofill we get a stringified value.
|
|
typeof value === "string" ? value.split(",") : value
|
|
);
|
|
} else {
|
|
setAlert("");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Box sx={{ maxWidth: "60vw" }}>
|
|
<Stack direction="column">
|
|
<FormControl sx={{ m: "8px auto", width: 200 }}>
|
|
<InputLabel id="demo-multiple-chip-label">who are you?</InputLabel>
|
|
<Select
|
|
labelId="demo-chip-label"
|
|
id="demo-multiple-chip"
|
|
value={props.person}
|
|
onChange={handlePersonChange}
|
|
input={<OutlinedInput id="select-chip" label="who are you?" />}
|
|
MenuProps={MenuProps}
|
|
>
|
|
{names.map((name) => (
|
|
<MenuItem key={name} value={name}>
|
|
{name}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
|
|
<Alert
|
|
severity="warning"
|
|
sx={{ display: alert, width: 200, m: "8px auto" }}
|
|
>
|
|
do not select more than {maxLimit} players
|
|
</Alert>
|
|
|
|
<FormControl sx={{ m: "8px auto", width: 200 }}>
|
|
<InputLabel id="demo-multiple-chip-label">players</InputLabel>
|
|
<Select
|
|
labelId="demo-multiple-chip-label"
|
|
id="demo-multiple-chip"
|
|
multiple
|
|
value={props.players}
|
|
onChange={handleChange}
|
|
input={<OutlinedInput id="select-multiple-chip" label="players" />}
|
|
renderValue={(selected) => (
|
|
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
|
|
{selected.map((value) => (
|
|
<Chip key={value} label={value} />
|
|
))}
|
|
</Box>
|
|
)}
|
|
MenuProps={MenuProps}
|
|
>
|
|
{names.map((name) =>
|
|
name !== props.person ? (
|
|
<MenuItem
|
|
key={name}
|
|
value={name}
|
|
style={getStyles(name, props.players, theme)}
|
|
>
|
|
{name}
|
|
</MenuItem>
|
|
) : null
|
|
)}
|
|
</Select>
|
|
<FormHelperText>max. {maxLimit}</FormHelperText>
|
|
</FormControl>
|
|
</Stack>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
function App() {
|
|
const [person, setPerson] = React.useState<string>("");
|
|
const [players, setPlayers] = React.useState<string[]>([]);
|
|
|
|
return (
|
|
<>
|
|
<h1>choose your best buddies for the Igloo</h1>
|
|
<div className="card">
|
|
{MultipleSelectChip({ person, setPerson, players, setPlayers })}
|
|
{SubmitButton({ person, players })}
|
|
<p>now: click submit.</p>
|
|
</div>
|
|
<p className="read-the-docs">
|
|
something not working? message <a href="https://t.me/x0124816">me</a>.
|
|
</p>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default App;
|