-
Notifications
You must be signed in to change notification settings - Fork 0
관리자 문의 조회 기능 구현 ( #issue 346 ) #352
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
Conversation
|
""" Walkthrough관리자 문의하기 조회 기능이 추가 및 확장되었습니다. 검색 파라미터(유저 ID, 시작일, 종료일)를 통한 필터링, 관련 UI 컴포넌트, 스타일 및 API/훅 구조가 도입 및 변경되었습니다. 깃허브 링크 업데이트 기능도 추가되어 사용자 프로필 정보 갱신이 가능해졌습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Admin as Admin UI
participant Lookup as AdminInquiryListLookup
participant Router as react-router-dom
participant Hook as useGetAllInquiries
participant API as getAllInquiries API
Admin->>Lookup: 필터 입력/제출
Lookup->>Router: URL 쿼리 파라미터 set
Router->>Hook: 파라미터 변경 감지
Hook->>API: getAllInquiries(childSearchParams)
API-->>Hook: 필터링된 문의 리스트 반환
Hook-->>Admin: 문의 리스트 렌더링
sequenceDiagram
participant User as 사용자
participant Profile as ProfileGithubSuccess
participant Hook as useGithubLink
participant API as patchGithubLink
User->>Profile: 깃허브 인증 성공 후 리다이렉트
Profile->>Hook: patchGithubLinkMutate(githubUrl)
Hook->>API: PATCH /user/github?githubUrl=
API-->>Hook: 응답
Hook-->>Profile: 성공/실패 모달 표시, 페이지 이동
Assessment against linked issues
Suggested reviewers
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
npm error Exit handler never called! 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms (1)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (6)
src/models/inquiry.ts (1)
10-14: 인터페이스 정의가 명확하고 적절합니다.검색 파라미터를 위한 인터페이스가 잘 정의되어 있습니다. 다만 검색 조건이 선택적일 수 있으므로 옵셔널 프로퍼티를 고려해볼 수 있습니다.
선택적 개선사항으로 다음과 같이 옵셔널 프로퍼티를 사용할 수 있습니다:
export interface AdminInquiryChangeSearchParams { - userId: string; - startDate: string; - endDate: string; + userId?: string; + startDate?: string; + endDate?: string; }src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx (1)
10-16: 빈 검색 파라미터 객체 생성이 적절합니다.프리뷰 컴포넌트에서는 필터링이 필요하지 않으므로 빈 문자열로 초기화한 것이 적절합니다. 다만 hook의 시그니처 변경으로 인한 결합도 증가를 고려해볼 필요가 있습니다.
선택적 개선사항으로 hook에서 기본값을 제공하여 결합도를 줄일 수 있습니다:
// useGetAllInquiries에서 기본값 제공 export const useGetAllInquiries = ( childSearchParams: AdminInquiryChangeSearchParams = { userId: '', startDate: '', endDate: '' } ) => { // ... };src/api/admin/customerService/inquiry.api.ts (1)
10-16: API 함수가 검색 파라미터를 지원하도록 올바르게 업데이트되었습니다.함수가 검색 파라미터를 받아 쿼리 파라미터로 전달하는 구조가 RESTful 패턴에 맞게 구현되었습니다.
매개변수 명명에 대한 개선 제안:
export const getAllInquiries = async ( - childSearchParams: AdminInquiryChangeSearchParams + searchParams: AdminInquiryChangeSearchParams ) => { try { const response = await httpClient.get<ApiAdminInquiry>(`/inquiry`, { - params: childSearchParams, + params: searchParams, }); return response.data.data; } catch (e) { console.error('전체 문의 조회 에러', e); throw e; } };
childSearchParams보다는searchParams가 더 명확한 의미를 전달합니다.src/components/admin/adminInquiry/AdminInquiry.styled.ts (1)
26-34: 상호작용 요소 중첩을 피하는 것을 고려해보세요.button 요소를 Link 내부에 중첩하는 것은 접근성 측면에서 문제가 될 수 있습니다. 이전 학습에서도 언급되었듯이 이런 경우 div를 사용하는 것이 더 의미적으로 올바릅니다.
-export const AdminInquiryUser = styled.button` +export const AdminInquiryUser = styled.div` width: fit-content; font-size: 1.1rem; z-index: 1; + cursor: pointer; transition: color 0.1s ease-in-out; &:hover { color: ${({ theme }) => theme.color.lightnavy}; } `;src/components/admin/adminInquiry/AdminInquiryListLookup.tsx (2)
47-74: 성능 최적화 및 중복 검증 로직
handleChangeDate함수가 매 렌더링마다 재생성되고 있으며, 날짜 검증 로직이 실시간 입력과 폼 제출 시 중복되어 있습니다.
useCallback을 사용하여 성능을 최적화하고 검증 로직을 통합하세요:+import React, { useState, useCallback } from 'react'; + const validateDateRange = useCallback((start: string, end: string) => { + if (start && end && start > end) { + return false; + } + return true; + }, []); + const handleChangeDate = useCallback(( e: React.ChangeEvent<HTMLInputElement>, key: SearchParamsInquiryKeyType - ) => { + ) => { const value = e.currentTarget.value; setSearchFilters((prev) => { const newFilters = { ...prev, [key]: value }; + + if (!validateDateRange(newFilters.startDate, newFilters.endDate)) { + handleModalOpen( + key === 'startDate' ? MODAL_MESSAGE.startDateInvalid : MODAL_MESSAGE.endDateInvalid + ); + return prev; + } + + return newFilters; }); - }; + }, [validateDateRange, handleModalOpen]);
84-89: 사용자 경험 개선 제안닉네임 입력 필드가 읽기 전용이지만 사용자에게 명확한 안내가 부족합니다. placeholder 텍스트만으로는 상호작용 방법이 명확하지 않을 수 있습니다.
사용자 가이드를 위한 시각적 힌트를 추가하는 것을 고려해보세요:
<S.LookupUser type='text' value={nickname} - placeholder='닉네임을 클릭하세요.' + placeholder='문의 목록에서 닉네임을 클릭하여 선택하세요.' readOnly + style={{ cursor: 'default', backgroundColor: '#f5f5f5' }} />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
src/api/admin/customerService/inquiry.api.ts(1 hunks)src/api/mypage.api.ts(2 hunks)src/components/admin/adminInquiry/AdminInquiry.styled.ts(1 hunks)src/components/admin/adminInquiry/AdminInquiry.tsx(2 hunks)src/components/admin/adminInquiry/AdminInquiryList.styled.ts(1 hunks)src/components/admin/adminInquiry/AdminInquiryList.tsx(2 hunks)src/components/admin/adminInquiry/AdminInquiryListLookup.styled.ts(1 hunks)src/components/admin/adminInquiry/AdminInquiryListLookup.tsx(1 hunks)src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx(1 hunks)src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx(2 hunks)src/constants/user/modalMessage.ts(1 hunks)src/hooks/admin/useGetAllInquiries.ts(1 hunks)src/hooks/user/useMyInfo.ts(2 hunks)src/models/inquiry.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: YouD0313
PR: devpalsPlus/frontend#334
File: src/components/common/admin/title/AdminTitle.styled.ts:4-10
Timestamp: 2025-06-05T15:59:56.230Z
Learning: YouD0313 prefers using position: fixed for admin headers due to layout requirements, even if it requires viewport-relative width calculations like calc(100vw - 20rem).
src/components/admin/adminInquiry/AdminInquiryList.styled.ts (3)
Learnt from: YouD0313
PR: devpalsPlus/frontend#342
File: src/components/user/mypage/activityLog/inquiries/inquiry/Inquiry.styled.ts:82-88
Timestamp: 2025-06-09T14:42:43.454Z
Learning: InquiryAnswerIconWrapper는 단일 ChevronRightIcon만 포함하며, 부모 InquiryAnswerContentWrapper가 이미 display: flex로 레이아웃을 제어하고 있어서 align-items: start 속성이 불필요할 수 있음
Learnt from: YouD0313
PR: devpalsPlus/frontend#334
File: src/components/common/admin/title/AdminTitle.styled.ts:4-10
Timestamp: 2025-06-05T15:59:56.230Z
Learning: YouD0313 prefers using position: fixed for admin headers due to layout requirements, even if it requires viewport-relative width calculations like calc(100vw - 20rem).
Learnt from: YouD0313
PR: devpalsPlus/frontend#334
File: src/components/common/admin/title/AdminTitle.styled.ts:4-10
Timestamp: 2025-06-05T16:04:56.917Z
Learning: YouD0313가 AdminTitle 컴포넌트에서 calc(100vw - 20rem)을 사용하는 이유: position: fixed 사용 시 내부 패딩 2rem이 제대로 적용되지 않아, 사이드바 너비(15rem)에 추가로 5rem을 더 빼서 총 20rem을 차감하여 레이아웃 문제를 해결함.
src/hooks/admin/useGetAllInquiries.ts (2)
Learnt from: layout-SY
PR: devpalsPlus/frontend#246
File: src/hooks/useAlarmList.ts:1-21
Timestamp: 2025-04-23T13:39:08.960Z
Learning: React Query의 useQuery 훅에서 queryFn으로 Promise를 반환하는 함수를 사용할 때는 불필요한 async/await을 사용하지 않는 것이 좋습니다. 예를 들어 `queryFn: async () => await getAlarmList()` 대신에 `queryFn: () => getAlarmList()`와 같이 직접 Promise를 반환하는 형태로 작성하는 것이 더 효율적입니다.
Learnt from: layout-SY
PR: devpalsPlus/frontend#246
File: src/hooks/useAlarmList.ts:1-21
Timestamp: 2025-04-23T13:39:08.960Z
Learning: React Query의 useQuery 훅에서 queryFn으로 Promise를 반환하는 함수를 사용할 때는 불필요한 async/await을 사용하지 않는 것이 좋습니다. 예를 들어 `queryFn: async () => await getAlarmList()` 대신에 `queryFn: () => getAlarmList()`와 같이 직접 Promise를 반환하는 형태로 작성하는 것이 더 효율적입니다.
src/components/admin/adminInquiry/AdminInquiry.styled.ts (2)
Learnt from: YouD0313
PR: devpalsPlus/frontend#255
File: src/components/common/customerService/CustomerServiceHeader.styled.ts:45-62
Timestamp: 2025-04-26T17:24:42.853Z
Learning: Interactive elements like buttons should not be nested inside other interactive elements like links (a tags). When creating a clickable UI inside a Link component, using a div instead of a button is more semantically correct.
Learnt from: YouD0313
PR: devpalsPlus/frontend#342
File: src/components/user/mypage/activityLog/inquiries/inquiry/Inquiry.styled.ts:82-88
Timestamp: 2025-06-09T14:42:43.454Z
Learning: InquiryAnswerIconWrapper는 단일 ChevronRightIcon만 포함하며, 부모 InquiryAnswerContentWrapper가 이미 display: flex로 레이아웃을 제어하고 있어서 align-items: start 속성이 불필요할 수 있음
src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx (4)
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
src/components/admin/adminInquiry/AdminInquiryList.tsx (4)
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
src/components/admin/adminInquiry/AdminInquiry.tsx (4)
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
src/components/admin/adminInquiry/AdminInquiryListLookup.tsx (4)
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
🧬 Code Graph Analysis (8)
src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx (2)
src/models/inquiry.ts (1)
AdminInquiryChangeSearchParams(10-14)src/hooks/admin/useGetAllInquiries.ts (1)
useGetAllInquiries(6-19)
src/api/admin/customerService/inquiry.api.ts (1)
src/models/inquiry.ts (1)
AdminInquiryChangeSearchParams(10-14)
src/hooks/admin/useGetAllInquiries.ts (3)
src/models/inquiry.ts (1)
AdminInquiryChangeSearchParams(10-14)src/hooks/queries/keys.ts (1)
Inquiries(52-54)src/api/admin/customerService/inquiry.api.ts (1)
getAllInquiries(10-22)
src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx (2)
src/hooks/useModal.ts (1)
useModal(3-36)src/hooks/user/useMyInfo.ts (1)
useGithubLink(92-108)
src/api/mypage.api.ts (2)
src/api/http.api.ts (1)
httpClient(80-80)src/models/apiCommon.ts (1)
ApiCommonBasicType(6-8)
src/components/admin/adminInquiry/AdminInquiry.tsx (1)
src/constants/routes.ts (1)
ADMIN_ROUTE(35-58)
src/hooks/user/useMyInfo.ts (2)
src/api/mypage.api.ts (1)
patchGithubLink(57-66)src/hooks/queries/keys.ts (1)
myInfoKey(12-14)
src/components/admin/adminInquiry/AdminInquiryListLookup.tsx (4)
src/hooks/useModal.ts (1)
useModal(3-36)src/models/inquiry.ts (1)
AdminInquiryChangeSearchParams(10-14)src/constants/user/modalMessage.ts (1)
MODAL_MESSAGE(1-39)src/components/admin/adminInquiry/AdminInquiryList.tsx (1)
SearchParamsInquiryKeyType(9-9)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: accessibility-test
🔇 Additional comments (23)
src/api/mypage.api.ts (1)
1-1: Import 추가 확인됨새로운
ApiCommonBasicTypeimport가 적절히 추가되었습니다.src/hooks/user/useMyInfo.ts (2)
11-11: Import 추가 확인됨새로운
patchGithubLinkAPI 함수 import가 적절히 추가되었습니다.
92-108: 잘 구현된 커스텀 훅
useGithubLink훅이 React Query 패턴을 올바르게 따르고 있습니다:
useMutation사용이 적절함- 성공 시 캐시 무효화로 데이터 일관성 보장
- 필요한 상태와 함수들을 적절히 반환
구현이 기존 패턴과 일치하며 재사용 가능한 구조입니다.
src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx (3)
7-7: Import 추가 확인됨새로운
useGithubLink훅 import가 적절히 추가되었습니다.
13-13: 훅 사용법 확인됨
useGithubLink훅에서 필요한 mutation 함수를 적절히 추출하고 있습니다.
34-34: 의존성 배열 올바르게 업데이트됨
useEffect에서 사용하는 모든 외부 변수들이 의존성 배열에 포함되어 있습니다. 이전 학습 내용에 따라 올바르게 구현되었습니다.src/constants/user/modalMessage.ts (1)
35-38: 날짜 유효성 검사를 위한 메시지가 적절히 추가되었습니다.날짜 범위 입력 검증을 위한 사용자 친화적인 메시지들이 기존 패턴과 일관성 있게 추가되었습니다.
src/components/admin/adminInquiry/AdminInquiryList.styled.ts (1)
9-10: 레이아웃 변경이 새로운 조회 기능에 적합합니다.수평 중앙 정렬에서 수직 컬럼 레이아웃으로 변경하여 문의 조회 필터 컴포넌트를 상단에 배치할 수 있도록 개선되었습니다.
src/components/admin/previewComponent/inquiresPreview/InquiresPreview.tsx (1)
7-7: 필요한 인터페이스 임포트가 추가되었습니다.업데이트된 hook과의 호환성을 위해 적절히 임포트되었습니다.
src/api/admin/customerService/inquiry.api.ts (1)
3-3: 필요한 타입 임포트가 추가되었습니다.새로운 검색 파라미터 인터페이스가 적절히 임포트되었습니다.
src/hooks/admin/useGetAllInquiries.ts (2)
6-8: 매개변수 타입 정의가 잘 구현되었습니다.
AdminInquiryChangeSearchParams타입을 받아서 필터링 기능을 지원하도록 적절히 구현되었습니다.
14-15: React Query queryKey와 queryFn 구현이 적절합니다.검색 매개변수를 queryKey에 포함시켜서 매개변수 변경 시 자동으로 재요청이 발생하도록 올바르게 구현되었습니다. 이전 학습에서 언급된 불필요한 async/await도 사용하지 않아 효율적입니다.
src/components/admin/adminInquiry/AdminInquiry.tsx (3)
12-12: URL 매개변수 관리를 위한 훅 추가가 적절합니다.사용자 필터링 기능을 위해
useSearchParams훅을 추가한 것이 적절합니다.
14-27: 클릭 이벤트 처리가 올바르게 구현되었습니다.
preventDefault와stopPropagation을 사용하여 링크 내부의 버튼 클릭이 부모 링크를 트리거하지 않도록 적절히 처리되었습니다. URL 매개변수 업데이트 로직도 정확합니다.
34-38: 사용자 상호작용 요소가 적절히 구현되었습니다.사용자 닉네임을 클릭 가능한 요소로 만들어 필터링 기능을 제공하는 것이 좋은 UX 개선입니다.
src/components/admin/adminInquiry/AdminInquiry.styled.ts (2)
22-24: wrapper 컴포넌트 추가가 적절합니다.상대 위치 지정을 위한 wrapper 컴포넌트 추가가 적절합니다.
36-48: 드롭다운 스타일이 잘 구현되었습니다.드롭다운 컴포넌트의 절대 위치 지정과 스타일링이 적절히 구현되었습니다.
src/components/admin/adminInquiry/AdminInquiryList.tsx (3)
9-9: 타입 정의가 적절합니다.
SearchParamsInquiryKeyType타입 정의가 재사용성을 위해 적절히 추가되었습니다.
11-19: URL 매개변수 처리가 올바르게 구현되었습니다.
useSearchParams를 사용하여 필터링 매개변수를 추출하고 훅에 전달하는 로직이 적절히 구현되었습니다.
33-33: 조회 컴포넌트 추가가 적절합니다.문의 목록 위에
AdminInquiryListLookup컴포넌트를 추가하여 필터링 UI를 제공하는 것이 좋은 UX 개선입니다.src/components/admin/adminInquiry/AdminInquiryListLookup.styled.ts (3)
3-28: 날짜 입력 필드 스타일링이 잘 구현되었습니다.날짜 입력 필드와 캘린더 피커에 대한 커스터마이징이 적절히 구현되었습니다. 특히 webkit 캘린더 피커 인디케이터를 투명하게 만든 것이 좋은 접근법입니다.
30-33: 폼 레이아웃이 적절합니다.flexbox를 사용한 레이아웃이 조회 UI에 적합하게 구현되었습니다.
51-67: 아이콘 버튼 스타일링이 일관성 있게 구현되었습니다.아이콘 wrapper와 버튼들의 스타일링이 테마 색상을 사용하여 일관성 있게 구현되었습니다.
| export const patchGithubLink = async (githubUrl: string) => { | ||
| try { | ||
| await httpClient.patch<ApiCommonBasicType>('/user/github', { | ||
| params: { githubUrl }, | ||
| }); | ||
| } catch (error) { | ||
| console.error('프로필 깃허브 업데이트: ', error); | ||
| throw error; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API 요청 구조 및 반환값 처리 개선 필요
현재 구현에서 몇 가지 문제점이 발견됩니다:
params속성 사용이 부적절할 수 있습니다 - PATCH 요청에서는 일반적으로 request body 또는 query parameter로 데이터를 전송합니다- 응답 데이터를 반환하지 않아 호출부에서 성공 여부를 확인하기 어렵습니다
다음과 같이 수정을 권장합니다:
-export const patchGithubLink = async (githubUrl: string) => {
- try {
- await httpClient.patch<ApiCommonBasicType>('/user/github', {
- params: { githubUrl },
- });
- } catch (error) {
- console.error('프로필 깃허브 업데이트: ', error);
- throw error;
- }
-};
+export const patchGithubLink = async (githubUrl: string) => {
+ try {
+ const response = await httpClient.patch<ApiCommonBasicType>(
+ '/user/github',
+ { githubUrl }
+ );
+ return response.data;
+ } catch (error) {
+ console.error('프로필 깃허브 업데이트: ', error);
+ throw error;
+ }
+};또는 query parameter로 전송하려면:
- await httpClient.patch<ApiCommonBasicType>('/user/github', {
- params: { githubUrl },
- });
+ const response = await httpClient.patch<ApiCommonBasicType>(
+ `/user/github?githubUrl=${encodeURIComponent(githubUrl)}`
+ );
+ return response.data;📝 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.
| export const patchGithubLink = async (githubUrl: string) => { | |
| try { | |
| await httpClient.patch<ApiCommonBasicType>('/user/github', { | |
| params: { githubUrl }, | |
| }); | |
| } catch (error) { | |
| console.error('프로필 깃허브 업데이트: ', error); | |
| throw error; | |
| } | |
| }; | |
| export const patchGithubLink = async (githubUrl: string) => { | |
| try { | |
| const response = await httpClient.patch<ApiCommonBasicType>( | |
| '/user/github', | |
| { githubUrl } | |
| ); | |
| return response.data; | |
| } catch (error) { | |
| console.error('프로필 깃허브 업데이트: ', error); | |
| throw error; | |
| } | |
| }; |
🤖 Prompt for AI Agents
In src/api/mypage.api.ts lines 57 to 66, the patchGithubLink function
incorrectly uses the 'params' property to send data in a PATCH request, which
should instead send the githubUrl in the request body or as query parameters.
Also, the function does not return the response, making it hard for callers to
verify success. Fix this by moving githubUrl into the request body (e.g., {
githubUrl }) and returning the awaited response from httpClient.patch so the
caller can handle the result.
|
|
||
| if (githubUrl) { | ||
| patchGithubLinkMutate(githubUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
비동기 처리 및 에러 핸들링 개선 필요
현재 구현에서 몇 가지 개선이 필요합니다:
patchGithubLinkMutate는 비동기 함수이지만await없이 호출되고 있습니다- mutation의 성공/실패 상태를 처리하지 않아 실제 API 호출 결과와 관계없이 성공 모달이 표시됩니다
다음과 같이 수정을 권장합니다:
- if (githubUrl) {
- patchGithubLinkMutate(githubUrl);
- handleModalOpen(MODAL_MESSAGE.githubProfileSuccess);
- setTimeout(() => {
- navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`, {
- state: { githubUrl },
- });
- }, 1000);
- }
+ if (githubUrl) {
+ patchGithubLinkMutate(githubUrl, {
+ onSuccess: () => {
+ handleModalOpen(MODAL_MESSAGE.githubProfileSuccess);
+ setTimeout(() => {
+ navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`, {
+ state: { githubUrl },
+ });
+ }, 1000);
+ },
+ onError: () => {
+ handleModalOpen(MODAL_MESSAGE.githubProfileFail);
+ setTimeout(() => {
+ navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`);
+ }, 1000);
+ }
+ });
+ }📝 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.
| if (githubUrl) { | |
| patchGithubLinkMutate(githubUrl); | |
| if (githubUrl) { | |
| patchGithubLinkMutate(githubUrl, { | |
| onSuccess: () => { | |
| handleModalOpen(MODAL_MESSAGE.githubProfileSuccess); | |
| setTimeout(() => { | |
| navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`, { | |
| state: { githubUrl }, | |
| }); | |
| }, 1000); | |
| }, | |
| onError: () => { | |
| handleModalOpen(MODAL_MESSAGE.githubProfileFail); | |
| setTimeout(() => { | |
| navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`); | |
| }, 1000); | |
| }, | |
| }); | |
| } |
🤖 Prompt for AI Agents
In src/components/user/mypage/myProfile/editProfile/ProfileGithubSuccess.tsx
around lines 18 to 20, the patchGithubLinkMutate function is called without
awaiting its asynchronous result and lacks error handling. Modify the code to
await the patchGithubLinkMutate call and handle its promise properly by adding
try-catch or using then-catch to manage success and failure states, ensuring the
success modal only shows on successful mutation and errors are handled
gracefully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ProfileGithubSuccess.tsx에서 useEffect를 불러올 때 async를 사용중인데 문제가 되니?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@YouD0313 useEffect에서 async를 사용하는 현재 패턴은 전혀 문제가 되지 않습니다!
useEffect(() => {
(async () => {
// 비동기 코드
})();
}, []);이런 즉시 실행 함수 표현식(IIFE) 패턴은 useEffect 내에서 비동기 코드를 사용할 때 매우 일반적이고 권장되는 방법입니다. useEffect 자체는 async 함수를 직접 받을 수 없기 때문에 이런 패턴을 사용하는 것이 정상입니다.
제가 이전 코멘트에서 지적한 문제는 async 사용이 아니라 patchGithubLinkMutate의 에러 핸들링 부족이었습니다. 현재 코드는 API 호출의 성공/실패 여부와 관계없이 항상 성공 모달을 표시하고 있어서, 실제로 API 호출이 실패하더라도 사용자에게는 성공했다고 잘못된 피드백을 주게 됩니다.
async 패턴 자체는 완전히 올바르게 사용하고 계십니다! 👍
🧠 Learnings used
Learnt from: layout-SY
PR: devpalsPlus/frontend#246
File: src/hooks/useAlarmList.ts:1-21
Timestamp: 2025-04-23T13:39:08.960Z
Learning: React Query의 useQuery 훅에서 queryFn으로 Promise를 반환하는 함수를 사용할 때는 불필요한 async/await을 사용하지 않는 것이 좋습니다. 예를 들어 `queryFn: async () => await getAlarmList()` 대신에 `queryFn: () => getAlarmList()`와 같이 직접 Promise를 반환하는 형태로 작성하는 것이 더 효율적입니다.
Learnt from: layout-SY
PR: devpalsPlus/frontend#246
File: src/hooks/useAlarmList.ts:1-21
Timestamp: 2025-04-23T13:39:08.960Z
Learning: React Query의 useQuery 훅에서 queryFn으로 Promise를 반환하는 함수를 사용할 때는 불필요한 async/await을 사용하지 않는 것이 좋습니다. 예를 들어 `queryFn: async () => await getAlarmList()` 대신에 `queryFn: () => getAlarmList()`와 같이 직접 Promise를 반환하는 형태로 작성하는 것이 더 효율적입니다.
Learnt from: layout-SY
PR: devpalsPlus/frontend#260
File: src/components/common/header/Header.tsx:30-32
Timestamp: 2025-04-30T06:28:07.990Z
Learning: testLiveAlarm 함수는 이미 내부적으로 에러 처리를 하고 Promise를 반환하므로, 컴포넌트에서 호출할 때 async/await과 try-catch 구문 없이 직접 호출해도 충분하다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#334
File: src/components/common/admin/title/AdminTitle.styled.ts:4-10
Timestamp: 2025-06-05T15:59:56.230Z
Learning: YouD0313 prefers using position: fixed for admin headers due to layout requirements, even if it requires viewport-relative width calculations like calc(100vw - 20rem).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그럼 githubUrl 조건문처리와 다르다고 생각하는거니? 커스텀훅에서 처리하는게 맞다고 얘기하는거야?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@YouD0313 좋은 질문입니다! 두 가지는 서로 다른 레벨의 검증이라고 생각합니다.
현재 상황 분석
1. githubUrl 조건문 처리 (클라이언트 사이드 검증)
- URL 파라미터가 존재하는지 확인
- 사용자가 올바른 경로로 왔는지 검증
2. API 호출 성공/실패 처리 (서버 통신 검증)
- 실제 서버와의 통신 결과 확인
- 네트워크 오류, 서버 오류 등을 처리
둘 다 필요한 이유
// 현재: githubUrl이 있어도 API 실패시 성공 모달이 표시됨
if (githubUrl) {
patchGithubLinkMutate(githubUrl); // API 실패해도
handleModalOpen(MODAL_MESSAGE.githubProfileSuccess); // 성공 모달 표시
}처리 위치에 대한 견해
컴포넌트에서 처리하는 것이 더 적절하다고 생각합니다:
- ✅ 각 컴포넌트마다 다른 성공/실패 UI 로직 구현 가능
- ✅ 현재 Modal과 Navigation 로직이 컴포넌트에 종속됨
- ✅ React Query의 onSuccess/onError 패턴과 일치
커스텀훅에서 처리하면 모든 컴포넌트가 동일한 에러 처리를 강제받게 되어 유연성이 떨어집니다.
결론: githubUrl 체크와 API 에러 처리는 모두 필요하며, 현재 구조에서는 컴포넌트의 onSuccess/onError 콜백 사용이 적절합니다.
🧠 Learnings used
Learnt from: layout-SY
PR: devpalsPlus/frontend#246
File: src/hooks/useAlarmList.ts:1-21
Timestamp: 2025-04-23T13:39:08.960Z
Learning: React Query의 useQuery 훅에서 queryFn으로 Promise를 반환하는 함수를 사용할 때는 불필요한 async/await을 사용하지 않는 것이 좋습니다. 예를 들어 `queryFn: async () => await getAlarmList()` 대신에 `queryFn: () => getAlarmList()`와 같이 직접 Promise를 반환하는 형태로 작성하는 것이 더 효율적입니다.
Learnt from: layout-SY
PR: devpalsPlus/frontend#246
File: src/hooks/useAlarmList.ts:1-21
Timestamp: 2025-04-23T13:39:08.960Z
Learning: React Query의 useQuery 훅에서 queryFn으로 Promise를 반환하는 함수를 사용할 때는 불필요한 async/await을 사용하지 않는 것이 좋습니다. 예를 들어 `queryFn: async () => await getAlarmList()` 대신에 `queryFn: () => getAlarmList()`와 같이 직접 Promise를 반환하는 형태로 작성하는 것이 더 효율적입니다.
Learnt from: layout-SY
PR: devpalsPlus/frontend#260
File: src/components/common/header/Header.tsx:30-32
Timestamp: 2025-04-30T06:28:07.990Z
Learning: testLiveAlarm 함수는 이미 내부적으로 에러 처리를 하고 Promise를 반환하므로, 컴포넌트에서 호출할 때 async/await과 try-catch 구문 없이 직접 호출해도 충분하다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#278
File: src/pages/login/LoginSuccess.tsx:13-24
Timestamp: 2025-05-11T09:39:02.041Z
Learning: useEffect 내에서 사용하는 모든 외부 변수(예: searchParams, storeLogin, navigate)는 의존성 배열에 포함되어야 합니다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#334
File: src/components/common/admin/title/AdminTitle.styled.ts:4-10
Timestamp: 2025-06-05T15:59:56.230Z
Learning: YouD0313 prefers using position: fixed for admin headers due to layout requirements, even if it requires viewport-relative width calculations like calc(100vw - 20rem).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
커스텀훅에서 처리된다면 컴포넌트에서 조건문이 필요할까?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@YouD0313 정말 좋은 지적입니다! 맞습니다. 커스텀훅에서 전체 플로우를 처리한다면 컴포넌트의 조건문이 불필요해집니다.
현재 구조의 문제점
// 컴포넌트가 너무 많은 책임을 가짐
if (githubUrl) {
patchGithubLinkMutate(githubUrl);
handleModalOpen(MODAL_MESSAGE.githubProfileSuccess);
// navigation logic...
} else {
handleModalOpen(MODAL_MESSAGE.githubProfileFail);
// navigation logic...
}개선된 구조 제안
커스텀훅에서 전체 처리:
// useGithubProcess.ts
export const useGithubProcess = (onModalOpen, navigate) => {
const { patchGithubLinkMutate } = useGithubLink();
const handleGithubProcess = useCallback((githubUrl) => {
if (!githubUrl) {
onModalOpen(MODAL_MESSAGE.githubProfileFail);
setTimeout(() => navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`), 1000);
return;
}
patchGithubLinkMutate(githubUrl, {
onSuccess: () => {
onModalOpen(MODAL_MESSAGE.githubProfileSuccess);
setTimeout(() => navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`, { state: { githubUrl } }), 1000);
},
onError: () => {
onModalOpen(MODAL_MESSAGE.githubProfileFail);
setTimeout(() => navigate(`${ROUTES.mypage}/${ROUTES.mypageEdit}`), 1000);
}
});
}, []);
return { handleGithubProcess };
};컴포넌트는 단순해짐:
// ProfileGithubSuccess.tsx
export default function ProfileGithubSuccess() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const { isOpen, message, handleModalOpen, handleModalClose } = useModal();
const { handleGithubProcess } = useGithubProcess(handleModalOpen, navigate);
useEffect(() => {
const githubUrl = searchParams.get('githubUrl');
handleGithubProcess(githubUrl);
}, [searchParams, handleGithubProcess]);
return <Modal isOpen={isOpen} onClose={handleModalClose}>{message}</Modal>;
}장점:
- ✅ 관심사의 분리: 훅은 비즈니스 로직, 컴포넌트는 UI
- ✅ 테스트 용이성: 각각 독립적으로 테스트 가능
- ✅ 재사용성: 다른 컴포넌트에서도 동일한 로직 사용 가능
- ✅ 컴포넌트 단순화: 조건문 제거
훌륭한 아키텍처 인사이트입니다! 👍
🧠 Learnings used
Learnt from: layout-SY
PR: devpalsPlus/frontend#260
File: src/components/common/header/Header.tsx:30-32
Timestamp: 2025-04-30T06:28:07.990Z
Learning: testLiveAlarm 함수는 이미 내부적으로 에러 처리를 하고 Promise를 반환하므로, 컴포넌트에서 호출할 때 async/await과 try-catch 구문 없이 직접 호출해도 충분하다.
Learnt from: YouD0313
PR: devpalsPlus/frontend#334
File: src/components/common/admin/title/AdminTitle.styled.ts:4-10
Timestamp: 2025-06-05T15:59:56.230Z
Learning: YouD0313 prefers using position: fixed for admin headers due to layout requirements, even if it requires viewport-relative width calculations like calc(100vw - 20rem).
src/api/mypage.api.ts
Outdated
| @@ -1,3 +1,4 @@ | |||
| import { ApiCommonBasicType } from '../models/apiCommon'; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type
…ess 컴포넌트에서 모달 및 내비게이션 로직 제거
구현내용
관리자 문의 조회 기능 구현
연관이슈
close #346
Summary by CodeRabbit
신규 기능
버그 수정
스타일
문서화