refactor(app): 공통 Header 컴포넌트 적용 및 SafeAreaView edges 수정

- Header.tsx 공통 컴포넌트 생성
- HomeScreen, MembersScreen, AlbumScreen에 공통 Header 적용
- SafeAreaView edges=[] 설정으로 중복 safe area 영역 제거
This commit is contained in:
caadiq 2026-01-12 12:54:09 +09:00
parent 58411f3dca
commit 7f1c210be7
4 changed files with 64 additions and 41 deletions

View file

@ -0,0 +1,46 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { colors } from '../../constants/colors';
interface HeaderProps {
// 페이지 제목 (없으면 "fromis_9" 표시)
title?: string;
}
// 모바일 웹 MobileHeader와 동일한 공통 헤더 컴포넌트
export default function Header({ title }: HeaderProps) {
const insets = useSafeAreaInsets();
return (
<View style={[styles.header, { paddingTop: insets.top }]}>
<View style={styles.headerContent}>
<Text style={styles.headerTitle}>
{title || 'fromis_9'}
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
header: {
backgroundColor: '#FFFFFF',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.05,
shadowRadius: 2,
elevation: 2,
},
headerContent: {
height: 56,
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: 16,
},
headerTitle: {
fontSize: 20,
fontWeight: '700',
color: colors.primary,
},
});

View file

@ -15,6 +15,7 @@ import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { getAlbums, Album } from '../api/albums';
import { colors } from '../constants/colors';
import Header from '../components/common/Header';
import type { AlbumStackParamList } from '../navigation/AppNavigator';
type NavigationProp = NativeStackNavigationProp<AlbumStackParamList>;
@ -48,7 +49,8 @@ export default function AlbumScreen() {
if (loading) {
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={styles.container} edges={[]}>
<Header title="앨범" />
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={colors.primary} />
</View>
@ -57,11 +59,9 @@ export default function AlbumScreen() {
}
return (
<SafeAreaView style={styles.container} edges={['top']}>
{/* 헤더 */}
<View style={styles.header}>
<Text style={styles.headerTitle}></Text>
</View>
<SafeAreaView style={styles.container} edges={[]}>
{/* 공통 헤더 */}
<Header title="앨범" />
{/* 앨범 목록 */}
<ScrollView
@ -113,23 +113,6 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center',
},
header: {
backgroundColor: '#FFFFFF',
paddingVertical: 14,
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#F3F4F6',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.05,
shadowRadius: 2,
elevation: 2,
},
headerTitle: {
fontSize: 18,
fontWeight: 'bold',
color: colors.textPrimary,
},
scrollView: {
flex: 1,
},

View file

@ -19,6 +19,7 @@ import { getAlbums, Album } from '../api/albums';
import { getMembers, Member } from '../api/members';
import { getUpcomingSchedules, Schedule } from '../api/schedules';
import { colors } from '../constants/colors';
import Header from '../components/common/Header';
import type { AlbumStackParamList } from '../navigation/AppNavigator';
type NavigationProp = NativeStackNavigationProp<AlbumStackParamList>;
@ -106,10 +107,8 @@ export default function HomeScreen() {
if (loading) {
return (
<SafeAreaView style={styles.container} edges={['top']}>
<View style={styles.header}>
<Text style={styles.headerTitle}>fromis_9</Text>
</View>
<SafeAreaView style={styles.container} edges={[]}>
<Header />
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={colors.primary} />
</View>
@ -118,11 +117,9 @@ export default function HomeScreen() {
}
return (
<SafeAreaView style={styles.container} edges={['top']}>
{/* 상단 헤더 */}
<View style={styles.header}>
<Text style={styles.headerTitle}>fromis_9</Text>
</View>
<SafeAreaView style={styles.container} edges={[]}>
{/* 공통 헤더 */}
<Header />
<ScrollView
style={styles.scrollView}

View file

@ -24,6 +24,7 @@ import dayjs from 'dayjs';
import { getMembers, Member } from '../api/members';
import { colors } from '../constants/colors';
import Header from '../components/common/Header';
const SCREEN_WIDTH = Dimensions.get('window').width;
const CARD_WIDTH = (SCREEN_WIDTH - 32 - 24) / 3;
@ -216,10 +217,8 @@ export default function MembersScreen() {
if (loading) {
return (
<SafeAreaView style={styles.container} edges={['top']}>
<View style={styles.header}>
<Text style={styles.headerTitle}></Text>
</View>
<SafeAreaView style={styles.container} edges={[]}>
<Header title="멤버" />
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={colors.primary} />
</View>
@ -228,11 +227,9 @@ export default function MembersScreen() {
}
return (
<SafeAreaView style={styles.container} edges={['top']}>
{/* 상단 헤더 */}
<View style={styles.header}>
<Text style={styles.headerTitle}></Text>
</View>
<SafeAreaView style={styles.container} edges={[]}>
{/* 공통 헤더 */}
<Header title="멤버" />
{/* 멤버 목록 */}
<ScrollView