mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-29 22:58:18 -05:00
Refetch after creating team
This commit is contained in:
@@ -14,6 +14,7 @@ export function Layout(p: { children: JSXElement }) {
|
||||
setMenuExpanded((expanded) => !expanded);
|
||||
}
|
||||
|
||||
// TODO: why logo wide?
|
||||
return (
|
||||
<>
|
||||
<header class={s.header}>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { DiscordIcon } from "../../../components/icons/Discord";
|
||||
import { useUser } from "../../../utils/UserContext";
|
||||
import s from "../styles/UserItem.module.css";
|
||||
|
||||
// TODO: redirect to same page on login
|
||||
export function UserItem() {
|
||||
const user = useUser();
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { useData } from "solid-app-router";
|
||||
import { createResource } from "solid-js";
|
||||
import { InferQueryOutput, trpcClient } from "../../utils/trpc-client";
|
||||
import type { UseDataResult } from "../../utils/types";
|
||||
import { trpcClient } from "../../utils/trpc-client";
|
||||
|
||||
export default function TournamentData({
|
||||
params,
|
||||
}: {
|
||||
params: { organization: string; tournament: string };
|
||||
}) {
|
||||
const [user] = createResource(
|
||||
return createResource(
|
||||
() => [params.organization, params.tournament],
|
||||
([organization, tournament]) =>
|
||||
trpcClient.query("tournament.get", {
|
||||
@@ -16,10 +14,6 @@ export default function TournamentData({
|
||||
tournament,
|
||||
})
|
||||
);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
export function useTournamentData(delta?: number) {
|
||||
return useData<UseDataResult<InferQueryOutput<"tournament.get">>>(delta);
|
||||
}
|
||||
export type ITournamentData = ReturnType<typeof TournamentData>;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useData } from "solid-app-router";
|
||||
import { createMemo, createSignal } from "solid-js";
|
||||
import { ErrorMessage } from "../../../components/ErrorMessage";
|
||||
import { trpcClient } from "../../../utils/trpc-client";
|
||||
import { useForm } from "../../../utils/useForm";
|
||||
import s from "../styles/ActionSection.module.css";
|
||||
import { useTournamentData } from "../TournamentPage.data";
|
||||
import type { ITournamentData } from "../TournamentPage.data";
|
||||
|
||||
const lengthIsCorrect = ({ value }: { value: string }) => {
|
||||
if (value.length >= 2 && value.length <= 40) {
|
||||
@@ -20,16 +21,31 @@ const uniqueName =
|
||||
return `There is already a team called "${value}" registered`;
|
||||
};
|
||||
|
||||
// TODO: show login action when not logged in
|
||||
// TODO: show add members action when captain and not started
|
||||
// TODO: show leave member action when not captain and not started
|
||||
// TODO: show checkin action when captain and check-in started
|
||||
// TODO: show report score and other in-game actions when there is a match ongoing
|
||||
// TODO: outlined when no crucial action, filled when there is?
|
||||
export function ActionSection() {
|
||||
const [expanded, setExpanded] = createSignal(false);
|
||||
const tournament = useTournamentData();
|
||||
const [teamName, setTeamName] = createSignal("");
|
||||
const [tournament, { refetch }] = useData<ITournamentData>();
|
||||
const { validate: _validate, formSubmit: _formSubmit, errors } = useForm();
|
||||
|
||||
const fn = (form: HTMLFormElement) => {
|
||||
return trpcClient.mutation("tournament.createTournamentTeam", {
|
||||
name: "Team Olive",
|
||||
tournamentId: 1,
|
||||
});
|
||||
const fn = async () => {
|
||||
try {
|
||||
await trpcClient.mutation("tournament.createTournamentTeam", {
|
||||
name: teamName(),
|
||||
tournamentId: tournament()!.id,
|
||||
});
|
||||
// TODO: mutate here?
|
||||
refetch();
|
||||
setExpanded(false);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
// TODO: deal with error
|
||||
}
|
||||
};
|
||||
|
||||
const registeredTeamNames = createMemo(() =>
|
||||
@@ -60,6 +76,8 @@ export function ActionSection() {
|
||||
name="team-name"
|
||||
id="team-name"
|
||||
required
|
||||
value={teamName()}
|
||||
onInput={(e) => setTeamName(e.currentTarget.value)}
|
||||
// @ts-expect-error
|
||||
use:_validate={[
|
||||
lengthIsCorrect,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Show } from "solid-js";
|
||||
import { DiscordIcon } from "../../../components/icons/Discord";
|
||||
import { TwitterIcon } from "../../../components/icons/Twitter";
|
||||
import { useTournamentData } from "../TournamentPage.data";
|
||||
import type { ITournamentData } from "../TournamentPage.data";
|
||||
import s from "../styles/InfoBanner.module.css";
|
||||
import { useData } from "solid-app-router";
|
||||
|
||||
export function InfoBanner() {
|
||||
const tournament = useTournamentData();
|
||||
const [tournament] = useData<ITournamentData>();
|
||||
|
||||
// TODO: skeleton
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { For, Show } from "solid-js";
|
||||
import { modesShort, stages } from "../../../utils/constants";
|
||||
import { useTournamentData } from "../TournamentPage.data";
|
||||
import type { ITournamentData } from "../TournamentPage.data";
|
||||
import s from "../styles/MapPoolTab.module.css";
|
||||
import type { Mode } from ".prisma/client";
|
||||
import { useData } from "solid-app-router";
|
||||
|
||||
export function MapPoolTab() {
|
||||
const tournament = useTournamentData(1);
|
||||
const [tournament] = useData<ITournamentData>(1);
|
||||
|
||||
return (
|
||||
<Show when={tournament()}>
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
import { createMemo, For, Show } from "solid-js";
|
||||
import { useTournamentData } from "../TournamentPage.data";
|
||||
import type { ITournamentData } from "../TournamentPage.data";
|
||||
import s from "../styles/TeamsTab.module.css";
|
||||
import { AvatarWithName } from "../../../components/AvatarWithName";
|
||||
import type { InferQueryOutput } from "../../../utils/trpc-client";
|
||||
import { useUser } from "../../../utils/UserContext";
|
||||
import { useData } from "solid-app-router";
|
||||
|
||||
const sortCaptainFirst = (a: { captain: boolean }, b: { captain: boolean }) => {
|
||||
return Number(b.captain) - Number(a.captain);
|
||||
};
|
||||
|
||||
const sortTeamsFullFirst = (a: { members: any[] }, b: { members: any[] }) => {
|
||||
const aSortValue = a.members.length >= 4 ? 1 : 0;
|
||||
const bSortValue = b.members.length >= 4 ? 1 : 0;
|
||||
const sortOwnTeamsAndFullTeamsFirst =
|
||||
(userId?: number) =>
|
||||
(
|
||||
a: { members: { member: { id: number } }[] },
|
||||
b: { members: { member: { id: number } }[] }
|
||||
) => {
|
||||
if (userId) {
|
||||
const aSortValue = Number(
|
||||
a.members.some(({ member }) => userId === member.id)
|
||||
);
|
||||
const bSortValue = Number(
|
||||
b.members.some(({ member }) => userId === member.id)
|
||||
);
|
||||
|
||||
return bSortValue - aSortValue;
|
||||
};
|
||||
if (aSortValue !== bSortValue) return bSortValue - aSortValue;
|
||||
}
|
||||
|
||||
const aSortValue = a.members.length >= 4 ? 1 : 0;
|
||||
const bSortValue = b.members.length >= 4 ? 1 : 0;
|
||||
|
||||
return bSortValue - aSortValue;
|
||||
};
|
||||
|
||||
export function TeamsTab() {
|
||||
const tournament = useTournamentData(1);
|
||||
const [tournament] = useData<ITournamentData>(1);
|
||||
const user = useUser();
|
||||
|
||||
const sortedTeams = createMemo(() =>
|
||||
tournament()
|
||||
?.teams.sort(sortTeamsFullFirst)
|
||||
?.teams.sort(sortOwnTeamsAndFullTeamsFirst(user()?.id))
|
||||
.map((team) => {
|
||||
return {
|
||||
...team,
|
||||
@@ -29,6 +48,7 @@ export function TeamsTab() {
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: looks kinda bad on mobile
|
||||
return (
|
||||
<div class={s.container}>
|
||||
<Show when={sortedTeams()}>{(teams) => <TeamsList teams={teams} />}</Show>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { NavLink, Outlet } from "solid-app-router";
|
||||
import { NavLink, Outlet, useData } from "solid-app-router";
|
||||
import { InfoBanner } from "./InfoBanner";
|
||||
import s from "../styles/TournamentPage.module.css";
|
||||
import { useTournamentData } from "../TournamentPage.data";
|
||||
import type { ITournamentData } from "../TournamentPage.data";
|
||||
import { Show } from "solid-js";
|
||||
import { ActionSection } from "./ActionSection";
|
||||
|
||||
export default function TournamentsPage() {
|
||||
const tournament = useTournamentData();
|
||||
const [tournament] = useData<ITournamentData>();
|
||||
|
||||
return (
|
||||
<div class={s.container}>
|
||||
|
||||
@@ -12,6 +12,7 @@ export async function findTournamentByNameForUrl({
|
||||
nameForUrl: tournamentNameForUrl.toLowerCase(),
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
description: true,
|
||||
startTime: true,
|
||||
@@ -42,6 +43,7 @@ export async function findTournamentByNameForUrl({
|
||||
captain: true,
|
||||
member: {
|
||||
select: {
|
||||
id: true,
|
||||
discordAvatar: true,
|
||||
discordName: true,
|
||||
discordId: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createTRPCClient } from "@trpc/client";
|
||||
import type { inferProcedureOutput } from "@trpc/server";
|
||||
import type { AppRouter } from "../server";
|
||||
|
||||
// TODO: transformer superjson
|
||||
export const trpcClient = createTRPCClient<AppRouter>({
|
||||
url: `${import.meta.env.VITE_BACKEND_URL}/trpc`,
|
||||
fetch: (input, init) => fetch(input, { ...init, credentials: "include" }),
|
||||
|
||||
Reference in New Issue
Block a user