Skip to content

Commit

Permalink
Merge pull request #161 from h8570rg/develop
Browse files Browse the repository at this point in the history
Prd
  • Loading branch information
h8570rg authored Jun 24, 2024
2 parents e299d53 + cd665f0 commit 3556e80
Show file tree
Hide file tree
Showing 15 changed files with 209 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { redirect } from "next/navigation";
import { z } from "zod";
import { serverServices } from "@/lib/services/server";
import { schema } from "@/lib/utils/schema";
import { matchPlayerInputModalKey } from "../../(routes)/[matchId]/(components)/MatchPlayerInputModal/hooks";

type State = {
errors?: {
Expand Down Expand Up @@ -81,5 +82,6 @@ export async function createMatch(
});

revalidatePath("/matches");
redirect(`/matches/${id}`);
// TODO: refactor
redirect(`/matches/${id}?${matchPlayerInputModalKey}=true`);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use server";

import { revalidatePath } from "next/cache";
import { z } from "zod";
import { serverServices } from "@/lib/services/server";
import { Rule } from "@/lib/type";
Expand Down Expand Up @@ -120,6 +121,8 @@ export async function addGame(
gamePlayers: playerScores,
});

revalidatePath(`/matches/${matchId}`);

return {
success: true,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ModalFooter,
ModalHeader,
} from "@/components/Modal";
import { NAME_MAX_LENGTH } from "@/lib/config";
import { Profile } from "@/lib/type";
import { State, createProfile } from "./actions";

