-
Notifications
You must be signed in to change notification settings - Fork 0
[feat] Avatar 컴포넌트 및 프로필 이미지 통합 #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
95d96aa
feat: Avatar 컴포넌트 및 기본 프로필 이미지 추가
ysw789 e345945
feat: 타입 및 API에 profileImageUrl 필드 추가
ysw789 2542637
feat: Manager 기능에 Avatar 컴포넌트 적용
ysw789 60703d1
feat: User 기능에 Avatar 컴포넌트 적용
ysw789 d62812f
feat: Shared UI와 프로필에 Avatar 컴포넌트 적용
ysw789 9117533
refactor: 남은 코드에서 이미지 처리 정리
ysw789 2e5fb9f
refactor: 불필요한 SubstituteProfileAvatar 제거
ysw789 26c8167
feat: 대타요청 DTO/타입에 profileImageUrl 필드 추가
ysw789 f095824
feat: 대타요청 어댑터에 프로필 이미지 매핑 연결
ysw789 bb3e7ab
fix: 대타요청 상세 Avatar에 profileImageUrl 전달
ysw789 d2c2ef6
test: 대타요청 어댑터 프로필 이미지 데이터 흐름 검증
ysw789 b0c4360
refactor: 근무자 선택 컴포넌트를 공유 Avatar로 마이그레이션
ysw789 cde9c06
fix: Avatar neutral 폴백에 onError 처리 추가 및 컬러 토큰 적용
ysw789 37afaab
refactor: 프로필 이미지 해석 로직 단순화 — workerName 체크 제거
ysw789 00c9f73
refactor: WorkerListItem 부모 div에서 중복 size 클래스 제거
ysw789 c9dcb02
fix: 보낸 대타요청에서 프로필 이미지 미노출, 받은 요청은 요청자 이미지만 표시
ysw789 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,4 +33,7 @@ coverage | |
|
|
||
| *storybook.log | ||
| storybook-static | ||
| .serena | ||
| .serena | ||
|
|
||
| CLAUDE.md | ||
| .claude | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
174 changes: 174 additions & 0 deletions
174
src/features/user/substitute/lib/adaptUserSubstituteRequest.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| import { describe, expect, it } from 'vitest' | ||
|
|
||
| import type { | ||
| ReceivedSubstituteRequestDto, | ||
| SentSubstituteRequestDetailApiDto, | ||
| SentSubstituteRequestDetailDto, | ||
| SentSubstituteRequestListItemDto, | ||
| SubstituteTargetDto, | ||
| } from '@/features/user/substitute/types' | ||
|
|
||
| import { | ||
| adaptReceivedSubstituteDetail, | ||
| adaptSentSubstituteDetail, | ||
| adaptUserSubstituteListItem, | ||
| normalizeSentSubstituteDetailDto, | ||
| } from './adaptUserSubstituteRequest' | ||
|
|
||
| const schedule = { | ||
| scheduleId: 1, | ||
| startDateTime: '2026-04-05T09:00:00', | ||
| endDateTime: '2026-04-05T13:00:00', | ||
| position: 'STAFF', | ||
| } | ||
| const workspace = { workspaceId: 10, workspaceName: '카페' } | ||
|
|
||
| function received( | ||
| profileImageUrl?: string | null | ||
| ): ReceivedSubstituteRequestDto { | ||
| return { | ||
| id: 1, | ||
| schedule, | ||
| workspace, | ||
| requester: { workerId: 5, workerName: '요청자', profileImageUrl }, | ||
| requestType: 'SPECIFIC', | ||
| status: 'PENDING', | ||
| createdAt: '2026-04-01T00:00:00', | ||
| } | ||
| } | ||
|
|
||
| function target(profileImageUrl?: string | null): SubstituteTargetDto { | ||
| return { | ||
| targetId: 7, | ||
| workerName: '대상자', | ||
| profileImageUrl, | ||
| status: 'PENDING', | ||
| } | ||
| } | ||
|
|
||
| function sentList(opts: { | ||
| acceptedWorker?: { | ||
| workerId: number | ||
| workerName: string | ||
| profileImageUrl?: string | null | ||
| } | null | ||
| targets?: SubstituteTargetDto[] | ||
| }): SentSubstituteRequestListItemDto { | ||
| return { | ||
| id: 2, | ||
| schedule, | ||
| workspace, | ||
| requestType: 'SPECIFIC', | ||
| status: 'PENDING', | ||
| createdAt: '2026-04-01T00:00:00', | ||
| targets: opts.targets, | ||
| acceptedWorker: opts.acceptedWorker ?? null, | ||
| } | ||
| } | ||
|
|
||
| function sentDetail(opts: { | ||
| acceptedWorker?: { | ||
| workerId: number | ||
| workerName: string | ||
| profileImageUrl?: string | null | ||
| } | null | ||
| targets?: SubstituteTargetDto[] | ||
| }): SentSubstituteRequestDetailDto { | ||
| return { | ||
| id: 3, | ||
| schedule, | ||
| workspace, | ||
| requester: { workerId: 5, workerName: '요청자' }, | ||
| requestType: 'SPECIFIC', | ||
| targets: opts.targets ?? [], | ||
| acceptedWorker: opts.acceptedWorker ?? null, | ||
| status: 'PENDING', | ||
| createdAt: '2026-04-01T00:00:00', | ||
| } | ||
| } | ||
|
|
||
| describe('대타요청 프로필 이미지 데이터 흐름', () => { | ||
| it('RECEIVED 목록은 요청자의 profileImageUrl을 imageUrl로 매핑한다', () => { | ||
| const item = adaptUserSubstituteListItem( | ||
| received('https://img/requester.png'), | ||
| 'RECEIVED' | ||
| ) | ||
| expect(item.imageUrl).toBe('https://img/requester.png') | ||
| }) | ||
|
|
||
| it('RECEIVED 상세는 요청자의 profileImageUrl을 imageUrl로 매핑한다', () => { | ||
| const detail = adaptReceivedSubstituteDetail( | ||
| received('https://img/requester.png') | ||
| ) | ||
| expect(detail.imageUrl).toBe('https://img/requester.png') | ||
| }) | ||
|
|
||
| it('SENT은 수락자가 있으면 수락자의 이미지를 사용한다', () => { | ||
| const accepted = { | ||
| workerId: 9, | ||
| workerName: '수락자', | ||
| profileImageUrl: 'https://img/accepted.png', | ||
| } | ||
| const targets = [target('https://img/target.png')] | ||
|
|
||
| expect( | ||
| adaptUserSubstituteListItem( | ||
| sentList({ acceptedWorker: accepted, targets }), | ||
| 'SENT' | ||
| ).imageUrl | ||
| ).toBe('https://img/accepted.png') | ||
| expect( | ||
| adaptSentSubstituteDetail( | ||
| sentDetail({ acceptedWorker: accepted, targets }) | ||
| ).imageUrl | ||
| ).toBe('https://img/accepted.png') | ||
| }) | ||
|
|
||
| it('SENT은 수락자가 없으면 첫 대상자의 이미지를 사용한다', () => { | ||
| const targets = [target('https://img/target.png')] | ||
|
|
||
| expect( | ||
| adaptUserSubstituteListItem(sentList({ targets }), 'SENT').imageUrl | ||
| ).toBe('https://img/target.png') | ||
| expect(adaptSentSubstituteDetail(sentDetail({ targets })).imageUrl).toBe( | ||
| 'https://img/target.png' | ||
| ) | ||
| }) | ||
|
|
||
| it('이미지 필드가 없으면 null로 정규화한다', () => { | ||
| expect( | ||
| adaptUserSubstituteListItem(received(), 'RECEIVED').imageUrl | ||
| ).toBeNull() | ||
| expect(adaptReceivedSubstituteDetail(received()).imageUrl).toBeNull() | ||
| expect( | ||
| adaptUserSubstituteListItem(sentList({ targets: [target()] }), 'SENT') | ||
| .imageUrl | ||
| ).toBeNull() | ||
| }) | ||
|
|
||
| it('normalize는 API target의 profileImageUrl을 정규화 target으로 전달한다', () => { | ||
| const api: SentSubstituteRequestDetailApiDto = { | ||
| id: 4, | ||
| schedule, | ||
| workspace, | ||
| requester: { workerId: 5, workerName: '요청자' }, | ||
| requestType: 'SPECIFIC', | ||
| targets: [ | ||
| { | ||
| target: { | ||
| workerId: 7, | ||
| workerName: '대상자', | ||
| profileImageUrl: 'https://img/target.png', | ||
| }, | ||
| status: 'PENDING', | ||
| }, | ||
| ], | ||
| status: 'PENDING', | ||
| createdAt: '2026-04-01T00:00:00', | ||
| } | ||
|
|
||
| expect( | ||
| normalizeSentSubstituteDetailDto(api).targets[0].profileImageUrl | ||
| ).toBe('https://img/target.png') | ||
| }) | ||
| }) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
마지막으로 순수 궁금증,,, 저는 클로드는 글로벌(
~/.gitignore_global)로 따로 빼두는 편인데 요거 보통 공유해서 쓰시나요?아님 루트에 놓고 쓰는게 편한데 깃헙에 올리기는 좀 그래서 추가하셨나여?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
별다른 이유는 없고 공용으로 만들어서 팀에서 공유하는 경우도 있고 스킬은 자기 입맛에 따라 바꿔서 쓰는 경우도 있어서 내부적으로 정해서 쓰면 될듯용~