diff --git a/src/api/rooms/getRoomMembers.ts b/src/api/rooms/getRoomMembers.ts index 50f136be..513f2d0a 100644 --- a/src/api/rooms/getRoomMembers.ts +++ b/src/api/rooms/getRoomMembers.ts @@ -7,6 +7,7 @@ export interface RoomMember { imageUrl: string; aliasName: string; followerCount: number; + isMyself: boolean; } // 독서메이트 조회 응답 타입 @@ -26,6 +27,7 @@ export interface Member { role: string; followersCount?: number; profileImageUrl?: string; + isMyself?: boolean; } export const convertRoomMembersToMembers = (roomMembers: RoomMember[]): Member[] => { @@ -36,6 +38,7 @@ export const convertRoomMembersToMembers = (roomMembers: RoomMember[]): Member[] role: member.aliasName || '독서메이트', followersCount: member.followerCount || 0, profileImageUrl: member.imageUrl || undefined, + isMyself: member.isMyself, }; return convertedMember; diff --git a/src/components/common/BookSearchBottomSheet/BookSearchBottomSheet.styled.ts b/src/components/common/BookSearchBottomSheet/BookSearchBottomSheet.styled.ts index 68803dd3..386dc41f 100644 --- a/src/components/common/BookSearchBottomSheet/BookSearchBottomSheet.styled.ts +++ b/src/components/common/BookSearchBottomSheet/BookSearchBottomSheet.styled.ts @@ -249,7 +249,7 @@ export const EmptyContainer = styled.div` `; export const EmptyText = styled.p` - color: #e0e0e0;}; + color: #e0e0e0; font-size: ${typography.fontSize.sm}; font-weight: ${typography.fontWeight.regular}; margin: 0; diff --git a/src/components/creategroup/RoomInfoSection.styled.ts b/src/components/creategroup/RoomInfoSection.styled.ts index d1b0c68d..de1792a3 100644 --- a/src/components/creategroup/RoomInfoSection.styled.ts +++ b/src/components/creategroup/RoomInfoSection.styled.ts @@ -20,6 +20,7 @@ export const TextArea = styled.textarea` font-weight: ${typography.fontWeight.regular}; padding: 0; margin: 0; + caret-color: ${colors.neongreen}; &::placeholder { color: ${colors.grey[300]}; diff --git a/src/components/createpost/PhotoSection.tsx b/src/components/createpost/PhotoSection.tsx index d95911e1..79b7c9c8 100644 --- a/src/components/createpost/PhotoSection.tsx +++ b/src/components/createpost/PhotoSection.tsx @@ -1,4 +1,4 @@ -import { useRef } from 'react'; +import { useRef, useMemo, useEffect } from 'react'; import { Section, SectionTitle } from '../../pages/group/CommonSection.styled'; import { PhotoContainer, @@ -49,9 +49,17 @@ const PhotoSection = ({ e.target.value = ''; }; - const createImageUrl = (file: File) => { - return URL.createObjectURL(file); - }; + // 사진 파일들을 blob URL로 변환 (메모리 누수 방지) + const photoUrls = useMemo(() => { + return photos.map(file => URL.createObjectURL(file)); + }, [photos]); + + // 컴포넌트 언마운트 또는 photos 변경 시 기존 blob URL 해제 + useEffect(() => { + return () => { + photoUrls.forEach(url => URL.revokeObjectURL(url)); + }; + }, [photoUrls]); const totalImageCount = existingImageUrls.length + photos.length; const isDisabled = totalImageCount >= 3 || readOnly || isEditMode; @@ -81,12 +89,12 @@ const PhotoSection = ({ ))} - {photos.map((photo, index) => ( + {photos.map((_, index) => (
- + {!readOnly && ( onPhotoRemove(index)}> 삭제 diff --git a/src/components/createpost/PostContentSection.styled.ts b/src/components/createpost/PostContentSection.styled.ts index a1ac59cf..1fe62c17 100644 --- a/src/components/createpost/PostContentSection.styled.ts +++ b/src/components/createpost/PostContentSection.styled.ts @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import { typography, semanticColors } from '../../styles/global/global'; +import { typography, semanticColors, colors } from '../../styles/global/global'; export const TextAreaBox = styled.div` position: relative; @@ -18,9 +18,32 @@ export const TextArea = styled.textarea<{ readOnly?: boolean }>` resize: none; outline: none; border: none; - overflow: hidden; + overflow-y: auto; cursor: ${props => (props.readOnly ? 'not-allowed' : 'text')}; padding: 0; + caret-color: ${colors.neongreen}; + + /* 얇은 스크롤바 스타일 */ + &::-webkit-scrollbar { + width: 4px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background-color: ${semanticColors.text.ghost}; + border-radius: 2px; + } + + &::-webkit-scrollbar-thumb:hover { + background-color: ${semanticColors.text.tertiary}; + } + + /* Firefox 스크롤바 스타일 */ + scrollbar-width: thin; + scrollbar-color: ${semanticColors.text.ghost} transparent; &::placeholder { color: ${semanticColors.text.ghost}; diff --git a/src/components/members/MemberList.tsx b/src/components/members/MemberList.tsx index b50d4347..ffd7bb29 100644 --- a/src/components/members/MemberList.tsx +++ b/src/components/members/MemberList.tsx @@ -23,12 +23,16 @@ interface MemberListProps { const MemberList = ({ members, onMemberClick }: MemberListProps) => { const navigate = useNavigate(); - const handleMemberClick = (memberId: string) => { + const handleMemberClick = (member: Member) => { if (onMemberClick) { - onMemberClick(memberId); + onMemberClick(member.id); } else { - // 기본 동작: 개별 유저 페이지로 이동 - navigate(`/otherfeed/${memberId}`); + // isMyself가 true면 본인 프로필 페이지로, 아니면 다른 유저 페이지로 이동 + if (member.isMyself) { + navigate(`/myfeed/${member.id}`); + } else { + navigate(`/otherfeed/${member.id}`); + } } }; @@ -39,11 +43,11 @@ const MemberList = ({ members, onMemberClick }: MemberListProps) => { key={member.id} role="button" tabIndex={0} - onClick={() => handleMemberClick(member.id)} + onClick={() => handleMemberClick(member)} onKeyDown={(e: KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); - handleMemberClick(member.id); + handleMemberClick(member); } }} > diff --git a/src/components/recordwrite/PageRangeSection.styled.ts b/src/components/recordwrite/PageRangeSection.styled.ts index 87d06c11..f4191a1b 100644 --- a/src/components/recordwrite/PageRangeSection.styled.ts +++ b/src/components/recordwrite/PageRangeSection.styled.ts @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import { colors, typography, semanticColors } from '../../styles/global/global'; +import { typography, semanticColors } from '../../styles/global/global'; export const Section = styled.div` display: flex; @@ -50,10 +50,12 @@ export const PageInput = styled.input<{ inputLength?: number }>` font-size: ${typography.fontSize.sm}; font-weight: ${typography.fontWeight.regular}; font-family: ${typography.fontFamily.primary}; - width: ${props => (props.inputLength ? `${Math.max(27, props.inputLength * 8)}px` : '27px')}; + width: ${props => { + if (!props.inputLength) return '12px'; + return `${Math.max(9, props.inputLength * 8)}px`; + }}; padding: 0; margin: 0; - caret-color: ${colors.white}; transition: width 0.2s ease; flex-shrink: 0; diff --git a/src/pages/groupMembers/GroupMembers.tsx b/src/pages/groupMembers/GroupMembers.tsx index c429263a..17aba5d1 100644 --- a/src/pages/groupMembers/GroupMembers.tsx +++ b/src/pages/groupMembers/GroupMembers.tsx @@ -65,8 +65,14 @@ const GroupMembers = () => { }; const handleMemberClick = (memberId: string) => { - // 특정 사용자 페이지로 이동 - navigate(`/otherfeed/${memberId}`); + // MemberList 컴포넌트에서 isMyself에 따른 네비게이션 처리를 담당하므로 + // 여기서는 기본 동작을 유지 + const member = members.find(m => m.id === memberId); + if (member?.isMyself) { + navigate(`/myfeed/${memberId}`); + } else { + navigate(`/otherfeed/${memberId}`); + } }; // 로딩 상태 diff --git a/src/pages/pollwrite/PollWrite.styled.ts b/src/pages/pollwrite/PollWrite.styled.ts index 70501609..59441edd 100644 --- a/src/pages/pollwrite/PollWrite.styled.ts +++ b/src/pages/pollwrite/PollWrite.styled.ts @@ -12,4 +12,5 @@ export const Container = styled.div` padding: 96px 20px 100px 20px; box-sizing: border-box; gap: 32px; + `; diff --git a/src/pages/recordwrite/RecordWrite.styled.ts b/src/pages/recordwrite/RecordWrite.styled.ts index 70501609..59441edd 100644 --- a/src/pages/recordwrite/RecordWrite.styled.ts +++ b/src/pages/recordwrite/RecordWrite.styled.ts @@ -12,4 +12,5 @@ export const Container = styled.div` padding: 96px 20px 100px 20px; box-sizing: border-box; gap: 32px; + `;