251 lines
7.1 KiB
TypeScript
251 lines
7.1 KiB
TypeScript
import { createRef, useEffect, useState } from "react";
|
|
import { ReactSortable, ReactSortableProps } from "react-sortablejs";
|
|
import { apiAuth, User } from "./api";
|
|
import { useSession } from "./Session";
|
|
|
|
type PlayerListProps = Partial<ReactSortableProps<any>> & {
|
|
orderedList?: boolean;
|
|
};
|
|
|
|
function PlayerList(props: PlayerListProps) {
|
|
return (
|
|
<ReactSortable {...props} animation={200}>
|
|
{props.list?.map((item, index) => (
|
|
<div key={item.id} className="item">
|
|
{props.orderedList
|
|
? index + 1 + ". " + item.display_name
|
|
: item.display_name}
|
|
</div>
|
|
))}
|
|
</ReactSortable>
|
|
);
|
|
}
|
|
|
|
interface PlayerInfoProps {
|
|
user: User;
|
|
players: User[];
|
|
}
|
|
|
|
export function Chemistry({ user, players }: PlayerInfoProps) {
|
|
const index = players.indexOf(user);
|
|
var otherPlayers = players.slice();
|
|
otherPlayers.splice(index, 1);
|
|
const [playersLeft, setPlayersLeft] = useState<User[]>([]);
|
|
const [playersMiddle, setPlayersMiddle] = useState<User[]>(otherPlayers);
|
|
const [playersRight, setPlayersRight] = useState<User[]>([]);
|
|
|
|
useEffect(() => {
|
|
setPlayersMiddle(otherPlayers);
|
|
}, [players]);
|
|
|
|
const [dialog, setDialog] = useState("dialog");
|
|
|
|
async function handleSubmit() {
|
|
const dialog = document.querySelector("dialog[id='ChemistryDialog']");
|
|
(dialog as HTMLDialogElement).showModal();
|
|
setDialog("sending...");
|
|
let left = playersLeft.map(({ id }) => id);
|
|
let middle = playersMiddle.map(({ id }) => id);
|
|
let right = playersRight.map(({ id }) => id);
|
|
const data = { user: user.id, hate: left, undecided: middle, love: right };
|
|
const response = await apiAuth("chemistry", data, "POST");
|
|
response ? setDialog(response) : setDialog("try sending again");
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div className="container">
|
|
<div className="box three">
|
|
<h2>😬</h2>
|
|
{playersLeft.length < 1 && (
|
|
<span className="grey hint">
|
|
drag people here that you'd rather not play with
|
|
</span>
|
|
)}
|
|
<PlayerList
|
|
list={playersLeft}
|
|
setList={setPlayersLeft}
|
|
group={"shared"}
|
|
className="dragbox"
|
|
/>
|
|
</div>
|
|
<div className="box three">
|
|
<h2>🤷</h2>
|
|
<PlayerList
|
|
list={playersMiddle}
|
|
setList={setPlayersMiddle}
|
|
group={"shared"}
|
|
className="middle dragbox"
|
|
/>
|
|
</div>
|
|
<div className="box three">
|
|
<h2>😍</h2>
|
|
{playersRight.length < 1 && (
|
|
<span className="grey hint">
|
|
drag people here that you love playing with from best to ... ok
|
|
</span>
|
|
)}
|
|
<PlayerList
|
|
list={playersRight}
|
|
setList={setPlayersRight}
|
|
group={"shared"}
|
|
className="dragbox"
|
|
orderedList
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<button className="submit" onClick={() => handleSubmit()}>
|
|
💾 <span className="submit_text">submit</span>
|
|
</button>
|
|
<dialog
|
|
id="ChemistryDialog"
|
|
onClick={(event) => {
|
|
event.currentTarget.close();
|
|
}}
|
|
>
|
|
{dialog}
|
|
</dialog>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function MVP({ user, players }: PlayerInfoProps) {
|
|
const [availablePlayers, setAvailablePlayers] = useState<User[]>(players);
|
|
const [rankedPlayers, setRankedPlayers] = useState<User[]>([]);
|
|
|
|
const [dialog, setDialog] = useState("dialog");
|
|
|
|
useEffect(() => {
|
|
setAvailablePlayers(players);
|
|
}, [players]);
|
|
|
|
async function handleSubmit() {
|
|
const dialog = document.querySelector("dialog[id='MVPDialog']");
|
|
(dialog as HTMLDialogElement).showModal();
|
|
setDialog("sending...");
|
|
let mvps = rankedPlayers.map(({ id }) => id);
|
|
const data = { user: user.id, mvps: mvps };
|
|
const response = await apiAuth("mvps", data, "POST");
|
|
response ? setDialog(response) : setDialog("try sending again");
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div className="container">
|
|
<div className="box two">
|
|
<h2>🥏🏃</h2>
|
|
{availablePlayers.length < 1 && (
|
|
<span className="grey hint">all sorted 👍</span>
|
|
)}
|
|
<PlayerList
|
|
list={availablePlayers}
|
|
setList={setAvailablePlayers}
|
|
group={{
|
|
name: "mvp-shared",
|
|
pull: function (to) {
|
|
return to.el.classList.contains("putclone") ? "clone" : true;
|
|
},
|
|
}}
|
|
className="dragbox"
|
|
/>
|
|
</div>
|
|
<div className="box two">
|
|
<h1>🏆</h1>
|
|
{rankedPlayers.length < 1 && (
|
|
<span className="grey hint">
|
|
carefully place as many of the <i>Most Valuable Players</i>{" "}
|
|
(according to your humble opinion) in this box
|
|
</span>
|
|
)}
|
|
<PlayerList
|
|
list={rankedPlayers}
|
|
setList={setRankedPlayers}
|
|
group={{
|
|
name: "mvp-shared",
|
|
pull: function (to) {
|
|
return to.el.classList.contains("putclone") ? "clone" : true;
|
|
},
|
|
}}
|
|
className="dragbox"
|
|
orderedList
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<button className="submit" onClick={() => handleSubmit()}>
|
|
💾 <span className="submit_text">submit</span>
|
|
</button>
|
|
<dialog
|
|
id="MVPDialog"
|
|
onClick={(event) => {
|
|
event.currentTarget.close();
|
|
}}
|
|
>
|
|
{dialog}
|
|
</dialog>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default function Rankings() {
|
|
const { user } = useSession();
|
|
const [players, setPlayers] = useState<User[] | null>(null);
|
|
const [openTab, setOpenTab] = useState("Chemistry");
|
|
|
|
async function loadPlayers() {
|
|
try {
|
|
const data = await apiAuth("player/list", null, "GET");
|
|
setPlayers(data as User[]);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
loadPlayers();
|
|
}, []);
|
|
const tabs = [
|
|
{ id: "Chemistry", label: "🧪 Chemistry" },
|
|
{ id: "MVP", label: "🏆 MVP" },
|
|
];
|
|
|
|
return (
|
|
<>
|
|
{user && players && (
|
|
<div>
|
|
<div className="container navbar">
|
|
{tabs.map((tab) => (
|
|
<button
|
|
key={tab.id}
|
|
className={
|
|
openTab === tab.id ? "tab-button active" : "tab-button"
|
|
}
|
|
onClick={() => setOpenTab(tab.id)}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
<span className="grey">
|
|
assign as many or as few players as you want
|
|
<br />
|
|
and don't forget to <b>submit</b> 💾 when you're done :)
|
|
</span>
|
|
{tabs.map((tab) => {
|
|
if (openTab !== tab.id) return null;
|
|
switch (tab.id) {
|
|
case "Chemistry":
|
|
return <Chemistry key={tab.id} {...{ user, players }} />;
|
|
case "MVP":
|
|
return <MVP key={tab.id} {...{ user, players }} />;
|
|
default:
|
|
return null;
|
|
}
|
|
})}
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|