add website
This commit is contained in:
14
prefs_page/src/App.css
Normal file
14
prefs_page/src/App.css
Normal file
@@ -0,0 +1,14 @@
|
||||
#root {
|
||||
max-width: 60vw;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
204
prefs_page/src/App.tsx
Normal file
204
prefs_page/src/App.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
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;
|
68
prefs_page/src/index.css
Normal file
68
prefs_page/src/index.css
Normal file
@@ -0,0 +1,68 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
10
prefs_page/src/main.tsx
Normal file
10
prefs_page/src/main.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
1
prefs_page/src/vite-env.d.ts
vendored
Normal file
1
prefs_page/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
Reference in New Issue
Block a user