feat: 홈페이지 개편 - #339
Conversation
Walkthrough홈페이지 재설계 관련: 추천 API·훅·타입 추가, 추천·검색·필터 클라이언트 컴포넌트 도입, TempleStayCard에 사이즈 변형 및 스타일 레시피 적용, 위시리스트 낙관적 업데이트 흐름을 추가합니다. Changes
Sequence DiagramsequenceDiagram
participant User
participant Client as RecommendTempleClient
participant UserAPI as User API
participant RecommendAPI as Recommend API
participant Cache as ReactQuery Cache
participant WishlistAPI as Wishlist API
participant Modal as Login Modal
User->>Client: 페이지 로드
Client->>UserAPI: useGetMyPage(enabled)
UserAPI-->>Client: 사용자 정보 (type, name, hasType)
alt 사용자 타입 보유
Client->>RecommendAPI: getTypeRecommend()
RecommendAPI-->>Client: 타입별 추천 목록
else 타입 미보유
Client->>RecommendAPI: getTypeRandom()
RecommendAPI-->>Client: 무작위 추천 목록
end
Client-->>User: 카드 3개 렌더링
alt 위시리스트 토글
User->>Client: 토글 클릭
alt 로그인됨
Client->>Cache: 낙관적 업데이트(로컬 변경)
Client->>WishlistAPI: add/remove 요청
WishlistAPI-->>Client: 성공
Client->>Cache: 관련 쿼리 무효화
else 미로그인
Client->>Modal: 로그인 모달 표시
Modal-->>User: 로그인 유도
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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. Comment |
|
🪷 Storybook 확인 🪷 |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/card/templeStayCard/TempleStayCard.tsx (1)
55-78: 호버 효과가 적용되지 않습니다.CSS 파일에
verticalImage,horizontalImage호버 스타일이 정의되어 있지만, 이 컴포넌트에서는styles.image({ layout })recipe만 사용하고 있습니다. 또한 컨테이너도styles.container({ layout, size })recipe를 사용하고 있어서, CSS의 호버 셀렉터(${verticalContainer}:hover &)가 동작하지 않습니다.호버 효과를 적용하려면 다음 중 하나의 방법이 필요합니다:
- 컨테이너에 레이아웃별 hover target 클래스를 추가하고, 이미지에도 해당 hover 스타일 클래스를 추가
- 또는
imagerecipe 내에 호버 효과를 통합🔧 제안하는 수정 방법 (방법 1)
<a href={link} - className={styles.container({ layout, size })} + className={`${styles.container({ layout, size })} ${ + layout === 'vertical' + ? size === 'small' + ? styles.verticalSmallContainer + : styles.verticalContainer + : styles.horizontalContainer + }`} onClick={() => logClickEvent('click_card_detail', { label: String(item.templestayId), }) }> {item.imgUrl ? ( <section className={styles.imgSection({ layout, size })}> <img - className={styles.image({ layout })} + className={`${styles.image({ layout })} ${ + layout === 'vertical' ? styles.verticalImage : styles.horizontalImage + }`} src={item.imgUrl} alt={item.templeName + ' 대표사진'} />
🤖 Fix all issues with AI agents
In `@src/components/detailTitle/DetailTitle.tsx`:
- Around line 31-37: The DetailTitle component currently renders the title prop
as a div when title is a ReactNode, losing heading semantics; change the
rendering so that the h2 element is always used and the ReactNode is rendered
inside the h2 (keeping titleStyle({ size })) so both string and ReactNode cases
use <h2> semantics; update the JSX in DetailTitle (where title, titleStyle, and
size are referenced) to always output an h2 with the title content and preserve
existing className/style logic.
🧹 Nitpick comments (4)
src/components/search/searchBar/SearchBar.tsx (1)
71-73: 주석 처리된 레거시 버튼 정리 권장.
사용하지 않는 JSX 주석은 유지보수 노이즈가 됩니다.🧹 정리 제안
- {/* <button className={styles.pointer} onClick={() => handleClearInput()}> - <Icon.IcnCloseLargeGray /> - </button> */}src/apis/recommend/type.ts (1)
11-17: 중복 응답 타입은 별칭으로 정리하면 유지보수에 유리합니다.
TypeRandomResponse와 동일하므로 한 곳만 변경해도 되도록 묶는 편이 깔끔합니다.♻️ 제안 리팩터링
-export interface TypeRecommendResponse { - results: TypeRandomTemplestay[]; -} +export type TypeRecommendResponse = TypeRandomResponse;src/app/RecommendTempleClient.tsx (1)
24-24: import 경로 스타일 불일치다른 import들은
@componentsalias를 사용하고 있는데, 이 라인만 상대 경로를 사용하고 있습니다. 일관성을 위해 alias 사용을 권장합니다.♻️ 제안하는 수정
-import styles from '../components/card/recommendCard/recommendCard.css'; +import styles from '@components/card/recommendCard/recommendCard.css';src/components/card/templeStayCard/templeStayCard.css.ts (1)
129-134:borderRadius값 형식 불일치Line 133에서
borderRadius: 4를 숫자로 사용하고 있는데, 다른 곳에서는'4px'문자열을 사용하고 있습니다 (예: line 24, 105, 110, 138). 일관성을 위해 통일하는 것을 권장합니다.♻️ 제안하는 수정
vertical: { width: '16.3rem', height: '17.2rem', - borderRadius: 4, + borderRadius: '4px', },
| <div className={detailTitleStyle}> | ||
| <div className={titleContainerStyle}> | ||
| <h2 className={titleStyle({ size })}>{title}</h2> | ||
| {typeof title === 'string' ? ( | ||
| <h2 className={titleStyle({ size })}>{title}</h2> | ||
| ) : ( | ||
| <div className={titleStyle({ size })}>{title}</div> | ||
| )} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the DetailTitle.tsx file
fd DetailTitle.tsxRepository: JEOLLOGA/JEOLLOGA-CLIENT
Length of output: 110
🏁 Script executed:
# Let's also check the overall structure of the detailTitle directory
fd -t f . src/components/detailTitle/ 2>/dev/null | head -20Repository: JEOLLOGA/JEOLLOGA-CLIENT
Length of output: 156
🏁 Script executed:
# Search for how DetailTitle is being used in the codebase
rg "DetailTitle" --type tsx --type ts -A 3 -B 1 | head -100Repository: JEOLLOGA/JEOLLOGA-CLIENT
Length of output: 95
🏁 Script executed:
# Let me read the DetailTitle.tsx file to verify the code
cat -n src/components/detailTitle/DetailTitle.tsxRepository: JEOLLOGA/JEOLLOGA-CLIENT
Length of output: 1512
🏁 Script executed:
# Search for DetailTitle usage without specifying file type
rg "DetailTitle" -A 3 -B 1 | head -150Repository: JEOLLOGA/JEOLLOGA-CLIENT
Length of output: 11553
ReactNode 전달 시 heading 시맨틱 손실
title prop이 ReactNode인 경우 div로 렌더링되어 스크린리더와 SEO에서 제목 계층이 깨집니다. h2 태그 내부에 ReactNode를 렌더링하도록 변경하여 시맨틱을 유지해야 합니다.
제안 수정안
- {typeof title === 'string' ? (
- <h2 className={titleStyle({ size })}>{title}</h2>
- ) : (
- <div className={titleStyle({ size })}>{title}</div>
- )}
+ <h2 className={titleStyle({ size })}>
+ {title}
+ </h2>📝 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.
| <div className={detailTitleStyle}> | |
| <div className={titleContainerStyle}> | |
| <h2 className={titleStyle({ size })}>{title}</h2> | |
| {typeof title === 'string' ? ( | |
| <h2 className={titleStyle({ size })}>{title}</h2> | |
| ) : ( | |
| <div className={titleStyle({ size })}>{title}</div> | |
| )} | |
| <div className={detailTitleStyle}> | |
| <div className={titleContainerStyle}> | |
| <h2 className={titleStyle({ size })}> | |
| {title} | |
| </h2> |
🤖 Prompt for AI Agents
In `@src/components/detailTitle/DetailTitle.tsx` around lines 31 - 37, The
DetailTitle component currently renders the title prop as a div when title is a
ReactNode, losing heading semantics; change the rendering so that the h2 element
is always used and the ReactNode is rendered inside the h2 (keeping titleStyle({
size })) so both string and ReactNode cases use <h2> semantics; update the JSX
in DetailTitle (where title, titleStyle, and size are referenced) to always
output an h2 with the title content and preserve existing className/style logic.
🛰️ 관련 이슈
🧑💻 작업 내용
📸 스크린샷 (선택)
Summary by CodeRabbit
릴리스 노트
새로운 기능
스타일
✏️ Tip: You can customize this high-level summary in your review settings.