121 lines
5.5 KiB
TypeScript
121 lines
5.5 KiB
TypeScript
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, Alert, Switch, Linking } from 'react-native'
|
||
import { COLORS } from '../../constants/Config'
|
||
import { useAuth } from '../../hooks/useAuth'
|
||
import { useState } from 'react'
|
||
import LineIcon from '../../components/LineIcon'
|
||
|
||
type IconName = Parameters<typeof LineIcon>[0]['name']
|
||
|
||
function MenuItem({ iconName, label, value, onPress, danger, toggle, enabled, onToggle }:
|
||
{ iconName: IconName; label: string; value?: string; onPress?: () => void; danger?: boolean
|
||
toggle?: boolean; enabled?: boolean; onToggle?: (v: boolean) => void }) {
|
||
return (
|
||
<TouchableOpacity style={s.item} onPress={onPress} disabled={toggle}>
|
||
<View style={[s.itemIcon, { backgroundColor: danger ? '#fee2e2' : 'rgba(0,160,200,.08)' }]}>
|
||
<LineIcon name={iconName} size={18} color={danger ? COLORS.danger : COLORS.accent} />
|
||
</View>
|
||
<View style={{ flex: 1 }}>
|
||
<Text style={[s.itemLabel, danger && { color: COLORS.danger }]}>{label}</Text>
|
||
{value && <Text style={s.itemValue}>{value}</Text>}
|
||
</View>
|
||
{toggle
|
||
? <Switch value={enabled} onValueChange={onToggle} trackColor={{ true: COLORS.accent }} />
|
||
: <Text style={s.chevron}>›</Text>
|
||
}
|
||
</TouchableOpacity>
|
||
)
|
||
}
|
||
|
||
export default function SettingsScreen() {
|
||
const { user, logout } = useAuth()
|
||
const [pushEnabled, setPush] = useState(true)
|
||
const [darkMode, setDark] = useState(false)
|
||
|
||
const handleLogout = () => {
|
||
Alert.alert('로그아웃', '정말 로그아웃하시겠습니까?', [
|
||
{ text: '취소', style: 'cancel' },
|
||
{ text: '로그아웃', style: 'destructive', onPress: logout },
|
||
])
|
||
}
|
||
|
||
return (
|
||
<ScrollView style={{ flex: 1, backgroundColor: COLORS.bg }}>
|
||
{/* 프로필 카드 */}
|
||
<View style={s.profile}>
|
||
<View style={s.avatar}>
|
||
<Text style={s.avatarText}>{(user?.display_name ?? user?.username ?? 'U')[0].toUpperCase()}</Text>
|
||
</View>
|
||
<View>
|
||
<Text style={s.displayName}>{user?.display_name ?? user?.username}</Text>
|
||
<Text style={s.role}>{user?.role ?? '-'}</Text>
|
||
{user?.email && <Text style={s.email}>{user.email}</Text>}
|
||
</View>
|
||
</View>
|
||
|
||
{/* 서버 정보 */}
|
||
<View style={s.section}>
|
||
<Text style={s.sectionTitle}>서버 연결</Text>
|
||
<MenuItem iconName="globe" label="GUARDiA 서버" value="zioinfo.co.kr:8443" />
|
||
<MenuItem iconName="lock" label="HTTPS 보안 연결" value="TLS 1.3" />
|
||
<MenuItem iconName="dashboard" label="API 버전" value="v2.0.0" />
|
||
</View>
|
||
|
||
{/* 알림 설정 */}
|
||
<View style={s.section}>
|
||
<Text style={s.sectionTitle}>알림</Text>
|
||
<MenuItem iconName="bell" label="푸시 알림" toggle enabled={pushEnabled} onToggle={setPush} />
|
||
<MenuItem iconName="alert" label="긴급 알림 (인시던트)" toggle enabled={true} onToggle={() => {}} />
|
||
<MenuItem iconName="sr" label="SR 상태 알림" toggle enabled={true} onToggle={() => {}} />
|
||
</View>
|
||
|
||
{/* 앱 설정 */}
|
||
<View style={s.section}>
|
||
<Text style={s.sectionTitle}>앱 설정</Text>
|
||
<MenuItem iconName="settings" label="다크 모드" toggle enabled={darkMode} onToggle={setDark} />
|
||
<MenuItem iconName="globe" label="언어" value="한국어" />
|
||
<MenuItem iconName="ai" label="앱 버전" value="1.0.0 (build 1)" />
|
||
</View>
|
||
|
||
{/* 지원 */}
|
||
<View style={s.section}>
|
||
<Text style={s.sectionTitle}>지원</Text>
|
||
<MenuItem iconName="server" label="사용 가이드"
|
||
onPress={() => Linking.openURL('http://zioinfo.co.kr:8090')} />
|
||
<MenuItem iconName="lock" label="GUARDiA ITSM 웹"
|
||
onPress={() => Linking.openURL('https://zioinfo.co.kr:8443')} />
|
||
<MenuItem iconName="mail" label="문의하기"
|
||
onPress={() => Linking.openURL('mailto:guardia@zioinfo.co.kr')} />
|
||
<MenuItem iconName="building" label="(주)지오정보기술" value="zioinfo.co.kr" />
|
||
</View>
|
||
|
||
{/* 로그아웃 */}
|
||
<View style={s.section}>
|
||
<MenuItem iconName="user" label="로그아웃" onPress={handleLogout} danger />
|
||
</View>
|
||
|
||
<View style={{ height: 32 }} />
|
||
</ScrollView>
|
||
)
|
||
}
|
||
|
||
const s = StyleSheet.create({
|
||
profile: { backgroundColor:COLORS.primary, padding:24,
|
||
flexDirection:'row', alignItems:'center', gap:16 },
|
||
avatar: { width:56, height:56, borderRadius:28,
|
||
backgroundColor:'rgba(255,255,255,.2)', justifyContent:'center', alignItems:'center' },
|
||
avatarText: { fontSize:24, fontWeight:'800', color:'#fff' },
|
||
displayName: { fontSize:18, fontWeight:'700', color:'#fff' },
|
||
role: { fontSize:12, color:'#aac4e8', marginTop:2 },
|
||
email: { fontSize:12, color:'#aac4e8' },
|
||
section: { backgroundColor:'#fff', marginHorizontal:0, marginTop:12 },
|
||
sectionTitle:{ fontSize:12, fontWeight:'600', color:COLORS.muted,
|
||
paddingHorizontal:16, paddingTop:14, paddingBottom:6,
|
||
textTransform:'uppercase', letterSpacing:.5 },
|
||
item: { flexDirection:'row', alignItems:'center', paddingHorizontal:16,
|
||
paddingVertical:14, borderBottomWidth:1, borderBottomColor:'#f1f5f9', gap:12 },
|
||
itemIcon: { width:34, height:34, borderRadius:9, alignItems:'center', justifyContent:'center' },
|
||
itemLabel: { fontSize:14, color:COLORS.text, fontWeight:'500' },
|
||
itemValue: { fontSize:12, color:COLORS.muted, marginTop:2 },
|
||
chevron: { fontSize:20, color:COLORS.muted },
|
||
})
|