From 3942f6f2834d6081a05d380fbf5fdc2c412048a0 Mon Sep 17 00:00:00 2001 From: minhd-vu Date: Tue, 27 Feb 2024 20:54:48 -0500 Subject: [PATCH] add spinners when loading --- components/Button.tsx | 117 +++++++++++++++++++++++++++++++++++ components/ConfirmKill.tsx | 29 --------- components/CreateParty.tsx | 25 -------- components/DenyKill.tsx | 29 --------- components/JoinParty.tsx | 14 ++++- components/KickPlayer.tsx | 34 +++------- components/KillTarget.tsx | 38 ------------ components/LeaveParty.tsx | 30 --------- components/NameForm.tsx | 12 +++- components/Party.tsx | 24 +++---- components/PromotePlayer.tsx | 34 +++------- components/Spinner.tsx | 3 - components/StartGame.tsx | 29 --------- components/StopGame.tsx | 29 --------- 14 files changed, 168 insertions(+), 279 deletions(-) create mode 100644 components/Button.tsx delete mode 100644 components/ConfirmKill.tsx delete mode 100644 components/CreateParty.tsx delete mode 100644 components/DenyKill.tsx delete mode 100644 components/KillTarget.tsx delete mode 100644 components/LeaveParty.tsx delete mode 100644 components/Spinner.tsx delete mode 100644 components/StartGame.tsx delete mode 100644 components/StopGame.tsx diff --git a/components/Button.tsx b/components/Button.tsx new file mode 100644 index 0000000..2ccf0d5 --- /dev/null +++ b/components/Button.tsx @@ -0,0 +1,117 @@ +import { ReactNode, useContext, useState } from "react"; +import { useSWRConfig } from "swr"; +import { ErrorContext } from "./App"; + +export function Button({ + route, + children, + className, + body, + spinnerSize = "sm", +}: { + route: string; + children: ReactNode; + className?: string; + body?: string; + spinnerSize?: string; +}) { + "use client"; + + const [isLoading, setLoading] = useState(false); + const { mutate } = useSWRConfig(); + const { setError } = useContext(ErrorContext); + + async function onClick() { + setLoading(true); + + const res = await fetch(route, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body, + }); + + if (!res.ok) { + setError(await res.json()); + setLoading(false); + return; + } + + mutate("/api/user"); + } + + return ( + + ); +} + +export function ConfirmKill() { + return ( + + ); +} + +export function CreateParty() { + return ( + + ); +} + +export function DenyKill() { + return ( + + ); +} + +export function KillTarget({ pending }: { pending: boolean }) { + if (pending) { + return ( + + ); + } + + return ( + + ); +} + +export function LeaveParty() { + return ( + + ); +} + +export function StartGame() { + return ( + + ); +} + +export function StopGame() { + return ( + + ); +} diff --git a/components/ConfirmKill.tsx b/components/ConfirmKill.tsx deleted file mode 100644 index edf99ed..0000000 --- a/components/ConfirmKill.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { useContext } from "react"; -import { useSWRConfig } from "swr"; -import { ErrorContext } from "./App"; - -export default function ConfirmKill() { - const { mutate } = useSWRConfig(); - const { setError } = useContext(ErrorContext); - - async function onClick() { - const res = await fetch("/api/kill/confirm", { - method: "POST", - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - - return ( - - ); -} diff --git a/components/CreateParty.tsx b/components/CreateParty.tsx deleted file mode 100644 index bf6953c..0000000 --- a/components/CreateParty.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; - -import { useSWRConfig } from "swr"; - -export default function CreateParty() { - const { mutate } = useSWRConfig(); - - async function onClick() { - const res = await fetch("/api/party", { - method: "POST", - }); - - if (!res.ok) { - throw new Error(await res.json()); - } - - mutate("/api/user"); - } - - return ( - - ); -} diff --git a/components/DenyKill.tsx b/components/DenyKill.tsx deleted file mode 100644 index 48b7ba8..0000000 --- a/components/DenyKill.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { useContext } from "react"; -import { useSWRConfig } from "swr"; -import { ErrorContext } from "./App"; - -export default function DenyKill() { - const { mutate } = useSWRConfig(); - const { setError } = useContext(ErrorContext); - - async function onClick() { - const res = await fetch("/api/kill/deny", { - method: "POST", - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - - return ( - - ); -} diff --git a/components/JoinParty.tsx b/components/JoinParty.tsx index 36fae79..43cbc34 100644 --- a/components/JoinParty.tsx +++ b/components/JoinParty.tsx @@ -4,8 +4,10 @@ import { Controller, SubmitHandler, useForm } from "react-hook-form"; import { useSWRConfig } from "swr"; import { PartyJoinBody } from "@/lib/party"; import { toSentence } from "./Alert"; +import { useState } from "react"; export default function JoinParty() { + const [isLoading, setLoading] = useState(false); const { mutate } = useSWRConfig(); const { handleSubmit, @@ -15,6 +17,8 @@ export default function JoinParty() { } = useForm(); const onSubmit: SubmitHandler = async ({ code }) => { + setLoading(true); + const res = await fetch("/api/party/join", { method: "POST", headers: { @@ -25,6 +29,7 @@ export default function JoinParty() { if (!res.ok) { setError("code", { message: await res.json() }); + setLoading(false); return; } @@ -73,7 +78,14 @@ export default function JoinParty() { )} /> - +

{toSentence(errors.code?.message)} diff --git a/components/KickPlayer.tsx b/components/KickPlayer.tsx index 662add6..733406e 100644 --- a/components/KickPlayer.tsx +++ b/components/KickPlayer.tsx @@ -1,34 +1,14 @@ "use client"; -import { useContext } from "react"; -import { useSWRConfig } from "swr"; -import { ErrorContext } from "./App"; +import { Button } from "./Button"; export default function KickPlayer({ playerId }: { playerId: string }) { - const { setError } = useContext(ErrorContext); - const { mutate } = useSWRConfig(); - - async function onClick() { - const res = await fetch("/api/party/kick", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ playerId }), - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - return ( - + ); } diff --git a/components/KillTarget.tsx b/components/KillTarget.tsx deleted file mode 100644 index 8378274..0000000 --- a/components/KillTarget.tsx +++ /dev/null @@ -1,38 +0,0 @@ -"use client"; - -import { useContext } from "react"; -import { useSWRConfig } from "swr"; -import { ErrorContext } from "./App"; - -export default function KillTarget({ pending }: { pending: boolean }) { - const { mutate } = useSWRConfig(); - const { setError } = useContext(ErrorContext); - - async function onClick() { - const res = await fetch("/api/kill", { - method: "POST", - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - - if (pending) { - return ( - - ); - } - - return ( - - ); -} diff --git a/components/LeaveParty.tsx b/components/LeaveParty.tsx deleted file mode 100644 index e7aa626..0000000 --- a/components/LeaveParty.tsx +++ /dev/null @@ -1,30 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { useSWRConfig } from "swr"; - -export default function LeaveParty() { - const [isLoading, setLoading] = useState(false); - const { mutate } = useSWRConfig(); - - async function onClick() { - setLoading(true); - - const res = await fetch("/api/party/leave", { - method: "POST", - }); - - if (!res.ok) { - throw new Error(await res.json()); - } - - mutate("/api/user"); - } - - return ( - - ); -} diff --git a/components/NameForm.tsx b/components/NameForm.tsx index fb49eaf..cac5953 100644 --- a/components/NameForm.tsx +++ b/components/NameForm.tsx @@ -4,8 +4,10 @@ import { Controller, SubmitHandler, useForm } from "react-hook-form"; import { useSWRConfig } from "swr"; import { UserBody } from "@/lib/user"; import { toSentence } from "./Alert"; +import { useState } from "react"; export default function NameForm() { + const [isLoading, setLoading] = useState(false); const { mutate } = useSWRConfig(); const { handleSubmit, @@ -15,6 +17,8 @@ export default function NameForm() { } = useForm(); const onSubmit: SubmitHandler = async ({ name }) => { + setLoading(true); + const res = await fetch("/api/user", { method: "POST", headers: { @@ -25,6 +29,7 @@ export default function NameForm() { if (!res.ok) { setError("name", { message: await res.json() }); + setLoading(false); return; } @@ -65,7 +70,12 @@ export default function NameForm() { )} /> - +

{toSentence(errors.name?.message)}

diff --git a/components/Party.tsx b/components/Party.tsx index 6115517..8c0f622 100644 --- a/components/Party.tsx +++ b/components/Party.tsx @@ -1,23 +1,24 @@ "use client"; import _ from "lodash"; -import LeaveParty from "./LeaveParty"; -import CreateParty from "./CreateParty"; import JoinParty from "./JoinParty"; -import StartGame from "./StartGame"; import { Party } from "@prisma/client"; import useSWR, { Fetcher } from "swr"; -import Spinner from "./Spinner"; -import StopGame from "./StopGame"; -import KillTarget from "./KillTarget"; import PartyCard from "./PartyCard"; import { User } from "@/lib/user"; -import ConfirmKill from "./ConfirmKill"; -import DenyKill from "./DenyKill"; import Player from "./Player"; import NameForm from "./NameForm"; import { useContext } from "react"; import { ErrorContext } from "./App"; +import { + ConfirmKill, + CreateParty, + DenyKill, + KillTarget, + LeaveParty, + StartGame, + StopGame, +} from "./Button"; export default function Party() { const fetcher: Fetcher = (url) => @@ -29,7 +30,7 @@ export default function Party() { }); if (isLoading) { - return ; + return ; } if (error) { @@ -120,8 +121,9 @@ export default function Party() { {party.winner &&

{`Last Round's Winner: ${party.winner.name}`}

}

Mode: {_.startCase(_.toLower(party.mode))}

{!isAdmin && ( -

- Waiting for party leader to start the party... +

+ Waiting for party leader to start the party{" "} +

)}

Players:

diff --git a/components/PromotePlayer.tsx b/components/PromotePlayer.tsx index c2cf608..a8406b1 100644 --- a/components/PromotePlayer.tsx +++ b/components/PromotePlayer.tsx @@ -1,34 +1,14 @@ "use client"; -import { useContext } from "react"; -import { useSWRConfig } from "swr"; -import { ErrorContext } from "./App"; +import { Button } from "./Button"; export default function PromotePlayer({ playerId }: { playerId: string }) { - const { mutate } = useSWRConfig(); - const { setError } = useContext(ErrorContext); - - async function onClick() { - const res = await fetch("/api/party/promote", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ playerId }), - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - return ( - + ); } diff --git a/components/Spinner.tsx b/components/Spinner.tsx deleted file mode 100644 index 4355233..0000000 --- a/components/Spinner.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Spinner() { - return ; -} diff --git a/components/StartGame.tsx b/components/StartGame.tsx deleted file mode 100644 index d79809e..0000000 --- a/components/StartGame.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { useContext } from "react"; -import { ErrorContext } from "./App"; -import { useSWRConfig } from "swr"; - -export default function StartGame() { - const { setError } = useContext(ErrorContext); - const { mutate } = useSWRConfig(); - - async function onClick() { - const res = await fetch("/api/party/start", { - method: "POST", - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - - return ( - - ); -} diff --git a/components/StopGame.tsx b/components/StopGame.tsx deleted file mode 100644 index 76b51fa..0000000 --- a/components/StopGame.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { useContext } from "react"; -import { useSWRConfig } from "swr"; -import { ErrorContext } from "./App"; - -export default function StopGame() { - const { setError } = useContext(ErrorContext); - const { mutate } = useSWRConfig(); - - async function onClick() { - const res = await fetch("/api/party/stop", { - method: "POST", - }); - - if (!res.ok) { - setError(await res.json()); - return; - } - - mutate("/api/user"); - } - - return ( - - ); -}