Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (3)
Walkthrough
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
📋 전체 변경 사항
🚶 Walkthrough
🎯 코드 리뷰 예상 난이도🎯 3 (Moderate) | ⏱️ ~25 분 💭 제안 리뷰어
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/web/src/apis/news/getNewsList.ts (1)
20-20: 💤 Low value타입 시그니처와 일치하도록 중복 체크를 제거하는 것이 좋겠습니다.
userId의 타입이number로 선언되어 있어null이 될 수 없으므로,userId !== null체크는 중복입니다. 다음과 같이 간소화할 수 있습니다:♻️ 제안하는 수정안
- enabled: userId !== null && userId !== 0 && (options?.enabled ?? true), + enabled: userId !== 0 && (options?.enabled ?? true),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/apis/news/getNewsList.ts` at line 20, The enabled condition includes a redundant null check for userId; since userId is typed as number (non-nullable), remove the userId !== null clause and simplify the expression in the enabled assignment (the property named enabled in apps/web/src/apis/news/getNewsList.ts) to only check userId !== 0 && (options?.enabled ?? true).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/web/src/app/university/`[homeUniversity]/[id]/_ui/UniversityDetail/_ui/UniversityBtns.tsx:
- Around line 80-95: The share button lacks a visible keyboard focus indicator;
update the button element that uses onClick={handleCopy} and the
isShareActive/IconShare/IconShareFilled visuals to include the same focus ring
classes used by the like button (e.g., add focus:ring-2 focus:ring-white/50 and
remove or replace focus:outline-none) so keyboard users see a clear focus state
while preserving the current hover/active animations and icon opacity toggles.
- Around line 54-59: handleCopy currently calls
navigator.clipboard.writeText(...).then(() => {}) without error handling and
creates a potential memory leak by using setTimeout without cleanup; update
handleCopy to await or use .then/.catch on navigator.clipboard.writeText to show
a success toast on resolve and an error toast on reject (include clear
messaging), and replace the raw setTimeout with a tracked timeoutId (e.g., store
id in a ref or state) so you can call clearTimeout during unmount; add a
useEffect cleanup that clears the timeoutId and prevents calling
setIsShareActive on an unmounted component.
---
Nitpick comments:
In `@apps/web/src/apis/news/getNewsList.ts`:
- Line 20: The enabled condition includes a redundant null check for userId;
since userId is typed as number (non-nullable), remove the userId !== null
clause and simplify the expression in the enabled assignment (the property named
enabled in apps/web/src/apis/news/getNewsList.ts) to only check userId !== 0 &&
(options?.enabled ?? true).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 9d0e914f-3443-4977-9d6b-efcf4c34a6ec
⛔ Files ignored due to path filters (2)
apps/web/public/svgs/shareIcon.svgis excluded by!**/*.svgapps/web/public/svgs/shareIconFilled.svgis excluded by!**/*.svg
📒 Files selected for processing (4)
apps/web/public/svgs/index.tsapps/web/src/apis/news/getNewsList.tsapps/web/src/app/university/[homeUniversity]/[id]/_ui/UniversityDetail/_ui/UniversityBtns.tsxapps/web/src/components/mentor/MentorCard/_ui/ArticlePreview.tsx
| const handleCopy = () => { | ||
| navigator.clipboard.writeText(window.location.href).then(() => {}); | ||
| toast.success("URL이 복사되었습니다."); | ||
| setIsShareActive(true); | ||
| setTimeout(() => setIsShareActive(false), 600); | ||
| }; |
There was a problem hiding this comment.
공유 기능 구현에서 두 가지 개선이 필요합니다.
다음 사항들을 확인해 주세요:
-
클립보드 API 에러 처리 누락 (Line 55)
navigator.clipboard.writeText()의 빈.then()콜백이 불필요하며, 실패 시 처리를 위한.catch()핸들러가 없습니다.- 클립보드 API는 권한 문제나 브라우저 제약으로 실패할 수 있습니다.
-
메모리 누수 가능성 (Lines 57-58)
setTimeout이 정리(cleanup)되지 않아, 600ms 이내에 컴포넌트가 언마운트되면 언마운트된 컴포넌트에 상태 업데이트를 시도하게 됩니다.- React에서 흔히 발생하는 안티패턴입니다.
🔧 개선된 구현 제안
- const handleCopy = () => {
- navigator.clipboard.writeText(window.location.href).then(() => {});
- toast.success("URL이 복사되었습니다.");
- setIsShareActive(true);
- setTimeout(() => setIsShareActive(false), 600);
- };
+ const handleCopy = () => {
+ navigator.clipboard
+ .writeText(window.location.href)
+ .then(() => {
+ toast.success("URL이 복사되었습니다.");
+ setIsShareActive(true);
+ })
+ .catch(() => {
+ toast.error("URL 복사에 실패했습니다.");
+ });
+ };
+
+ useEffect(() => {
+ if (!isShareActive) return;
+ const timer = setTimeout(() => setIsShareActive(false), 600);
+ return () => clearTimeout(timer);
+ }, [isShareActive]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@apps/web/src/app/university/`[homeUniversity]/[id]/_ui/UniversityDetail/_ui/UniversityBtns.tsx
around lines 54 - 59, handleCopy currently calls
navigator.clipboard.writeText(...).then(() => {}) without error handling and
creates a potential memory leak by using setTimeout without cleanup; update
handleCopy to await or use .then/.catch on navigator.clipboard.writeText to show
a success toast on resolve and an error toast on reject (include clear
messaging), and replace the raw setTimeout with a tracked timeoutId (e.g., store
id in a ref or state) so you can call clearTimeout during unmount; add a
useEffect cleanup that clears the timeoutId and prevents calling
setIsShareActive on an unmounted component.
| <button | ||
| type="button" | ||
| onClick={handleCopy} | ||
| className={`/* stroke: #FFF; stroke-width: 1px; */ /* fill: linear-gradient(...) */ /* CSS의 fill은 SVG 속성이지만, 버튼 배경으로 적용합니다. */ /* backdrop-filter: blur(2px); */ /* filter: drop-shadow(...) */ /* 기타 스타일 */ rounded-full border border-white/80 bg-[linear-gradient(136deg,rgba(255,255,255,0.4)_14.87%,rgba(199,212,250,0.8)_89.1%)] p-3 drop-shadow-[2px_2px_6px_#C7D4FA] backdrop-blur-[2px] transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none focus:ring-2 focus:ring-white/50 active:scale-95`} | ||
| className="relative h-10 w-10 transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none active:scale-95" | ||
| > | ||
| {copyIcon} | ||
| <IconShare | ||
| width={40} | ||
| height={40} | ||
| className={`absolute inset-0 transition-opacity duration-300 ease-in-out ${isShareActive ? "opacity-0" : "opacity-100"}`} | ||
| /> | ||
| <IconShareFilled | ||
| width={40} | ||
| height={40} | ||
| className={`absolute inset-0 transition-opacity duration-300 ease-in-out ${isShareActive ? "opacity-100" : "opacity-0"}`} | ||
| /> | ||
| </button> |
There was a problem hiding this comment.
공유 버튼의 키보드 접근성 개선이 필요합니다.
아이콘 전환 애니메이션 구현은 깔끔하지만, 버튼에 포커스 인디케이터가 없어 키보드 네비게이션 사용자가 현재 포커스 위치를 파악하기 어렵습니다.
위의 좋아요 버튼(Line 76)에는 focus:ring-2 focus:ring-white/50이 있지만, 공유 버튼에는 focus:outline-none만 있고 대체 포커스 스타일이 없습니다.
♿ 접근성 개선 제안
<button
type="button"
onClick={handleCopy}
- className="relative h-10 w-10 transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none active:scale-95"
+ className="relative h-10 w-10 rounded-full transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none focus:ring-2 focus:ring-white/50 active:scale-95"
>📝 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.
| <button | |
| type="button" | |
| onClick={handleCopy} | |
| className={`/* stroke: #FFF; stroke-width: 1px; */ /* fill: linear-gradient(...) */ /* CSS의 fill은 SVG 속성이지만, 버튼 배경으로 적용합니다. */ /* backdrop-filter: blur(2px); */ /* filter: drop-shadow(...) */ /* 기타 스타일 */ rounded-full border border-white/80 bg-[linear-gradient(136deg,rgba(255,255,255,0.4)_14.87%,rgba(199,212,250,0.8)_89.1%)] p-3 drop-shadow-[2px_2px_6px_#C7D4FA] backdrop-blur-[2px] transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none focus:ring-2 focus:ring-white/50 active:scale-95`} | |
| className="relative h-10 w-10 transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none active:scale-95" | |
| > | |
| {copyIcon} | |
| <IconShare | |
| width={40} | |
| height={40} | |
| className={`absolute inset-0 transition-opacity duration-300 ease-in-out ${isShareActive ? "opacity-0" : "opacity-100"}`} | |
| /> | |
| <IconShareFilled | |
| width={40} | |
| height={40} | |
| className={`absolute inset-0 transition-opacity duration-300 ease-in-out ${isShareActive ? "opacity-100" : "opacity-0"}`} | |
| /> | |
| </button> | |
| <button | |
| type="button" | |
| onClick={handleCopy} | |
| className="relative h-10 w-10 rounded-full transition-transform duration-200 ease-in-out hover:scale-110 focus:outline-none focus:ring-2 focus:ring-white/50 active:scale-95" | |
| > | |
| <IconShare | |
| width={40} | |
| height={40} | |
| className={`absolute inset-0 transition-opacity duration-300 ease-in-out ${isShareActive ? "opacity-0" : "opacity-100"}`} | |
| /> | |
| <IconShareFilled | |
| width={40} | |
| height={40} | |
| className={`absolute inset-0 transition-opacity duration-300 ease-in-out ${isShareActive ? "opacity-100" : "opacity-0"}`} | |
| /> | |
| </button> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@apps/web/src/app/university/`[homeUniversity]/[id]/_ui/UniversityDetail/_ui/UniversityBtns.tsx
around lines 80 - 95, The share button lacks a visible keyboard focus indicator;
update the button element that uses onClick={handleCopy} and the
isShareActive/IconShare/IconShareFilled visuals to include the same focus ring
classes used by the like button (e.g., add focus:ring-2 focus:ring-white/50 and
remove or replace focus:outline-none) so keyboard users see a clear focus state
while preserving the current hover/active animations and icon opacity toggles.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 072042c070
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| toast.custom( | ||
| () => ( | ||
| <div className="animate-fadeIn pointer-events-auto flex h-[62px] w-[350px] items-center justify-center gap-2.5 rounded-[12px] bg-white px-5 py-4 shadow-[0px_4px_40px_0px_rgba(0,0,0,0.25)]"> |
There was a problem hiding this comment.
Let icon toasts grow for long messages
When callers pass a long message, this fixed h-[62px] w-[350px] container has no wrapping or word-break guard, so text can spill out of the white toast card instead of remaining readable. This now affects existing paths that pass long strings through showIconToast, such as SurveyModal including the full survey URL on popup-block errors and global API error messages; use a min-height/auto height and a max-width/break-words style instead of a fixed-height box.
Useful? React with 👍 / 👎.
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)
apps/web/src/app/university/score/ScoreCard.tsx (1)
36-44:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winREJECTED 상태 배지 클릭 시 중복 토스트 발생 가능성
현재 구조에서는:
- REJECTED 배지 자체에
onClick핸들러가 있어 거절 사유 토스트를 표시ScoreScreen.tsx에서 이 카드 전체를<button>으로 감싸고handleScoreClick을 연결배지를 클릭하면 이벤트 버블링으로 인해 두 토스트가 연속으로 표시될 수 있습니다.
제안: 이벤트 버블링 방지
<div className="flex h-5 cursor-pointer items-center gap-0.5 rounded-[20px] bg-accent-custom-red-light p-2.5" - onClick={() => showIconToast("logo", rejectedReason ?? "승인이 거절되었습니다.")} + onClick={(e) => { + e.stopPropagation(); + showIconToast("logo", rejectedReason ?? "승인이 거절되었습니다."); + }} >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/app/university/score/ScoreCard.tsx` around lines 36 - 44, The REJECTED badge's onClick in ScoreCard.tsx currently calls showIconToast(...) but doesn't stop event propagation, causing ScoreScreen.tsx's parent <button> with handleScoreClick to also fire and produce duplicate toasts; update the badge's onClick handler to accept the click event, call event.stopPropagation(), then call showIconToast(rejectedReason ?? "승인이 거절되었습니다.") so the badge toast shows without triggering handleScoreClick in the parent.
🧹 Nitpick comments (2)
apps/web/src/app/university/score/ScoreScreen.tsx (1)
20-28: ⚡ Quick winAPPROVED 상태 클릭에 대한 사용자 피드백 누락
handleScoreClick이 REJECTED와 PENDING 상태에는 토스트를 표시하지만, APPROVED 상태의 성적을 클릭했을 때는 아무 피드백이 없습니다. 사용자 입장에서는 클릭이 동작하지 않는 것처럼 느껴질 수 있습니다.제안: APPROVED 상태에 대한 안내 추가 또는 버튼 비활성화
옵션 1: APPROVED에도 안내 토스트 추가
const handleScoreClick = (status: ScoreSubmitStatus) => { if (status === ScoreSubmitStatus.REJECTED) { showIconToast("cap", "승인거절된 성적은 사용할 수 없습니다"); return; } if (status === ScoreSubmitStatus.PENDING) { showIconToast("cap", "심사중인 성적은 사용할 수 없습니다"); + return; } + // APPROVED 상태는 이미 선택되어 있음을 안내 + showIconToast("cap", "이미 사용 중인 성적입니다"); };옵션 2: APPROVED 카드는 버튼으로 감싸지 않기
렌더링 시 조건부로 버튼 래퍼 적용🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/app/university/score/ScoreScreen.tsx` around lines 20 - 28, handleScoreClick currently only handles REJECTED and PENDING so clicking an APPROVED score gives no feedback; update the click behavior by adding handling for ScoreSubmitStatus.APPROVED (e.g., call showIconToast with a helpful message like "이미 승인된 성적입니다") or remove the clickable wrapper for APPROVED items instead. Modify handleScoreClick to include an APPROVED branch (referencing ScoreSubmitStatus and showIconToast) or change the render logic that wraps the card/button so it conditionally applies the click handler only when status !== ScoreSubmitStatus.APPROVED (locate the component that renders the clickable card and the handleScoreClick usage).apps/web/src/components/mentor/MentorCard/index.tsx (1)
111-117: 💤 Low value아티클 로딩 상태에 대한 피드백 부재
현재 구현은 아티클이 로드되는 동안 아무것도 표시하지 않습니다. 카드를 확장할 때 아티클 API 호출이 진행 중이면 사용자는 아티클 섹션이 나타나기까지 빈 공간을 보게 됩니다.
제안: 로딩 상태 표시 추가
+ const { data: articles, isLoading: isLoadingArticles } = useGetArticleList(id ?? 0, { enabled: isExpanded && !!id }); {/* 멘토 아티클 */} - {latestArticle && ( + {(latestArticle || (isExpanded && isLoadingArticles)) && ( <div className="mb-4"> <h4 className="mb-2 text-blue-600 typo-sb-5">멘토 아티클</h4> - <ArticlePreview article={latestArticle} /> + {isLoadingArticles ? ( + <div className="text-k-400 typo-regular-4">아티클을 불러오는 중...</div> + ) : latestArticle ? ( + <ArticlePreview article={latestArticle} /> + ) : null} </div> )}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/mentor/MentorCard/index.tsx` around lines 111 - 117, The MentorCard renders nothing while the article API is loading (only checks latestArticle), causing blank space; add an explicit loading state (e.g., isLoadingArticle) used alongside latestArticle so the render shows a loading indicator or skeleton where ArticlePreview would be while the fetch is in progress, set isLoadingArticle=true before the API call that populates latestArticle and false on success/error, and update the JSX around latestArticle/ArticlePreview to render spinner/skeleton when isLoadingArticle is true and ArticlePreview only when latestArticle is available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/app/university/score/ScoreScreen.tsx`:
- Around line 47-65: The ScoreCard is wrapped in an interactive <button> while
the REJECTED badge inside ScoreCard also has its own click handler, causing
nested interactive elements and double toasts; fix by removing the external
<button> wrapper and either (A) make the whole card clickable by passing an
onClick prop from where ScoreCard is used (e.g., pass onClick={() =>
handleScoreClick(score.verifyStatus)} into ScoreCard and remove the badge's
internal onClick), or (B) keep the badge interactive and render the outer
container as a non-interactive element (div) with proper keyboard handling/role
if needed; apply the same change for the other occurrence around lines
referenced (70-85). Ensure you update ScoreCard props and its internal badge
handler accordingly (remove or conditionally disable badge onClick when
card-level onClick is provided).
---
Outside diff comments:
In `@apps/web/src/app/university/score/ScoreCard.tsx`:
- Around line 36-44: The REJECTED badge's onClick in ScoreCard.tsx currently
calls showIconToast(...) but doesn't stop event propagation, causing
ScoreScreen.tsx's parent <button> with handleScoreClick to also fire and produce
duplicate toasts; update the badge's onClick handler to accept the click event,
call event.stopPropagation(), then call showIconToast(rejectedReason ?? "승인이
거절되었습니다.") so the badge toast shows without triggering handleScoreClick in the
parent.
---
Nitpick comments:
In `@apps/web/src/app/university/score/ScoreScreen.tsx`:
- Around line 20-28: handleScoreClick currently only handles REJECTED and
PENDING so clicking an APPROVED score gives no feedback; update the click
behavior by adding handling for ScoreSubmitStatus.APPROVED (e.g., call
showIconToast with a helpful message like "이미 승인된 성적입니다") or remove the
clickable wrapper for APPROVED items instead. Modify handleScoreClick to include
an APPROVED branch (referencing ScoreSubmitStatus and showIconToast) or change
the render logic that wraps the card/button so it conditionally applies the
click handler only when status !== ScoreSubmitStatus.APPROVED (locate the
component that renders the clickable card and the handleScoreClick usage).
In `@apps/web/src/components/mentor/MentorCard/index.tsx`:
- Around line 111-117: The MentorCard renders nothing while the article API is
loading (only checks latestArticle), causing blank space; add an explicit
loading state (e.g., isLoadingArticle) used alongside latestArticle so the
render shows a loading indicator or skeleton where ArticlePreview would be while
the fetch is in progress, set isLoadingArticle=true before the API call that
populates latestArticle and false on success/error, and update the JSX around
latestArticle/ArticlePreview to render spinner/skeleton when isLoadingArticle is
true and ArticlePreview only when latestArticle is available.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: dfb9e483-7ca2-4d20-89ff-11e721737210
⛔ Files ignored due to path filters (5)
apps/web/public/svgs/toast/cap.svgis excluded by!**/*.svgapps/web/public/svgs/toast/like.svgis excluded by!**/*.svgapps/web/public/svgs/toast/link.svgis excluded by!**/*.svgapps/web/public/svgs/toast/logo.svgis excluded by!**/*.svgapps/web/public/svgs/toast/univ.svgis excluded by!**/*.svg
📒 Files selected for processing (45)
apps/web/public/svgs/toast/index.tsapps/web/src/apis/Auth/postAppleAuth.tsapps/web/src/apis/Auth/postEmailLogin.tsapps/web/src/apis/Auth/postKakaoAuth.tsapps/web/src/apis/MyPage/patchPassword.tsapps/web/src/apis/MyPage/patchProfile.tsapps/web/src/apis/Scores/postCreateGpa.tsapps/web/src/apis/Scores/postCreateLanguageTest.tsapps/web/src/apis/community/deleteComment.tsapps/web/src/apis/community/deletePost.tsapps/web/src/apis/community/patchUpdatePost.tsapps/web/src/apis/community/postCreateComment.tsapps/web/src/apis/community/postCreatePost.tsapps/web/src/apis/reports/postReport.tsapps/web/src/app/(home)/_ui/FindLastYearScoreBar/index.tsxapps/web/src/app/community/[boardCode]/[postId]/Content.tsxapps/web/src/app/community/[boardCode]/[postId]/KebabMenu.tsxapps/web/src/app/community/[boardCode]/[postId]/modify/PostModifyForm.tsxapps/web/src/app/community/[boardCode]/create/PostForm.tsxapps/web/src/app/community/_hooks/useCommunityImageUpload.tsapps/web/src/app/layout.tsxapps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/index.tsxapps/web/src/app/my/_ui/MyProfileContent/index.tsxapps/web/src/app/my/apply-mentor/_components/UniversityScreen/index.tsxapps/web/src/app/my/apply-mentor/page.tsxapps/web/src/app/my/favorite/_ui/FavoriteContent/_hooks/useSelectUniversities.tsapps/web/src/app/sign-up/email/EmailSignUpForm.tsxapps/web/src/app/university/[homeUniversity]/[id]/_ui/UniversityDetail/_ui/UniversityBtns.tsxapps/web/src/app/university/application/apply/ApplyPageContent.tsxapps/web/src/app/university/application/apply/GpaStep.tsxapps/web/src/app/university/application/apply/LanguageStep.tsxapps/web/src/app/university/score/ScoreCard.tsxapps/web/src/app/university/score/ScoreScreen.tsxapps/web/src/components/layout/GlobalLayout/ui/AIInspectorFab/index.tsxapps/web/src/components/login/signup/SignupPrepareScreen.tsxapps/web/src/components/login/signup/SignupProfileScreen.tsxapps/web/src/components/login/signup/SignupRegionScreen.tsxapps/web/src/components/login/signup/SignupSurvey.tsxapps/web/src/components/mentor/MentorCard/index.tsxapps/web/src/components/modal/SurveyModal.tsxapps/web/src/lib/react-query/queryClient.tsapps/web/src/lib/toast/options.tsapps/web/src/lib/toast/showIconToast.tsxapps/web/src/utils/authUtils.tsapps/web/src/utils/axiosInstance.ts
💤 Files with no reviewable changes (1)
- apps/web/src/lib/toast/options.ts
✅ Files skipped from review due to trivial changes (9)
- apps/web/public/svgs/toast/index.ts
- apps/web/src/apis/reports/postReport.ts
- apps/web/src/apis/MyPage/patchProfile.ts
- apps/web/src/apis/Scores/postCreateLanguageTest.ts
- apps/web/src/lib/toast/showIconToast.tsx
- apps/web/src/components/login/signup/SignupSurvey.tsx
- apps/web/src/apis/MyPage/patchPassword.ts
- apps/web/src/components/modal/SurveyModal.tsx
- apps/web/src/apis/Auth/postAppleAuth.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/src/app/university/[homeUniversity]/[id]/_ui/UniversityDetail/_ui/UniversityBtns.tsx
| <button | ||
| key={score.id} | ||
| name={languageTestMapping[score.languageTestResponse.languageTestType]} | ||
| score={formatLanguageTestScore( | ||
| score.languageTestResponse.languageTestType, | ||
| score.languageTestResponse.languageTestScore, | ||
| )} | ||
| status={score.verifyStatus} | ||
| // date={new Date(score.issueDate).toISOString()} | ||
| date="2026-01-01" | ||
| isFocused={score.verifyStatus === "APPROVED"} | ||
| rejectedReason={score.rejectedReason} | ||
| /> | ||
| type="button" | ||
| className="text-left" | ||
| onClick={() => handleScoreClick(score.verifyStatus)} | ||
| > | ||
| <ScoreCard | ||
| name={languageTestMapping[score.languageTestResponse.languageTestType]} | ||
| score={formatLanguageTestScore( | ||
| score.languageTestResponse.languageTestType, | ||
| score.languageTestResponse.languageTestScore, | ||
| )} | ||
| status={score.verifyStatus} | ||
| // date={new Date(score.issueDate).toISOString()} | ||
| date="2026-01-01" | ||
| isFocused={score.verifyStatus === "APPROVED"} | ||
| rejectedReason={score.rejectedReason} | ||
| /> | ||
| </button> |
There was a problem hiding this comment.
버튼으로 감싼 ScoreCard 내부에 클릭 가능한 배지 포함
ScoreCard를 <button>으로 감싸면서 접근성 문제가 발생합니다:
- ScoreCard의 REJECTED 배지도 클릭 가능한 요소(onClick 핸들러 포함)
- 이는 중첩된 인터랙티브 요소를 만들어 스크린 리더 사용자에게 혼란을 줄 수 있습니다
- REJECTED 배지 클릭 시 이벤트 버블링으로 인해 두 개의 토스트가 표시될 수 있습니다
더 나은 접근 방식:
- ScoreCard를 버튼으로 감싸지 않고, 카드 내부의 배지에만 onClick 유지
- 또는 카드 전체를 클릭 가능하게 만들고 배지의 개별 onClick 제거
Also applies to: 70-85
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/app/university/score/ScoreScreen.tsx` around lines 47 - 65, The
ScoreCard is wrapped in an interactive <button> while the REJECTED badge inside
ScoreCard also has its own click handler, causing nested interactive elements
and double toasts; fix by removing the external <button> wrapper and either (A)
make the whole card clickable by passing an onClick prop from where ScoreCard is
used (e.g., pass onClick={() => handleScoreClick(score.verifyStatus)} into
ScoreCard and remove the badge's internal onClick), or (B) keep the badge
interactive and render the outer container as a non-interactive element (div)
with proper keyboard handling/role if needed; apply the same change for the
other occurrence around lines referenced (70-85). Ensure you update ScoreCard
props and its internal badge handler accordingly (remove or conditionally
disable badge onClick when card-level onClick is provided).
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a7b29305ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| const isDetail = mentor && "passTip" in mentor; | ||
|
|
||
| const { data: articles } = useGetArticleList(id ?? 0, { enabled: isExpanded && !!id }); |
There was a problem hiding this comment.
Avoid fetching articles with chat room IDs
When this shared card is used in apps/web/src/app/my/match/_ui/MatchContent/index.tsx, the mentor prop is synthesized with id: room.id because the chat-room API does not provide a mentor id. After this change, expanding that matched-mentor card calls the news query with the chat room id (/news?author-id=<room.id>), which can either show an unrelated author's latest article or surface an error toast instead of the matched mentor's article. Gate this fetch to real mentor records or pass a separate author/mentor id for article lookup.
Useful? React with 👍 / 👎.
|
@enunsnv 님 코드래빗이랑 코덱스 리뷰만 반영해주시고 머지 가시죵 ! |
작업 내용
1. 파견학교 상세 페이지 좋아요 / 공유 버튼 디자인 수정 반영
2. 멘토 카드 아티클 추가
3. 토스트 디자인 수정
※ 디자인 시안에는 포함되어 있지 않아 임의로 추가하였습니다.
수정이 필요한 경우 말씀해주시면 반영하겠습니다.
※ 디자인 시안에는 포함되어 있지 않아 임의로 추가하였습니다.
수정이 필요한 경우 말씀해주시면 반영하겠습니다.
테스트하지 못했습니다 🥲
4.
새로운 아티클 추가 하기아티클 섹션에서 가장 상단에 고정특이 사항
3번 작업의 토스트 디자인을 전역으로 적용하였습니다. 솔커 로고로 통일하였으며, 추가적으로 수정 사항이 있다면 알려주세요🙂
또한 모든 토스트를 전부 다 확인해보지는 못 했기 때문에 혹시 적용 안된 곳이 있다면 알려주세요 !
질문 사항
리뷰 요구사항 (선택)