Conversation
- redirect , signup
- 임시 확인 용도
Summary of ChangesHello @aaaaaattt, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 관리자 OAuth 로그인 및 등록 기능을 도입합니다. 카카오 로그인 리다이렉트를 처리하고, 데이터베이스에 등록되지 않은 관리자를 위한 전용 회원가입 페이지를 제공하는 새로운 라우트를 설정합니다. 이러한 변경 사항은 관리자 로그인 프로세스를 간소화하고 새로운 관리자를 위한 등록 경로를 제공하는 것을 목표로 합니다. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdded Kakao OAuth initiation and callback handling, introduced an admin signup page with form, styles, types, and API helper, and updated routes and route constants to include callback and signup keys. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant LoginBtn as LoginButton
participant KakaoAuth as Kakao OAuth
participant Callback as KakaoCallback
participant Backend as Backend (/auth/kakao/login)
User->>LoginBtn: Click "카카오 로그인"
LoginBtn->>KakaoAuth: Redirect (client_id, redirect_uri, response_type=code)
KakaoAuth-->>User: Authenticate & consent
KakaoAuth->>Callback: Redirect to /login/redirect?code=...
Callback->>Callback: Extract authorizationCode
Callback->>Backend: POST { authorizationCode }
Backend-->>Callback: Response (user status / tokens)
Callback-->>User: Show LoadingSpinner (token/navigation handling placeholder)
sequenceDiagram
autonumber
actor User
participant SignupPage as AdminSignupPage
participant Form as SignupForm
participant API as Backend (/auth/register)
User->>SignupPage: Open /signup
SignupPage->>Form: Render form
User->>Form: Fill fields & Submit
Form->>API: POST signup JSON
API-->>Form: 200 OK / Error
alt Success
Form-->>User: Show success toast
Form->>SignupPage: navigate('/login') after delay
else Error
Form-->>User: Show error toast
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧬 Code graph analysis (1)src/pages/admin/Signup/components/SignupForm/index.tsx (5)
🔇 Additional comments (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
이번 PR은 관리자 OAuth 로그인 및 회원가입 기능 추가에 대한 내용이네요. 전반적으로 기능 구현의 골격은 잘 잡혀있지만, 몇 가지 개선이 필요한 부분이 보입니다. 특히 KakaoCallback 컴포넌트의 하드코딩된 URL과 에러 처리, SignupForm의 비동기 처리 로직 오류 등은 반드시 수정이 필요합니다. 또한, 코드 일관성과 잠재적 버그를 방지하기 위한 몇 가지 제안 사항들을 포함했습니다. 아래의 상세 리뷰를 확인해주세요.
| const onSubmit = async (signupFormValue: SignupFormInputs) => { | ||
| try { | ||
| console.log('회원가입 data:', signupFormValue); | ||
| postSignupForm(signupFormValue) | ||
| .then(() => { | ||
| toast.success('제출 성공!', { | ||
| style: { | ||
| backgroundColor: theme.colors.primary, | ||
| color: 'white', | ||
| }, | ||
| duration: 1000, | ||
| }); | ||
| setTimeout(() => { | ||
| navigate(`/`); | ||
| }, 1000); | ||
| }) | ||
| .catch(() => { | ||
| toast.error('제출 실패!', { | ||
| duration: 1000, | ||
| style: { | ||
| backgroundColor: 'white', | ||
| color: theme.colors.error, | ||
| }, | ||
| }); | ||
| }); | ||
|
|
||
| toast.success('회원가입 완료!', { | ||
| style: { backgroundColor: theme.colors.primary, color: 'white' }, | ||
| duration: 1000, | ||
| }); | ||
|
|
||
| setTimeout(() => { | ||
| navigate('/login'); | ||
| }, 1000); | ||
| } catch (error) { | ||
| toast.error('회원가입 실패', { duration: 1000 }); | ||
| } | ||
| }; |
There was a problem hiding this comment.
onSubmit 함수의 비동기 로직에 심각한 오류가 있습니다.
async함수 내에서await대신.then()을 사용하여postSignupForm을 호출하고 있어, API 호출이 완료되기를 기다리지 않고 바로 다음 코드가 실행됩니다.- API 호출 직후 성공 토스트(
회원가입 완료!)와 페이지 이동(navigate('/login')) 로직이 중복되어 실행됩니다. 이로 인해 API 호출 결과와 상관없이 항상 성공 메시지가 표시되고 페이지가 이동하는 버그가 발생합니다.
await를 사용하여 비동기 흐름을 명확히 하고, 성공/실패에 따른 처리를 try...catch 블록 안에서 일관되게 관리해야 합니다.
const onSubmit = async (signupFormValue: SignupFormInputs) => {
try {
await postSignupForm(signupFormValue);
toast.success('회원가입 완료!', {
style: { backgroundColor: theme.colors.primary, color: 'white' },
duration: 1000,
});
setTimeout(() => {
navigate('/login');
}, 1000);
} catch (error) {
toast.error('회원가입에 실패했습니다.', {
duration: 1000,
style: {
backgroundColor: 'white',
color: theme.colors.error,
},
});
}
};
|
|
||
| // 1-1. accessToken, refreshToken 발급 | ||
| // localStorage.setItem('accessToken', res.data.accessToken); | ||
| // localStorage.setItem('refreshToken ', res.data.accessToken); |
There was a problem hiding this comment.
주석 처리된 코드이지만, refreshToken을 저장하는 부분에 두 가지 문제가 있습니다.
'refreshToken '키에 불필요한 공백이 포함되어 있습니다.refreshToken을 저장해야 하는 곳에res.data.accessToken이 할당되어 있습니다.res.data.refreshToken을 사용해야 합니다.
| // localStorage.setItem('refreshToken ', res.data.accessToken); | |
| // localStorage.setItem('refreshToken', res.data.refreshToken); |
|
|
||
| useEffect(() => { | ||
| const code = new URL(window.location.href).searchParams.get('code'); | ||
| if (!code) return; |
| console.log(code); | ||
| const fetchToken = async () => { | ||
| try { | ||
| const res = await axios.post('http://localhost:8080/api/auth/kakao/login', { |
There was a problem hiding this comment.
API 요청 URL이 하드코딩되어 있습니다. 개발, 스테이징, 프로덕션 등 다양한 환경에 대응하기 어렵고 보안에도 취약할 수 있습니다. .env 파일에 환경 변수로 분리하여 관리하는 것을 권장합니다.
예: const API_URL = import.meta.env.VITE_API_URL;
| const res = await axios.post('http://localhost:8080/api/auth/kakao/login', { | |
| const res = await axios.post(`${import.meta.env.VITE_API_BASE_URL}/auth/kakao/login`, { |
| } catch (error) { | ||
| console.log('error:', error); | ||
| } |
| <Button to='/signup' width='100%' type='submit'> | ||
| {'회원가입'} | ||
| </Button> |
There was a problem hiding this comment.
| </Button> | ||
| <KakaoButtonWrapper> | ||
| <Button width='100%' type='submit'> | ||
| <Button width='100%' type='submit' onClick={handleKakaoLogin}> |
There was a problem hiding this comment.
src/pages/admin/Signup/Page.tsx
Outdated
| [`@media (max-width: ${theme.breakpoints.web})`]: { | ||
| padding: '1.5rem', | ||
| }, |
src/pages/Routes.tsx
Outdated
| element: <KakaoCallback />, | ||
| }, | ||
| { | ||
| path: COMMON.SINGUP, |
|
|
||
| const onSubmit = async (signupFormValue: SignupFormInputs) => { | ||
| try { | ||
| console.log('회원가입 data:', signupFormValue); |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (5)
src/pages/admin/Login/component/LoginButton/index.tsx (1)
18-20: Use route constant instead of hardcoded path.For consistency with the rest of the codebase, use
ROUTE_PATH.COMMON.SIGNUP(after fixing the typo) instead of the hardcoded'/signup'path.After fixing the typo in
routerPath.ts, apply this diff:+import { ROUTE_PATH } from '@/constants/routerPath'; + import styled from '@emotion/styled'; import { Button } from '@/shared/components/Button'; const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; const REDIRECT_URI = import.meta.env.VITE_KAKAO_REDIRECT_URI; export const LoginButton = () => { const handleKakaoLogin = () => { const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; window.location.href = kakaoAuthUrl; }; return ( <Container> <Button width='100%' type='submit'> {'로그인'} </Button> - <Button to='/signup' width='100%' type='submit'> + <Button to={`/${ROUTE_PATH.COMMON.SIGNUP}`} width='100%' type='submit'> {'회원가입'} </Button>src/pages/admin/Signup/api/signup.ts (1)
3-15: Consider adding a request timeout.The fetch call has no timeout, which could cause the signup form to hang indefinitely if the backend is unresponsive.
Consider adding a timeout using
AbortController:export const postSignupForm = async (formData: SignupFormInputs): Promise<SignupFormInputs> => { const url = `${import.meta.env.VITE_API_BASE_URL}/auth/register`; + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout + + try { - const response = await fetch(url, { + const response = await fetch(url, { - method: 'POST', + method: 'POST', - headers: { + headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/json', - }, + }, - body: JSON.stringify(formData), + body: JSON.stringify(formData), + signal: controller.signal, - }); + }); + clearTimeout(timeoutId); - if (!response.ok) throw new Error('회원 가입 양식을 제출하지 못했습니다.'); - return await response.json(); + if (!response.ok) throw new Error('회원 가입 양식을 제출하지 못했습니다.'); + return await response.json(); + } catch (error) { + clearTimeout(timeoutId); + if (error instanceof Error && error.name === 'AbortError') { + throw new Error('요청 시간이 초과되었습니다.'); + } + throw error; + } };src/pages/admin/Login/KakaoCallback.tsx (2)
21-32: Remove or implement commented-out logic.The commented-out sections indicate incomplete implementation. Based on the PR description, token handling will be in a separate PR, but these comments should either be removed or converted to proper TODO comments with issue references.
Apply one of these approaches:
Option 1: Remove if implementation is planned soon
- // CASE 1) 기존 회원 - - // 1-1. accessToken, refreshToken 발급 - // localStorage.setItem('accessToken', res.data.accessToken); - // localStorage.setItem('refreshToken ', res.data.accessToken); - // ------------------------------------------------------------ - // 2-2 main 페이지 이동 - // navigate('/'); // 로그인 후 홈으로 이동 - - // CASE 2) 기존 회원 - // 2-1. 임시 토큰 - // 2-2. navigate('/signup')Option 2: Convert to proper TODO with issue reference
- // CASE 1) 기존 회원 - // 1-1. accessToken, refreshToken 발급 - // localStorage.setItem('accessToken', res.data.accessToken); - // localStorage.setItem('refreshToken ', res.data.accessToken); - // ------------------------------------------------------------ - // 2-2 main 페이지 이동 - // navigate('/'); // 로그인 후 홈으로 이동 - - // CASE 2) 기존 회원 - // 2-1. 임시 토큰 - // 2-2. navigate('/signup') + // TODO(#issue-number): Implement token handling and navigation based on user status + // - Existing users: Store access/refresh tokens and navigate to main page + // - New users: Store temporary token and navigate to signup page
14-36: Add timeout to the axios request.Similar to the signup API, the axios call should have a timeout to prevent indefinite hanging.
Apply this diff:
const fetchToken = async () => { try { - const res = await axios.post('http://localhost:8080/api/auth/kakao/login', { + const res = await axios.post(`${import.meta.env.VITE_API_BASE_URL}/auth/kakao/login`, { authorizationCode: code, - }); + }, { + timeout: 10000, // 10 second timeout + });src/pages/admin/Signup/components/SignupForm/index.styled.ts (1)
48-52: Remove unused ErrorMessage styled componentThe
ErrorMessageinsrc/pages/admin/Signup/components/SignupForm/index.styled.tsis never imported or used (the only otherErrorMessageis a local definition in ClubDetailEdit/Page.tsx); delete it or clarify its intended purpose.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/constants/routerPath.ts(1 hunks)src/pages/Routes.tsx(2 hunks)src/pages/admin/Login/KakaoCallback.tsx(1 hunks)src/pages/admin/Login/component/LoginButton/index.tsx(1 hunks)src/pages/admin/Signup/Page.tsx(1 hunks)src/pages/admin/Signup/api/signup.ts(1 hunks)src/pages/admin/Signup/components/HeaderTitle/index.tsx(1 hunks)src/pages/admin/Signup/components/SignupForm/index.styled.ts(1 hunks)src/pages/admin/Signup/components/SignupForm/index.tsx(1 hunks)src/pages/admin/Signup/type/signup.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
src/pages/admin/Signup/components/SignupForm/index.styled.ts (1)
src/styles/theme.ts (1)
theme(3-10)
src/pages/admin/Login/component/LoginButton/index.tsx (1)
src/shared/components/Button/index.tsx (1)
Button(17-64)
src/pages/admin/Signup/Page.tsx (3)
src/pages/admin/Signup/components/HeaderTitle/index.tsx (1)
HeaderTitle(3-9)src/pages/admin/Signup/components/SignupForm/index.tsx (1)
SignupForm(12-146)src/styles/theme.ts (1)
theme(3-10)
src/pages/admin/Login/KakaoCallback.tsx (1)
src/shared/components/LoadingSpinner.tsx (1)
LoadingSpinner(19-19)
src/pages/Routes.tsx (2)
src/pages/admin/Login/KakaoCallback.tsx (1)
KakaoCallback(6-42)src/pages/admin/Signup/Page.tsx (1)
AdminSignupPage(5-12)
src/pages/admin/Signup/api/signup.ts (1)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)
src/pages/admin/Signup/components/HeaderTitle/index.tsx (2)
src/pages/user/Main/components/ClubListSection/Club.styled.ts (1)
TextWrapper(94-101)src/styles/theme.ts (1)
theme(3-10)
src/pages/admin/Signup/components/SignupForm/index.tsx (5)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)src/pages/admin/Signup/api/signup.ts (1)
postSignupForm(3-15)src/styles/theme.ts (1)
theme(3-10)src/shared/components/Form/InputField/OutlineInputField.tsx (1)
OutlineInputField(9-20)src/shared/components/Button/index.tsx (1)
Button(17-64)
🪛 GitHub Actions: Dongarium FE CI/CD
src/pages/Routes.tsx
[error] 13-13: ESLint: import/order violation - './admin/Login/KakaoCallback' import should occur before import of './admin/Login/Page'.
🪛 GitHub Check: lint
src/pages/admin/Login/KakaoCallback.tsx
[failure] 3-3:
axios import should occur before import of react
src/pages/Routes.tsx
[failure] 14-14:
./admin/Signup/Page import should occur before import of ./user/Apply/Page
[failure] 13-13:
./admin/Login/KakaoCallback import should occur before import of ./admin/Login/Page
src/pages/admin/Signup/components/SignupForm/index.tsx
[failure] 61-61:
'error' is defined but never used
[failure] 9-9:
@/pages/admin/Signup/api/signup import should occur before import of @/shared/components/Button
[failure] 6-6:
@/pages/admin/Signup/components/SignupForm/index.styled import should occur before import of @/shared/components/Button
🔇 Additional comments (6)
src/pages/admin/Signup/type/signup.ts (1)
1-7: LGTM!The type definition is clear and matches the form fields described in the PR objectives.
src/pages/admin/Signup/components/HeaderTitle/index.tsx (1)
3-22: LGTM!The component provides a clean, styled header for the admin signup page with appropriate theming.
src/pages/Routes.tsx (1)
40-40: Update route path after fixing the typo.Once the typo in
ROUTE_PATH.COMMON.SINGUPis corrected toSIGNUP(see comment onrouterPath.ts), update this reference accordingly.src/pages/admin/Signup/Page.tsx (1)
5-32: LGTM!The component provides a well-structured layout with proper responsive design using theme breakpoints. The composition of
HeaderTitleandSignupFormis clean and maintainable.src/pages/admin/Login/KakaoCallback.tsx (1)
3-3: Fix the import ordering violation.Move the
axiosimport to follow the import order convention (third-party imports after React imports).Apply this diff:
import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -import axios from 'axios'; import { LoadingSpinner } from '@/shared/components/LoadingSpinner'; +import axios from 'axios';Likely an incorrect or invalid review comment.
src/pages/admin/Signup/components/SignupForm/index.styled.ts (1)
3-15: LGTM: Well-structured responsive wrapper.The responsive design pattern is clean, with the width and media query breakpoint properly aligned at 48rem.
src/constants/routerPath.ts
Outdated
| CLUBDETAIL: 'clubs/:clubId', | ||
| LOGIN: 'login', | ||
| CALLBACK: 'login/redirect', | ||
| SINGUP: 'signup', |
There was a problem hiding this comment.
Fix the typo in the constant name.
The constant SINGUP appears to be a typo and should be SIGNUP.
Apply this diff to correct the typo:
- SINGUP: 'signup',
+ SIGNUP: 'signup',Note: This change will require updating all references to ROUTE_PATH.COMMON.SINGUP throughout the codebase (e.g., in Routes.tsx).
🤖 Prompt for AI Agents
In src/constants/routerPath.ts at line 17, the constant name SINGUP is a typo
and should be renamed to SIGNUP; update the exported constant key from SINGUP to
SIGNUP and keep its value 'signup' unchanged, then update all usages across the
codebase (e.g., replace ROUTE_PATH.COMMON.SINGUP with ROUTE_PATH.COMMON.SIGNUP
in Routes.tsx and any other files) to avoid breaking references.
| const handleKakaoLogin = () => { | ||
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; | ||
| window.location.href = kakaoAuthUrl; | ||
| }; |
There was a problem hiding this comment.
❓ Verification inconclusive
Verify environment variables are defined.
Ensure that VITE_KAKAO_REST_API_KEY and VITE_KAKAO_REDIRECT_URI are properly configured in the environment files. Missing values will result in an incomplete OAuth URL.
Run the following script to check if environment variable examples or documentation exist:
🏁 Script executed:
#!/bin/bash
# Check for .env files and documentation mentioning Kakao environment variables
fd -t f '\.env' --exec cat {} \; | rg -i 'kakao|VITE_KAKAO'
fd -t f 'README' --exec cat {} \; | rg -i 'kakao|environment|\.env'Length of output: 0
Add and document Kakao OAuth environment variables
- Add
VITE_KAKAO_REST_API_KEYandVITE_KAKAO_REDIRECT_URIto.env.example(or equivalent). - Document their usage in the README and ensure they’re set in all deployment environments.
🤖 Prompt for AI Agents
In src/pages/admin/Login/component/LoginButton/index.tsx lines 8-11, you need to
switch the hardcoded REST_API_KEY and REDIRECT_URI to use Vite env vars and add
+ document those variables: add VITE_KAKAO_REST_API_KEY and
VITE_KAKAO_REDIRECT_URI to .env.example with short descriptions and example
values, update the README (Auth / Kakao section) to show how to obtain and set
those vars for local, staging and production, and verify your deployment
configurations (CI/CD, hosting env settings) include the two VITE_KAKAO_* vars;
ensure the component reads them via import.meta.env.VITE_KAKAO_REST_API_KEY and
import.meta.env.VITE_KAKAO_REDIRECT_URI (and include a brief runtime
fallback/error log if missing).
| const code = new URL(window.location.href).searchParams.get('code'); | ||
| if (!code) return; | ||
|
|
||
| console.log(code); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Remove debug console.log statements.
Console.log statements should be removed before merging to production.
Apply this diff to remove debug logs:
- console.log(code);
const fetchToken = async () => {
try {
const res = await axios.post('http://localhost:8080/api/auth/kakao/login', {
authorizationCode: code,
});
- console.log('응답res ', res);
// CASE 1) 기존 회원
...
} catch (error) {
- console.log('error:', error);
+ console.error('Kakao login failed:', error);
}Consider using a proper logger or at least console.error for error cases.
Also applies to: 19-19, 34-34
🤖 Prompt for AI Agents
In src/pages/admin/Login/KakaoCallback.tsx around lines 13, 19 and 34, remove
the debug console.log statements (e.g., console.log(code)) before merging to
production; replace any necessary runtime diagnostics with a proper logger or,
for errors only, use console.error, and ensure no stray console.log calls remain
in those lines of the file.
| import { useForm, FormProvider } from 'react-hook-form'; | ||
| import { useNavigate } from 'react-router-dom'; | ||
| import { toast } from 'sonner'; | ||
| import { Button } from '@/shared/components/Button'; | ||
| import { OutlineInputField } from '@/shared/components/Form/InputField/OutlineInputField'; | ||
| import * as S from '@/pages/admin/Signup/components/SignupForm/index.styled'; | ||
| import { theme } from '@/styles/theme'; | ||
|
|
||
| import { postSignupForm } from '@/pages/admin/Signup/api/signup'; | ||
| import type { SignupFormInputs } from '@/pages/admin/Signup/type/signup'; |
There was a problem hiding this comment.
Fix import order per ESLint rules.
The linter indicates that local imports should come before shared component imports. Reorder as follows:
Apply this diff:
import { useForm, FormProvider } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { toast } from 'sonner';
+import * as S from '@/pages/admin/Signup/components/SignupForm/index.styled';
+import { postSignupForm } from '@/pages/admin/Signup/api/signup';
+import type { SignupFormInputs } from '@/pages/admin/Signup/type/signup';
import { Button } from '@/shared/components/Button';
import { OutlineInputField } from '@/shared/components/Form/InputField/OutlineInputField';
-import * as S from '@/pages/admin/Signup/components/SignupForm/index.styled';
import { theme } from '@/styles/theme';
-
-import { postSignupForm } from '@/pages/admin/Signup/api/signup';
-import type { SignupFormInputs } from '@/pages/admin/Signup/type/signup';🧰 Tools
🪛 GitHub Check: lint
[failure] 9-9:
@/pages/admin/Signup/api/signup import should occur before import of @/shared/components/Button
[failure] 6-6:
@/pages/admin/Signup/components/SignupForm/index.styled import should occur before import of @/shared/components/Button
🤖 Prompt for AI Agents
In src/pages/admin/Signup/components/SignupForm/index.tsx around lines 1-10, the
import order violates ESLint (local imports should come before shared imports);
reorder so all local project imports (any starting with "@/pages", "@/styles",
and the component's own styled import) appear before shared/library imports
(like "@/shared/..." and external libs). Specifically, move the imports for S
(index.styled), theme, postSignupForm, and SignupFormInputs above the shared
Button and OutlineInputField imports, and keep third-party imports (react,
react-router-dom, sonner) at the top.
| import { KakaoCallback } from './admin/Login/KakaoCallback'; | ||
| import { AdminSignupPage } from './admin/Signup/Page'; |
There was a problem hiding this comment.
Fix the import ordering violations.
The ESLint import/order rule requires imports to be ordered alphabetically within their group. The new imports should be placed before the existing ./admin/Login/Page and ./user/Apply/Page imports.
Apply this diff to fix the import order:
import { ClubDetailPage } from '@/pages/user/ClubDetail/Page';
import { MainPage } from '@/pages/user/Main/Page.tsx';
import { ApplicationDetailPage } from './admin/ApplicationDetail/Page';
+import { KakaoCallback } from './admin/Login/KakaoCallback';
import { LoginPage } from './admin/Login/Page';
+import { AdminSignupPage } from './admin/Signup/Page';
import { ClubApplicationPage } from './user/Apply/Page';
-
-import { KakaoCallback } from './admin/Login/KakaoCallback';
-import { AdminSignupPage } from './admin/Signup/Page';
-📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { KakaoCallback } from './admin/Login/KakaoCallback'; | |
| import { AdminSignupPage } from './admin/Signup/Page'; | |
| import { ClubDetailPage } from '@/pages/user/ClubDetail/Page'; | |
| import { MainPage } from '@/pages/user/Main/Page.tsx'; | |
| import { ApplicationDetailPage } from './admin/ApplicationDetail/Page'; | |
| import { KakaoCallback } from './admin/Login/KakaoCallback'; | |
| import { LoginPage } from './admin/Login/Page'; | |
| import { AdminSignupPage } from './admin/Signup/Page'; | |
| import { ClubApplicationPage } from './user/Apply/Page'; |
🧰 Tools
🪛 GitHub Actions: Dongarium FE CI/CD
[error] 13-13: ESLint: import/order violation - './admin/Login/KakaoCallback' import should occur before import of './admin/Login/Page'.
🪛 GitHub Check: lint
[failure] 14-14:
./admin/Signup/Page import should occur before import of ./user/Apply/Page
[failure] 13-13:
./admin/Login/KakaoCallback import should occur before import of ./admin/Login/Page
🤖 Prompt for AI Agents
In src/pages/Routes.tsx around lines 13 to 14, the new imports violate the
ESLint import/order alphabetical rule; move the imports for
./admin/Login/KakaoCallback and ./admin/Signup/Page so they appear
alphabetically before the existing ./admin/Login/Page and ./user/Apply/Page
imports (i.e., reorder the import block so all relative imports are alphabetized
within their group).
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (12)
src/pages/admin/Login/KakaoCallback.tsx (5)
13-13: Remove debug console.log statements.Development console.log statements should be removed before merging to production.
Remove lines 13, 19, and 34:
- console.log(code); const fetchToken = async () => { try { const res = await axios.post('http://localhost:8080/api/auth/kakao/login', { authorizationCode: code, }); - console.log('응답res ', res); // ... rest of code } catch (error) { - console.log('error:', error); } };
10-11: UseuseSearchParamsand handle OAuth errors.
- React Router's
useSearchParamsis more idiomatic than parsingwindow.location.href.- When users deny consent or Kakao OAuth fails, an
errorquery parameter is sent. This case is not handled, leaving users stuck on a loading screen.Apply this diff:
+import { useNavigate, useSearchParams } from 'react-router-dom'; -import { useNavigate } from 'react-router-dom'; export const KakaoCallback = () => { const navigate = useNavigate(); + const [searchParams] = useSearchParams(); useEffect(() => { - const code = new URL(window.location.href).searchParams.get('code'); + const code = searchParams.get('code'); + const error = searchParams.get('error'); + + if (error) { + console.error('Kakao OAuth error:', error); + navigate('/login'); + return; + } + if (!code) return;
16-18: Use environment variable for API URL.The API URL is hardcoded to
localhost:8080, which will fail in production. Use theVITE_API_BASE_URLenvironment variable for consistency with other API calls (e.g., signup.ts).Apply this diff:
- const res = await axios.post('http://localhost:8080/api/auth/kakao/login', { + const res = await axios.post(`${import.meta.env.VITE_API_BASE_URL}/auth/kakao/login`, { authorizationCode: code, });
21-32: Fix typo in commented refreshToken storage.While this code is commented (pending token flow implementation per PR description), line 25 has two errors:
'refreshToken 'key contains an extra space- Should use
res.data.refreshToken, notres.data.accessTokenFix before uncommenting:
// 1-1. accessToken, refreshToken 발급 // localStorage.setItem('accessToken', res.data.accessToken); - // localStorage.setItem('refreshToken ', res.data.accessToken); + // localStorage.setItem('refreshToken', res.data.refreshToken);
33-35: Provide user feedback on error.The error handler only logs to console, leaving users stuck on a loading screen. Add user-visible error handling (toast notification or redirect to login).
Apply this diff:
} catch (error) { - console.log('error:', error); + console.error('Kakao login error:', error); + // TODO: Add toast notification + navigate('/login'); }src/pages/admin/Signup/Page.tsx (1)
26-28: Remove redundant media query.The web breakpoint media query sets
padding: '1.5rem', which is identical to the defaultpadding: '0 1.5rem'(vertical padding is already 0 in both). This media query can be removed.Apply this diff:
padding: '0 1.5rem', boxSizing: 'border-box', - [`@media (max-width: ${theme.breakpoints.web})`]: { - padding: '1.5rem', - }, [`@media (max-width: ${theme.breakpoints.mobile})`]: { padding: '1rem', },src/pages/admin/Login/component/LoginButton/index.tsx (2)
18-20: Removetype='submit'from navigation button.The signup button uses the
toprop for navigation, sotype='submit'is semantically incorrect and could cause confusion.Apply this diff:
- <Button to='/signup' width='100%' type='submit'> + <Button to='/signup' width='100%'> {'회원가입'} </Button>
22-27: Changetype='submit'totype='button'on Kakao login button.The Kakao login button uses
onClickfor navigation, not form submission. Usingtype='submit'may cause unintended form submission behavior.Apply this diff:
- <Button width='100%' type='submit' onClick={handleKakaoLogin}> + <Button width='100%' type='button' onClick={handleKakaoLogin}> <ButtonContent>src/pages/Routes.tsx (1)
34-41: Fix typo: SINGUP → SIGNUP.The route key
COMMON.SINGUPcontains a typo. This should beCOMMON.SIGNUPfor consistency and correctness. The typo originates fromsrc/constants/routerPath.tsand should be fixed there first, then updated here.Apply this diff:
{ - path: COMMON.SINGUP, + path: COMMON.SIGNUP, element: <AdminSignupPage />, },src/constants/routerPath.ts (1)
16-17: Fix typo: SINGUP → SIGNUP.The constant name contains a typo. Change
SINGUPtoSIGNUP.Apply this diff:
LOGIN: 'login', CALLBACK: 'login/redirect', - SINGUP: 'signup', + SIGNUP: 'signup', },src/pages/admin/Signup/api/signup.ts (1)
3-15: Use axios for consistency and handle empty response bodies safely.The codebase uses axios elsewhere (see KakaoCallback.tsx), but this function uses fetch, creating inconsistency. Additionally,
response.json()will throw if the server returns an empty body on successful POST, which is common for registration endpoints.Refactor to use axios:
+import axios from 'axios'; import type { SignupFormInputs } from '../type/signup'; -export const postSignupForm = async (formData: SignupFormInputs): Promise<SignupFormInputs> => { +export const postSignupForm = async (formData: SignupFormInputs): Promise<void> => { const url = `${import.meta.env.VITE_API_BASE_URL}/auth/register`; - const response = await fetch(url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(formData), - }); - - if (!response.ok) throw new Error('회원 가입 양식을 제출하지 못했습니다.'); - return await response.json(); + try { + await axios.post(url, formData); + } catch (error) { + throw new Error('회원 가입 양식을 제출하지 못했습니다.'); + } };src/pages/admin/Signup/components/SignupForm/index.tsx (1)
27-63: Fix the async signup flow—success fires even on failure
postSignupFormisn’t awaited, so both success toasts and navigations fire immediately, even if the request rejects. The extratoast.success/navigateoutside the promise chain guarantees duplicate notifications and a second redirect. This also leaves the ESLint failure ('error' is defined but never used). Await the API call once, keep a single success branch, and handle errors in onecatchto keep the UX and lint clean.- const onSubmit = async (signupFormValue: SignupFormInputs) => { - try { - console.log('회원가입 data:', signupFormValue); - postSignupForm(signupFormValue) - .then(() => { - toast.success('제출 성공!', { - style: { - backgroundColor: theme.colors.primary, - color: 'white', - }, - duration: 1000, - }); - setTimeout(() => { - navigate(`/`); - }, 1000); - }) - .catch(() => { - toast.error('제출 실패!', { - duration: 1000, - style: { - backgroundColor: 'white', - color: theme.colors.error, - }, - }); - }); - - toast.success('회원가입 완료!', { - style: { backgroundColor: theme.colors.primary, color: 'white' }, - duration: 1000, - }); - - setTimeout(() => { - navigate('/login'); - }, 1000); - } catch (error) { - toast.error('회원가입 실패', { duration: 1000 }); - } - }; + const onSubmit = async (signupFormValue: SignupFormInputs) => { + try { + await postSignupForm(signupFormValue); + + toast.success('회원가입 완료!', { + style: { backgroundColor: theme.colors.primary, color: 'white' }, + duration: 1000, + }); + + setTimeout(() => { + navigate('/login'); + }, 1000); + } catch { + toast.error('회원가입 실패', { + duration: 1000, + style: { + backgroundColor: 'white', + color: theme.colors.error, + }, + }); + } + };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/constants/routerPath.ts(1 hunks)src/pages/Routes.tsx(2 hunks)src/pages/admin/Login/KakaoCallback.tsx(1 hunks)src/pages/admin/Login/component/LoginButton/index.tsx(1 hunks)src/pages/admin/Signup/Page.tsx(1 hunks)src/pages/admin/Signup/api/signup.ts(1 hunks)src/pages/admin/Signup/components/HeaderTitle/index.tsx(1 hunks)src/pages/admin/Signup/components/SignupForm/index.styled.ts(1 hunks)src/pages/admin/Signup/components/SignupForm/index.tsx(1 hunks)src/pages/admin/Signup/type/signup.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
src/pages/admin/Signup/components/SignupForm/index.tsx (5)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)src/pages/admin/Signup/api/signup.ts (1)
postSignupForm(3-15)src/styles/theme.ts (1)
theme(3-10)src/shared/components/Form/InputField/OutlineInputField.tsx (1)
OutlineInputField(9-20)src/shared/components/Button/index.tsx (1)
Button(17-64)
src/pages/admin/Login/component/LoginButton/index.tsx (1)
src/shared/components/Button/index.tsx (1)
Button(17-64)
src/pages/admin/Login/KakaoCallback.tsx (1)
src/shared/components/LoadingSpinner.tsx (1)
LoadingSpinner(19-19)
src/pages/Routes.tsx (2)
src/pages/admin/Login/KakaoCallback.tsx (1)
KakaoCallback(6-42)src/pages/admin/Signup/Page.tsx (1)
AdminSignupPage(5-12)
src/pages/admin/Signup/components/HeaderTitle/index.tsx (2)
src/pages/user/Main/components/ClubListSection/Club.styled.ts (1)
TextWrapper(94-101)src/styles/theme.ts (1)
theme(3-10)
src/pages/admin/Signup/components/SignupForm/index.styled.ts (1)
src/styles/theme.ts (1)
theme(3-10)
src/pages/admin/Signup/api/signup.ts (1)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)
src/pages/admin/Signup/Page.tsx (3)
src/pages/admin/Signup/components/HeaderTitle/index.tsx (1)
HeaderTitle(3-9)src/pages/admin/Signup/components/SignupForm/index.tsx (1)
SignupForm(12-146)src/styles/theme.ts (1)
theme(3-10)
🪛 GitHub Actions: Dongarium FE CI/CD
src/pages/admin/Signup/components/SignupForm/index.tsx
[error] 61-61: ESLint: 'error' is defined but never used. (no-unused-vars)
🪛 GitHub Check: lint
src/pages/admin/Signup/components/SignupForm/index.tsx
[failure] 61-61:
'error' is defined but never used
🔇 Additional comments (3)
src/pages/admin/Signup/components/HeaderTitle/index.tsx (1)
3-22: LGTM!The HeaderTitle component is well-structured and follows the project's styling patterns. The implementation is clean and straightforward.
src/pages/admin/Signup/type/signup.ts (1)
1-7: LGTM!The type definition is clear and appropriate for the signup form data contract.
src/pages/admin/Signup/Page.tsx (1)
5-12: LGTM!The page structure is clean and well-organized, composing HeaderTitle and SignupForm within a responsive Layout.
| const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; | ||
| const REDIRECT_URI = import.meta.env.VITE_KAKAO_REDIRECT_URI; | ||
|
|
||
| export const LoginButton = () => { | ||
| const handleKakaoLogin = () => { | ||
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; | ||
| window.location.href = kakaoAuthUrl; | ||
| }; |
There was a problem hiding this comment.
Validate environment variables before use.
The REST_API_KEY and REDIRECT_URI could be undefined if environment variables are not set. This would result in a malformed OAuth URL at runtime.
Add validation and error handling:
const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY;
const REDIRECT_URI = import.meta.env.VITE_KAKAO_REDIRECT_URI;
export const LoginButton = () => {
const handleKakaoLogin = () => {
+ if (!REST_API_KEY || !REDIRECT_URI) {
+ console.error('Kakao OAuth configuration missing');
+ return;
+ }
const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
window.location.href = kakaoAuthUrl;
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; | |
| const REDIRECT_URI = import.meta.env.VITE_KAKAO_REDIRECT_URI; | |
| export const LoginButton = () => { | |
| const handleKakaoLogin = () => { | |
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; | |
| window.location.href = kakaoAuthUrl; | |
| }; | |
| const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; | |
| const REDIRECT_URI = import.meta.env.VITE_KAKAO_REDIRECT_URI; | |
| export const LoginButton = () => { | |
| const handleKakaoLogin = () => { | |
| if (!REST_API_KEY || !REDIRECT_URI) { | |
| console.error('Kakao OAuth configuration missing'); | |
| return; | |
| } | |
| const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; | |
| window.location.href = kakaoAuthUrl; | |
| }; | |
| // …rest of the component | |
| }; |
🤖 Prompt for AI Agents
In src/pages/admin/Login/component/LoginButton/index.tsx around lines 4 to 11,
the code builds the Kakao OAuth URL using REST_API_KEY and REDIRECT_URI without
checking they exist; validate both import.meta.env values before using them, and
handle missing values by preventing navigation and surfacing an error (e.g.,
disable the button and show a console/error message or throw a clear error).
Specifically, if either REST_API_KEY or REDIRECT_URI is falsy, do not construct
or assign window.location.href; instead set an error state or log a descriptive
message indicating which env var is missing so the UI can avoid creating a
malformed OAuth URL and inform the developer/operator.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
src/pages/admin/Login/component/LoginButton/index.tsx (1)
4-11: Critical: Add runtime validation for environment variables.The environment variables
REST_API_KEYandREDIRECT_URIcan be undefined if not configured, leading to a malformed OAuth URL (https://kauth.kakao.com/oauth/authorize?client_id=undefined&redirect_uri=undefined&response_type=code). This will cause silent failures in the Kakao login flow.Apply this diff to add validation:
const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; const REDIRECT_URI = import.meta.env.VITE_KAKAO_REDIRECT_URI; export const LoginButton = () => { const handleKakaoLogin = () => { + if (!REST_API_KEY || !REDIRECT_URI) { + console.error('Kakao OAuth configuration missing'); + return; + } const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; window.location.href = kakaoAuthUrl; };src/pages/admin/Signup/components/SignupForm/index.tsx (1)
1-9: Fix import order to resolve pipeline failure.The import of
@/styles/themeon line 5 should come after the shared component imports to comply with the project's ESLint import order rules.Apply this diff:
import { useForm, FormProvider } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import { toast } from 'sonner'; import { postSignupForm } from '@/pages/admin/Signup/api/signup'; -import { theme } from '@/styles/theme'; import * as S from '@/pages/admin/Signup/components/SignupForm/index.styled'; import { Button } from '@/shared/components/Button'; import { OutlineInputField } from '@/shared/components/Form/InputField/OutlineInputField'; +import { theme } from '@/styles/theme'; import type { SignupFormInputs } from '@/pages/admin/Signup/type/signup';
🧹 Nitpick comments (3)
src/pages/admin/Login/component/LoginButton/index.tsx (1)
15-17: Clarify the purpose of the login button.The first button labeled "로그인" has no
onClickhandler ortoprop, making it non-functional. If this is a placeholder for future token-based login functionality (per the PR notes mentioning token verification work in a separate branch), consider adding a comment or removing it temporarily to avoid user confusion.If this is intentional, add a comment:
- <Button width='100%' type='button'> + {/* TODO: Implement token-based login - see separate PR */} + <Button width='100%' type='button' disabled> {'로그인'} </Button>src/pages/admin/Signup/components/SignupForm/index.tsx (1)
36-44: Log the caught error for debugging.The
errorparameter in the catch block is unused (flagged by the linter). Logging it would help with debugging signup failures.Apply this diff:
} catch (error) { + console.error('Signup failed:', error); toast.error('회원가입 실패!', { duration: 1000, style: { backgroundColor: 'white', color: theme.colors.error, }, }); }src/pages/admin/Login/Page.tsx (1)
9-9: Consider clarifying the temporary removal of LoginInput.The commented-out
LoginInputcomponent should either be removed entirely or enhanced with a TODO comment explaining its temporary removal, since the PR notes indicate that token-based login will be implemented in a separate branch.Apply this diff to clarify:
- {/* <LoginInput /> */} + {/* TODO: Re-enable LoginInput after token verification flow is implemented (separate PR) */}Or simply remove the comment if it's not needed:
- {/* <LoginInput /> */}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/constants/routerPath.ts(1 hunks)src/pages/Routes.tsx(2 hunks)src/pages/admin/Login/KakaoCallback.tsx(1 hunks)src/pages/admin/Login/Page.tsx(1 hunks)src/pages/admin/Login/component/LoginButton/index.tsx(1 hunks)src/pages/admin/Signup/Page.tsx(1 hunks)src/pages/admin/Signup/components/SignupForm/index.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/pages/Routes.tsx
- src/pages/admin/Login/KakaoCallback.tsx
- src/pages/admin/Signup/Page.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/pages/admin/Signup/components/SignupForm/index.tsx (5)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)src/pages/admin/Signup/api/signup.ts (1)
postSignupForm(3-15)src/styles/theme.ts (1)
theme(3-10)src/shared/components/Form/InputField/OutlineInputField.tsx (1)
OutlineInputField(9-20)src/shared/components/Button/index.tsx (1)
Button(17-64)
src/pages/admin/Login/component/LoginButton/index.tsx (1)
src/shared/components/Button/index.tsx (1)
Button(17-64)
🪛 GitHub Actions: Dongarium FE CI/CD
src/pages/admin/Signup/components/SignupForm/index.tsx
[error] 5-5: @/styles/theme import should occur after import of @/shared/components/Form/InputField/OutlineInputField import/order
🪛 GitHub Check: lint
src/pages/admin/Signup/components/SignupForm/index.tsx
[failure] 36-36:
'error' is defined but never used
[failure] 5-5:
@/styles/theme import should occur after import of @/shared/components/Form/InputField/OutlineInputField
🔇 Additional comments (2)
src/pages/admin/Signup/components/SignupForm/index.tsx (1)
47-126: LGTM: Clean form implementation with appropriate validation.The form structure is well-organized with proper validation rules for each field:
- Email pattern validation
- 6-digit student ID format
- Korean phone number format (010-XXXX-XXXX)
- Required field checks with helpful error messages
The use of
FormProviderandreact-hook-formfollows best practices, and the disabled state during submission prevents duplicate submissions.src/constants/routerPath.ts (1)
16-17: LGTM: Route constants correctly defined.The new route constants are appropriately named and structured:
CALLBACKfor Kakao OAuth redirect handlingSIGNUPfor the admin signup pageThese align well with the new components (
KakaoCallbackandAdminSignupPage) introduced in this PR.
- OAuth 일원화
|
npm install 했는데도 husky가 안되시는건가용? |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/pages/admin/Signup/components/SignupForm/index.tsx (1)
66-116: Consider extracting validation patterns for reusability.The validation patterns (email, studentId, phoneNumber) are defined inline and could be reused across the codebase. Consider extracting them to a shared constants file.
Example:
// src/constants/validationPatterns.ts export const VALIDATION_PATTERNS = { email: { value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: '올바른 이메일 형식이 아닙니다.', }, studentId: { value: /^\d{6}$/, message: '학번은 숫자 6자리여야 합니다.', }, phoneNumber: { value: /^\d{2,3}-\d{3,4}-\d{4}$/, message: '올바른 전화번호 형식이 아닙니다.', }, } as const;Then use:
{...methods.register('email', { required: '이메일을 입력하세요.', pattern: VALIDATION_PATTERNS.email, })}Note: The phone number pattern requires dashes, which might be inconvenient for users pasting numbers without formatting. Consider adding input masking or accepting both formats.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/pages/admin/Signup/components/SignupForm/index.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/admin/Signup/components/SignupForm/index.tsx (5)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)src/pages/admin/Signup/api/signup.ts (1)
postSignupForm(3-15)src/styles/theme.ts (1)
theme(3-10)src/shared/components/Form/InputField/OutlineInputField.tsx (1)
OutlineInputField(9-20)src/shared/components/Button/index.tsx (1)
Button(17-64)
🪛 GitHub Actions: Dongarium FE CI/CD
src/pages/admin/Signup/components/SignupForm/index.tsx
[error] 36-36: ESLint: 'error' is defined but never used. (no-unused-vars). Command: npm run lint
🪛 GitHub Check: lint
src/pages/admin/Signup/components/SignupForm/index.tsx
[failure] 36-36:
'error' is defined but never used
| const onSubmit = async (signupFormValue: SignupFormInputs) => { | ||
| try { | ||
| await postSignupForm(signupFormValue); | ||
| toast.success('회원가입 완료!', { | ||
| style: { backgroundColor: theme.colors.primary, color: 'white' }, | ||
| duration: 1000, | ||
| }); | ||
| setTimeout(() => { | ||
| navigate(`/login`); | ||
| }, 1000); | ||
| } catch (error) { | ||
| toast.error('회원가입 실패!', { | ||
| duration: 1000, | ||
| style: { | ||
| backgroundColor: 'white', | ||
| color: theme.colors.error, | ||
| }, | ||
| }); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Fix unused error variable and navigation timing issue.
Two concerns:
-
Pipeline failure: The
errorparameter on Line 36 is unused. Either prefix it with an underscore (_error) to mark as intentionally unused, or log it for debugging. -
Navigation timing hazard: The
setTimeouton Lines 33-35 can trigger navigation after the component unmounts, potentially causing React warnings or failed navigations if the user closes the tab or navigates elsewhere during the 1-second delay.
Apply this diff to address both issues:
- } catch (error) {
+ } catch (_error) {
toast.error('회원가입 실패!', {
duration: 1000,
style: {
backgroundColor: 'white',
color: theme.colors.error,
},
});
}For the navigation timing issue, consider one of these patterns:
Option 1: Use toast's onAutoClose callback (cleaner)
try {
await postSignupForm(signupFormValue);
toast.success('회원가입 완료!', {
style: { backgroundColor: theme.colors.primary, color: 'white' },
duration: 1000,
+ onAutoClose: () => navigate('/login'),
});
- setTimeout(() => {
- navigate(`/login`);
- }, 1000);Option 2: Store timeout ID and cleanup in useEffect
useEffect(() => {
return () => {
// cleanup any pending timeouts when component unmounts
};
}, []);
// In onSubmit:
const timeoutId = setTimeout(() => navigate('/login'), 1000);
// Store timeoutId for cleanup if needed🧰 Tools
🪛 GitHub Actions: Dongarium FE CI/CD
[error] 36-36: ESLint: 'error' is defined but never used. (no-unused-vars). Command: npm run lint
🪛 GitHub Check: lint
[failure] 36-36:
'error' is defined but never used
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
src/pages/admin/Signup/components/SignupForm/index.tsx (3)
1-9: Reorder imports per ESLint rules.Local project imports (
@/styles,@/pagestypes) should come before shared component imports (@/shared). Move Lines 8-9 before Lines 6-7.Apply this diff:
import { useForm, FormProvider } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import { toast } from 'sonner'; import { postSignupForm } from '@/pages/admin/Signup/api/signup'; import * as S from '@/pages/admin/Signup/components/SignupForm/index.styled'; +import type { SignupFormInputs } from '@/pages/admin/Signup/type/signup'; +import { theme } from '@/styles/theme'; import { Button } from '@/shared/components/Button'; import { OutlineInputField } from '@/shared/components/Form/InputField/OutlineInputField'; -import { theme } from '@/styles/theme'; -import type { SignupFormInputs } from '@/pages/admin/Signup/type/signup';
36-36: Fix unused error variable and naming conflict.The catch parameter
errorsis unused (causing pipeline failure) and shadows theerrorsfromformState(Line 24), which is confusing.Apply this diff to fix both issues and add error logging:
- } catch (errors) { + } catch (error) { + console.error('Signup failed:', error); toast.error('회원가입 실패!', {
33-35: Fix navigation timing hazard.
setTimeoutcan trigger after component unmount, causing React warnings or failed navigation. Use toast'sonAutoClosecallback instead.Apply this diff:
toast.success('회원가입 완료!', { style: { backgroundColor: theme.colors.primary, color: 'white' }, duration: 1000, + onAutoClose: () => navigate('/login'), }); - setTimeout(() => { - navigate(`/login`); - }, 1000);
🧹 Nitpick comments (1)
src/pages/admin/Signup/components/SignupForm/index.tsx (1)
54-119: Consider extracting repetitive field pattern.Each form field follows the same pattern:
FormField→Label→OutlineInputFieldwithregister,invalid,message. Consider extracting a reusableFormFieldWrappercomponent to reduce duplication and improve maintainability.Example:
const FormFieldWrapper = ({ label, name, placeholder, validation, error }: FormFieldWrapperProps) => ( <S.FormField> <S.Label>{label}</S.Label> <OutlineInputField placeholder={placeholder} {...methods.register(name, validation)} invalid={!!error} message={error?.message} /> </S.FormField> );Then use it like:
<FormFieldWrapper label="이름" name="name" placeholder="이름을 입력하세요." validation={{ required: '이름을 입력하세요.' }} error={errors.name} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/pages/admin/Signup/components/SignupForm/index.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/admin/Signup/components/SignupForm/index.tsx (5)
src/pages/admin/Signup/type/signup.ts (1)
SignupFormInputs(1-7)src/pages/admin/Signup/api/signup.ts (1)
postSignupForm(3-15)src/styles/theme.ts (1)
theme(3-10)src/shared/components/Form/InputField/OutlineInputField.tsx (1)
OutlineInputField(9-20)src/shared/components/Button/index.tsx (1)
Button(17-64)
🪛 GitHub Actions: Dongarium FE CI/CD
src/pages/admin/Signup/components/SignupForm/index.tsx
[error] 36-36: 'errors' is defined but never used @typescript-eslint/no-unused-vars
🪛 GitHub Check: lint
src/pages/admin/Signup/components/SignupForm/index.tsx
[failure] 36-36:
'errors' is defined but never used
| placeholder='010-0000-0000' | ||
| {...methods.register('phoneNumber', { | ||
| required: '전화번호를 입력하세요.', | ||
| pattern: { | ||
| value: /^\d{2,3}-\d{3,4}-\d{4}$/, | ||
| message: '올바른 전화번호 형식이 아닙니다.', |
There was a problem hiding this comment.
Phone number pattern mismatch with placeholder.
The regex pattern allows 2-3 digit area codes (\d{2,3}), but the placeholder shows 010-0000-0000 (3 digits). If only 3-digit area codes like 010 are valid, update the pattern to /^010-\d{3,4}-\d{4}$/. Otherwise, update the placeholder to reflect the flexibility, e.g., 010-1234-5678 또는 02-1234-5678.
Apply this diff if only 3-digit area codes are intended:
pattern: {
- value: /^\d{2,3}-\d{3,4}-\d{4}$/,
+ value: /^010-\d{3,4}-\d{4}$/,
message: '올바른 전화번호 형식이 아닙니다.',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| placeholder='010-0000-0000' | |
| {...methods.register('phoneNumber', { | |
| required: '전화번호를 입력하세요.', | |
| pattern: { | |
| value: /^\d{2,3}-\d{3,4}-\d{4}$/, | |
| message: '올바른 전화번호 형식이 아닙니다.', | |
| placeholder='010-0000-0000' | |
| {...methods.register('phoneNumber', { | |
| required: '전화번호를 입력하세요.', | |
| pattern: { | |
| value: /^010-\d{3,4}-\d{4}$/, | |
| message: '올바른 전화번호 형식이 아닙니다.', |
🤖 Prompt for AI Agents
In src/pages/admin/Signup/components/SignupForm/index.tsx around lines 109-114,
the phone placeholder "010-0000-0000" conflicts with the current regex allowing
2-3 digit area codes; fix by either (A) if only 3-digit area codes like 010 are
valid, change the validation pattern to require "010" specifically (replace
current pattern with one matching /^010-\d{3,4}-\d{4}$/), or (B) if both 2- and
3-digit area codes are allowed, update the placeholder to reflect that
flexibility (e.g., "010-1234-5678 또는 02-1234-5678"); apply the corresponding
change to the register call and/or placeholder text so pattern and placeholder
match.
…ogin [FEAT] 관리자 Oauth 로그인 관련 Redirect 추가
…ogin [FEAT] 관리자 Oauth 로그인 관련 Redirect 추가
#️⃣연관된 이슈
📝작업 내용
스크린샷 (선택)
💬리뷰 요구사항(선택)
Summary by CodeRabbit
New Features
Bug Fixes / UI Changes