Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: modal v2 and update home page modal #419

Merged
merged 27 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5ad532a
chore: rename effect-new-2 to frosted-shadow-box
JohnsonMao Oct 27, 2024
1f68254
refactor: box fancy
JohnsonMao Oct 27, 2024
4619a4c
feat: button add icon size
JohnsonMao Oct 27, 2024
2962eb2
refactor: header icon and button
JohnsonMao Oct 27, 2024
1b0d71b
test: update border width case
JohnsonMao Oct 28, 2024
ca696f8
feat: Modal component
JohnsonMao Oct 28, 2024
56040c1
chore: modify modal size and create room modal title
JohnsonMao Oct 29, 2024
6febfb1
feat: update input component
JohnsonMao Oct 30, 2024
8a09703
feat(common): add select box group component
JohnsonMao Oct 31, 2024
4dbedfe
refactor(common): carousel style
JohnsonMao Oct 31, 2024
f5f9d92
fix(common): box fancy pseudo element cover bug
JohnsonMao Oct 31, 2024
6fa6d26
feat(common): add input OTP component
JohnsonMao Nov 1, 2024
c2c0dea
fix(input): clicking on the input edge is unresponsive
JohnsonMao Nov 1, 2024
4139c05
feat(modal): luck body scroll when modal is open
JohnsonMao Nov 1, 2024
b7ae8b3
feat(Cover): handle error to display fallback image
JohnsonMao Nov 2, 2024
69cb81b
chore: modify style, fix typo and Image to Cover
JohnsonMao Nov 2, 2024
a08e440
feat(user): add user info form
JohnsonMao Nov 2, 2024
1a37039
feat(room): add create room form
JohnsonMao Nov 2, 2024
1a97dad
feat(room): add game room action buttons
JohnsonMao Nov 2, 2024
be46eb8
feat(game): add game card simple and detailed
JohnsonMao Nov 2, 2024
acb4495
feat(InputOTP): add ref support for external focus control
JohnsonMao Nov 2, 2024
85ce81b
refactor: change to features
JohnsonMao Nov 2, 2024
d0a3f8b
chore: search bar send alert
JohnsonMao Nov 2, 2024
6d3db27
fix: loop join room bug
JohnsonMao Nov 2, 2024
ed44add
chore: i18n
JohnsonMao Nov 2, 2024
00fa281
fix: sonar cloud issue
JohnsonMao Nov 2, 2024
3dece29
feat(Modal): add keyboard event handler
JohnsonMao Nov 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(room): add create room form
  • Loading branch information
JohnsonMao committed Nov 2, 2024
commit 1a3703977985eb918281174f39c4b5bd8d38d359
169 changes: 169 additions & 0 deletions features/room/components/CreateRoomForm/CreateRoomForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { useState, FormEvent, useRef, useEffect } from "react";
import { useRouter } from "next/router";
import useRequest from "@/hooks/useRequest";
import Button from "@/components/shared/Button/v2";
import Input from "@/components/shared/Input";
import InputOTP, { InputOTPRef } from "@/components/shared/InputOTP";
import Icon from "@/components/shared/Icon";
import SelectBoxGroup from "@/components/shared/SelectBoxGroup";
import { createRoomEndpoint, CreateRoomFormType } from "@/requests/rooms";

const items = [
{
key: "Public",
label: (
<div className="px-2 py-1 flex gap-2.5 items-center justify-center whitespace-nowrap">
<Icon name="House" className="w-8 h-8" />
公開房間
</div>
),
value: false,
},
{
key: "Private",
label: (
<div className="px-2 py-1 flex gap-2.5 items-center justify-center whitespace-nowrap">
<Icon name="HouseLock" className="w-8 h-8" />
私人房間
</div>
),
value: true,
},
];

interface CreateRoomFormProps {
gameId: string;
minPlayers: number;
maxPlayers: number;
onCancel: () => void;
}

type CreateRoomFormErrors = Partial<Record<keyof CreateRoomFormType, string>>;

function CreateRoomForm({
gameId,
minPlayers,
maxPlayers,
onCancel,
}: Readonly<CreateRoomFormProps>) {
const [roomForm, setRoomForm] = useState<CreateRoomFormType>({
name: "",
gameId,
minPlayers,
maxPlayers,
password: "",
});
const { fetch } = useRequest();
const router = useRouter();
const [isLockRoom, setIsLockRoom] = useState(false);
const passwordInputRef = useRef<InputOTPRef>(null);
const gameNameInputRef = useRef<HTMLInputElement>(null);
const [errors, setErrors] = useState<CreateRoomFormErrors>({});

const handleChange =
<T extends keyof CreateRoomFormType>(key: T) =>
(value: CreateRoomFormType[T]) => {
setRoomForm((pre) => ({
...pre,
[key]: value,
}));
};

const handleSubmit = async (event: FormEvent) => {
event.preventDefault();
setErrors({});

const newErrors: CreateRoomFormErrors = {};

if (isLockRoom && roomForm.password?.length !== 4) {
passwordInputRef.current?.focus();
newErrors.password = "請輸入遊戲密碼";
}
if (!roomForm.name) {
gameNameInputRef.current?.focus();
newErrors.name = "請輸入房間名稱";
}

if (Object.keys(newErrors).length) {
setErrors(newErrors);
return;
}

const result = await fetch(createRoomEndpoint(roomForm));
router.push(`/rooms/${result.id}`);
};

useEffect(() => {
if (isLockRoom) {
passwordInputRef.current?.focus();
} else {
setRoomForm((pre) => ({
...pre,
password: "",
}));
}
}, [isLockRoom]);

return (
<form onSubmit={handleSubmit}>
<div className="mb-8 flex flex-col gap-4">
<Input
ref={gameNameInputRef}
label="房間名稱"
placeholder="為你的房間取一個名字"
inputWrapperClassName="w-full"
onChange={handleChange("name")}
hintText={errors.name}
error={!!errors.name}
value={roomForm.name}
autoFocus
/>
<div>
<div className="mb-1 text-sm font-medium text-primary-200">
房間人數
</div>
<div className="mb-1 text-sm font-medium text-primary-300">
{minPlayers}-{maxPlayers}人
</div>
</div>
<SelectBoxGroup
label="房間類型"
items={items}
labelClassName="text-sm"
itemWrapperClassName="flex"
itemClassName="grow"
value={isLockRoom}
onChange={setIsLockRoom}
/>
{isLockRoom && (
<InputOTP
ref={passwordInputRef}
label="房間密碼"
labelClassName="text-sm"
hintText={errors.password}
error={!!errors.password}
value={roomForm.password}
onChange={handleChange("password")}
length={4}
/>
)}
</div>
<footer className="flex justify-center gap-6">
<Button
type="button"
variant="secondary"
onClick={onCancel}
className="w-36 py-2.5"
>
關閉
</Button>
<Button type="submit" className="flex w-36 py-2.5">
<Icon name="Gamepad" className="w-6 h-6" />
即刻遊戲
</Button>
</footer>
</form>
);
}

export default CreateRoomForm;
1 change: 1 addition & 0 deletions features/room/components/CreateRoomForm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./CreateRoomForm";
1 change: 1 addition & 0 deletions features/room/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as CreateRoomModal } from "./components/CreateRoomForm";