import Menu from "../../components/Menu";
import redirect from "../../Modules/league";
import Head from "next/head";
import { useState, useEffect, useContext } from "react";
import { TransferPlayer as Player } from "../../components/Player";
import { useSession } from "next-auth/react";
import db from "../../Modules/database";
import Link from "../../components/Link";
import {
Alert,
AlertTitle,
Button,
Checkbox,
FormControlLabel,
FormGroup,
FormLabel,
LinearProgress,
MenuItem,
Select,
Slider,
Switch,
TextField,
} from "@mui/material";
import { Box } from "@mui/system";
import { TranslateContext } from "../../Modules/context";
import { GetServerSideProps } from "next";
import { GETResult } from "../api/transfer/[league]";
import { Selectable } from "kysely";
import { LeagueSettings } from "#type/db";
// Shows the amount of transfers left
function TransfersLeft({
ownership,
allowedTransfers,
transferCount,
}: {
ownership: GETResult["ownership"];
allowedTransfers: number;
transferCount: number;
}) {
const session = useSession();
const t = useContext(TranslateContext);
const user = session.data ? session.data.user.id : 1;
return (
{t("{amount} transfers left", {
amount:
Object.values(ownership).filter(
(e) => e.filter((e) => !e.transfer && e.owner === user).length > 0,
).length == 0
? t("Unlimited")
: allowedTransfers - transferCount,
})}
);
}
// Used for the selecting and unselecting of a position
function Postion({
position,
positions,
setPositions,
}: {
position: string;
positions: string[];
setPositions: React.Dispatch>;
}) {
const t = useContext(TranslateContext);
return (
<>
{
e.target.checked
? setPositions([...positions, position])
: setPositions(positions.filter((e2) => e2 != position));
}}
/>
}
label={t(position)}
/>
>
);
}
function MainPage({
league,
maxPrice,
transferOpen,
leagueSettings,
}: {
maxPrice: number;
league: number;
transferOpen: boolean;
leagueSettings: Selectable;
}) {
const positionList = ["gk", "def", "mid", "att"];
const [players, setPlayers] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [finished, setFinished] = useState(false);
const [loading, setLoading] = useState(false);
const [positions, setPositions] = useState(positionList);
const [money, setMoney] = useState(0);
const [ownership, setOwnership] = useState({});
const [transferCount, setTransferCount] = useState(0);
const [orderBy, setOrderBy] = useState("value");
const [showHidden, setShowHidden] = useState(false);
const [onlySales, setOnlySales] = useState(false);
const [timeLeft, setTimeLeft] = useState(0);
const [open, setOpen] = useState(transferOpen);
const [clubSearch, setClubSearch] = useState("");
const [price, setPrice] = useState([0, Math.ceil(maxPrice / 500000) / 2]);
const [salePrice, setSalePrice] = useState(true);
const t = useContext(TranslateContext);
useEffect(() => {
search(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
searchTerm,
positions,
orderBy,
showHidden,
clubSearch,
price,
onlySales,
salePrice,
]);
// Used to get the data for a list of transfers and money
function transferData() {
fetch(`/api/transfer/${league}`).then(async (val) => {
const res: GETResult = await val.json();
setMoney(res.money);
setOwnership(res.ownership);
setTransferCount(res.transferCount);
setTimeLeft(res.timeLeft);
setOpen(res.transferOpen);
});
}
// Used to lower the time left by one every second
useEffect(() => {
const id = setInterval(
() => setTimeLeft((timeLeft) => (timeLeft > 0 ? timeLeft - 1 : 0)),
1000,
);
return () => {
clearInterval(id);
};
}, []);
// Used to calculate transfer message
const transferMessage = (
{t("Transfer Market {open} for {day} D {hour} H {minute} M {second} S", {
open: open ? t("open") : t("closed"),
day: Math.floor(timeLeft / 3600 / 24),
hour: Math.floor(timeLeft / 3600) % 24,
minute: Math.floor(timeLeft / 60) % 60,
second: timeLeft % 60,
})}
);
useEffect(transferData, [league]);
// Used to search the isNew is used to check if it should reload everything back from the start
async function search(isNew: boolean) {
let length = -1;
if (!isNew) {
if (finished) {
return;
} else {
length = players.length;
}
} else {
setPlayers([]);
setFinished(false);
}
// Gets the data and returns the amount of players found
setLoading(true);
const newLength = await fetch(
`/api/player/${leagueSettings.league}/search?${
isNew ? "" : `limit=${players.length + 50}&`
}searchTerm=${encodeURIComponent(
searchTerm,
)}&clubSearch=${encodeURIComponent(
clubSearch,
)}&positions=${encodeURIComponent(
JSON.stringify(positions),
)}&order_by=${encodeURIComponent(orderBy)}&league=${league}&minPrice=${
price[0] * 1000000
}&maxPrice=${
price[1] * 1000000
}&showHidden=${showHidden}&onlySales=${onlySales}&salePrice=${salePrice}`,
).then(async (val) => {
const res: string[] = await val.json();
setPlayers(res);
return res.length;
});
setLoading(false);
if (newLength == length) {
setFinished(true);
} else {
setFinished(false);
}
}
const Part1 = (
{t("Money left: {amount} M", { amount: money / 1000000 })}
{transferMessage}
{
setSearchTerm(val.target.value);
}}
value={searchTerm}
label="Search Player"
id="searchPlayer"
>
{
setClubSearch(val.target.value);
}}
value={clubSearch}
id="searchClub"
label={t("Search Club")}
helperText={t("Use the acronymn ex: FCB, VFB")}
>
{t("Value: {price1} M to {price2} M", {
price1: price[0],
price2: price[1],
})}
setPrice(value as number[])}
id="value"
max={Math.ceil(maxPrice / 500000) / 2}
/>
{
setSalePrice(e.target.checked);
}}
checked={salePrice}
/>
}
label={t("Use sale price instead of value")}
/>
{t("Sort players by: ")}
setOrderBy(val.target.value)}
id="order"
>
{[
["value", "Value"],
["total_points", "Total Points"],
["average_points", "Average Points"],
["last_match", "Last Match"],
].map((val) => (
{t(val[1])}
))}
);
const Part2 = (
{t("Positions to search: ")}
{positionList.map((position) => (
))}
{
setShowHidden(e.target.checked);
}}
checked={showHidden}
/>
}
label={t("Show hidden players")}
/>
{
setOnlySales(e.target.checked);
}}
checked={onlySales}
/>
}
label={t("Show only players on sale")}
/>
{t("Download Data")}
{t("Clicking on a player's name will show more information. ")}
);
return (
{
// Checks if scrolled to the bottom
const bottom =
e.currentTarget.scrollHeight -
e.currentTarget.scrollTop -
e.currentTarget.clientHeight;
// Checks if there are only 2 players left that are not shown and if true requests 10 more players
if (bottom < (e.currentTarget.scrollHeight / players.length) * 2) {
search(false);
setFinished(true);
}
}}
>
{t("Transfers for {leagueName}", {
leagueName: leagueSettings.leagueName,
})}
{t("Transfers for {leagueName}", {
leagueName: leagueSettings.leagueName,
})}
{Part1}
{Part2}
{Part1}
{Part2}
{players.map((val) => (
0}
duplicatePlayers={leagueSettings.duplicatePlayers}
leagueType={leagueSettings.league}
showHidden={showHidden}
/>
))}
{loading && }
);
}
export default function Home(props: {
maxPrice: number;
league: number;
transferOpen: boolean;
leagueSettings: Selectable;
}) {
const t = useContext(TranslateContext);
const { archived, leagueName, fantasyEnabled } = props.leagueSettings;
// Checks if the league is archived
if (archived !== 0) {
return (
<>
{t("Transfers for {leagueName}", { leagueName })}
{t("Transfers for {leagueName}", { leagueName })}
{t("This league is archived")}
{t("This league is archived and this screen is disabled. ")}
>
);
} else if (!fantasyEnabled) {
return (
<>
{t("Squad for {leagueName}", {
leagueName,
})}
{t("Squad for {leagueName}", {
leagueName,
})}
{t("Fantasy is Disabled")}
{t("Fantasy manager must be enabled in the league to use this. ")}
>
);
} else {
return ;
}
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const leagueID = parseInt(String(ctx?.params?.league));
// Gets the amount of allowed transfers
const league = await db
.selectFrom("leagueSettings")
.selectAll()
.where("leagueID", "=", leagueID)
.select("league")
.executeTakeFirst()
.then((e) => (e ? e.league : "Bundesliga"));
const maxPrice = await db
.selectFrom("players")
.select("value")
.orderBy("value", "desc")
.where("league", "=", league)
.executeTakeFirst()
.then((e) => (e ? e.value : 0));
return await redirect(ctx, { maxPrice });
};