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 { getAlbums, Album } from '../api/albums';
import { colors } from '../constants/colors'; import { colors } from '../constants/colors';
import Header from '../components/common/Header';
import type { AlbumStackParamList } from '../navigation/AppNavigator'; import type { AlbumStackParamList } from '../navigation/AppNavigator';
type NavigationProp = NativeStackNavigationProp<AlbumStackParamList>; type NavigationProp = NativeStackNavigationProp<AlbumStackParamList>;
@ -48,7 +49,8 @@ export default function AlbumScreen() {
if (loading) { if (loading) {
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container} edges={[]}>
<Header title="앨범" />
<View style={styles.loadingContainer}> <View style={styles.loadingContainer}>
<ActivityIndicator size="large" color={colors.primary} /> <ActivityIndicator size="large" color={colors.primary} />
</View> </View>
@ -57,11 +59,9 @@ export default function AlbumScreen() {
} }
return ( return (
<SafeAreaView style={styles.container} edges={['top']}> <SafeAreaView style={styles.container} edges={[]}>
{/* 헤더 */} {/* 공통 헤더 */}
<View style={styles.header}> <Header title="앨범" />
<Text style={styles.headerTitle}></Text>
</View>
{/* 앨범 목록 */} {/* 앨범 목록 */}
<ScrollView <ScrollView
@ -113,23 +113,6 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
alignItems: '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: { scrollView: {
flex: 1, flex: 1,
}, },

View file

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

View file

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