Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (7)
📒 Files selected for processing (32)
Walkthrough인앱 알림 페이지와 토스트 UI를 구현하는 변경입니다. SSE를 통한 실시간 알림 수신, 무한 스크롤 알림 목록 페이지, 알림 토스트 컴포넌트를 추가하고, 관련 API 클라이언트와 React Query 훅을 제공합니다. 동시에 토큰 갱신 동시성 제어, 헤더 및 바텀 네비게이션 구조 개선, 레이아웃 메트릭 기반 오버레이 관리를 포함합니다. Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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.
Pull request overview
Adds a full in-app notification experience (SSE stream + unread count + read API) and integrates it into the app shell (header/bottom-nav/layout) so users can receive toasts and browse a notification inbox page.
Changes:
- Implemented inbox notification data layer (entities, queries, cache helpers, APIs) and SSE streaming hook.
- Added UI for notifications: header bell, in-app toast layer, and
/notificationslist page with infinite scroll + read handling. - Refactored layout/header/bottom-nav to support notification entry flow and bottom overlay inset positioning.
Reviewed changes
Copilot reviewed 32 out of 39 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/ts/notification.ts | Notification presentation mapping + helpers (message/icon/tone/path normalization). |
| src/utils/ts/accessToken.ts | JWT exp parsing utilities for expiration checks. |
| src/stores/authStore.ts | Reuses shared access token expiry logic. |
| src/pages/Notifications/index.tsx | New notifications inbox page UI + navigation/read behavior. |
| src/pages/Notifications/hooks/useInboxNotifications.ts | React Query hooks for inbox list, unread count, and mark-as-read mutation with cache updates. |
| src/index.css | Adds fade-in-down animation; removes unused chat tooltip anchor support; minor selector formatting. |
| src/contexts/useLayoutElementsContext.tsx | Extends layout context to include layoutElement and bottomOverlayInset. |
| src/components/notification/hooks/useInboxNotificationStream.ts | SSE inbox notification stream hook + token refresh scheduling. |
| src/components/notification/InboxNotificationLayer.tsx | Global layer that receives SSE notifications, updates caches, and shows toast queue. |
| src/components/notification/InAppNotificationToast.tsx | Toast UI rendered via Portal and positioned above bottom overlays. |
| src/components/layout/layoutMetrics.ts | Centralizes bottom overlay inset calculations and toast/list bottom gaps. |
| src/components/layout/index.tsx | Layout refactor: header presentation, bottom inset CSS var, layout root ref, and notification layer mount. |
| src/components/layout/hooks/useLayoutElements.ts | New hook to manage layout element refs + inset measurement. |
| src/components/layout/hooks/useLayoutBottomOverlayInset.ts | Measures bottom overlay inset using bottom nav + viewport changes. |
| src/components/layout/Header/types.ts | Adds notification header type. |
| src/components/layout/Header/routeTitles.ts | Adds /notifications title mapping. |
| src/components/layout/Header/presentation.ts | New header “presentation” resolver (type/title/padding). |
| src/components/layout/Header/index.tsx | Uses presentation resolver; renders new notification header via SubpageHeader. |
| src/components/layout/Header/headerConfig.ts | Routes /notifications to notification header type. |
| src/components/layout/Header/constants.ts | Renames header height constant to SUBPAGE_HEADER_HEIGHT. |
| src/components/layout/Header/components/SubpageHeader.tsx | New reusable fixed subpage header (back button + title + optional right slot). |
| src/components/layout/Header/components/NotificationBell.tsx | Replaces chat bell with notifications bell + unread indicator icon and link to /notifications. |
| src/components/layout/Header/components/ManagerHeader.tsx | Refactors to reuse SubpageHeader + notification bell slot. |
| src/components/layout/Header/components/InfoHeader.tsx | Removes chat-tooltip behavior; uses new notification bell. |
| src/components/layout/BottomNav/index.tsx | Switches to manual selection logic (Link + aria-current), including /notifications mapping to Home tab. |
| src/components/common/Portal.tsx | Allows `DocumentFragment |
| src/assets/svg/unread-notification.svg | New unread notification icon asset. |
| src/assets/svg/person-icon.svg | New person icon asset. |
| src/assets/svg/notifications.svg | New notifications icon asset. |
| src/assets/svg/chat-icon.svg | New chat icon asset. |
| src/assets/image/notification-toast-approved.png | New toast image asset (approved variant). |
| src/apis/notification/queries.ts | Adds react-query key helpers for notification domain. |
| src/apis/notification/index.ts | Adds inbox list/unread-count/read APIs. |
| src/apis/notification/entity.ts | Adds inbox notification entities/types. |
| src/apis/notification/cache.ts | Adds cache helpers (prepend notification, mark read, unread count inc/dec). |
| src/apis/auth/index.ts | Deduplicates concurrent refresh token calls with a shared promise. |
| src/App.tsx | Registers /notifications route under protected layout. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (9)
src/components/layout/Header/headerConfig.ts (1)
46-46: 기존 코드:==대신===사용 권장이 PR의 변경사항은 아니지만, Line 46에서
==대신===를 사용하는 것이 TypeScript 컨벤션에 맞습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/Header/headerConfig.ts` at line 46, The match function in headerConfig uses loose equality (match: (pathname) => pathname == '/schedule') which should be strict; update the arrow function in headerConfig.ts to use === instead of == (i.e., change pathname == '/schedule' to pathname === '/schedule') so the match comparison uses strict equality.src/apis/notification/cache.ts (1)
1-6: import 순서 수정 필요코딩 가이드라인에 따르면 import 순서는
external → internal(@/**)순이어야 합니다.@tanstack/react-query가@/apis/notification/entity앞에 와야 합니다.♻️ 수정 제안
+import type { InfiniteData } from '@tanstack/react-query'; + import type { InboxNotification, InboxNotificationListResponse, InboxNotificationUnreadCountResponse, } from '@/apis/notification/entity'; -import type { InfiniteData } from '@tanstack/react-query';As per coding guidelines: "Follow import order: builtin → external → internal (
@/**) → parent → sibling → index"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apis/notification/cache.ts` around lines 1 - 6, The imports are out of order: external modules must come before internal alias imports; reorder the two import blocks so the external import from '@tanstack/react-query' (InfiniteData) appears above the internal '@/apis/notification/entity' import (InboxNotification, InboxNotificationListResponse, InboxNotificationUnreadCountResponse); update the import ordering in src/apis/notification/cache.ts accordingly to follow builtin → external → internal convention.src/apis/notification/index.ts (1)
1-2: import 경로에 path alias 사용 권장코딩 가이드라인에 따르면 상대 경로 대신
@/*path alias를 사용해야 합니다.♻️ 수정 제안
import type { InboxNotificationListResponse, InboxNotificationUnreadCountResponse } from '@/apis/notification/entity'; -import { apiClient } from '../client'; +import { apiClient } from '@/apis/client';As per coding guidelines: "Use path alias
@/*for imports instead of relative paths"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apis/notification/index.ts` around lines 1 - 2, The import in src/apis/notification/index.ts uses a relative path for apiClient; update the import of apiClient (symbol: apiClient) to use the project path alias (e.g., replace "../client" with the corresponding "@/..." alias used across the repo) so it follows the coding guideline to use `@/`* path aliases; keep the existing type import from '@/apis/notification/entity' unchanged and ensure the alias matches your tsconfig/webpack settings.src/App.tsx (1)
45-45: 신규 import는 alias 경로로 맞춰주세요.Line 45는 새로 추가된 import라
@/*alias 규칙을 따르는 편이 좋습니다.수정 예시
-const NotificationsPage = lazy(() => import('./pages/Notifications')); +const NotificationsPage = lazy(() => import('@/pages/Notifications'));As per coding guidelines "Use
@/*alias for import paths instead of relative paths".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/App.tsx` at line 45, The lazy import using NotificationsPage currently uses a relative path; update the import to use the project alias by changing the lazy call for NotificationsPage (const NotificationsPage = lazy(() => import('./pages/Notifications'))) to import from the alias path (e.g. import('@/pages/Notifications')) so it follows the "@/ *" import convention.src/components/layout/Header/components/NotificationBell.tsx (1)
4-4: 공용 헤더가 페이지 레이어에 의존하고 있습니다.
NotificationBell이src/pages/Notifications/hooks/useInboxNotifications를 직접 import하면 공용 레이아웃이 페이지 디렉터리에 묶입니다. unread count 훅은notification공용 레이어로 올려서 헤더와 페이지가 같이 쓰게 분리하는 편이 안전합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/Header/components/NotificationBell.tsx` at line 4, NotificationBell currently imports useUnreadInboxNotificationCount from src/pages/Notifications/hooks/useInboxNotifications, coupling the shared header to the page layer; move the unread-count hook into the shared notification layer and update imports: extract the hook logic from useUnreadInboxNotificationCount (and any dependent types) into the common notification package/module (e.g., notification/hooks or notification/useUnreadInboxNotificationCount), export it from that module, then change NotificationBell to import useUnreadInboxNotificationCount from the new shared notification module and remove any page-layer-only imports so both Header/NotificationBell and the Notifications page consume the same shared hook.src/components/layout/index.tsx (1)
9-11: 추가된 layout import는 alias로 맞춰주세요.이번에 늘어난 import도 상대 경로를 쓰고 있어서 이 계층만 규칙이 다시 섞입니다.
@/components/layout/...형태로 통일하는 편이 좋겠습니다. As per coding guidelines, "Use path alias@/*for imports instead of relative paths".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/index.tsx` around lines 9 - 11, The three imports in index.tsx (SUBPAGE_HEADER_HEIGHT, getHeaderPresentation, useLayoutElements) currently use relative paths; change them to use the project path alias format (e.g. import { SUBPAGE_HEADER_HEIGHT } from '@/components/layout/Header/constants', import { getHeaderPresentation } from '@/components/layout/Header/presentation', and import { useLayoutElements } from '@/components/layout/hooks/useLayoutElements') so all layout imports follow the '@/...' alias convention.src/components/layout/hooks/useLayoutElements.ts (1)
2-2: import 경로는@/alias로 통일해주세요.신규 훅 파일이라 지금 상대 경로를 남기면 같은 레이어 안에서도 import 규칙이 섞입니다. As per coding guidelines, "Use path alias
@/*for imports instead of relative paths".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/hooks/useLayoutElements.ts` at line 2, The import in useLayoutElements.ts uses a relative path for the hook; replace the relative import of useLayoutBottomOverlayInset with the project path-alias form (useLayoutBottomOverlayInset from '@/components/layout/hooks/useLayoutBottomOverlayInset') so all imports follow the "@/..." alias convention and avoid mixing relative paths with aliased imports.src/components/layout/BottomNav/index.tsx (1)
68-72: 바텀 네비 라벨은 타이포 토큰으로 맞춰주세요.여기만 임의 값(
text-[12px],leading-[1.6],font-semibold)을 쓰면 다른 라벨과 맞추기 어려워집니다.text-cap*같은 토큰으로 치환하는 편이 좋겠습니다. As per coding guidelines, "Use semantic typography utilities (text-h1,text-body1, etc.) before custom styles".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/layout/BottomNav/index.tsx` around lines 68 - 72, The span in the BottomNav component is using hardcoded typography classes (text-[12px], leading-[1.6], font-semibold) which breaks consistency; replace those with the project's semantic typography utility token (e.g., text-cap / text-cap-*, or the equivalent token used across the app) and remove the custom leading/font weight so the label inherits the token's styles while keeping the existing conditional color (`isSelected ? 'text-primary-500' : 'text-text-400'`) logic intact; update the span with the appropriate semantic class name instead of the three inline tokens to match the app's typography system.src/components/notification/InAppNotificationToast.tsx (1)
45-60: 새 토스트도 테마 토큰으로 맞춰주세요.배경/텍스트 색상과 타이포가
rgba(...), hex,text-[..]로 직접 박혀 있어서 다른 화면과 일관성이 깨집니다.theme.css의 색상/타이포 토큰으로 맞춰 두는 편이 유지보수에 낫습니다.As per coding guidelines,
Prioritize color tokens from src/styles/theme.cssandUse typography tokens (text-h1 through text-cap2) from src/styles/theme.css.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/notification/InAppNotificationToast.tsx` around lines 45 - 60, The toast uses hardcoded colors and inline typography classes—replace those with theme tokens from src/styles/theme.css: update the root container class (currently using bg-[rgba(231,235,239,0.9)] and shadow) to use the appropriate background and shadow color tokens; replace the message <p> classes (text-[16px], text-text-700, leading) with the matching typography token (e.g., one of text-h1..text-cap2) and the theme text color token; and replace the button classes (bg-white, text-[13px], text-[`#5A6B7F`], active:bg-[`#F4F6F9`]) with the corresponding theme background/text/active color tokens. Modify the className strings in InAppNotificationToast (root element, the <p> rendering message, and the action <button>) to reference the theme tokens so styling is consistent and maintainable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/layout/BottomNav/index.tsx`:
- Line 25: The matchesPath implementation is too broad—matchesPath: (pathname)
=> pathname === '/home' || pathname === '/notifications'—so the Home link is
marked as the active page on /notifications; update matchesPath to only return
true when the route exactly matches the link target (e.g., pathname === to) so
aria-current="page" is only set for the actual page, or alternatively change the
logic to use location-based/section highlighting for non-page emphasis; apply
the same fix to the other occurrence around the second matchesPath block (lines
noted in the review).
In `@src/components/notification/hooks/useInboxNotificationStream.ts`:
- Around line 162-164: The reconnect path in useInboxNotificationStream
currently only waits NOTIFICATION_STREAM_RECONNECT_DELAY and reopens the stream
(check the block using signal.aborted and NOTIFICATION_STREAM_RECONNECT_DELAY
around lines ~162 and the reconnect logic around 220–243) but doesn't
resynchronize inbox caches; after a successful reconnect, call the app's query
invalidation for inbox-related data (e.g., use the existing
queryClient.invalidateQueries for the inbox/unread count keys) or emit a
reconnect event up (e.g., dispatch a "reconnect" through the same event emitter
used by the stream) so inbox list and unread count are refreshed; place this
invalidate/emit right after the stream is successfully re-established and guard
it by signal.aborted to avoid racing during shutdown.
- Around line 77-119: The retry flag hasRetriedAfterUnauthorized is scoped to
the whole function so once a 401 is handled it prevents refresh on later
reconnects; to fix, reset hasRetriedAfterUnauthorized when you successfully
establish a stream (i.e., after receiving an ok response from the fetch in
useInboxNotificationStream or just before you start processing the event
stream), so subsequent reconnect attempts can retry refresh on a fresh 401;
reference hasRetriedAfterUnauthorized, refreshAccessToken, and the
fetch/response.ok handling in useInboxNotificationStream and set the flag back
to false upon successful connection.
In `@src/components/notification/InboxNotificationLayer.tsx`:
- Around line 30-52: Prevent enqueuing while on the /notifications route by
adding a route check at the top of enqueueNotification (use your router or
location.pathname) and early-return when on that route; also, on component
mount/route-enter, clear the toast queue via setNotificationQueue([]) so
previously buffered notifications are dropped. Update enqueueNotification (and
related usages that call setNotificationQueue like the startTransition block) to
skip updating the queue and skip calling prependInboxNotification only when the
current path is "/notifications" while still updating server-side state like
seenNotificationIdsRef or unread counts as needed.
In `@src/pages/Notifications/hooks/useInboxNotifications.ts`:
- Around line 38-47: The unreadCount is always decremented in the onSuccess
handler even when the notification was already read, causing the badge to
underflow; change the onSuccess logic so you first compute the read-state
transition via setInboxNotificationReadState (or a helper) and only call
decrementInboxUnreadCount when that update actually changed a notification from
unread→read. In practice, have setInboxNotificationReadState return whether a
transition happened (or return the updated list and detect the change by
comparing previousData), then call
queryClient.setQueryData(notificationQueryKeys.inbox.unreadCount(), ...) to
decrement only when the transition flag is true.
In `@src/pages/Notifications/index.tsx`:
- Around line 97-110: handleNotificationClick currently returns early when
markAsRead throws, blocking navigation; change the try/catch around markAsRead
so failures are swallowed (optionally log or trigger the existing toast) and do
not return, then continue to compute destinationPath via
normalizeInboxNotificationPath and call navigate(destinationPath) as before;
refer to handleNotificationClick, markAsRead, normalizeInboxNotificationPath,
and navigate when making this change.
---
Nitpick comments:
In `@src/apis/notification/cache.ts`:
- Around line 1-6: The imports are out of order: external modules must come
before internal alias imports; reorder the two import blocks so the external
import from '@tanstack/react-query' (InfiniteData) appears above the internal
'@/apis/notification/entity' import (InboxNotification,
InboxNotificationListResponse, InboxNotificationUnreadCountResponse); update the
import ordering in src/apis/notification/cache.ts accordingly to follow builtin
→ external → internal convention.
In `@src/apis/notification/index.ts`:
- Around line 1-2: The import in src/apis/notification/index.ts uses a relative
path for apiClient; update the import of apiClient (symbol: apiClient) to use
the project path alias (e.g., replace "../client" with the corresponding "@/..."
alias used across the repo) so it follows the coding guideline to use `@/`* path
aliases; keep the existing type import from '@/apis/notification/entity'
unchanged and ensure the alias matches your tsconfig/webpack settings.
In `@src/App.tsx`:
- Line 45: The lazy import using NotificationsPage currently uses a relative
path; update the import to use the project alias by changing the lazy call for
NotificationsPage (const NotificationsPage = lazy(() =>
import('./pages/Notifications'))) to import from the alias path (e.g.
import('@/pages/Notifications')) so it follows the "@/ *" import convention.
In `@src/components/layout/BottomNav/index.tsx`:
- Around line 68-72: The span in the BottomNav component is using hardcoded
typography classes (text-[12px], leading-[1.6], font-semibold) which breaks
consistency; replace those with the project's semantic typography utility token
(e.g., text-cap / text-cap-*, or the equivalent token used across the app) and
remove the custom leading/font weight so the label inherits the token's styles
while keeping the existing conditional color (`isSelected ? 'text-primary-500' :
'text-text-400'`) logic intact; update the span with the appropriate semantic
class name instead of the three inline tokens to match the app's typography
system.
In `@src/components/layout/Header/components/NotificationBell.tsx`:
- Line 4: NotificationBell currently imports useUnreadInboxNotificationCount
from src/pages/Notifications/hooks/useInboxNotifications, coupling the shared
header to the page layer; move the unread-count hook into the shared
notification layer and update imports: extract the hook logic from
useUnreadInboxNotificationCount (and any dependent types) into the common
notification package/module (e.g., notification/hooks or
notification/useUnreadInboxNotificationCount), export it from that module, then
change NotificationBell to import useUnreadInboxNotificationCount from the new
shared notification module and remove any page-layer-only imports so both
Header/NotificationBell and the Notifications page consume the same shared hook.
In `@src/components/layout/Header/headerConfig.ts`:
- Line 46: The match function in headerConfig uses loose equality (match:
(pathname) => pathname == '/schedule') which should be strict; update the arrow
function in headerConfig.ts to use === instead of == (i.e., change pathname ==
'/schedule' to pathname === '/schedule') so the match comparison uses strict
equality.
In `@src/components/layout/hooks/useLayoutElements.ts`:
- Line 2: The import in useLayoutElements.ts uses a relative path for the hook;
replace the relative import of useLayoutBottomOverlayInset with the project
path-alias form (useLayoutBottomOverlayInset from
'@/components/layout/hooks/useLayoutBottomOverlayInset') so all imports follow
the "@/..." alias convention and avoid mixing relative paths with aliased
imports.
In `@src/components/layout/index.tsx`:
- Around line 9-11: The three imports in index.tsx (SUBPAGE_HEADER_HEIGHT,
getHeaderPresentation, useLayoutElements) currently use relative paths; change
them to use the project path alias format (e.g. import { SUBPAGE_HEADER_HEIGHT }
from '@/components/layout/Header/constants', import { getHeaderPresentation }
from '@/components/layout/Header/presentation', and import { useLayoutElements }
from '@/components/layout/hooks/useLayoutElements') so all layout imports follow
the '@/...' alias convention.
In `@src/components/notification/InAppNotificationToast.tsx`:
- Around line 45-60: The toast uses hardcoded colors and inline typography
classes—replace those with theme tokens from src/styles/theme.css: update the
root container class (currently using bg-[rgba(231,235,239,0.9)] and shadow) to
use the appropriate background and shadow color tokens; replace the message <p>
classes (text-[16px], text-text-700, leading) with the matching typography token
(e.g., one of text-h1..text-cap2) and the theme text color token; and replace
the button classes (bg-white, text-[13px], text-[`#5A6B7F`], active:bg-[`#F4F6F9`])
with the corresponding theme background/text/active color tokens. Modify the
className strings in InAppNotificationToast (root element, the <p> rendering
message, and the action <button>) to reference the theme tokens so styling is
consistent and maintainable.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6133d1e6-5c85-440e-80b6-6b97c4df8b94
⛔ Files ignored due to path filters (7)
src/assets/image/chat-cat-header.pngis excluded by!**/*.png,!src/assets/**and included by**src/assets/image/notification-toast-approved.pngis excluded by!**/*.png,!src/assets/**and included by**src/assets/image/notification-toast-general.pngis excluded by!**/*.png,!src/assets/**and included by**src/assets/svg/chat-icon.svgis excluded by!**/*.svg,!src/assets/**and included by**src/assets/svg/notifications.svgis excluded by!**/*.svg,!src/assets/**and included by**src/assets/svg/person-icon.svgis excluded by!**/*.svg,!src/assets/**and included by**src/assets/svg/unread-notification.svgis excluded by!**/*.svg,!src/assets/**and included by**
📒 Files selected for processing (32)
src/App.tsxsrc/apis/auth/index.tssrc/apis/notification/cache.tssrc/apis/notification/entity.tssrc/apis/notification/index.tssrc/apis/notification/queries.tssrc/components/common/Portal.tsxsrc/components/layout/BottomNav/index.tsxsrc/components/layout/Header/components/InfoHeader.tsxsrc/components/layout/Header/components/ManagerHeader.tsxsrc/components/layout/Header/components/NotificationBell.tsxsrc/components/layout/Header/components/SubpageHeader.tsxsrc/components/layout/Header/constants.tssrc/components/layout/Header/headerConfig.tssrc/components/layout/Header/index.tsxsrc/components/layout/Header/presentation.tssrc/components/layout/Header/routeTitles.tssrc/components/layout/Header/types.tssrc/components/layout/hooks/useLayoutBottomOverlayInset.tssrc/components/layout/hooks/useLayoutElements.tssrc/components/layout/index.tsxsrc/components/layout/layoutMetrics.tssrc/components/notification/InAppNotificationToast.tsxsrc/components/notification/InboxNotificationLayer.tsxsrc/components/notification/hooks/useInboxNotificationStream.tssrc/contexts/useLayoutElementsContext.tsxsrc/index.csssrc/pages/Notifications/hooks/useInboxNotifications.tssrc/pages/Notifications/index.tsxsrc/stores/authStore.tssrc/utils/ts/accessToken.tssrc/utils/ts/notification.ts
de441ba to
b32ac18
Compare
* 205 feat 이미지 전처리 기능 구현 (#206) * feat: 전처리 로직 및 WebWorker 구현 * feat: 전처리 적용 및 preview 동시성 제어 로직 추가 * refactor: 리뷰 반영 * [hotfix] 하단바 너비 수정 (#208) * hotfix: 하단바 너비 수정 * chore: 불필요한 값 제거 * refactor: 고정 gap 제거 * Reapply "[feat] 광고 배너 추가 (#200)" This reverts commit c51ec85. * [feat] 하단바 리디자인 (#213) * chore: asset 추가 * feat: 하단바 리디자인 반영 및 레이아웃 수정 * [refactor] 광고 카드 레이아웃 밀림 수정 (#215) * refactor: 광고 개수 측정 시기 변경 및 기본값 제거 * feat: 스켈레톤 UI 추가 * feat: 인앱 알림 페이지 및 토스트 구현 (#217) * feat: 알림 API 및 스트림 기반 추가 * feat: 인앱 알림 레이어 추가 * feat: 알림 페이지 및 헤더 진입 구현 * fix: 알림 스트림 401 재시도 조건 정리 * fix: 알림 목록 이동 차단 제거 * refactor: 알림 공용 훅 위치 정리 * fix: 알림 재연결 캐시 동기화 추가 * fix: 알림 목록 토스트 큐 누적 방지 * fix: 알림 읽음 카운트 감소 조건 보강 * [refactor] 도메인별 TanStack Query 훅 정리 (#219) * chore: pwa용 이미지 제거 * refactor: auth 도메인 쿼리와 뮤테이션 정리 * refactor: council과 schedule 조회 훅 정리 * refactor: chat과 notification 캐시 처리 정리 * refactor: club 조회와 지원 플로우 정리 * refactor: manager 도메인 캐시 처리 정리 * refactor: studyTime 도메인 쿼리와 뮤테이션 정리 * refactor: 광고와 업로드 도메인 훅 정리 * [refactor] mutaton query 및 hook 추가 수정 (#221) * refactor: auth와 user myInfo 훅 정리 * refactor: club과 schedule 조회 훅 정리 * refactor: chat과 notification 훅 구조 정리 * refactor: club 지원 뮤테이션 훅 정리 * refactor: manager 뮤테이션 훅 구조 정리 * refactor: mutation 훅 cache 정리 * refactor: 컨벤션 통일 * refactor: isRead 조건 정리 * fix: 채팅 스크롤 문제 수정 * refactor: 불필요한 코드 제거 * [fix] 모바일 환경 입력창과 키보드 간의 간격이 큰 문제 수정 (#223) * chore: 가공용 safeArea 변수 선언 * refactor: 고정 패딩 값 수정 및 safeArea 적용 변경 * feat: 키보드 활성화 감지 및 safeArea 적용 여부 기능 추가 * refactor: 매직넘버 상수화 및 가로모드 처리 * [fix] 키보드 활성화 시 화면 흔들림 문제 수정 (#225) * refactor: 채팅 viewport 훅 네이밍 정리 * refactor: viewport 높이 잠금 훅 적용 시점 조정 * [fix] 키보드 활성화 시 채팅 화면 전체가 흔들리는 문제 수정 (#227) * refactor: 채팅 viewport 훅 네이밍 정리 * refactor: viewport 높이 잠금 훅 적용 시점 조정 * fix: 채팅 화면 스크롤 잠금으로 키보드 흔들림 완화 * fix: 입력 포커스 중 viewport offset 고정 (#229) * fix: 문서 루트 스크롤 잠금으로 빈 공간 잔류 방지 (#232) * [fix] 키보드 활성화 시 채팅 화면 상단 고정이 깨지고 빈 공간이 남는 문제 수정 (#234) * fix: 채팅 화면 상단 고정 깨짐과 빈 공간 잔류 수정 * refactor: 라우트 조건 수정 * fix: 문서 스크롤 위치 감지 보강 * refactor: 입력 요소 판별 유틸과 스크롤 주석 정리 * [fix] 키보드 활성화 시 채팅 화면에서 문서 스크롤이 발생하는 문제 수정 (#236) * fix: 채팅 문서 스크롤 제스처 차단 * fix: 입력 요소 터치 동작 예외 처리 * [fix] 키보드 활성화 시 채팅방이 마지막 메시지 위치를 유지하지 못하는 문제 수정 (#238) * fix: 키보드 활성화 시 채팅 하단 정렬 유지 * refactor: 채팅 리사이즈 관찰 안정화 * fix: mypage 연계 약관 페이지 뒤로가기 수정 (#240) * refactor: alias import 경로 정리 * fix: query 설정과 suspense 분기 정리 * refactor: 관리자 화면 스타일 유틸 정리 * fix: 이미지 전처리 예외 처리 보강 * fix: 헤더와 회비 화면 동작 정리 * fix: 공통 유틸 안정성 개선 * fix: 이미지 전처리 실패 처리를 보정 * fix: 모집 공고 저장 후 설정 반영 순서 조정 * fix: 부원 직책 변경 실패 처리를 보강 * fix: 약관 링크 접근성을 개선 * fix: 공통 쿼리와 유틸 안정성을 보완 * [feat] 동적 버전 정보 표시 구현 (#211) * feat: 동적 버전 정보 표시 구현 * refactor: 버전 정보 미 존재시 v 표시 제거 * [feat] 메인화면 동아리 카드 디자인 수정 반영 (#242) * feat: 메인화면 동아리 카드 디자인 수정 * chore: 하단바 아이콘 수정 * refactor: 코드래빗 리뷰 반영 * refactor: and 연산자로 변경 * apiClient 코드 중복 제거 및 네이티브 브릿지 인증 동기화 중앙화 (#244) * refactor: apiClient 코드 중복 제거 및 네이티브 브릿지 인증 동기화 중앙화 * refactor: body 직렬화 가드를 plain object/array로 한정 * fix: body 읽기 중 AbortError가 ParseError로 오분류되는 문제 수정 * [refactor] 에러 처리 유틸 및 utils 구조 정리 (#246) * refactor: 에러 처리 유틸 및 공통 토스트 흐름 정리 * refactor: utils 폴더 구조를 역할별로 정리 * refactor: 코드래빗 리뷰 반영 * refactor: 코드래빗 리뷰 반영 * Update src/pages/Home/components/HomeClubSection.tsx * fix: 인증 세션 복구 흐름 정리 * fix: 홈 동아리 카드 레이아웃 정리 * [feat] 총동아리 페이지 리디자인 및 하단 오버레이 정리 (#249) * refactor: 하단 오버레이 처리 공통화 * feat: 총동아리 페이지와 헤더 리디자인 반영 * fix: 채팅 하단 여백과 외부 링크 속성 수정 * refactor: 총동아리 헤더 설정 정리 * fix: 총동아리 상세 접근성과 스타일 보완 * [feat] 마이페이지 관리자 카드 분리 및 채팅 미확인 배지 반영 (#251) * feat: 하단 채팅 배지 표시 및 조회 조건 보완 * refactor: 관리자 정보 카드 컴포넌트 분리 * feat: 채팅 페이지 리디자인 (#252) * feat: 채팅 페이지 리디자인 * fix:tailwind 문법 수정 * fix: 코드 수정 * fix: 폰트 색상 및 위치 수정 * fix: 채팅방 사람수 정렬 * fix: 오타 수정 * chore: conflict 해결 중 누락된 부분 수정 * [refactor] 광고 렌더링 조건 수정 (#254) * refactor: 광고 렌더링 조건 수정 * docs: 문서명 변경 --------- Co-authored-by: 박성주 <145267904+ParkSungju01@users.noreply.github.com>
* [배포] 이미지 전처리, 광고 기능, 하단바 리디자인, 인앱 알림 페이지 및 토스트 프로덕션 배포 (#230) * 205 feat 이미지 전처리 기능 구현 (#206) * feat: 전처리 로직 및 WebWorker 구현 * feat: 전처리 적용 및 preview 동시성 제어 로직 추가 * refactor: 리뷰 반영 * [hotfix] 하단바 너비 수정 (#208) * hotfix: 하단바 너비 수정 * chore: 불필요한 값 제거 * refactor: 고정 gap 제거 * Reapply "[feat] 광고 배너 추가 (#200)" This reverts commit c51ec85. * [feat] 하단바 리디자인 (#213) * chore: asset 추가 * feat: 하단바 리디자인 반영 및 레이아웃 수정 * [refactor] 광고 카드 레이아웃 밀림 수정 (#215) * refactor: 광고 개수 측정 시기 변경 및 기본값 제거 * feat: 스켈레톤 UI 추가 * feat: 인앱 알림 페이지 및 토스트 구현 (#217) * feat: 알림 API 및 스트림 기반 추가 * feat: 인앱 알림 레이어 추가 * feat: 알림 페이지 및 헤더 진입 구현 * fix: 알림 스트림 401 재시도 조건 정리 * fix: 알림 목록 이동 차단 제거 * refactor: 알림 공용 훅 위치 정리 * fix: 알림 재연결 캐시 동기화 추가 * fix: 알림 목록 토스트 큐 누적 방지 * fix: 알림 읽음 카운트 감소 조건 보강 * [refactor] 도메인별 TanStack Query 훅 정리 (#219) * chore: pwa용 이미지 제거 * refactor: auth 도메인 쿼리와 뮤테이션 정리 * refactor: council과 schedule 조회 훅 정리 * refactor: chat과 notification 캐시 처리 정리 * refactor: club 조회와 지원 플로우 정리 * refactor: manager 도메인 캐시 처리 정리 * refactor: studyTime 도메인 쿼리와 뮤테이션 정리 * refactor: 광고와 업로드 도메인 훅 정리 * [refactor] mutaton query 및 hook 추가 수정 (#221) * refactor: auth와 user myInfo 훅 정리 * refactor: club과 schedule 조회 훅 정리 * refactor: chat과 notification 훅 구조 정리 * refactor: club 지원 뮤테이션 훅 정리 * refactor: manager 뮤테이션 훅 구조 정리 * refactor: mutation 훅 cache 정리 * refactor: 컨벤션 통일 * refactor: isRead 조건 정리 * fix: 채팅 스크롤 문제 수정 * refactor: 불필요한 코드 제거 * [fix] 모바일 환경 입력창과 키보드 간의 간격이 큰 문제 수정 (#223) * chore: 가공용 safeArea 변수 선언 * refactor: 고정 패딩 값 수정 및 safeArea 적용 변경 * feat: 키보드 활성화 감지 및 safeArea 적용 여부 기능 추가 * refactor: 매직넘버 상수화 및 가로모드 처리 * [fix] 키보드 활성화 시 화면 흔들림 문제 수정 (#225) * refactor: 채팅 viewport 훅 네이밍 정리 * refactor: viewport 높이 잠금 훅 적용 시점 조정 * [fix] 키보드 활성화 시 채팅 화면 전체가 흔들리는 문제 수정 (#227) * refactor: 채팅 viewport 훅 네이밍 정리 * refactor: viewport 높이 잠금 훅 적용 시점 조정 * fix: 채팅 화면 스크롤 잠금으로 키보드 흔들림 완화 * fix: 입력 포커스 중 viewport offset 고정 (#229) * fix: 문서 루트 스크롤 잠금으로 빈 공간 잔류 방지 (#232) * [fix] 키보드 활성화 시 채팅 화면 상단 고정이 깨지고 빈 공간이 남는 문제 수정 (#234) * fix: 채팅 화면 상단 고정 깨짐과 빈 공간 잔류 수정 * refactor: 라우트 조건 수정 * fix: 문서 스크롤 위치 감지 보강 * refactor: 입력 요소 판별 유틸과 스크롤 주석 정리 * [fix] 키보드 활성화 시 채팅 화면에서 문서 스크롤이 발생하는 문제 수정 (#236) * fix: 채팅 문서 스크롤 제스처 차단 * fix: 입력 요소 터치 동작 예외 처리 * [fix] 키보드 활성화 시 채팅방이 마지막 메시지 위치를 유지하지 못하는 문제 수정 (#238) * fix: 키보드 활성화 시 채팅 하단 정렬 유지 * refactor: 채팅 리사이즈 관찰 안정화 * fix: mypage 연계 약관 페이지 뒤로가기 수정 (#240) * refactor: alias import 경로 정리 * fix: query 설정과 suspense 분기 정리 * refactor: 관리자 화면 스타일 유틸 정리 * fix: 이미지 전처리 예외 처리 보강 * fix: 헤더와 회비 화면 동작 정리 * fix: 공통 유틸 안정성 개선 * fix: 이미지 전처리 실패 처리를 보정 * fix: 모집 공고 저장 후 설정 반영 순서 조정 * fix: 부원 직책 변경 실패 처리를 보강 * fix: 약관 링크 접근성을 개선 * fix: 공통 쿼리와 유틸 안정성을 보완 * [feat] 동적 버전 정보 표시 구현 (#211) * feat: 동적 버전 정보 표시 구현 * refactor: 버전 정보 미 존재시 v 표시 제거 * [feat] 메인화면 동아리 카드 디자인 수정 반영 (#242) * feat: 메인화면 동아리 카드 디자인 수정 * chore: 하단바 아이콘 수정 * refactor: 코드래빗 리뷰 반영 * refactor: and 연산자로 변경 * apiClient 코드 중복 제거 및 네이티브 브릿지 인증 동기화 중앙화 (#244) * refactor: apiClient 코드 중복 제거 및 네이티브 브릿지 인증 동기화 중앙화 * refactor: body 직렬화 가드를 plain object/array로 한정 * fix: body 읽기 중 AbortError가 ParseError로 오분류되는 문제 수정 * [refactor] 에러 처리 유틸 및 utils 구조 정리 (#246) * refactor: 에러 처리 유틸 및 공통 토스트 흐름 정리 * refactor: utils 폴더 구조를 역할별로 정리 * refactor: 코드래빗 리뷰 반영 * refactor: 코드래빗 리뷰 반영 * Update src/pages/Home/components/HomeClubSection.tsx * fix: 인증 세션 복구 흐름 정리 * fix: 홈 동아리 카드 레이아웃 정리 * [feat] 총동아리 페이지 리디자인 및 하단 오버레이 정리 (#249) * refactor: 하단 오버레이 처리 공통화 * feat: 총동아리 페이지와 헤더 리디자인 반영 * fix: 채팅 하단 여백과 외부 링크 속성 수정 * refactor: 총동아리 헤더 설정 정리 * fix: 총동아리 상세 접근성과 스타일 보완 * [feat] 마이페이지 관리자 카드 분리 및 채팅 미확인 배지 반영 (#251) * feat: 하단 채팅 배지 표시 및 조회 조건 보완 * refactor: 관리자 정보 카드 컴포넌트 분리 * feat: 채팅 페이지 리디자인 (#252) * feat: 채팅 페이지 리디자인 * fix:tailwind 문법 수정 * fix: 코드 수정 * fix: 폰트 색상 및 위치 수정 * fix: 채팅방 사람수 정렬 * fix: 오타 수정 * chore: conflict 해결 중 누락된 부분 수정 * [refactor] 광고 렌더링 조건 수정 (#254) * refactor: 광고 렌더링 조건 수정 * docs: 문서명 변경 --------- Co-authored-by: 박성주 <145267904+ParkSungju01@users.noreply.github.com> * refactor: 가이드 페이지 이미지 변경 및 구조 개선 (#260) * hotfix: 가이드 이미지 경로 변경 --------- Co-authored-by: 박성주 <145267904+ParkSungju01@users.noreply.github.com>
✨ 요약
😎 해결한 이슈
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항