Conversation
Walkthrough클라이언트 사이드 이미지 전처리 기능을 추가했습니다. 새 유틸리티 Possibly related PRs
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 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 Tip CodeRabbit can use TruffleHog to scan for secrets in your code with verification capabilities.Add a TruffleHog config file (e.g. trufflehog-config.yml, trufflehog.yml) to your project to customize detectors and scanning behavior. The tool runs only when a config file is present. |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 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/pages/Manager/ManagedClubProfile/index.tsx`:
- Around line 91-116: The bug: deleting an image during async prepare can be
undone when prepare completes; update handleImageSelect and handleDeleteImage so
a delete during preparation prevents the prepared result from being applied.
Concretely, add a ref flag (e.g., imageDeletedRef) and set it true in
handleDeleteImage and false at start of handleImageSelect; before calling
setImageFile/setImagePreview (and before creating/assigning localPreviewUrlRef),
check that isPreparingImage is still true and imageDeletedRef is false (or
simply that imageDeletedRef is false) — if deletion occurred, discard the
preparedFile and don't set state. Also disable the delete UI when
isPreparingImage or ensure handleDeleteImage sets imageDeletedRef and clears any
pending preview refs (localPreviewUrlRef) so the prepared result cannot restore
the deleted image.
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 169-193: The images are being appended in completion order because
onResolved uses setImages((prev) => [...prev, newItem]) inside
mapWithConcurrencyLimit; change this so uploads preserve the user's selection
order: either have mapWithConcurrencyLimit provide the original index for each
result and insert each preparedFile at that fixed index into images (use
setImages(prev => { const next=[...prev]; next[index]=newItem; return next; })),
or await mapWithConcurrencyLimit(...) to get an array of prepared files in the
original order and then call setImages once to append them in order and
setCurrentImageIndex based on previousImageCount; update references to
mapWithConcurrencyLimit, prepareImageFile, setImages, and setCurrentImageIndex
accordingly.
In `@src/utils/ts/imagePreprocessor.ts`:
- Around line 65-73: The worker initialization currently lets any exception from
new Worker(...) or runWorkerPreprocess() short-circuit and return the original
file, disabling the canvas fallback; update getWorker() to wrap the Worker
construction in a try/catch and on any error set imagePreprocessWorker = null
and return null so runMainThreadPreprocess() remains possible, and likewise wrap
calls to runWorkerPreprocess() (and the worker message/setup blocks referenced
around lines 103-121 and 196-210) so any thrown error clears
imagePreprocessWorker and returns null instead of failing the whole preprocess;
reference functions/variables imagePreprocessWorker, getWorker,
runWorkerPreprocess, and runMainThreadPreprocess when making these changes.
- Around line 39-41: getOutputMimeType() is hardcoded to always return
WEBP_MIME_TYPE which forces conversion to image/webp; update imagePreprocessor
logic to avoid breaking uploads by either preserving the original input mime
type or consulting a runtime capability flag before returning WebP.
Specifically, modify getOutputMimeType() (and callers in imagePreprocessor) to:
1) accept the original file mime/type or an options object, 2) check a
config/env flag or a new function like isBackendWebPSupported() (or query
src/apis/upload/entity.ts capabilities) and only return WEBP_MIME_TYPE when
supported, otherwise return the original mime (e.g., image/jpeg or image/png) as
a safe fallback, and 3) ensure upload code paths in src/apis/upload/index.ts
still handle the returned mime type.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d855c1ad-8080-489d-9b5a-69c0cf0b1111
📒 Files selected for processing (6)
src/pages/Club/Application/clubFeePage.tsxsrc/pages/Manager/ManagedClubProfile/index.tsxsrc/pages/Manager/ManagedRecruitmentWrite/index.tsxsrc/utils/ts/imagePreprocessor.tssrc/utils/ts/imagePreprocessor.worker.tssrc/utils/ts/promise.ts
| const [isPreparingImage, setIsPreparingImage] = useState(false); | ||
| const { value: isImageOpen, setTrue: openImage, setFalse: closeImage } = useBooleanState(); | ||
| const isSubmitting = isApplyingToClub || isUploadingImage; | ||
| const isSubmitting = isApplyingToClub || isPreparingImage || isUploadingImage; | ||
|
|
There was a problem hiding this comment.
전처리 중에도 파일 선택 버튼이 다시 열립니다.
초기 업로드에서는 previewUrl이 아직 없어서 큰 추가 버튼이 계속 렌더링되는데, 이 버튼은 여전히 fileInputRef.current?.click()를 바로 호출합니다. 그래서 전처리 중 두 번째 파일 선택창을 열 수 있고, 새 선택은 handleImageSelect의 early return으로 조용히 버려집니다. 이 CTA도 isPreparingImage 동안 비활성화해 주세요.
Also applies to: 43-58
| function getOutputMimeType() { | ||
| return WEBP_MIME_TYPE; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check the structure and find the relevant files
git ls-files src/utils/ts/imagePreprocessor.ts src/apis/upload/index.ts src/apis/upload/entity.tsRepository: BCSDLab/KONECT_FRONT_END
Length of output: 152
🏁 Script executed:
# Read the imagePreprocessor file to see lines 39-41 and 164-193
wc -l src/utils/ts/imagePreprocessor.tsRepository: BCSDLab/KONECT_FRONT_END
Length of output: 105
🏁 Script executed:
# Read the imagePreprocessor file
cat -n src/utils/ts/imagePreprocessor.tsRepository: BCSDLab/KONECT_FRONT_END
Length of output: 7417
🏁 Script executed:
# Read the upload API files
cat -n src/apis/upload/index.tsRepository: BCSDLab/KONECT_FRONT_END
Length of output: 567
🏁 Script executed:
# Read the upload entity file
cat -n src/apis/upload/entity.tsRepository: BCSDLab/KONECT_FRONT_END
Length of output: 250
🏁 Script executed:
# Search for usages of getOutputMimeType
rg "getOutputMimeType" -A 2 -B 2Repository: BCSDLab/KONECT_FRONT_END
Length of output: 1501
🏁 Script executed:
# Search for MIME type handling and WebP references
rg "image/webp|WEBP_MIME|webp" -iRepository: BCSDLab/KONECT_FRONT_END
Length of output: 1040
WebP 변환이 백엔드에서 지원되는지 확인 필요
getOutputMimeType()이 항상 image/webp를 반환하도록 하드코딩되어 있어서 JPEG/PNG 입력이 모두 WebP로 변환됩니다(line 164). 그런데 src/apis/upload/index.ts에서는 파일을 그대로 업로드하고, src/apis/upload/entity.ts에 지원 포맷 제약이 없어서 백엔드가 WebP를 받아주는지 명확하지 않습니다. 서버/스토리지가 WebP를 지원하지 않으면 이미지 업로드가 전체적으로 깨질 수 있으므로, 원본 포맷 유지 옵션이나 명시적인 WebP 지원 확인이 필요합니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/utils/ts/imagePreprocessor.ts` around lines 39 - 41, getOutputMimeType()
is hardcoded to always return WEBP_MIME_TYPE which forces conversion to
image/webp; update imagePreprocessor logic to avoid breaking uploads by either
preserving the original input mime type or consulting a runtime capability flag
before returning WebP. Specifically, modify getOutputMimeType() (and callers in
imagePreprocessor) to: 1) accept the original file mime/type or an options
object, 2) check a config/env flag or a new function like
isBackendWebPSupported() (or query src/apis/upload/entity.ts capabilities) and
only return WEBP_MIME_TYPE when supported, otherwise return the original mime
(e.g., image/jpeg or image/png) as a safe fallback, and 3) ensure upload code
paths in src/apis/upload/index.ts still handle the returned mime type.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pages/Manager/ManagedRecruitmentWrite/index.tsx (1)
536-542:⚠️ Potential issue | 🟡 Minor
disabled={isPreparingImages}누락다른 이미지 관련 버튼들(삭제, 이전, 다음)은
isPreparingImages시 비활성화되지만, "이미지 추가" 버튼은 누락되어 있습니다.handleImageClick에서 early return 하지만 UI 일관성을 위해 추가하세요.수정 제안
<button type="button" onClick={handleImageClick} + disabled={isPreparingImages} - className="bg-primary-500 rounded-full px-4 py-2 text-[13px] leading-[1.6] font-semibold text-white" + className="bg-primary-500 rounded-full px-4 py-2 text-[13px] leading-[1.6] font-semibold text-white disabled:cursor-not-allowed disabled:opacity-50" > 이미지 추가 </button>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx` around lines 536 - 542, The "이미지 추가" button lacks the disabled prop used elsewhere and should be disabled while images are preparing; update the button rendered for the "이미지 추가" action to include disabled={isPreparingImages} so it matches the other image buttons and prevents clicks that are already handled by the early return in handleImageClick; locate the button element in ManagedRecruitmentWrite (the one with onClick={handleImageClick}) and add the disabled prop (and optionally the same visual styling/aria attributes used on the other image control buttons) to keep UI state consistent.
🧹 Nitpick comments (4)
src/pages/Manager/ManagedRecruitmentWrite/index.tsx (4)
567-573: 중첩 삼항 연산자 - 가독성 고려현재 구현이 동작하지만, 상태가 더 추가되면 유지보수가 어려워질 수 있습니다. 필요 시 헬퍼 함수로 추출을 고려해보세요.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx` around lines 567 - 573, Replace the nested ternary used to render the submit button label (the JSX using isPreparingImages, isUploading, isPending) with a small helper function (e.g., getSubmitButtonLabel) or a prior if/else/switch block inside the ManagedRecruitmentWrite component that returns the correct string; update the JSX to call that helper (getSubmitButtonLabel()) so the logic is clearer and easier to extend when additional states are added.
203-203: 빈 catch 블록 - 의도된 동작인지 확인 필요
prepareImageFile은 에러 시 원본 파일을 반환하므로 reject하지 않지만,mapWithConcurrencyLimit자체의 예외는 무시됩니다. 로깅이나 최소한의 처리를 고려해보세요.선택적 개선안
) - .catch(() => {}) + .catch((error) => { + console.error('Image preparation failed:', error); + }) .finally(() => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx` at line 203, 현재 .catch(() => {})로 예외를 완전히 무시하고 있어 mapWithConcurrencyLimit 내부 또는 prepareImageFile 호출 중 발생한 에러를 놓칩니다; prepareImageFile이 항상 원본을 반환하더라도 mapWithConcurrencyLimit의 예외는 처리해야 하므로 빈 catch를 제거하고 에러를 로깅하거나 적절히 처리하도록 변경하세요: 해당 catch를 잡아 prepareImageFile, mapWithConcurrencyLimit 호출 컨텍스트(예: 파일 이름 또는 인덱스)를 포함한 에러 메시지를 콘솔 또는 기존 로거(processLogger 등)에 기록하고, 필요 시 재시도 또는 rethrow하여 상위에서 인지되게 만드세요.
3-3:cn()유틸리티 사용 권장가이드라인에 따르면
cn()fromsrc/utils/ts/cn.ts사용을 권장합니다.twMerge직접 사용 대신cn()으로 통일하면 clsx와 tailwind-merge를 함께 활용할 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx` at line 3, Replace direct use of twMerge with the shared cn utility: remove the import of twMerge and import cn from src/utils/ts/cn.ts, then replace all calls to twMerge(...) with cn(...) so clsx + tailwind-merge behavior is preserved; update any exported/used identifiers in this file (e.g., where twMerge is referenced in ManagedRecruitmentWrite component) to use cn instead.
44-297: 페이지 로직 분리 고려가이드라인에 따르면 페이지별 로직은
hooks/디렉토리로 분리하는 것을 권장합니다. 이미지 핸들링(handleImageSelect,handleDeleteImage등)과 폼 상태 관리를 커스텀 훅으로 분리하면 테스트와 재사용성이 향상됩니다.현재 PR 범위를 넘어서므로 후속 작업으로 진행해도 무방합니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx` around lines 44 - 297, The page contains a lot of state and image-handling logic that should be moved into reusable hooks; extract the form state and image logic into one or two custom hooks (e.g., useRecruitmentForm and/or useRecruitmentImages) that encapsulate state variables (startDate, endDate, startTime, endTime, content, isRecruitmentEnabled, isAlwaysRecruiting, images, currentImageIndex, isPreparingImages, isUploading, hasHandledExisting, hasInitializedRecruitmentEnabled), refs (textareaRef, fileInputRef) and handlers (handleImageSelect, handlePrevImage, handleNextImage, handleDeleteImage, handleImageClick, handleContentChange, handleReset, handleRecruitmentEnabledChange) and return only the state and functions the component needs; keep submit logic (handleSubmit) either in the form hook or left in the page but adapt it to consume the hook-provided state and image upload utilities (uploadImage, saveRecruitment, patchSettings), and update ManagedRecruitmentWrite to use these hooks so the component becomes a thin view layer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 536-542: The "이미지 추가" button lacks the disabled prop used
elsewhere and should be disabled while images are preparing; update the button
rendered for the "이미지 추가" action to include disabled={isPreparingImages} so it
matches the other image buttons and prevents clicks that are already handled by
the early return in handleImageClick; locate the button element in
ManagedRecruitmentWrite (the one with onClick={handleImageClick}) and add the
disabled prop (and optionally the same visual styling/aria attributes used on
the other image control buttons) to keep UI state consistent.
---
Nitpick comments:
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 567-573: Replace the nested ternary used to render the submit
button label (the JSX using isPreparingImages, isUploading, isPending) with a
small helper function (e.g., getSubmitButtonLabel) or a prior if/else/switch
block inside the ManagedRecruitmentWrite component that returns the correct
string; update the JSX to call that helper (getSubmitButtonLabel()) so the logic
is clearer and easier to extend when additional states are added.
- Line 203: 현재 .catch(() => {})로 예외를 완전히 무시하고 있어 mapWithConcurrencyLimit 내부 또는
prepareImageFile 호출 중 발생한 에러를 놓칩니다; prepareImageFile이 항상 원본을 반환하더라도
mapWithConcurrencyLimit의 예외는 처리해야 하므로 빈 catch를 제거하고 에러를 로깅하거나 적절히 처리하도록 변경하세요:
해당 catch를 잡아 prepareImageFile, mapWithConcurrencyLimit 호출 컨텍스트(예: 파일 이름 또는 인덱스)를
포함한 에러 메시지를 콘솔 또는 기존 로거(processLogger 등)에 기록하고, 필요 시 재시도 또는 rethrow하여 상위에서 인지되게
만드세요.
- Line 3: Replace direct use of twMerge with the shared cn utility: remove the
import of twMerge and import cn from src/utils/ts/cn.ts, then replace all calls
to twMerge(...) with cn(...) so clsx + tailwind-merge behavior is preserved;
update any exported/used identifiers in this file (e.g., where twMerge is
referenced in ManagedRecruitmentWrite component) to use cn instead.
- Around line 44-297: The page contains a lot of state and image-handling logic
that should be moved into reusable hooks; extract the form state and image logic
into one or two custom hooks (e.g., useRecruitmentForm and/or
useRecruitmentImages) that encapsulate state variables (startDate, endDate,
startTime, endTime, content, isRecruitmentEnabled, isAlwaysRecruiting, images,
currentImageIndex, isPreparingImages, isUploading, hasHandledExisting,
hasInitializedRecruitmentEnabled), refs (textareaRef, fileInputRef) and handlers
(handleImageSelect, handlePrevImage, handleNextImage, handleDeleteImage,
handleImageClick, handleContentChange, handleReset,
handleRecruitmentEnabledChange) and return only the state and functions the
component needs; keep submit logic (handleSubmit) either in the form hook or
left in the page but adapt it to consume the hook-provided state and image
upload utilities (uploadImage, saveRecruitment, patchSettings), and update
ManagedRecruitmentWrite to use these hooks so the component becomes a thin view
layer.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 37bb061c-b71b-42a9-9e4e-f2f19b00e3f9
📒 Files selected for processing (3)
src/pages/Manager/ManagedClubProfile/index.tsxsrc/pages/Manager/ManagedRecruitmentWrite/index.tsxsrc/utils/ts/imagePreprocessor.ts
✅ Files skipped from review due to trivial changes (1)
- src/utils/ts/imagePreprocessor.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/pages/Manager/ManagedClubProfile/index.tsx
* 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
릴리스 노트