272 lines
7.8 KiB
TypeScript
272 lines
7.8 KiB
TypeScript
import { 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[]>([]);
|
|
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();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
openPage(openTab, "aliceblue");
|
|
}, [user]);
|
|
|
|
function openPage(pageName: string, color: string) {
|
|
// Hide all elements with class="tabcontent" by default */
|
|
var i, tabcontent, tablinks;
|
|
tabcontent = document.getElementsByClassName("tabcontent");
|
|
for (i = 0; i < tabcontent.length; i++) {
|
|
(tabcontent[i] as HTMLElement).style.display = "none";
|
|
}
|
|
// Remove the background color of all tablinks/buttons
|
|
tablinks = document.getElementsByClassName("tablink");
|
|
for (i = 0; i < tablinks.length; i++) {
|
|
let button = tablinks[i] as HTMLElement;
|
|
button.style.opacity = "50%";
|
|
}
|
|
// Show the specific tab content
|
|
(document.getElementById(pageName) as HTMLElement).style.display = "block";
|
|
// Add the specific color to the button used to open the tab content
|
|
let activeButton = document.getElementById(
|
|
pageName + "Button"
|
|
) as HTMLElement;
|
|
activeButton.style.fontWeight = "bold";
|
|
activeButton.style.opacity = "100%";
|
|
document.body.style.backgroundColor = color;
|
|
setOpenTab(pageName);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div className="container navbar">
|
|
<button
|
|
className="tablink"
|
|
id="ChemistryButton"
|
|
onClick={() => openPage("Chemistry", "aliceblue")}
|
|
>
|
|
🧪 Chemistry
|
|
</button>
|
|
<button
|
|
className="tablink"
|
|
id="MVPButton"
|
|
onClick={() => openPage("MVP", "aliceblue")}
|
|
>
|
|
🏆 MVP
|
|
</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>
|
|
|
|
<div id="Chemistry" className="tabcontent">
|
|
{user && <Chemistry {...{ user, players }} />}
|
|
</div>
|
|
<div id="MVP" className="tabcontent">
|
|
{user && <MVP {...{ user, players }} />}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|