Skip to content

Commit

Permalink
add mode selector
Browse files Browse the repository at this point in the history
  • Loading branch information
minhd-vu committed Feb 28, 2024
1 parent 4fb3636 commit 9628130
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 23 deletions.
50 changes: 50 additions & 0 deletions app/api/party/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,53 @@ export async function POST() {

return Response.json(res);
}

type PartyPatchBody = {
mode?: Mode;
};

export async function PATCH(req: Request) {
const session = await getServerSession();
if (!session?.user?.email) {
return Response.json("User is not authenticated", { status: 401 });
}

const user = await prisma.user.findUniqueOrThrow({
where: {
email: session.user.email,
},
include: {
party: true,
},
});

if (!user.party) {
return Response.json("User is not in a party", {
status: 400,
});
}

if (user.party.adminId !== user.id) {
return Response.json("User must be the admin to adjust party settings", {
status: 403,
});
}

const body: PartyPatchBody = await req.json();
if (!body.mode) {
return Response.json("Party mode is required", {
status: 400,
});
}

const party = await prisma.party.update({
where: {
id: user.party.id,
},
data: {
mode: body.mode,
},
});

return Response.json(party);
}
6 changes: 3 additions & 3 deletions components/JoinParty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ export default function JoinParty() {
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M4 5h2" />
Expand Down
6 changes: 3 additions & 3 deletions components/NameForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export default function NameForm() {
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" />
Expand Down
7 changes: 6 additions & 1 deletion components/Party.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
StartGame,
StopGame,
} from "./Button";
import SelectMode from "./SelectMode";

export default function Party() {
const fetcher: Fetcher<User, string> = (url) =>
Expand Down Expand Up @@ -119,7 +120,11 @@ export default function Party() {
return (
<PartyCard code={party.code}>
{party.winner && <h2>{`Last Round's Winner: ${party.winner.name}`}</h2>}
<h2>Mode: {_.startCase(_.toLower(party.mode))}</h2>
{isAdmin ? (
<SelectMode mode={party.mode} />
) : (
<h2>Mode: {_.startCase(_.toLower(party.mode))}</h2>
)}
{!isAdmin && (
<p className="text-sm italic">
Waiting for party leader to start the party{" "}
Expand Down
12 changes: 6 additions & 6 deletions components/PartyCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ export default function PartyCard({
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z" />
Expand All @@ -47,11 +47,11 @@ export default function PartyCard({
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z" />
Expand Down
20 changes: 10 additions & 10 deletions components/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ export function AdminIcon() {
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 6l4 6l5 -4l-2 10h-14l-2 -10l5 4z" fill="currentColor" />
Expand All @@ -35,16 +35,16 @@ export function AliveIcon() {
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M6.979 3.074a6 6 0 0 1 4.988 1.425l.037 .033l.034 -.03a6 6 0 0 1 4.733 -1.44l.246 .036a6 6 0 0 1 3.364 10.008l-.18 .185l-.048 .041l-7.45 7.379a1 1 0 0 1 -1.313 .082l-.094 -.082l-7.493 -7.422a6 6 0 0 1 3.176 -10.215z"
stroke-width="0"
strokeWidth="0"
fill="currentColor"
/>
</svg>
Expand All @@ -61,11 +61,11 @@ export function DeadIcon() {
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="1.5"
strokeWidth="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 4c4.418 0 8 3.358 8 7.5c0 1.901 -.755 3.637 -2 4.96l0 2.54a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1 -1v-2.54c-1.245 -1.322 -2 -3.058 -2 -4.96c0 -4.142 3.582 -7.5 8 -7.5z" />
Expand Down
76 changes: 76 additions & 0 deletions components/SelectMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use client";

import { Mode } from "@prisma/client";
import { useContext, useState } from "react";
import { ErrorContext } from "./App";
import { useSWRConfig } from "swr";

export default function SelectMode({ mode }: { mode: Mode }) {
const modes = Object.values(Mode);
const { setError } = useContext(ErrorContext);
const { mutate } = useSWRConfig();
const [isLoading, setLoading] = useState(
Object.fromEntries(Object.values(Mode).map((m) => [m, false])),
);

async function onClick(e: Mode) {
setLoading((prev) => ({ ...prev, [e]: true }));

const res = await fetch("/api/party", {
method: "PATCH",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ mode: e }),
});

setLoading((prev) => ({ ...prev, [e]: false }));

if (!res.ok) {
setError(await res.json());
return;
}

mutate("/api/user");
}

return (
<div className="flex flex-row items-baseline space-x-1">
<span>Mode:</span>
<div className="dropdown dropdown-start">
<div tabIndex={0} role="button" className="btn btn-ghost btn-sm">
{mode}
<svg
width="12px"
height="12px"
className="h-2 w-2 fill-current opacity-60 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 2048 2048"
>
<path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"></path>
</svg>
</div>
<ul
tabIndex={0}
className="dropdown-content z-[1] p-2 shadow-2xl bg-base-300 rounded-box my-1"
>
{modes.map((e) => (
<li key={e}>
<button
className={`btn btn-sm btn-block ${mode === e ? "btn-primary" : "btn-ghost"}`}
onClick={() => onClick(e)}
>
<span className={isLoading[e] ? "invisible" : "visible"}>
{e}
</span>
{isLoading[e] && (
<span className="loading loading-spinner loading-xs absolute text-center" />
)}
</button>
</li>
))}
</ul>
</div>
</div>
);
}

0 comments on commit 9628130

Please sign in to comment.