diff --git a/components/Modal/Modal.tsx b/components/Modal/Modal.tsx index e041d50..dbfa652 100644 --- a/components/Modal/Modal.tsx +++ b/components/Modal/Modal.tsx @@ -68,7 +68,7 @@ const Modal = ({ />
{/* 닫기 버튼 영역 */}

- 위키에 작성하기 위해 + 다음 퀴즈를 맞추고
- 아래 퀴즈에 답해주세요. + 위키를 작성해 보세요.

@@ -121,7 +121,6 @@ function WikiQuizModal({ 제출 - {!keyboardVisible && (

{QUIZ_MESSAGES.WIKI_DESCRIPTION}

diff --git a/components/UserProfile.tsx b/components/UserProfile.tsx index 96ccc63..714afd7 100644 --- a/components/UserProfile.tsx +++ b/components/UserProfile.tsx @@ -24,11 +24,11 @@ function UserProfile({ // 프로필 이미지 관련 상태와 이벤트 핸들러 훅 const { - isLoading, // 이미지 로딩 상태 - previewImage, // 이미지 미리보기 URL - fileInputRef, // 파일 입력 요소 참조 - handleImageClick, // 이미지 클릭 핸들러 - handleFileChange, // 파일 변경 핸들러 + isLoading, + previewImage, + fileInputRef, + handleImageClick, + handleFileChange, } = useProfileImage((url) => onDataChange('image', url)); /** @@ -52,24 +52,26 @@ function UserProfile({ } return ( -

+

{label} - {data[field]} - {/* truncate 클래스 - overflow:hidden, text-overflow:ellipsis, white-space:nowrap */} + {data[field]}

); }; return ( - // 메인 컨테이너 -
- {/* 레이아웃 컨테이너: PC에서는 세로, 모바일/태블릿에서는 가로 배치 */} +
+ {/* 프로필 이미지와 정보를 포함하는 상단 컨테이너 */}
{/* 프로필 이미지 섹션 */}
{/* 이미지 업로드 버튼 */} - {/* 숨겨진 파일 입력 필드: 실제 파일 선택 다이얼로그를 위한 요소 */} + {/* 숨겨진 파일 입력 필드 */}
- {/* 프로필 정보 섹션: 사용자 정보를 표시하는 영역 */} + {/* 프로필 정보 섹션 */}
-
- {/* 기본 정보 영역: 항상 표시되는 필수 정보들 */} +
+ {/* 기본 정보 영역 */}
{renderField('거주 도시', 'city')} {renderField('MBTI', 'mbti')} @@ -149,75 +155,59 @@ function UserProfile({ {isEditing && renderField('SNS 계정', 'sns')}
- {/* 추가 정보 영역: 편집 모드와 조회 모드에서 다르게 표시 */} - {isEditing ? ( - // 편집 모드: 모든 필드를 그리드로 표시 -
+ {/* PC용 추가 정보 섹션 */} + {!isEditing && ( +
+ {renderField('SNS 계정', 'sns')} + {renderField('생일', 'birthday')} + {renderField('별명', 'nickname')} + {renderField('혈액형', 'bloodType')} + {renderField('국적', 'nationality')} +
+ )} + + {/* 편집 모드일 때 추가 정보 */} + {isEditing && ( +
{renderField('생일', 'birthday')} {renderField('별명', 'nickname')} {renderField('혈액형', 'bloodType')} {renderField('국적', 'nationality')}
- ) : ( - // 조회 모드: PC와 모바일/태블릿에서 다르게 표시 - <> - {/* 모바일/태블릿용 펼침/접힘 섹션 */} -
- {!isExpanded ? ( - // 접힌 상태: 펼치기 버튼 표시 -
- -
- ) : ( - // 펼친 상태: 추가 정보와 접기 버튼 표시 -
-
- {renderField('SNS 계정', 'sns')} - {renderField('생일', 'birthday')} - {renderField('별명', 'nickname')} - {renderField('혈액형', 'bloodType')} - {renderField('국적', 'nationality')} -
-
- -
-
- )} -
+ )} - {/* PC용 추가 정보 섹션: 항상 표시 */} -
- {renderField('SNS 계정', 'sns')} - {renderField('생일', 'birthday')} - {renderField('별명', 'nickname')} - {renderField('혈액형', 'bloodType')} - {renderField('국적', 'nationality')} -
- + {/* 모바일/태블릿용 추가 정보 섹션 */} + {!isEditing && isExpanded && ( +
+ {renderField('SNS 계정', 'sns')} + {renderField('생일', 'birthday')} + {renderField('별명', 'nickname')} + {renderField('혈액형', 'bloodType')} + {renderField('국적', 'nationality')} +
)}
+ + {/* 모바일/태블릿용 확장 버튼 */} + {!isEditing && ( +
+ +
+ )}
); } diff --git a/hooks/modal/useKeyboardVisibilty.tsx b/hooks/modal/useKeyboardVisibilty.tsx index 44735a7..5ead6c5 100644 --- a/hooks/modal/useKeyboardVisibilty.tsx +++ b/hooks/modal/useKeyboardVisibilty.tsx @@ -5,18 +5,35 @@ export function useKeyboardVisibility( isMobile: boolean ) { const [keyboardVisible, setKeyboardVisible] = useState(false); + const [initialScreenHeight] = useState( + typeof window !== 'undefined' ? window.screen.height : 0 + ); useEffect(() => { - if (!isMobile) return undefined; + if (!isMobile) { + setKeyboardVisible(false); + return undefined; + } + + let scrollTimeout: NodeJS.Timeout; const handleKeyboardVisibility = (): void => { - const isKeyboardVisible = window.innerHeight < window.screen.height; - setKeyboardVisible(isKeyboardVisible); + // visualViewport API 사용 (지원되는 경우) + if (window.visualViewport) { + const isKeyboardVisible = + window.visualViewport.height < initialScreenHeight * 0.8; + setKeyboardVisible(isKeyboardVisible); + } else { + // fallback: 기존 방식 + const isKeyboardVisible = + window.innerHeight < initialScreenHeight * 0.8; + setKeyboardVisible(isKeyboardVisible); + } // 키보드가 보일 때 입력 필드로 포커스 및 스크롤 - if (isKeyboardVisible && inputRef.current !== null) { - inputRef.current.focus(); - void setTimeout(() => { + if (inputRef.current !== null) { + clearTimeout(scrollTimeout); + scrollTimeout = setTimeout(() => { if (inputRef.current !== null) { inputRef.current.scrollIntoView({ behavior: 'smooth', @@ -27,12 +44,30 @@ export function useKeyboardVisibility( } }; + // 초기 상태 설정 handleKeyboardVisibility(); - window.addEventListener('resize', handleKeyboardVisibility); - return () => { - window.removeEventListener('resize', handleKeyboardVisibility); - }; - }, [isMobile, inputRef]); + + // 이벤트 리스너 설정 + if (window.visualViewport) { + window.visualViewport.addEventListener( + 'resize', + handleKeyboardVisibility + ); + return () => { + window.visualViewport?.removeEventListener( + 'resize', + handleKeyboardVisibility + ); + clearTimeout(scrollTimeout); + }; + } else { + window.addEventListener('resize', handleKeyboardVisibility); + return () => { + window.removeEventListener('resize', handleKeyboardVisibility); + clearTimeout(scrollTimeout); + }; + } + }, [isMobile, inputRef, initialScreenHeight]); return keyboardVisible; }