-
Notifications
You must be signed in to change notification settings - Fork 3
Feat: 스켈레톤 컴포넌트 추가 #148
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
Feat: 스켈레톤 컴포넌트 추가 #148
Conversation
Walkthrough이 변경 사항은 Changes
Possibly related PRs
Suggested reviewers
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
src/components/common/crew-list/crew-card.tsxOops! Something went wrong! :( ESLint: 8.57.1 ESLint couldn't determine the plugin "react-hooks" uniquely.
Please remove the "plugins" setting from either config or remove either plugin installation. If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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: 4
🧹 Outside diff range and nitpick comments (8)
src/components/common/skeleton/gathering-skeleton-list/index.tsx (1)
3-5: prop 이름을 더 명확하게 개선하는 것이 좋습니다.
num이라는 prop 이름은 그 목적이 명확하지 않습니다. 스켈레톤 아이템의 개수를 나타내는 것이므로,itemCount또는skeletonCount와 같이 더 명시적인 이름을 사용하는 것이 좋습니다.interface GatheringSkeletonListProps { - num: number; + itemCount: number; }src/components/common/skeleton/crew-skeleton-list/index.tsx (1)
3-6: prop 이름을 더 명확하게 개선하면 좋을 것 같습니다.
num과columnprop의 이름이 다소 모호합니다. 아래와 같이 더 명확한 이름을 사용하는 것을 제안드립니다:
num→skeletonCountcolumn→columnCountinterface CrewSkeletonListProps { - num: number; - column?: number; + skeletonCount: number; + columnCount?: number; }src/components/common/skeleton/my-gathering-skeleton/index.tsx (2)
3-3: 컴포넌트 문서화 및 타입 정의 추가 제안컴포넌트의 재사용성과 유지보수성을 높이기 위해 다음 사항들을 추가하면 좋을 것 같습니다:
- JSDoc 문서화
- Props 인터페이스 정의
+interface MyGatheringSkeletonProps { + className?: string; +} + +/** + * 모임 정보가 로딩중일 때 표시되는 스켈레톤 UI 컴포넌트 + */ -export default function MyGatheringSkeleton() { +export default function MyGatheringSkeleton({ className }: MyGatheringSkeletonProps) {
5-15: 시맨틱 마크업 및 상수 추출 제안현재 구현은 잘 작동하지만, 다음과 같은 개선사항들을 고려해보시면 좋을 것 같습니다:
- div 대신 시맨틱 HTML 요소 사용
- 반복되는 크기값을 상수로 추출
+const SKELETON_SIZES = { + image: { + default: 'h-28 w-28', + md: 'md:h-32 md:w-32' + }, + title: 'h-4 w-40', + description: 'h-4 w-32', + status: 'h-4 w-24' +} as const; + export default function MyGatheringSkeleton() { return ( - <div className="flex gap-6 p-6"> - <Skeleton className="h-28 w-28 rounded-xl md:h-32 md:w-32" /> - <div className="relative flex flex-col gap-3"> - <Skeleton className="h-4 w-40" /> + <article className="flex gap-6 p-6"> + <Skeleton className={`${SKELETON_SIZES.image.default} rounded-xl ${SKELETON_SIZES.image.md}`} /> + <section className="relative flex flex-col gap-3"> + <Skeleton className={SKELETON_SIZES.title} /> <div className="flex gap-2"> - <Skeleton className="h-4 w-32" /> - <Skeleton className="h-4 w-24" /> + <Skeleton className={SKELETON_SIZES.description} /> + <Skeleton className={SKELETON_SIZES.status} /> </div> - <Skeleton className="absolute bottom-0 h-4 w-24" /> - </div> - </div> + <Skeleton className={`absolute bottom-0 ${SKELETON_SIZES.status}`} /> + </section> + </article>src/app/(crew)/my-crew/hosted/page.tsx (1)
Line range hint
3-3: 사용하지 않는 import 제거 필요
CrewSkeletonList로 대체되었으므로Loaderimport는 더 이상 필요하지 않습니다.다음과 같이 수정해주세요:
- import { Loader } from '@mantine/core'; import { useGetMyCrewHostedQuery } from '@/src/_queries/crew/my-crew-hosted-list-query'; import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll'; import CrewCardList from '@/src/components/common/crew-list/crew-card-list'; import CrewSkeletonList from '@/src/components/common/skeleton/crew-skeleton-list';Also applies to: 7-7
src/app/(crew)/my-crew/joined/page.tsx (1)
19-19: 접근성 개선을 위한 제안이 있습니다.스켈레톤 UI는 시각적으로 로딩 상태를 잘 표현하고 있지만, 스크린 리더 사용자를 위한 접근성 개선이 필요해 보입니다.
다음과 같이 aria-label을 추가하는 것을 제안드립니다:
-<CrewSkeletonList num={6} column={1} /> +<CrewSkeletonList num={6} column={1} aria-label="크루 목록을 불러오는 중입니다" />src/components/gathering-list/liked-list-container.tsx (1)
41-46: 스켈레톤 UI 구현이 잘 되었으나, 상수 정의가 필요합니다.스켈레톤 아이템의 개수(6)를 매직 넘버로 직접 사용하는 대신 상수로 정의하면 좋겠습니다.
다음과 같이 변경을 제안합니다:
+const SKELETON_ITEMS_COUNT = 6; export default function LikedList() { // ... if (isLoading) return ( <div className="mx-auto max-w-[1200px] px-4"> - <GatheringSkeletonList num={6} /> + <GatheringSkeletonList num={SKELETON_ITEMS_COUNT} /> </div> ); // ... }src/app/(crew)/page.tsx (1)
5-5: 불필요한 import 제거 필요
Skeleton컴포넌트가 직접적으로 사용되지 않고 있습니다. 사용하지 않는 import는 제거하는 것이 좋습니다.다음과 같이 수정해주세요:
-import { Divider, Loader, Skeleton, TextInput } from '@mantine/core'; +import { Divider, Loader, TextInput } from '@mantine/core';
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
src/app/(crew)/my-crew/hosted/page.tsx(2 hunks)src/app/(crew)/my-crew/joined/page.tsx(2 hunks)src/app/(crew)/page.tsx(3 hunks)src/components/common/skeleton/crew-skeleton-list/index.tsx(1 hunks)src/components/common/skeleton/crew-skeleton/index.tsx(1 hunks)src/components/common/skeleton/gathering-skeleton-list/index.tsx(1 hunks)src/components/common/skeleton/gathering-skeleton/index.tsx(1 hunks)src/components/common/skeleton/my-gathering-skeleton/index.tsx(1 hunks)src/components/gathering-list/liked-list-container.tsx(2 hunks)
✅ Files skipped from review due to trivial changes (2)
- src/components/common/skeleton/crew-skeleton/index.tsx
- src/components/common/skeleton/gathering-skeleton/index.tsx
🔇 Additional comments (7)
src/components/common/skeleton/gathering-skeleton-list/index.tsx (1)
9-9: 반응형 그리드 레이아웃이 적절히 구현되었습니다.
모바일(1열), 태블릿(2열), 데스크톱(3열)에 대한 반응형 레이아웃이 잘 구현되어 있습니다.
src/components/common/skeleton/my-gathering-skeleton/index.tsx (1)
1-1: 깔끔한 import 구문입니다!
필요한 Skeleton 컴포넌트만 정확하게 import 되어 있습니다.
src/app/(crew)/my-crew/hosted/page.tsx (1)
19-19: 스켈레톤 UI 구현이 적절해 보입니다
로딩 상태를 위한 스켈레톤 UI 구현이 잘 되었습니다. 다만, 타입 안정성을 위해 props 타입을 확인해보시면 좋겠습니다.
CrewSkeletonList 컴포넌트의 props 타입을 확인하기 위해 다음 스크립트를 실행합니다:
✅ Verification successful
Props 타입이 올바르게 정의되어 있습니다
CrewSkeletonList 컴포넌트의 props는 적절하게 타입이 정의되어 있으며, 사용하신 num={6} column={1} 값이 타입 정의와 일치합니다:
num: number(필수)column?: number(선택, 기본값 제공)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify CrewSkeletonList component props types
ast-grep --pattern 'interface $interface {
$$$
}' src/components/common/skeleton/crew-skeleton-list/index.tsx
Length of output: 113
Script:
#!/bin/bash
# Let's first check if the file exists and see its content
fd "crew-skeleton-list" --type f
# Then let's try to find type definitions or interfaces using ripgrep
rg "type|interface.*Props" -A 5 --type tsx
Length of output: 105
Script:
#!/bin/bash
# Let's try to find the file first
fd "crew-skeleton-list"
# Then let's look for type definitions using ripgrep without file type restriction
rg "type|interface.*Props" -A 5 "crew-skeleton-list"
# Also search for the component definition
rg "CrewSkeletonList" -A 5
Length of output: 4011
src/app/(crew)/my-crew/joined/page.tsx (2)
7-7: 깔끔한 임포트 구문입니다!
스켈레톤 컴포넌트의 임포트가 일관된 패턴을 따르고 있습니다.
18-22: 로딩 상태 처리가 잘 구현되어 있습니다.
초기 로딩과 다음 페이지 로딩 시 스켈레톤 UI를 일관되게 표시하고 있으며, 무한 스크롤을 위한 ref 처리도 적절합니다.
src/components/gathering-list/liked-list-container.tsx (1)
8-8: 스켈레톤 컴포넌트 임포트가 적절히 추가되었습니다.
컴포넌트 임포트 위치와 상대 경로가 적절합니다.
src/app/(crew)/page.tsx (1)
137-137: 스켈레톤 UI 구현이 적절해 보입니다
로딩 상태 표시를 위한 스켈레톤 컴포넌트 구현이 적절합니다:
- 페이지네이션 사이즈(6)와 일치하는 스켈레톤 개수
- 그리드 레이아웃을 위한 column 속성 적용
다음 스크립트로 스켈레톤 컴포넌트의 구현을 확인해보세요:
✅ Verification successful
스켈레톤 UI 구현이 일관되게 적용되어 있습니다
스켈레톤 컴포넌트의 구현과 사용이 적절하게 되어 있음을 확인했습니다:
- CrewSkeletonList가 재사용 가능한 컴포넌트로 구현되어 있음
- 다른 페이지들(joined, hosted)에서도 동일한 패턴으로 사용됨
- CrewSkeleton 컴포넌트가 카드 레이아웃에 맞게 구조화되어 있음
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# CrewSkeletonList 컴포넌트의 구현 확인
ast-grep --pattern 'export default function CrewSkeletonList({ num, column }: Props) {
$$$
}'
# 스켈레톤 컴포넌트가 적용된 다른 페이지들 확인
rg -l "CrewSkeletonList"
Length of output: 284
Script:
#!/bin/bash
# CrewSkeletonList 컴포넌트의 구현 내용 확인
cat src/components/common/skeleton/crew-skeleton-list/index.tsx
# 다른 페이지들에서의 CrewSkeletonList 사용 패턴 확인
rg "CrewSkeletonList" -A 2 src/app/(crew)/my-crew/joined/page.tsx src/app/(crew)/my-crew/hosted/page.tsx
Length of output: 809
Script:
#!/bin/bash
# 다른 페이지들에서의 CrewSkeletonList 사용 패턴 확인 (경로에 괄호가 있어 따옴표로 감싸기)
rg "CrewSkeletonList" -A 2 "./src/app/(crew)/my-crew/joined/page.tsx" "./src/app/(crew)/my-crew/hosted/page.tsx"
# CrewSkeleton 컴포넌트 구현 확인
cat src/components/common/skeleton/crew-skeleton/index.tsx
Length of output: 1644
| {[...Array(num)].map((_, index) => ( | ||
| // eslint-disable-next-line react/no-array-index-key | ||
| <GatheringSkeleton key={index} /> | ||
| ))} |
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
배열 인덱스를 key로 사용하는 것은 피해야 합니다.
현재 구현에서는 배열 인덱스를 key로 사용하고 있는데, 이는 React의 재조정(reconciliation) 과정에서 문제를 일으킬 수 있습니다. 스켈레톤 아이템의 경우 정적이므로 큰 문제가 되지 않을 수 있으나, 더 안전한 방법을 사용하는 것이 좋습니다.
- {[...Array(num)].map((_, index) => (
- // eslint-disable-next-line react/no-array-index-key
- <GatheringSkeleton key={index} />
- ))}
+ {Array.from({ length: num }, (_, index) => (
+ <GatheringSkeleton key={`skeleton-${index}`} />
+ ))}또한, Array.from()을 사용하면 스프레드 연산자를 사용하는 것보다 더 명확하고 효율적입니다.
📝 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.
| {[...Array(num)].map((_, index) => ( | |
| // eslint-disable-next-line react/no-array-index-key | |
| <GatheringSkeleton key={index} /> | |
| ))} | |
| {Array.from({ length: num }, (_, index) => ( | |
| <GatheringSkeleton key={`skeleton-${index}`} /> | |
| ))} |
| export default function CrewSkeletonList({ num, column }: CrewSkeletonListProps) { | ||
| const columnStyle = column === 2 ? 'lg:grid-cols-2' : 'lg:grid-cols-1'; | ||
| return ( | ||
| <div className={`grid grid-cols-1 gap-2 ${columnStyle}`}> |
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
접근성 개선이 필요합니다.
로딩 상태를 스크린 리더 사용자에게도 알려주기 위해 적절한 ARIA 속성을 추가하는 것이 좋습니다.
- <div className={`grid grid-cols-1 gap-2 ${columnStyle}`}>
+ <div
+ className={`grid grid-cols-1 gap-2 ${columnStyle}`}
+ role="status"
+ aria-label="콘텐츠 로딩 중"
+ aria-busy="true"
+ >📝 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={`grid grid-cols-1 gap-2 ${columnStyle}`}> | |
| <div | |
| className={`grid grid-cols-1 gap-2 ${columnStyle}`} | |
| role="status" | |
| aria-label="콘텐츠 로딩 중" | |
| aria-busy="true" | |
| > |
| export default function CrewSkeletonList({ num, column }: CrewSkeletonListProps) { | ||
| const columnStyle = column === 2 ? 'lg:grid-cols-2' : 'lg:grid-cols-1'; | ||
| return ( | ||
| <div className={`grid grid-cols-1 gap-2 ${columnStyle}`}> | ||
| {[...Array(num)].map((_, index) => ( | ||
| // eslint-disable-next-line react/no-array-index-key | ||
| <CrewSkeleton key={index} /> | ||
| ))} | ||
| </div> | ||
| ); | ||
| } |
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
컴포넌트 구현에 대한 몇 가지 개선사항이 있습니다.
key값으로 배열 인덱스를 사용하는 것은 React의 재조정(reconciliation) 과정에서 문제를 일으킬 수 있습니다.- 배열 생성 방식을 최적화할 수 있습니다.
- 컬럼 스타일 로직을 더 명확하게 표현할 수 있습니다.
아래와 같이 개선하는 것을 제안드립니다:
-export default function CrewSkeletonList({ num, column }: CrewSkeletonListProps) {
- const columnStyle = column === 2 ? 'lg:grid-cols-2' : 'lg:grid-cols-1';
+export default function CrewSkeletonList({
+ skeletonCount,
+ columnCount
+}: CrewSkeletonListProps) {
+ const columnStyle = `lg:grid-cols-${columnCount ?? 1}`;
return (
<div className={`grid grid-cols-1 gap-2 ${columnStyle}`}>
- {[...Array(num)].map((_, index) => (
- // eslint-disable-next-line react/no-array-index-key
- <CrewSkeleton key={index} />
+ {Array.from({ length: skeletonCount }, (_, index) => (
+ <CrewSkeleton
+ key={`skeleton-${index}-${Date.now()}`}
+ />
))}
</div>
);
}변경사항 설명:
Array.from을 사용하여 더 명확하고 효율적인 배열 생성- 더 안정적인 key 생성 방식 적용
- 널 병합 연산자를 사용하여 컬럼 스타일 로직 단순화
스켈레톤 아이템의 개수가 많을 경우를 대비하여 성능 최적화를 위해 React.memo를 고려해보시는 것도 좋을 것 같습니다.
Committable suggestion skipped: line range outside the PR's diff.
| import { Skeleton } from '@mantine/core'; | ||
|
|
||
| export default function MyGatheringSkeleton() { | ||
| return ( | ||
| <div className="flex gap-6 p-6"> | ||
| <Skeleton className="h-28 w-28 rounded-xl md:h-32 md:w-32" /> | ||
| <div className="relative flex flex-col gap-3"> | ||
| <Skeleton className="h-4 w-40" /> | ||
| <div className="flex gap-2"> | ||
| <Skeleton className="h-4 w-32" /> | ||
| <Skeleton className="h-4 w-24" /> | ||
| </div> | ||
| <Skeleton className="absolute bottom-0 h-4 w-24" /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
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.
💡 Codebase verification
스켈레톤 컴포넌트가 현재 미사용 상태입니다
검증 결과, MyGatheringSkeleton 컴포넌트는 정의된 파일(src/components/common/skeleton/my-gathering-skeleton/index.tsx) 외에 다른 곳에서 사용되지 않고 있습니다. 이는 다음 두 가지 가능성을 시사합니다:
- 새로 추가된 컴포넌트로 아직 사용되지 않은 상태
- 더 이상 필요하지 않은 미사용 컴포넌트
개발자의 의도에 따라 다음 조치가 필요합니다:
- 새로운 기능을 위한 컴포넌트라면 사용 계획 확인
- 불필요한 컴포넌트라면 제거 고려
🔗 Analysis chain
컴포넌트 사용 패턴 확인 필요
이 스켈레톤 컴포넌트가 다른 페이지들과 일관되게 사용되고 있는지 확인이 필요합니다.
Let me try different commands to gather the necessary information.
Let me try one more search with different commands to find the component usage.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 스켈레톤 컴포넌트의 사용 패턴 확인
# MyGatheringSkeleton 컴포넌트의 사용처 확인
echo "MyGatheringSkeleton 사용 현황:"
rg "MyGatheringSkeleton" --type tsx
# 다른 스켈레톤 컴포넌트들과의 일관성 확인
echo "\n다른 스켈레톤 컴포넌트 현황:"
fd --type f ".*skeleton.*\.tsx$" src/components
Length of output: 223
Script:
#!/bin/bash
# MyGatheringSkeleton 컴포넌트 사용처 확인
echo "MyGatheringSkeleton 사용 현황:"
rg "MyGatheringSkeleton" -t ts -t tsx
# 다른 스켈레톤 컴포넌트 검색
echo -e "\n스켈레톤 컴포넌트 파일 목록:"
find src/components -type f -name "*skeleton*.tsx"
# 스켈레톤 컴포넌트 임포트 패턴 확인
echo -e "\n스켈레톤 컴포넌트 임포트 패턴:"
rg "import.*Skeleton" -t ts -t tsx
# MyGatheringSkeleton 구현 확인
echo -e "\nMyGatheringSkeleton 구현 확인:"
ast-grep --pattern 'export default function MyGatheringSkeleton() { $$$ }'
Length of output: 1965
Script:
#!/bin/bash
# 전체 코드베이스에서 MyGatheringSkeleton 문자열 검색
echo "MyGatheringSkeleton 사용 현황:"
find . -type f -exec grep -l "MyGatheringSkeleton" {} \;
# 스켈레톤 관련 파일 검색 (대소문자 구분 없이)
echo -e "\n스켈레톤 관련 파일:"
find . -type f -iname "*skeleton*.tsx" -o -iname "*skeleton*.ts"
# Mantine Skeleton 임포트 검색
echo -e "\nMantine Skeleton 임포트:"
find . -type f -exec grep -l "@mantine/core.*Skeleton" {} \;
Length of output: 187
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: 1
🧹 Outside diff range and nitpick comments (1)
src/components/common/skeleton/profile-skeleton/index.tsx (1)
6-9: 상수로 추출하면 좋을 것 같습니다.크기 값들을 의미 있는 상수로 추출하면 유지보수성이 향상될 것 같습니다.
다음과 같이 수정해보세요:
+const PROFILE_IMAGE_SIZE = 'h-28 w-28'; +const NAME_SKELETON_SIZE = 'h-6 w-40'; +const INFO_SKELETON_SIZE = 'h-4 w-36'; + export default function ProfileSkeleton() { return ( <div className="flex items-center gap-6.5"> - <Skeleton circle className="h-28 w-28" /> + <Skeleton circle className={PROFILE_IMAGE_SIZE} /> <div className="flex flex-col gap-3"> - <Skeleton className="h-6 w-40" /> - <Skeleton className="h-4 w-36" /> + <Skeleton className={NAME_SKELETON_SIZE} /> + <Skeleton className={INFO_SKELETON_SIZE} /> </div> </div> ); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
src/app/(crew)/my-page/_components/profile-card/container.tsx(2 hunks)src/components/common/skeleton/profile-skeleton/index.tsx(1 hunks)
🔇 Additional comments (3)
src/components/common/skeleton/profile-skeleton/index.tsx (1)
1-1: 깔끔한 import 구문입니다!
필요한 Skeleton 컴포넌트만 정확하게 import하였습니다.
src/app/(crew)/my-page/_components/profile-card/container.tsx (2)
13-13: 스켈레톤 컴포넌트 임포트가 적절히 추가되었습니다.
공통 컴포넌트에서 ProfileSkeleton을 가져오는 임포트 구문이 올바르게 작성되었습니다.
42-42: 로딩 상태 처리가 개선되었습니다.
스켈레톤 UI를 사용하여 사용자 경험이 향상되었습니다. 인증 상태 확인 로직도 잘 유지되었습니다.
다른 페이지에서도 일관된 로딩 처리가 이루어지는지 확인이 필요합니다:
✅ Verification successful
Let's search for loading states and skeleton components with proper file type flags. This will help us verify the consistency of loading state handling across the application.
로딩 상태 처리가 일관되게 구현되어 있습니다
코드베이스 분석 결과, 다음과 같이 스켈레톤 UI가 일관되게 사용되고 있음을 확인했습니다:
- 크루 목록 페이지들(
page.tsx,joined/page.tsx,hosted/page.tsx)에서CrewSkeletonList컴포넌트 사용 - 프로필 페이지에서
ProfileSkeleton컴포넌트 사용
각 페이지의 특성에 맞는 스켈레톤 컴포넌트를 사용하여 일관된 사용자 경험을 제공하고 있습니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 다른 페이지들의 로딩 상태 처리 방식 확인
rg -t tsx "isLoading.*return.*Skeleton" ./src/app
Length of output: 79
Script:
#!/bin/bash
# Search for loading state handling patterns in TypeScript/React files
rg -t ts -t tsx "(?:isLoading|loading).*return.*(?:Skeleton|skeleton)" ./src/app
# Also search for Skeleton component usage
rg -t ts -t tsx "Skeleton" ./src/app
Length of output: 175
Script:
#!/bin/bash
# Search for loading states and skeleton components without file type restrictions
rg "(?:isLoading|loading).*return.*(?:Skeleton|skeleton)" ./src/app
# Find all files containing Skeleton components
rg "Skeleton" ./src/app
Length of output: 1077
| export default function ProfileSkeleton() { | ||
| return ( | ||
| <div className="flex items-center gap-6.5"> | ||
| <Skeleton circle className="h-28 w-28" /> | ||
| <div className="flex flex-col gap-3"> | ||
| <Skeleton className="h-6 w-40" /> | ||
| <Skeleton className="h-4 w-36" /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
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
접근성 개선이 필요합니다.
스켈레톤 UI의 목적을 스크린 리더 사용자에게도 전달하기 위해 적절한 ARIA 속성을 추가하는 것이 좋습니다.
다음과 같이 수정해보세요:
export default function ProfileSkeleton() {
return (
- <div className="flex items-center gap-6.5">
+ <div
+ className="flex items-center gap-6.5"
+ role="status"
+ aria-label="프로필 정보 로딩 중"
+ >
<Skeleton circle className="h-28 w-28" />
<div className="flex flex-col gap-3">
<Skeleton className="h-6 w-40" />
<Skeleton className="h-4 w-36" />
</div>
</div>
);
}📝 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 default function ProfileSkeleton() { | |
| return ( | |
| <div className="flex items-center gap-6.5"> | |
| <Skeleton circle className="h-28 w-28" /> | |
| <div className="flex flex-col gap-3"> | |
| <Skeleton className="h-6 w-40" /> | |
| <Skeleton className="h-4 w-36" /> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| export default function ProfileSkeleton() { | |
| return ( | |
| <div | |
| className="flex items-center gap-6.5" | |
| role="status" | |
| aria-label="프로필 정보 로딩 중" | |
| > | |
| <Skeleton circle className="h-28 w-28" /> | |
| <div className="flex flex-col gap-3"> | |
| <Skeleton className="h-6 w-40" /> | |
| <Skeleton className="h-4 w-36" /> | |
| </div> | |
| </div> | |
| ); | |
| } |
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: 1
🧹 Outside diff range and nitpick comments (1)
src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx (1)
7-16: 성능 최적화를 위한 제안사항이 있습니다.
numprop에 대한 상한값 제한이 필요해 보입니다.- 반응형 그리드 레이아웃을 위한 미디어 쿼리 추가를 고려해 주세요.
다음과 같은 개선을 제안드립니다:
+const MAX_SKELETONS = 10; + export default function ReviewableReviewSkeletonList({ num }: ReviewableReviewSkeletonListProps) { + const safeNum = Math.min(num, MAX_SKELETONS); return ( - <div className="grid grid-cols-1 gap-12" aria-label="콘텐츠 로딩 중"> + <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-12" aria-label="콘텐츠 로딩 중"> {[...Array(num)].map((_, index) => (
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (7)
src/components/common/skeleton/crew-skeleton-list/index.tsx(1 hunks)src/components/common/skeleton/gathering-skeleton-list/index.tsx(1 hunks)src/components/common/skeleton/my-review-skeleton-list/index.tsx(1 hunks)src/components/common/skeleton/my-review-skeleton/index.tsx(1 hunks)src/components/common/skeleton/profile-skeleton/index.tsx(1 hunks)src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx(1 hunks)src/components/common/skeleton/reviewable-review-skeleton/index.tsx(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- src/components/common/skeleton/my-review-skeleton/index.tsx
- src/components/common/skeleton/reviewable-review-skeleton/index.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/common/skeleton/crew-skeleton-list/index.tsx
- src/components/common/skeleton/gathering-skeleton-list/index.tsx
- src/components/common/skeleton/profile-skeleton/index.tsx
🔇 Additional comments (4)
src/components/common/skeleton/my-review-skeleton-list/index.tsx (2)
1-5: 인터페이스 구현이 깔끔합니다!
타입스크립트 컨벤션을 잘 따르고 있으며, Props 인터페이스가 명확하게 정의되어 있습니다.
9-9: 접근성 레이블 일관성 확인 필요
다른 스켈레톤 컴포넌트들과 로딩 상태를 나타내는 aria-label이 일관되게 사용되고 있는지 확인이 필요합니다.
✅ Verification successful
aria-label이 일관되게 구현되어 있음을 확인했습니다
모든 스켈레톤 컴포넌트에서 "콘텐츠 로딩 중"이라는 동일한 aria-label을 사용하고 있어 접근성 관점에서 일관성이 잘 유지되고 있습니다.
확인된 파일들:
- src/components/common/skeleton/profile-skeleton/index.tsx
- src/components/common/skeleton/gathering-skeleton-list/index.tsx
- src/components/common/skeleton/my-review-skeleton-list/index.tsx
- src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx
- src/components/common/skeleton/crew-skeleton-list/index.tsx
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 스켈레톤 컴포넌트의 aria-label 사용 패턴 확인
rg -t tsx -t jsx "aria-label.*로딩" src/
Length of output: 68
Script:
#!/bin/bash
# Search for aria-label usage in all files under src directory
rg --type-add 'react:*.{tsx,jsx}' -t react "aria-label.*로딩|aria-label.*loading" src/
Length of output: 724
Script:
#!/bin/bash
# Find all skeleton component files
fd "skeleton" src/ -e tsx -e jsx
Length of output: 32
Script:
#!/bin/bash
# Search for any aria-label usage in skeleton components
fd "skeleton" src/ -e tsx -e jsx --exec rg -l "aria-label"
Length of output: 56
src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx (2)
1-5: 인터페이스 구현이 깔끔하고 명확합니다!
타입스크립트 컨벤션을 잘 따르고 있으며, Props 인터페이스가 적절하게 정의되어 있습니다.
10-13: 🛠️ Refactor suggestion
배열 인덱스를 key로 사용하는 것을 재고해 주세요.
배열 인덱스를 key로 사용하면 React의 재조정(reconciliation) 과정에서 문제가 발생할 수 있습니다. 더 안정적인 key 생성 방법을 고려해 보세요.
다음과 같이 수정하는 것을 제안드립니다:
- <ReviewableReviewSkeleton key={index} />
+ <ReviewableReviewSkeleton key={`skeleton-${index}-${Date.now()}`} />Likely invalid or redundant comment.
| export default function MyReviewSkeletonList({ num }: MyReviewSkeletonListProps) { | ||
| return ( | ||
| <div className="grid grid-cols-1 gap-6" aria-label="콘텐츠 로딩 중"> | ||
| {[...Array(num)].map((_, index) => ( | ||
| // eslint-disable-next-line react/no-array-index-key | ||
| <MyReviewSkeleton key={index} /> | ||
| ))} | ||
| </div> | ||
| ); | ||
| } |
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
컴포넌트 구현에 대한 개선 제안
현재 구현에서 몇 가지 개선할 점이 있습니다:
- 배열 인덱스를 key로 사용하는 것은 React의 성능 최적화에 좋지 않을 수 있습니다.
- num prop에 대한 유효성 검사가 필요합니다.
- 배열 생성 로직을 더 명확하게 표현할 수 있습니다.
다음과 같이 개선해보세요:
interface MyReviewSkeletonListProps {
num: number;
}
export default function MyReviewSkeletonList({ num }: MyReviewSkeletonListProps) {
+ const skeletonCount = Math.max(0, Math.floor(num));
return (
<div className="grid grid-cols-1 gap-6" aria-label="콘텐츠 로딩 중">
- {[...Array(num)].map((_, index) => (
- // eslint-disable-next-line react/no-array-index-key
- <MyReviewSkeleton key={index} />
+ {Array.from({ length: skeletonCount }, (_, index) => (
+ <MyReviewSkeleton key={`skeleton-${index}`} />
))}
</div>
);
}📝 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 default function MyReviewSkeletonList({ num }: MyReviewSkeletonListProps) { | |
| return ( | |
| <div className="grid grid-cols-1 gap-6" aria-label="콘텐츠 로딩 중"> | |
| {[...Array(num)].map((_, index) => ( | |
| // eslint-disable-next-line react/no-array-index-key | |
| <MyReviewSkeleton key={index} /> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| interface MyReviewSkeletonListProps { | |
| num: number; | |
| } | |
| export default function MyReviewSkeletonList({ num }: MyReviewSkeletonListProps) { | |
| const skeletonCount = Math.max(0, Math.floor(num)); | |
| return ( | |
| <div className="grid grid-cols-1 gap-6" aria-label="콘텐츠 로딩 중"> | |
| {Array.from({ length: skeletonCount }, (_, index) => ( | |
| <MyReviewSkeleton key={`skeleton-${index}`} /> | |
| ))} | |
| </div> | |
| ); | |
| } |
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: 1
🧹 Outside diff range and nitpick comments (7)
src/components/common/skeleton/my-gathering-skeleton-list/index.tsx (4)
1-6: 인터페이스 문서화 및 prop 이름 개선 제안인터페이스와 prop에 대한 명확성을 높이기 위해 다음과 같은 개선을 제안드립니다:
+/** + * 모임 스켈레톤 리스트의 props 인터페이스 + */ interface MyGatheringSkeletonListProps { - num: number; + /** + * 표시할 스켈레톤 아이템의 개수 + */ + skeletonCount: number; }
14-19: 시맨틱한 클래스명 사용 및 매직 넘버 제거 제안width 값을 매직 넘버(w-1/6)로 하드코딩하는 대신, 의미 있는 커스텀 클래스를 사용하는 것이 좋습니다.
- <div className="w-1/6"> + <div className="gathering-date-column"> <div className="flex flex-col gap-2"> - <Skeleton className="h-4 w-36" /> - <Skeleton className="h-4 w-20" /> + <Skeleton className="gathering-date-skeleton" /> + <Skeleton className="gathering-time-skeleton" /> </div>CSS 파일에 다음과 같이 정의하는 것을 추천드립니다:
.gathering-date-column { width: 16.666667%; } .gathering-date-skeleton { height: 1rem; width: 9rem; } .gathering-time-skeleton { height: 1rem; width: 5rem; }
20-22: 접근성 개선 제안스켈레톤 UI의 접근성을 개선하기 위해 ARIA 속성을 추가하는 것이 좋습니다.
- <div className="relative -mb-3.5 w-0.5 bg-gray-200"> + <div + className="relative -mb-3.5 w-0.5 bg-gray-200" + role="presentation" + aria-hidden="true" + >
23-25: 로딩 상태 명시적 표현 제안스켈레톤 UI가 로딩 상태임을 스크린 리더 사용자에게 알려주는 것이 좋습니다.
- <div className="flex-1 pb-6 md:pl-8"> + <div + className="flex-1 pb-6 md:pl-8" + role="status" + aria-label="모임 정보 로딩 중" + > <MyGatheringSkeleton />src/app/(crew)/my-gathering/hosted/page.tsx (1)
16-18: 로딩 상태 관리가 적절히 구현되었습니다.
isLoading상태를 활용하여 스켈레톤 UI를 제어하는 방식이 적절합니다. 다만, 에러 상태도 함께 처리하면 좋을 것 같습니다.다음과 같이 에러 처리를 추가하는 것을 고려해보세요:
- const { data, isLoading, refetch } = useQuery( + const { data, isLoading, error, refetch } = useQuery( useGetHostedGatheringListQuery(formatDateToRequest(selectedDate)), );src/app/(crew)/my-gathering/joined/page.tsx (2)
16-18: 로딩 상태 관리가 적절히 구현되었습니다.
isLoading상태를 활용하여 스켈레톤 UI를 구현한 것이 좋습니다. 다만, 에러 상태도 함께 처리하면 좋을 것 같습니다.다음과 같이 에러 처리를 추가하는 것을 고려해보세요:
- const { data, isLoading, refetch } = useQuery( + const { data, isLoading, error, refetch } = useQuery( useGetJoinedGatheringListQuery(formatDateToRequest(selectedDate)), );
33-34: 스켈레톤 UI의 아이템 개수를 설정 파일로 관리하면 좋겠습니다.하드코딩된 숫자(6)를 상수나 설정 파일로 분리하면 유지보수가 더 용이할 것 같습니다.
다음과 같이 상수를 분리하는 것을 제안드립니다:
+const SKELETON_ITEMS_COUNT = 6; export default function MyGatheringJoinedPage() { // ... - {isLoading && <MyGatheringSkeletonList num={6} />} + {isLoading && <MyGatheringSkeletonList num={SKELETON_ITEMS_COUNT} />}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
src/app/(crew)/my-gathering/hosted/page.tsx(2 hunks)src/app/(crew)/my-gathering/joined/page.tsx(2 hunks)src/components/common/skeleton/my-gathering-skeleton-list/index.tsx(1 hunks)
🔇 Additional comments (3)
src/app/(crew)/my-gathering/hosted/page.tsx (2)
9-9: 스켈레톤 컴포넌트 임포트가 적절히 추가되었습니다.
컴포넌트 임포트 섹션에 올바르게 배치되어 있으며, 프로젝트의 임포트 컨벤션을 잘 따르고 있습니다.
33-34: 스켈레톤 UI 렌더링 로직이 깔끔하게 구현되었습니다.
로딩 상태에 따른 조건부 렌더링이 명확하게 구현되어 있습니다. 다만, 고정된 숫자(6)를 사용하는 것에 대해 검토가 필요합니다.
실제 데이터의 평균 개수를 확인하여 스켈레톤 아이템의 개수를 조정하는 것이 좋을 것 같습니다:
✅ Verification successful
Let me gather more information about the actual data structure and skeleton component.
스켈레톤 UI의 고정된 아이템 개수(6)는 적절해 보입니다.
API 응답이 페이지네이션이나 제한 없이 날짜 기반으로만 데이터를 가져오는 구조이며, 스켈레톤 UI는 로딩 상태를 자연스럽게 표현하기 위한 용도로 사용되고 있습니다. 실제 데이터의 개수와 정확히 일치하지 않더라도, UX 관점에서 6개의 아이템은 적절한 수준입니다.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: 실제 데이터의 평균 개수를 확인하기 위해 관련 컴포넌트 검색
# GatheringListWithDate 컴포넌트에서 실제 렌더링되는 아이템 수 확인
ast-grep --pattern 'const GatheringListWithDate = ({ gatheringList }: Props) => {
$$$
}'
# 실제 API 응답 데이터 구조 확인
rg -A 5 "useGetHostedGatheringListQuery"
Length of output: 1917
Script:
#!/bin/bash
# Check the skeleton component implementation
ast-grep --pattern 'const MyGatheringSkeletonList = ({ num }: Props) => {
$$$
}'
# Check the API response type and structure
rg -A 5 "type GatheringCardProps"
# Check if there are any pagination or limit parameters in the API
rg -A 5 "getHostedGatheringList"
Length of output: 1747
src/app/(crew)/my-gathering/joined/page.tsx (1)
9-9: 스켈레톤 컴포넌트 임포트가 적절히 추가되었습니다.
컴포넌트 네이밍과 임포트 경로가 프로젝트 컨벤션을 잘 따르고 있습니다.
| {[...Array(num)].map((_, index) => ( | ||
| // eslint-disable-next-line react/no-array-index-key | ||
| <div key={index} className="md:flex"> |
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
배열 생성 및 키 처리 방식 개선 필요
현재 구현에서 발견된 몇 가지 개선이 필요한 부분입니다:
- Array spread 대신 더 효율적인 방법을 사용할 수 있습니다.
- 인덱스를 키로 사용하는 것은 재정렬이나 필터링이 발생할 경우 문제가 될 수 있습니다.
- {[...Array(num)].map((_, index) => (
- // eslint-disable-next-line react/no-array-index-key
- <div key={index} className="md:flex">
+ {Array.from({ length: num }, (_, index) => (
+ <div key={`skeleton-${index}`} className="md:flex">📝 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.
| {[...Array(num)].map((_, index) => ( | |
| // eslint-disable-next-line react/no-array-index-key | |
| <div key={index} className="md:flex"> | |
| {Array.from({ length: num }, (_, index) => ( | |
| <div key={`skeleton-${index}`} className="md:flex"> |
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: 0
🧹 Outside diff range and nitpick comments (1)
tailwind.config.ts (1)
124-124: 박스 섀도우 속성이 잘 정의되었습니다.새로운
card섀도우 속성이 카드 컴포넌트의 호버 효과에 적절하게 정의되었습니다. 다만, 다음과 같은 제안을 드립니다:
- 주석을 추가하여 이 섀도우의 용도와 사용 사례를 문서화하면 좋을 것 같습니다.
다음과 같이 주석을 추가하는 것을 제안드립니다:
boxShadow: { xl: '0 4px 4px 0 rgba(0,0,0,0.25)', bg: '0 4px 30px 1px rgba(0,122,255,0.04)', - card: '0 4px 15px 1px rgba(0,122,255,0.1)', + // CrewCard 컴포넌트의 호버 상태에서 사용되는 엘리베이션 효과 + card: '0 4px 15px 1px rgba(0,122,255,0.1)', xs: '0px 2px 4px 0px rgba(0, 0, 0, 0.02)', },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
src/components/common/crew-list/crew-card.tsx(1 hunks)tailwind.config.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/components/common/crew-list/crew-card.tsx
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: 1
🧹 Outside diff range and nitpick comments (1)
src/components/common/input/date-time-picker/index.tsx (1)
64-64: 스타일링 관련 제안사항반응형 디자인과 선택된 날짜의 스타일링이 잘 구현되어 있습니다. 다만 다음과 같은 개선사항을 제안드립니다:
- 테마의 일관성을 위해 Tailwind 설정에서 border-radius 값을 관리
- 반응형 브레이크포인트에 대한 주석 추가
day: 'w-full aspect-square text-gray-800 data-[selected=true]:text-white ' + - 'data-[selected=true]:rounded-xl flex', + 'data-[selected=true]:rounded-xl flex /* md: >= 768px */',
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
src/components/common/crew-list/crew-card-list.tsx(1 hunks)src/components/common/input/date-time-picker/index.tsx(2 hunks)src/components/common/skeleton/crew-skeleton-list/index.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/common/skeleton/crew-skeleton-list/index.tsx
🔇 Additional comments (1)
src/components/common/crew-list/crew-card-list.tsx (1)
36-36: 그리드 간격 조정이 적절해 보입니다!
카드 간의 간격을 늘림으로써 가독성과 시각적 계층 구조가 개선되었습니다. 이는 사용자 경험을 향상시키는 긍정적인 변화입니다.
| const newDate = new Date(selected); | ||
| const isSelected = selected; | ||
|
|
||
| newDate.setFullYear(Number(date.getFullYear())); | ||
| newDate.setMonth(Number(date.getMonth())); | ||
| newDate.setDate(Number(date.getDate())); | ||
|
|
||
| const kstDate = new Date(newDate.getTime() - newDate.getTimezoneOffset() * 60000).toISOString(); | ||
|
|
||
| if (isSelected) { | ||
| setSelected(date); | ||
| setSelected(newDate); | ||
| onChange(kstDate); |
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
날짜 선택 로직 개선이 필요합니다
다음과 같은 개선사항을 제안드립니다:
- 불필요한
isSelected체크를 제거하고 로직을 단순화 - DST(일광절약시간제) 변경 시 발생할 수 있는 문제를 방지하기 위해
date-fns라이브러리 사용 고려
다음과 같이 수정하는 것을 추천드립니다:
- const newDate = new Date(selected);
- const isSelected = selected;
+ const newDate = new Date(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ selected.getHours(),
+ selected.getMinutes()
+ );
- newDate.setFullYear(Number(date.getFullYear()));
- newDate.setMonth(Number(date.getMonth()));
- newDate.setDate(Number(date.getDate()));
const kstDate = new Date(newDate.getTime() - newDate.getTimezoneOffset() * 60000).toISOString();
- if (isSelected) {
- setSelected(newDate);
- onChange(kstDate);
- }
+ setSelected(newDate);
+ onChange(kstDate);📝 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 newDate = new Date(selected); | |
| const isSelected = selected; | |
| newDate.setFullYear(Number(date.getFullYear())); | |
| newDate.setMonth(Number(date.getMonth())); | |
| newDate.setDate(Number(date.getDate())); | |
| const kstDate = new Date(newDate.getTime() - newDate.getTimezoneOffset() * 60000).toISOString(); | |
| if (isSelected) { | |
| setSelected(date); | |
| setSelected(newDate); | |
| onChange(kstDate); | |
| const newDate = new Date( | |
| date.getFullYear(), | |
| date.getMonth(), | |
| date.getDate(), | |
| selected.getHours(), | |
| selected.getMinutes() | |
| ); | |
| const kstDate = new Date(newDate.getTime() - newDate.getTimezoneOffset() * 60000).toISOString(); | |
| setSelected(newDate); | |
| onChange(kstDate); |
HaeJungg
left a comment
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.
수고하셨습니다👍
🔖 Issue Ticket
#147
✍️ Description
스켈레톤 컴포넌트 작성 후 페이지에 적용했습니다
로딩처리 되있는 페이지에 한해서 적용했습니다!
적용된 페이지
마이페이지 리뷰 스켈레톤 리스트 컴포넌트는 만들어져있습니다!
예은님 작업완료되면 적용해주세용
✅ Checklist
PR
Test
Summary by CodeRabbit
Summary by CodeRabbit
새로운 기능
CrewSkeletonList,GatheringSkeletonList,MyGatheringSkeletonList,ProfileSkeleton등 여러 스켈레톤 로딩 컴포넌트를 추가하여 데이터 로딩 중 사용자 경험을 개선했습니다.MyCrewHostedPage,MyCrewJoinedPage,HomePage,MyGatheringHostedPage,MyGatheringJoinedPage등에서 로딩 상태 표시를 스켈레톤 리스트로 변경했습니다.스타일
CrewCard컴포넌트에 호버 시 그림자 효과를 추가하여 시각적 피드백을 향상시켰습니다.card를 추가하여 컴포넌트의 시각적 스타일링 옵션을 확장했습니다.버그 수정