Expand All @@ -24,8 +25,8 @@ export function ProfileCreateModal({
const player = result.data;
if (player) {
onProfileCreate(player);
onClose();
}
onClose();
return result;
},
{},
Expand All @@ -45,7 +46,12 @@ export function ProfileCreateModal({
<ModalHeader>プレイヤー名入力</ModalHeader>
<form action={formAction} noValidate>
<ModalBody>
<Input name="name" errorMessage={state.errors?.name} />
<Input
name="name"
errorMessage={state.errors?.name}
description={`${NAME_MAX_LENGTH}文字以内で入力してください`}
maxLength={NAME_MAX_LENGTH}
/>
</ModalBody>
<ModalFooter>
<Button color="primary" type="submit">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import { revalidatePath } from "next/cache";
import { serverServices } from "@/lib/services/server";
import { Profile } from "@/lib/type";

// 新しいplayerのみ
export async function updateMatchPlayers({
matchId,
playerIds,
}: {
matchId: string;
playerIds: string[];
}) {
const { updateMatchPlayers } = serverServices();
await updateMatchPlayers({ matchId, playerIds });
const { addMatchPlayers } = serverServices();
await addMatchPlayers({ matchId, playerIds });
revalidatePath(`/matches/${matchId}`);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function MatchPlayerInputModalContent({
<>
<ModalHeader>プレイヤー選択</ModalHeader>
<ModalBody>
<div className="flex h-[700px] max-h-[80dvh] flex-col">
<div className="flex h-[700px] max-h-[60dvh] flex-col">
<div className="mb-3 space-y-5">
<Input
placeholder="ユーザーIDもしくは名前で検索"
Expand All @@ -109,7 +109,11 @@ export function MatchPlayerInputModalContent({
key={player.id}
color="primary"
avatar={<Avatar name="" />}
onClose={() => handlePlayersRemove(player)}
onClose={
!players.some((p) => p.id === player.id)
? () => handlePlayersRemove(player)
: undefined
}
>
{player.name}
</Chip>
Expand Down Expand Up @@ -216,7 +220,9 @@ export function MatchPlayerInputModalContent({
setIsPending(true);
await updateMatchPlayers({
matchId,
playerIds: selectedPlayers.map((p) => p.id),
playerIds: selectedPlayers
.map((p) => p.id)
.filter((p) => !players.some((p2) => p2.id === p)),
});
setIsPending(false);
onClose();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useQueryControlledModal } from "@/components/Modal";

export const matchPlayerInputModalKey = "player-input";

export const useMatchPlayerInputModal = () => {
return useQueryControlledModal("player-input");
return useQueryControlledModal(matchPlayerInputModalKey);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@ import { Button } from "@/components/Button";
import { Icon } from "@/components/Icon";
import { useGameInputModal } from "../../../GameInputModal/hooks";

export function AddGameButton({ isDisabled }: { isDisabled: boolean }) {
export function AddGameButton({ isPlayersShort }: { isPlayersShort: boolean }) {
const gameInputModal = useGameInputModal();

function handleClick() {
if (isPlayersShort) {
alert("プレイヤーが足りません");
return;
}
gameInputModal.onOpen();
}

return (
<Button
fullWidth
size="lg"
onClick={gameInputModal.onOpen}
isDisabled={isDisabled}
onClick={handleClick}
startContent={<Icon className="size-5" name="edit" />}
variant="ghost"
>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";

import { useMatchPlayerInputModal } from "../../../MatchPlayerInputModal/hooks";

export function MatchPlayerInputButton(
props: React.ComponentPropsWithoutRef<"button">,
) {
const gameInputModal = useMatchPlayerInputModal();

return <button onClick={gameInputModal.onOpen} {...props}></button>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { serverServices } from "@/lib/services/server";
import { MatchPlayer } from "@/lib/type";
import { AddGameButton } from "./(components)/AddGameButton";
import { ChipInputButton } from "./(components)/ChipInputButton";
import { MatchPlayerInputButton } from "./(components)/MatchPlayerInputButton";
import styles from "./styles.module.css";

type Column = {
Expand Down Expand Up @@ -64,7 +65,7 @@ export async function MatchTable({

return (
<div className={classNames(className, "flex flex-col")}>
<div
<MatchPlayerInputButton
className={classNames(
styles["row"],
"flex items-center rounded-lg bg-default-100 text-foreground-500",
Expand All @@ -87,38 +88,45 @@ export async function MatchTable({
)}
</div>
))}
</div>
</MatchPlayerInputButton>
<div className="grow">
{gameRows.map((item, index) => (
<div
className={classNames(styles["row"], "flex items-center py-1")}
key={index}
>
<div
className={classNames(
styles["col"],
styles["col--index"],
styles["col--body"],
)}
>
{index + 1}
</div>
{columns.map((column) => (
<div
key={column.id}
className={classNames(styles["col"], styles["col--body"], {
"text-danger": item[column.id] < 0,
})}
{gameRows.length === 0 && (
<p className="my-10 text-center text-small text-foreground-light">
まだデータはありません
</p>
)}
{gameRows.length > 0 && (
<ol className="py-1">
{gameRows.map((item, index) => (
<li
className={classNames(styles["row"], "flex items-center")}
key={index}
>
{item[column.id]}
</div>
<div
className={classNames(
styles["col"],
styles["col--index"],
styles["col--body"],
)}
>
{index + 1}
</div>
{columns.map((column) => (
<div
key={column.id}
className={classNames(styles["col"], styles["col--body"], {
"text-danger": item[column.id] < 0,
})}
>
{item[column.id]}
</div>
))}
</li>
))}
</div>
))}
</ol>
)}
<div>
{/* TODO: disabledやめる */}
<AddGameButton isDisabled={isPlayersShort} />
{/* <AddChipButton isDisabled={isPlayersShort} /> */}
<AddGameButton isPlayersShort={isPlayersShort} />
</div>
</div>
<div className="rounded-lg bg-default-100 text-foreground-500">
Expand Down Expand Up @@ -159,6 +167,7 @@ export async function MatchTable({
key={column.id}
>
{column.chipCount}
{column.chipCount !== null && <span></span>}
</div>
))}
</ChipInputButton>
Expand All @@ -178,6 +187,7 @@ export async function MatchTable({
key={column.id}
>
{column.result}
<span></span>
</div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use client";

import { forwardRef } from "react";
import {
Modal,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader,
useQueryControlledModal,
} from "@/components/Modal";
import { calcMethodLabel, chipRateLabel, rateLabel } from "@/lib/config";
import { Rule } from "@/lib/type";

export const useRuleModal = () => {
return useQueryControlledModal("rule");
};

export function RuleModal({ rule }: { rule: Rule }) {
const { isOpen, onClose } = useRuleModal();

return (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalContent>
<ModalHeader>ルール</ModalHeader>
<ModalBody>
<table className="table-fixed border-separate border-spacing-y-1">
<tbody className="[&_td]:text-center">
<tr>
<th>プレイ人数</th>
<td>{rule.playersCount}</td>
</tr>
<tr>
<th>レート</th>
<td>{rateLabel[rule.rate]}</td>
</tr>
<tr>
<th>チップ</th>
<td>{chipRateLabel[rule.chipRate]}</td>
</tr>
<tr>
<th>ウマ</th>
<td className="space-x-4">
<span>{rule.incline.incline1}</span>
<span>{rule.incline.incline2}</span>
<span>{rule.incline.incline3}</span>
{rule.playersCount === 4 && (
<span>{rule.incline.incline4}</span>
)}
</td>
</tr>
<tr>
<th>飛び賞</th>
<td>{rule.crackBoxBonus}</td>
</tr>
<tr>
<th>持ち点</th>
<td>{rule.defaultPoints}</td>
</tr>
<tr>
<th>オカ</th>
<td>{rule.defaultCalcPoints}</td>
</tr>
<tr>
<th>計算</th>
<td>{calcMethodLabel[rule.calcMethod]}</td>
</tr>
</tbody>
</table>
</ModalBody>
{/* スペーサーとして */}
<ModalFooter />
</ModalContent>
</Modal>
);
}

export const RuleModalTrigger = forwardRef<
HTMLButtonElement,
React.ComponentPropsWithoutRef<"button">
>(function RuleModalTrigger({ onClick, ...props }, ref) {
const ruleModal = useRuleModal();
return (
<button
ref={ref}
onClick={(e) => {
ruleModal.onOpen();
onClick?.(e);
}}
{...props}
/>
);
});
Loading

0 comments on commit 3556e80

Please sign in to comment.