Skip to content

Commit

Permalink
Merge pull request #197 from boostcampwm-2024/feature/#194
Browse files Browse the repository at this point in the history
[Feat] 게슀트 λ‘œκ·ΈμΈμ—μ„œμ˜ λ‹‰λ„€μž„ μ„€μ • κ΅¬ν˜„
  • Loading branch information
mssak authored Nov 28, 2024
2 parents 09bd7e8 + 4a46ebb commit de9205f
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 19 deletions.
6 changes: 4 additions & 2 deletions packages/frontend/src/apis/login.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import instance from '@/apis/instance';

export async function postGuestLogin() {
const { data } = await instance.get('/auth/guest-login');
export async function getGuestLogin(userId: string) {
const { data } = await instance.get(`/auth/guest-login`, {
params: { userId },
});
return data;
}
53 changes: 36 additions & 17 deletions packages/frontend/src/components/landingPage/GuestLoginButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useState } from 'react';
import Button from '@/components/common/Button';
import NicknameModal from './NicknameModal';
import { useNavigate } from 'react-router-dom';
import { postGuestLogin } from '@/apis/login';
import { getGuestLogin } from '@/apis/login';
import { useAuthStore } from '@/states/store/authStore';
import { useSocketStore } from '@/states/store/socketStore';
import { useSignalingSocketStore } from '@/states/store/signalingSocketStore';
Expand All @@ -10,31 +12,48 @@ export default function GuestLoginButton() {
const { setUserData } = useAuthStore();
const { connectSocket } = useSocketStore();
const { connectSignalingSocket } = useSignalingSocketStore();
const [showModal, setShowModal] = useState(false);

async function handleClick() {
try {
localStorage.removeItem('auth-storage');
localStorage.removeItem('room-storage');
localStorage.removeItem('lobbyPageVisited');
localStorage.removeItem('roomCreateTooltipShown');
localStorage.removeItem('modalTooltipShown');
localStorage.removeItem('gamePageVisited');
const clearLocalStorage = () => {
[
'auth-storage',
'room-storage',
'lobbyPageVisited',
'roomCreateTooltipShown',
'modalTooltipShown',
'gamePageVisited',
].forEach((key) => localStorage.removeItem(key));
};

const { userId, password } = await postGuestLogin();
const handleLogin = async (nickname: string) => {
try {
clearLocalStorage();
const { userId, password } = await getGuestLogin(nickname);
await connectSocket(userId, password);
await connectSignalingSocket(userId);
setUserData(userId, password);
navigate('/lobby');
} catch (error) {
console.error('Guest login failed:', error);
console.error('게슀트 λ‘œκ·ΈμΈμ— μ‹€νŒ¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.', error);
}
}
};

return (
<Button
className="text-xl font-semibold text-black bg-white hover:bg-gray-300"
onClick={handleClick}
buttonText="λΉ„νšŒμ›μœΌλ‘œ μ‹œμž‘ν•˜κΈ°"
/>
<>
<Button
className="text-xl font-semibold text-black bg-white hover:bg-gray-300"
onClick={() => setShowModal(true)}
buttonText="λΉ„νšŒμ›μœΌλ‘œ μ‹œμž‘ν•˜κΈ°"
/>
{showModal && (
<NicknameModal
onConfirm={(nickname) => {
setShowModal(false);
handleLogin(nickname);
}}
onClose={() => setShowModal(false)}
/>
)}
</>
);
}
72 changes: 72 additions & 0 deletions packages/frontend/src/components/landingPage/NicknameModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import ReactDOM from 'react-dom';
import { useState, useEffect, useRef } from 'react';

interface INicknameModalProps {
onConfirm: (nickname: string) => void;
onClose: () => void;
}

export default function NicknameModal({ onConfirm, onClose }: INicknameModalProps) {
const [nickname, setNickname] = useState('');
const [errorMessage, setErrorMessage] = useState('');
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);

const handleConfirm = async () => {
if (nickname.trim().length < 2 || nickname.trim().length > 10) {
setErrorMessage('λ‹‰λ„€μž„μ€ 2자 이상 10자 μ΄ν•˜λ‘œ μž…λ ₯ν•΄μ£Όμ„Έμš”.');
return;
}

setErrorMessage('');
try {
await onConfirm(nickname.trim());
} catch (error) {
setErrorMessage('λ‹‰λ„€μž„ μ„€μ • 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.');
}
};

const handleClose = () => {
setNickname('');
onClose();
};

return ReactDOM.createPortal(
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
<div className="max-w-lg p-8 bg-white shadow-lg rounded-2xl w-96">
<h2 className="mb-4 text-xl font-semibold text-center text-gray-900">λ‹‰λ„€μž„ μ„€μ •</h2>
<input
ref={inputRef}
type="text"
aria-label="λ‹‰λ„€μž„ μž…λ ₯"
placeholder="λ‹‰λ„€μž„μ„ μž…λ ₯ν•˜μ„Έμš”"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
className="w-full py-2 mb-2 text-left text-gray-700 placeholder-gray-500 border-b-2 focus:outline-none"
/>
{errorMessage && <p className="mb-4 text-sm text-red-500">{errorMessage}</p>}
<div className="flex justify-center gap-4 mt-4">
<button
onClick={handleClose}
className="w-32 py-2 text-black border border-black rounded-lg hover:bg-gray-100"
aria-label="λ‹‰λ„€μž„ μ„€μ • μ·¨μ†Œ"
>
μ·¨μ†Œ
</button>
<button
onClick={handleConfirm}
className="w-32 py-2 bg-black rounded-lg text-white-default hover:bg-gray-800"
>
확인
</button>
</div>
</div>
</div>,
document.getElementById('portal-root') as HTMLElement,
);
}

0 comments on commit de9205f

Please sign in to comment.