feat: migrate Chemistry and api out of App.tsx

This commit is contained in:
julius 2025-01-25 13:19:38 +01:00
parent cdb360d4f3
commit 1065b0cdeb
Signed by: julius
GPG Key ID: C80A63E6A5FD7092
4 changed files with 167 additions and 149 deletions

View File

@ -19,7 +19,6 @@ h1,
h2 {
margin-top: 0px;
margin-bottom: 0px;
background-color: ghostwhite;
}
.container {

View File

@ -1,157 +1,11 @@
import "./App.css";
import { useState } from "react";
import { ReactSortable, ReactSortableProps } from "react-sortablejs";
const baseUrl = import.meta.env.VITE_BASE_URL as string;
interface Player {
id: number;
name: string;
}
function loadPlayers() {
const players = [
"August",
"Beate",
"Ceasar",
"Daedalus",
"Elli",
"Ford P.",
"Gabriel",
"Hugo",
"Ivar Johansson",
"Jürgen Gordon Malinauskas",
"Karsten Uwe Kalinowski",
].map((v, i) => {
return { id: i, name: v } as Player;
});
return players;
}
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.name : item.name}
</div>
))}
</ReactSortable>
);
}
async function api(path: string, data: any): Promise<any> {
const request = new Request(`${baseUrl}${path}/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
let response: Response;
try {
response = await fetch(request);
} catch (e) {
throw new Error(`request failed: ${e}`);
}
return response;
}
import Chemistry from "./Chemistry";
function App() {
const players = loadPlayers();
const [user, setUser] = useState<Player[]>([]);
const [playersLeft, setPlayersLeft] = useState<Player[]>([]);
const [playersMiddle, setPlayersMiddle] = useState<Player[]>(players);
const [playersRight, setPlayersRight] = useState<Player[]>([]);
const [dialog, setDialog] = useState("dialog");
async function handleSubmit() {
const dialog = document.querySelector("dialog");
dialog?.showModal();
if (user.length < 1) {
setDialog("who are you?");
} else {
setDialog("sending...");
let _user = user.map(({ name }) => name)[0];
let left = playersLeft.map(({ name }) => name);
let middle = playersMiddle.map(({ name }) => name);
let right = playersRight.map(({ name }) => name);
const data = { user: _user, hate: left, undecided: middle, love: right };
const response = await api("chemistry", data);
response.ok ? setDialog("success!") : setDialog("try sending again");
}
}
return (
<>
<img alt="logo" height="128px" src="logo.svg" />
<h1>cutt</h1>
<span className="grey">cool ultimate team tool</span>
<div className="box user">
<h2>who are you?</h2>
<PlayerList
list={user}
setList={setUser}
group={{
name: "shared",
put: function (to) {
return to.el.children.length < 1;
},
}}
className="dragbox"
/>
</div>
<div className="container">
<div className="box">
<h2>😬</h2>
<PlayerList
list={playersLeft}
setList={setPlayersLeft}
group={"shared"}
className="dragbox"
orderedList
/>
</div>
<div className="box">
<h2>🤷</h2>
<PlayerList
list={playersMiddle}
setList={setPlayersMiddle}
group={"shared"}
className="middle dragbox"
/>
</div>
<div className="box">
<h2>😍</h2>
<PlayerList
list={playersRight}
setList={setPlayersRight}
group={"shared"}
className="dragbox"
orderedList
/>
</div>
</div>
<button onClick={() => handleSubmit()}>submit</button>
<dialog
onClick={(event) => {
event.currentTarget.close();
}}
>
{dialog}
</dialog>
<footer>
<p className="grey">
something not working? message <a href="https://t.me/x0124816">me</a>.
</p>
</footer>
<Chemistry />
</>
);
}
export default App;

148
src/Chemistry.tsx Normal file
View File

@ -0,0 +1,148 @@
import { useState } from "react";
import { ReactSortable, ReactSortableProps } from "react-sortablejs";
import api from "./api";
interface Player {
id: number;
name: string;
}
function loadPlayers() {
const players = [
"August",
"Beate",
"Ceasar",
"Daedalus",
"Elli",
"Ford P.",
"Gabriel",
"Hugo",
"Ivar Johansson",
"Jürgen Gordon Malinauskas",
"Karsten Uwe Kalinowski",
].map((v, i) => {
return { id: i, name: v } as Player;
});
return players;
}
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.name : item.name}
</div>
))}
</ReactSortable>
);
}
export default function Chemistry() {
const players = loadPlayers();
const [user, setUser] = useState<Player[]>([]);
const [playersLeft, setPlayersLeft] = useState<Player[]>([]);
const [playersMiddle, setPlayersMiddle] = useState<Player[]>(players);
const [playersRight, setPlayersRight] = useState<Player[]>([]);
const [dialog, setDialog] = useState("dialog");
async function handleSubmit() {
const dialog = document.querySelector("dialog");
dialog?.showModal();
if (user.length < 1) {
setDialog("who are you?");
} else {
setDialog("sending...");
let _user = user.map(({ name }) => name)[0];
let left = playersLeft.map(({ name }) => name);
let middle = playersMiddle.map(({ name }) => name);
let right = playersRight.map(({ name }) => name);
const data = { user: _user, hate: left, undecided: middle, love: right };
const response = await api("chemistry", data);
response.ok ? setDialog("success!") : setDialog("try sending again");
}
}
return (
<>
<img alt="logo" height="128px" src="logo.svg" />
<h1>cutt</h1>
<span className="grey">cool ultimate team tool</span>
<div className="box user">
<h2>your name?</h2>
{user.length < 1 && <span className="grey">drag your name here:</span>}
<PlayerList
list={user}
setList={setUser}
group={{
name: "shared",
put: function (to) {
return to.el.children.length < 1;
},
}}
className="dragbox"
/>
</div>
<div className="container">
<div className="box">
<h2>😬</h2>
{playersLeft.length < 1 && (
<span className="grey">
drag people here that you'd rather not play with
</span>
)}
<PlayerList
list={playersLeft}
setList={setPlayersLeft}
group={"shared"}
className="dragbox"
orderedList
/>
</div>
<div className="box">
<h2>🤷</h2>
<PlayerList
list={playersMiddle}
setList={setPlayersMiddle}
group={"shared"}
className="middle dragbox"
/>
</div>
<div className="box">
<h2>😍</h2>
{playersRight.length < 1 && (
<span className="grey">
drag people here that you love playing with
</span>
)}
<PlayerList
list={playersRight}
setList={setPlayersRight}
group={"shared"}
className="dragbox"
orderedList
/>
</div>
</div>
<button onClick={() => handleSubmit()}>submit</button>
<dialog
onClick={(event) => {
event.currentTarget.close();
}}
>
{dialog}
</dialog>
<footer>
<p className="grey">
something not working? message <a href="https://t.me/x0124816">me</a>.
</p>
</footer>
</>
);
}

17
src/api.ts Normal file
View File

@ -0,0 +1,17 @@
const baseUrl = import.meta.env.VITE_BASE_URL as string;
export default async function api(path: string, data: any): Promise<any> {
const request = new Request(`${baseUrl}${path}/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
let response: Response;
try {
response = await fetch(request);
} catch (e) {
throw new Error(`request failed: ${e}`);
}
return response;
}