[feat] 모집 공고에 시간 추가 및 지원서 정렬 추가#131
Conversation
📝 WalkthroughWalkthroughRecruitment 관련 날짜 필드를 startDate/endDate에서 startAt/endAt로 교체했고, Manager 쪽에 시:분 단위 시간 입력·표시(타임피커 및 관련 유틸)를 추가했습니다. Application 타입에서 studentNumber를 number→string으로 변경하고 feePaymentImageUrl?: string을 추가했으며, ClubApplicationsParams와 PaginationResponse 확장을 도입해 애플리케이션 조회에 페이지네이션·정렬·필터를 지원하도록 API 시그니처를 변경했습니다. 메시지/콘텐츠 링크 자동화를 위한 LinkifiedText 컴포넌트도 추가되었습니다. Possibly related issues
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)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
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)
196-205:⚠️ Potential issue | 🟡 MinorhandleDeleteImage에서 방어적 검사 추가 권장
images[currentImageIndex]가 undefined일 경우에 대한 방어적 처리가 없습니다. 경쟁 상태(race condition)에서 문제가 발생할 수 있습니다.🛡️ 방어적 코드 추가
const handleDeleteImage = () => { + const currentImage = images[currentImageIndex]; + if (!currentImage) return; + - URL.revokeObjectURL(images[currentImageIndex].previewUrl); + URL.revokeObjectURL(currentImage.previewUrl); const newImages = images.filter((_, index) => index !== currentImageIndex);🤖 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 196 - 205, handleDeleteImage currently assumes images[currentImageIndex] exists; add defensive checks to avoid runtime errors by verifying images.length > 0 and currentImageIndex is within bounds before calling URL.revokeObjectURL or slicing the array. Specifically, in handleDeleteImage ensure images and images[currentImageIndex] are defined (e.g., images.length > 0 && currentImageIndex >= 0 && currentImageIndex < images.length) before revoking the preview URL and building newImages, then proceed to call setImages and adjust setCurrentImageIndex as before.
🧹 Nitpick comments (2)
src/pages/Manager/ManagedRecruitmentWrite/index.tsx (1)
42-74: 헬퍼 함수들을 유틸리티 모듈로 분리 권장
isValidTimeFormat,normalizeTime,parseDateTimeDot,formatDateTimeDot,combineDateTime함수들이 이 컴포넌트에만 정의되어 있습니다.src/utils/ts/date.ts로 이동하면 재사용성과 테스트 용이성이 향상됩니다.🤖 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 42 - 74, Extract the helper functions isValidTimeFormat, normalizeTime, parseDateTimeDot, formatDateTimeDot, and combineDateTime into src/utils/ts/date.ts as exported utilities; ensure you also export or import any constants they depend on (e.g., TIME_MINUTE_STEP, DEFAULT_START_TIME) and the formatDateDot helper so the logic remains intact, then update ManagedRecruitmentWrite to import these functions from the new module and remove the local definitions; keep function signatures identical and add unit tests in the utils module to cover edge cases (invalid dates, time normalization) if not already present.src/pages/Manager/components/TimePicker/index.tsx (1)
162-188: 스크롤 영역에 접근성 속성 추가 권장스크롤 가능한 시간 선택 영역에
role="listbox"및aria-label속성을 추가하면 스크린 리더 사용자 경험이 개선됩니다.♿ 접근성 개선 제안
<div ref={hourRef} onScroll={createScrollHandler(hourOptions, setDraftHour)} + role="listbox" + aria-label="시간 선택" className="h-full snap-y snap-mandatory overflow-y-auto [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden" >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Manager/components/TimePicker/index.tsx` around lines 162 - 188, The scrollable hour container (the div using hourRef and hourOptions) needs ARIA attributes for screen readers: add role="listbox" and a descriptive aria-label (e.g., "Select hour") to that div, and ensure each hour button (created in the hourOptions.map with onClick calling setDraftHour and scrollToItem) has role="option" plus aria-selected={isSelected} so assistive tech can identify selectable items and the current selection; keep existing behavior (PADDING_HEIGHT, pad2, twMerge) unchanged.
🤖 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/apis/club/entity.ts`:
- Around line 140-145: The detail response type for student number is
inconsistent with the Application model: update the
ClubApplicationDetailResponse.studentNumber type from number to string so it
matches Application.studentNumber (and update any related DTOs/interfaces that
reference ClubApplicationDetailResponse.studentNumber to the string type as
well); locate the symbol ClubApplicationDetailResponse and change its
studentNumber declaration to string to ensure type consistency across
Application.studentNumber and all consumers.
In `@src/apis/club/index.ts`:
- Around line 34-35: The import list is misformatted causing Prettier lint
failures; reformat the import block that currently reads "type
ClubApplicationsParams, } from './entity';" into a properly spaced multi-line
import (for example: import { type ClubApplicationsParams } from './entity'; or
each specifier on its own line with consistent commas) and apply the same
Prettier-style formatting fix to the other import block around the Club-related
imports referenced (the block that spans the other occurrence with the same
specifiers). Ensure trailing commas, consistent spacing, and that import braces
and specifiers follow the project's Prettier rules so lint passes.
In `@src/pages/Club/ClubList/components/ClubCard.tsx`:
- Around line 10-11: The parsing of applicationDeadline in ClubCard is currently
splitting on '.' (datePart and the [year, month, day] extraction) which fails
for ISO timestamps and yields NaN; update ClubCard to normalize ISO dates before
splitting by either using the existing utility formatIsoDateToYYYYMMDD (call it
with applicationDeadline) or implement a short normalization step that extracts
the YYYY-MM-DD part (or replaces '-' with '.') to produce a consistent
YYYY.MM.DD string, then derive year/month/day from that normalized string so the
badge logic (datePart, year, month, day) works for both ISO and dotted formats.
---
Outside diff comments:
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 196-205: handleDeleteImage currently assumes
images[currentImageIndex] exists; add defensive checks to avoid runtime errors
by verifying images.length > 0 and currentImageIndex is within bounds before
calling URL.revokeObjectURL or slicing the array. Specifically, in
handleDeleteImage ensure images and images[currentImageIndex] are defined (e.g.,
images.length > 0 && currentImageIndex >= 0 && currentImageIndex <
images.length) before revoking the preview URL and building newImages, then
proceed to call setImages and adjust setCurrentImageIndex as before.
---
Nitpick comments:
In `@src/pages/Manager/components/TimePicker/index.tsx`:
- Around line 162-188: The scrollable hour container (the div using hourRef and
hourOptions) needs ARIA attributes for screen readers: add role="listbox" and a
descriptive aria-label (e.g., "Select hour") to that div, and ensure each hour
button (created in the hourOptions.map with onClick calling setDraftHour and
scrollToItem) has role="option" plus aria-selected={isSelected} so assistive
tech can identify selectable items and the current selection; keep existing
behavior (PADDING_HEIGHT, pad2, twMerge) unchanged.
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 42-74: Extract the helper functions isValidTimeFormat,
normalizeTime, parseDateTimeDot, formatDateTimeDot, and combineDateTime into
src/utils/ts/date.ts as exported utilities; ensure you also export or import any
constants they depend on (e.g., TIME_MINUTE_STEP, DEFAULT_START_TIME) and the
formatDateDot helper so the logic remains intact, then update
ManagedRecruitmentWrite to import these functions from the new module and remove
the local definitions; keep function signatures identical and add unit tests in
the utils module to cover edge cases (invalid dates, time normalization) if not
already present.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
src/apis/club/entity.ts (2)
154-160:PaginationResponse재사용 고려.페이지네이션 필드들이
PaginationResponse와 유사해 보입니다. 기존 타입을 extend하거나 재사용할 수 있는지 확인해 보세요.// 예시: PaginationResponse 구조와 동일하다면 export interface ClubApplicationsResponse extends PaginationResponse { applications: Application[]; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apis/club/entity.ts` around lines 154 - 160, The ClubApplicationsResponse duplicates pagination fields that match the existing PaginationResponse; update ClubApplicationsResponse to reuse or extend PaginationResponse (e.g., make ClubApplicationsResponse extend PaginationResponse and keep the applications: Application[] field) so you remove duplicated fields and keep pagination logic centralized; update any code that constructs or types ClubApplicationsResponse to rely on the new shape.
304-308:ClubSettingsRecruitment타입을 조건부로 정의해야 합니다.
isAlwaysRecruiting: true일 때startAt,endAt는 불필요합니다. 이미 존재하는ClubRecruitmentRequest처럼 판별 조합(discriminated union) 타입으로 변경하는 것이 좋습니다:type ClubSettingsRecruitment = | { isAlwaysRecruiting: true; startAt?: never; endAt?: never; } | { isAlwaysRecruiting: false; startAt: string; endAt: string; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apis/club/entity.ts` around lines 304 - 308, Replace the flat interface ClubSettingsRecruitment with a discriminated union similar to ClubRecruitmentRequest: provide one variant where isAlwaysRecruiting: true and startAt/endAt are disallowed (startAt?: never; endAt?: never) and another where isAlwaysRecruiting: false and startAt/endAt are required strings; update any code expecting the old shape to use the discriminated union for proper type-narrowing (look for usages of ClubSettingsRecruitment).src/pages/Manager/ManagedRecruitmentWrite/index.tsx (2)
36-39: 중복 스타일 상수
compactDateButtonStyle과compactTimeButtonStyle이 동일합니다. 하나로 통합하는 것을 고려해 보세요.♻️ 통합 제안
-const compactDateButtonStyle = - 'group flex h-10 min-w-0 w-full items-center justify-between rounded-lg border border-indigo-50 bg-white px-3 text-left shadow-[0_2px_6px_rgba(2,23,48,0.06)]'; -const compactTimeButtonStyle = - 'group flex h-10 min-w-0 w-full items-center justify-between rounded-lg border border-indigo-50 bg-white px-3 text-left shadow-[0_2px_6px_rgba(2,23,48,0.06)]'; +const compactInputButtonStyle = + 'group flex h-10 min-w-0 w-full items-center justify-between rounded-lg border border-indigo-50 bg-white px-3 text-left shadow-[0_2px_6px_rgba(2,23,48,0.06)]';🤖 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 36 - 39, compactDateButtonStyle and compactTimeButtonStyle are identical; replace them with a single shared constant (e.g., compactButtonStyle) and update all references to compactDateButtonStyle and compactTimeButtonStyle to use the new constant; ensure the new constant preserves the current string value and keep the original names removed to avoid duplicates (search for usages of compactDateButtonStyle/compactTimeButtonStyle and update imports/consumers accordingly).
161-170: 기존 이미지 URL 처리
isExisting이true인 경우previewUrl은 서버 URL이므로URL.revokeObjectURL호출은 무의미합니다 (해롭지는 않음). 명시적으로 체크하면 의도가 더 명확해집니다.♻️ 선택적 개선
const handleDeleteImage = () => { - URL.revokeObjectURL(images[currentImageIndex].previewUrl); + const target = images[currentImageIndex]; + if (!target.isExisting) { + URL.revokeObjectURL(target.previewUrl); + } const newImages = images.filter((_, index) => index !== currentImageIndex);🤖 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 161 - 170, The deletion logic in handleDeleteImage currently always calls URL.revokeObjectURL on images[currentImageIndex].previewUrl even when that image is an existing server URL; update handleDeleteImage to first guard that images[currentImageIndex] exists and then only call URL.revokeObjectURL if images[currentImageIndex].isExisting is false (i.e., it's a local object URL), then proceed to create newImages, call setImages(newImages) and adjust setCurrentImageIndex as before (using currentImageIndex and newImages.length).
🤖 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/utils/ts/date.ts`:
- Around line 12-13: timePart splitting assumes a colon and two parts so calling
minute.padStart can throw; update the logic around the destructuring of timePart
(the line using const [hour, minute] = timePart.split(':')) to validate and/or
normalize the split parts before calling padStart: ensure timePart contains both
hour and minute (fallback minute to '00' and hour to '0' or throw a clear
error), then call hour.padStart(2,'0') and minute.padStart(2,'0'); reference the
timePart, hour, minute and padStart symbols when editing.
---
Nitpick comments:
In `@src/apis/club/entity.ts`:
- Around line 154-160: The ClubApplicationsResponse duplicates pagination fields
that match the existing PaginationResponse; update ClubApplicationsResponse to
reuse or extend PaginationResponse (e.g., make ClubApplicationsResponse extend
PaginationResponse and keep the applications: Application[] field) so you remove
duplicated fields and keep pagination logic centralized; update any code that
constructs or types ClubApplicationsResponse to rely on the new shape.
- Around line 304-308: Replace the flat interface ClubSettingsRecruitment with a
discriminated union similar to ClubRecruitmentRequest: provide one variant where
isAlwaysRecruiting: true and startAt/endAt are disallowed (startAt?: never;
endAt?: never) and another where isAlwaysRecruiting: false and startAt/endAt are
required strings; update any code expecting the old shape to use the
discriminated union for proper type-narrowing (look for usages of
ClubSettingsRecruitment).
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 36-39: compactDateButtonStyle and compactTimeButtonStyle are
identical; replace them with a single shared constant (e.g., compactButtonStyle)
and update all references to compactDateButtonStyle and compactTimeButtonStyle
to use the new constant; ensure the new constant preserves the current string
value and keep the original names removed to avoid duplicates (search for usages
of compactDateButtonStyle/compactTimeButtonStyle and update imports/consumers
accordingly).
- Around line 161-170: The deletion logic in handleDeleteImage currently always
calls URL.revokeObjectURL on images[currentImageIndex].previewUrl even when that
image is an existing server URL; update handleDeleteImage to first guard that
images[currentImageIndex] exists and then only call URL.revokeObjectURL if
images[currentImageIndex].isExisting is false (i.e., it's a local object URL),
then proceed to create newImages, call setImages(newImages) and adjust
setCurrentImageIndex as before (using currentImageIndex and newImages.length).
| const [hour, minute] = timePart.split(':'); | ||
| return `${date} ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`; |
There was a problem hiding this comment.
timePart가 불완전할 경우 런타임 에러 발생 가능
timePart가 "12" (콜론 없음)처럼 불완전하면 minute가 undefined가 되어 padStart 호출 시 에러가 발생합니다.
🛡️ 방어 코드 추가 제안
const [hour, minute] = timePart.split(':');
+ if (!hour || !minute) return date;
return `${date} ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`;📝 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 [hour, minute] = timePart.split(':'); | |
| return `${date} ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`; | |
| const [hour, minute] = timePart.split(':'); | |
| if (!hour || !minute) return date; | |
| return `${date} ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/utils/ts/date.ts` around lines 12 - 13, timePart splitting assumes a
colon and two parts so calling minute.padStart can throw; update the logic
around the destructuring of timePart (the line using const [hour, minute] =
timePart.split(':')) to validate and/or normalize the split parts before calling
padStart: ensure timePart contains both hour and minute (fallback minute to '00'
and hour to '0' or throw a clear error), then call hour.padStart(2,'0') and
minute.padStart(2,'0'); reference the timePart, hour, minute and padStart
symbols when editing.
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 (2)
src/pages/Manager/ManagedRecruitmentWrite/index.tsx (1)
159-168:⚠️ Potential issue | 🟡 Minor기존 이미지의 URL.revokeObjectURL 호출 문제
isExisting이미지는 blob URL이 아닌 서버 URL이므로revokeObjectURL호출이 불필요합니다.handleReset(line 118-120)에서는 올바르게 처리하고 있으나,handleDeleteImage에서는 체크가 빠져있어요.🔧 수정 제안
const handleDeleteImage = () => { - URL.revokeObjectURL(images[currentImageIndex].previewUrl); + const target = images[currentImageIndex]; + if (!target.isExisting) { + URL.revokeObjectURL(target.previewUrl); + } const newImages = images.filter((_, index) => index !== currentImageIndex);🤖 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 159 - 168, handleDeleteImage currently always calls URL.revokeObjectURL(images[currentImageIndex].previewUrl) even for existing images that use server URLs; modify handleDeleteImage to first check images[currentImageIndex].isExisting (or similar flag) and only call URL.revokeObjectURL when isExisting is false (i.e., the image is a blob/object URL), guard against missing previewUrl, then proceed with the existing filtering and currentImageIndex adjustment logic (using images, currentImageIndex, setImages, setCurrentImageIndex) as before.src/apis/club/entity.ts (1)
113-123:⚠️ Potential issue | 🟡 Minor
ClubRecruitment응답 타입에 조건부 필드 처리 추가
ClubRecruitmentRequest와ClubSettingsRecruitment는isAlwaysRecruiting필드로 discriminated union을 구성해isAlwaysRecruiting: true일 때startAt/endAt를 제외하고 있습니다. 하지만ClubRecruitment응답 타입에는 이 필드가 없어 타입이 inconsistent합니다.isAlwaysRecruiting필드를 응답 타입에도 추가하거나,startAt/endAt를 optional로 변경해 일관성을 맞춰주세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apis/club/entity.ts` around lines 113 - 123, The ClubRecruitment response type is inconsistent with ClubRecruitmentRequest/ClubSettingsRecruitment: add the discriminant and make the date fields conditional — update the ClubRecruitment interface to include isAlwaysRecruiting: boolean and make startAt and endAt optional (or nullable) so the shape matches the union used elsewhere (referencing ClubRecruitment, ClubRecruitmentRequest, and ClubSettingsRecruitment); ensure any callers/serializers handle the optional startAt/endAt when isAlwaysRecruiting is true.
🧹 Nitpick comments (1)
src/pages/Manager/ManagedRecruitmentWrite/index.tsx (1)
415-427: 이미지 인디케이터에 고유 key 사용 권장이미지 인디케이터(dot buttons)에서index를 key로 사용 중입니다. "if list of items is supposed to have features of deleting, resorting, adding new items— in this case, you have to take care of the key in a proper way to avoid any performance issues and avoid unexpected bugs."이미지 배열은 추가/삭제가 가능하므로,
previewUrl이나 고유 ID를 key로 사용하는 것이 더 안전합니다.♻️ 수정 제안
-{images.map((_, index) => ( +{images.map((img, index) => ( <button - key={index} + key={img.previewUrl} type="button" onClick={() => setCurrentImageIndex(index)}🤖 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 415 - 427, The image indicator uses index as the React key which can break when images are added/removed; update the map over images in the component that renders the dot buttons to use a stable unique property from each image (e.g., image.previewUrl or image.id) instead of index (keep using currentImageIndex and setCurrentImageIndex for selection), e.g., change images.map((_, index) => ...) to images.map((image, index) => ...) and set key to image.previewUrl or image.id so keys remain stable across adds/removes.
🤖 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/apis/club/entity.ts`:
- Around line 113-123: The ClubRecruitment response type is inconsistent with
ClubRecruitmentRequest/ClubSettingsRecruitment: add the discriminant and make
the date fields conditional — update the ClubRecruitment interface to include
isAlwaysRecruiting: boolean and make startAt and endAt optional (or nullable) so
the shape matches the union used elsewhere (referencing ClubRecruitment,
ClubRecruitmentRequest, and ClubSettingsRecruitment); ensure any
callers/serializers handle the optional startAt/endAt when isAlwaysRecruiting is
true.
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 159-168: handleDeleteImage currently always calls
URL.revokeObjectURL(images[currentImageIndex].previewUrl) even for existing
images that use server URLs; modify handleDeleteImage to first check
images[currentImageIndex].isExisting (or similar flag) and only call
URL.revokeObjectURL when isExisting is false (i.e., the image is a blob/object
URL), guard against missing previewUrl, then proceed with the existing filtering
and currentImageIndex adjustment logic (using images, currentImageIndex,
setImages, setCurrentImageIndex) as before.
---
Nitpick comments:
In `@src/pages/Manager/ManagedRecruitmentWrite/index.tsx`:
- Around line 415-427: The image indicator uses index as the React key which can
break when images are added/removed; update the map over images in the component
that renders the dot buttons to use a stable unique property from each image
(e.g., image.previewUrl or image.id) instead of index (keep using
currentImageIndex and setCurrentImageIndex for selection), e.g., change
images.map((_, index) => ...) to images.map((image, index) => ...) and set key
to image.previewUrl or image.id so keys remain stable across adds/removes.
* chore: 타입 변경 반영 * [feat] 모집 공고에 시간 추가 및 지원서 정렬 추가 (#131) * feat: 모집 공고에 시작, 종료 시간 추가 * feat: 지원자 목록 정렬 추가 및 시간 표시 * feat: 채팅, 모집 공고 링크 파싱 기능 추가 * feat: 인스타그램 파싱 추가 * fix: prettier error * refactor: 유틸 분리 및 타입 변경 * chore: 타입 변경 반영 * chore: 동일 스타일 통합 및 entity 확장 사용 * chore:ios 토큰 테스트를 위한 로직 추가 * Revert "chore:ios 토큰 테스트를 위한 로직 추가" This reverts commit 98570fc.
* chore: 타입 변경 반영 * [feat] 모집 공고에 시간 추가 및 지원서 정렬 추가 (#131) * feat: 모집 공고에 시작, 종료 시간 추가 * feat: 지원자 목록 정렬 추가 및 시간 표시 * feat: 채팅, 모집 공고 링크 파싱 기능 추가 * feat: 인스타그램 파싱 추가 * fix: prettier error * refactor: 유틸 분리 및 타입 변경 * chore: 타입 변경 반영 * chore: 동일 스타일 통합 및 entity 확장 사용 * chore:ios 토큰 테스트를 위한 로직 추가 * Revert "chore:ios 토큰 테스트를 위한 로직 추가" This reverts commit 98570fc. * hotfix: 모집 공고 textarea 길이 자동 재계산 추가 * Reapply "chore:ios 토큰 테스트를 위한 로직 추가" This reverts commit 3a56f4a. * chore: ios토큰 * feat: 가이드 페이지 이미지 변경 * chore: 푸시알림 로직 임시 변경 * refactor: 푸시 알림 토큰 로직 브릿지 방식으로 수정 (#134) * refactor: 푸시 알림 토큰 로직 브릿지 방식으로 수정 * fix: try catch 적용 * feat: 페이지네이션 추가 * feat: 수정 * feat: 페이지네이션 수정 * feat: 디자인 수정 * feat: 로직 수정 * fix: key 수정 * chore: 스테이지 용 임시 UI 제거 --------- Co-authored-by: hyejun <hyejunkkim228@gmail.com>
* develop → main 배포 (#125) * feat: 알림설정 구현 (#108) * chore: min-w 추가 * [chore] 코드래빗 설정 파일 추가 (#110) * chore: 코드래빗 설정 파일 추가 * chore: 불필요한 tools 설정 제거 * [feat] preMember 목록 분리 및 삭제 기능 추가 (#115) * feat: preMember 목록 분리 및 삭제 기능 추가 * chore: Pascal case * chore: 변경된 변수명 반영 * feat: 학번 숫자 필터링 추가 * [feat] 채팅 목차 알림 상태 추가 (#113) * chore: svg 추가 * feat: 채팅목록 알림 끄기 설정시 UI 추가 * feat: 목차 열릴시 애니메이션 추가 * [feat] 달력 카테고리 분류 추가 (#118) * feat: 카테고리 추가 * chore: 불필요한 코드 삭제 * [refactor] 관리자 페이지 및 마이페이지 UI 수정 및 리팩토링 (#117) * feat: 정보 카드에서 정보 페이지로 이동하도록 기능 추가 * feat: 토스트 전역상태 추가 * refactor: query 훅 분리 및 onSuccess 콜백 옵션 제거 * refactor: query 훅 사용처 수정 * refactor: 사용처 수정 2 * fix: 채팅창 스크롤 초기화 문제 수정 및 줄바꿈 기준 변경 * feat: 토글 스위치 구현 * refactor: 모집 공고 관련 목록 페이지 디자인 수정 * feat: 컴포넌트 구현 및 icon 추가 * refactor: z-index 값 수정 * refactor: API 필드 변경 사항 반영 * refactor: 모집 공고 페이지 디자인 수정 및 라우트 백 수정 * refactor: 학교 목록에 없을 시 문구 디자인 수정 * fix: lint error * fix: 타입 변경 * feat: 모집 관련 페이지 API 추가사항 반영 * refactor: 토스트 타이머 클린업 추라 * refactor: 전역토스트 사용 변경 * refactor: 관리자 클럽 조회 훅 호출 범위 줄이기 * feat: onError handler add * chore: add button type and remove fragment * [feat] 문의하기 버튼 로직 추가 (#120) * feat: API 추가 및 연결 * chore: placeholder 제거 * [fix] 채팅 스크롤 미갱신 버그 및 멤버 직위 렌더링 수정 (#122) * fix: 채팅 스크롤 미작동 수정 * fix: 한글 출력으로 수정 * feat: 첫 글자 보여주도록 수정 (#124) * hotfix: 동아리 소개 줄바꿈 적용 및 한 줄 소개 글자수 제한 상향 * chore: 리뷰 반영 * fix: disabled 조건 변경 * 126 fix 배포 전 qa 사항 반영 (#127) * fix: 가입 버튼 문구 수정 * fix: 검색창 placeholder 수정 * fix: 불필요해진 UI 비활성화 * fix: 모집공고 없을 때 빈 화면 처리 * fix: 무의미한 회비페이지 수정 * feat: 토글 시 자동 페이지 이동 추가 * fix: 페이지 이동 조건 수정 --------- Co-authored-by: 김혜준 <114041848+hyejun0228@users.noreply.github.com> Co-authored-by: hyejun <hyejunkkim228@gmail.com> * develop -> main 배포 (#132) * chore: 타입 변경 반영 * [feat] 모집 공고에 시간 추가 및 지원서 정렬 추가 (#131) * feat: 모집 공고에 시작, 종료 시간 추가 * feat: 지원자 목록 정렬 추가 및 시간 표시 * feat: 채팅, 모집 공고 링크 파싱 기능 추가 * feat: 인스타그램 파싱 추가 * fix: prettier error * refactor: 유틸 분리 및 타입 변경 * chore: 타입 변경 반영 * chore: 동일 스타일 통합 및 entity 확장 사용 * chore:ios 토큰 테스트를 위한 로직 추가 * Revert "chore:ios 토큰 테스트를 위한 로직 추가" This reverts commit 98570fc. * hotfix: 모집 공고 textarea 길이 자동 재계산 추가 * feat: 페이지네이션 추가 * feat: 수정 * feat: 페이지네이션 수정 * feat: 디자인 수정 * feat: 로직 수정 * fix: key 수정 * develop-> main (#135) * chore: 타입 변경 반영 * [feat] 모집 공고에 시간 추가 및 지원서 정렬 추가 (#131) * feat: 모집 공고에 시작, 종료 시간 추가 * feat: 지원자 목록 정렬 추가 및 시간 표시 * feat: 채팅, 모집 공고 링크 파싱 기능 추가 * feat: 인스타그램 파싱 추가 * fix: prettier error * refactor: 유틸 분리 및 타입 변경 * chore: 타입 변경 반영 * chore: 동일 스타일 통합 및 entity 확장 사용 * chore:ios 토큰 테스트를 위한 로직 추가 * Revert "chore:ios 토큰 테스트를 위한 로직 추가" This reverts commit 98570fc. * hotfix: 모집 공고 textarea 길이 자동 재계산 추가 * Reapply "chore:ios 토큰 테스트를 위한 로직 추가" This reverts commit 3a56f4a. * chore: ios토큰 * feat: 가이드 페이지 이미지 변경 * chore: 푸시알림 로직 임시 변경 * refactor: 푸시 알림 토큰 로직 브릿지 방식으로 수정 (#134) * refactor: 푸시 알림 토큰 로직 브릿지 방식으로 수정 * fix: try catch 적용 * feat: 페이지네이션 추가 * feat: 수정 * feat: 페이지네이션 수정 * feat: 디자인 수정 * feat: 로직 수정 * fix: key 수정 * chore: 스테이지 용 임시 UI 제거 --------- Co-authored-by: hyejun <hyejunkkim228@gmail.com> * [feat] sentry 모니터링 추가 (#141) (#142) * chore: sentry 의존성 추가 * feat: sentry 세팅 * chore: 워크플로우 수정 및 vite 세팅 * chore: 임시 추가 * refactor: 색상 토큰 파일 분리 * refactor: 타이포그래피 스타일 파일 분리 * refactor: 피그마 타이포그래피 네이밍으로 클래스 정렬 * fix: 리뷰 코멘트 기반 접근성 및 토큰 정리 --------- Co-authored-by: 김혜준 <114041848+hyejun0228@users.noreply.github.com> Co-authored-by: hyejun <hyejunkkim228@gmail.com>
Summary by CodeRabbit
릴리스 노트
New Features
Improvements
Chores