feat(app): Messenger app Variant design applied
Config.ts: - COLORS: accent #4f6ef7 -> #00A0C8(cyan), primary #003366(navy) - gnbBg: deeper navy #001530 _layout.tsx: - TabBar: elevated shadow, cyan active tint, bolder label index.tsx (Dashboard): - StatCard: top color bar + icon box (screenshot9 pattern) - Header: deep navy gradient rounded bottom - QuickBtn: bg-light card style - Section: deeper shadow, navy title login.tsx: - Background: deep navy #001530 - Card: white + strong shadow - Button: solid cyan with shadow - Label: cyan uppercase Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6fffc03074
commit
e47f91b6cf
@ -96,30 +96,45 @@ export default function LoginScreen() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Variant 스타일 로그인 — 딥네이비 배경 + 흰 카드 */
|
||||||
const s = StyleSheet.create({
|
const s = StyleSheet.create({
|
||||||
container: { flex: 1, backgroundColor: COLORS.primary },
|
container: { flex: 1, backgroundColor: '#001530' },
|
||||||
inner: { flexGrow: 1, justifyContent: 'center', padding: 24 },
|
inner: { flexGrow: 1, justifyContent: 'center', padding: 28 },
|
||||||
logoBox: { alignItems: 'center', marginBottom: 32 },
|
logoBox: { alignItems: 'center', marginBottom: 36 },
|
||||||
logoIcon: { fontSize: 56, marginBottom: 8 },
|
logoIcon: { fontSize: 52, marginBottom: 10 },
|
||||||
logoTitle: { fontSize: 32, fontWeight: '800', color: '#fff', letterSpacing: 2 },
|
logoTitle: { fontSize: 34, fontWeight: '900', color: '#fff', letterSpacing: 1.5 },
|
||||||
logoSub: { fontSize: 13, color: '#aac4e8', marginTop: 4 },
|
logoSub: { fontSize: 13, color: 'rgba(0,160,200,.85)', marginTop: 5 },
|
||||||
badge: { marginTop: 10, backgroundColor: 'rgba(255,255,255,.15)',
|
badge: {
|
||||||
paddingHorizontal: 14, paddingVertical: 4, borderRadius: 20 },
|
marginTop: 10,
|
||||||
badgeText: { color: '#fff', fontSize: 11, fontWeight: '600' },
|
backgroundColor: 'rgba(0,160,200,.15)',
|
||||||
card: { backgroundColor: '#fff', borderRadius: 16, padding: 24,
|
borderWidth: 1, borderColor: 'rgba(0,160,200,.3)',
|
||||||
shadowColor: '#000', shadowOffset: { width: 0, height: 8 },
|
paddingHorizontal: 14, paddingVertical: 5, borderRadius: 20,
|
||||||
shadowOpacity: 0.15, shadowRadius: 24, elevation: 8 },
|
},
|
||||||
cardTitle: { fontSize: 18, fontWeight: '700', color: COLORS.primary,
|
badgeText: { color: '#00A0C8', fontSize: 11, fontWeight: '700' },
|
||||||
marginBottom: 20, textAlign: 'center' },
|
card: {
|
||||||
field: { marginBottom: 14 },
|
backgroundColor: '#fff', borderRadius: 20, padding: 28,
|
||||||
label: { fontSize: 12, fontWeight: '600', color: COLORS.muted,
|
shadowColor: '#001530', shadowOffset: { width: 0, height: 12 },
|
||||||
marginBottom: 6, textTransform: 'uppercase', letterSpacing: .5 },
|
shadowOpacity: 0.25, shadowRadius: 32, elevation: 10,
|
||||||
input: { borderWidth: 1.5, borderColor: COLORS.border, borderRadius: 10,
|
},
|
||||||
padding: 13, fontSize: 15, color: COLORS.text, backgroundColor: '#fafafa' },
|
cardTitle: {
|
||||||
btn: { backgroundColor: COLORS.primary, borderRadius: 10, padding: 15,
|
fontSize: 18, fontWeight: '800', color: '#003366',
|
||||||
alignItems: 'center', marginTop: 8 },
|
marginBottom: 22, textAlign: 'center', letterSpacing: -0.3,
|
||||||
|
},
|
||||||
|
field: { marginBottom: 16 },
|
||||||
|
label: { fontSize: 11, fontWeight: '700', color: '#00A0C8',
|
||||||
|
marginBottom: 6, textTransform: 'uppercase', letterSpacing: .6 },
|
||||||
|
input: {
|
||||||
|
borderWidth: 1.5, borderColor: '#E2E8F0', borderRadius: 12,
|
||||||
|
padding: 14, fontSize: 15, color: '#1E293B', backgroundColor: '#F8FAFC',
|
||||||
|
},
|
||||||
|
btn: {
|
||||||
|
backgroundColor: '#00A0C8', borderRadius: 12, padding: 16,
|
||||||
|
alignItems: 'center', marginTop: 8,
|
||||||
|
shadowColor: '#00A0C8', shadowOffset: { width: 0, height: 4 },
|
||||||
|
shadowOpacity: .3, shadowRadius: 10, elevation: 4,
|
||||||
|
},
|
||||||
btnDisabled: { opacity: .6 },
|
btnDisabled: { opacity: .6 },
|
||||||
btnText: { color: '#fff', fontSize: 16, fontWeight: '700' },
|
btnText: { color: '#fff', fontSize: 16, fontWeight: '800', letterSpacing: 0.3 },
|
||||||
hint: { textAlign: 'center', color: COLORS.muted, fontSize: 12, marginTop: 16 },
|
hint: { textAlign: 'center', color: '#64748B', fontSize: 12, marginTop: 16 },
|
||||||
version: { textAlign: 'center', color: 'rgba(255,255,255,.4)', fontSize: 11, marginTop: 24 },
|
version: { textAlign: 'center', color: 'rgba(0,160,200,.4)', fontSize: 11, marginTop: 24 },
|
||||||
})
|
})
|
||||||
|
|||||||
@ -12,11 +12,11 @@ function TabIcon({ icon, label, focused }: { icon: string; label: string; focuse
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tab = StyleSheet.create({
|
const tab = StyleSheet.create({
|
||||||
wrap: { alignItems: 'center', paddingTop: 4 },
|
wrap: { alignItems: 'center', paddingTop: 4, paddingHorizontal: 2 },
|
||||||
active: {},
|
active: {},
|
||||||
icon: { fontSize: 22 },
|
icon: { fontSize: 21 },
|
||||||
label: { fontSize: 10, color: COLORS.muted, marginTop: 2 },
|
label: { fontSize: 10, color: COLORS.muted, marginTop: 2, letterSpacing: 0.2 },
|
||||||
labelActive: { color: COLORS.accent, fontWeight: '600' },
|
labelActive: { color: COLORS.accent, fontWeight: '700' },
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function TabLayout() {
|
export default function TabLayout() {
|
||||||
@ -25,8 +25,20 @@ export default function TabLayout() {
|
|||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerStyle: { backgroundColor: COLORS.gnbBg },
|
headerStyle: { backgroundColor: COLORS.gnbBg },
|
||||||
headerTintColor: '#fff',
|
headerTintColor: '#fff',
|
||||||
headerTitleStyle: { fontWeight: '700' },
|
headerTitleStyle: { fontWeight: '800', fontSize: 16, letterSpacing: -0.3 },
|
||||||
tabBarStyle: { backgroundColor: '#fff', borderTopColor: COLORS.border, height: 60 },
|
tabBarStyle: {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
borderTopColor: COLORS.border,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
height: 62,
|
||||||
|
elevation: 8,
|
||||||
|
shadowColor: '#003366',
|
||||||
|
shadowOffset: { width: 0, height: -2 },
|
||||||
|
shadowOpacity: 0.08,
|
||||||
|
shadowRadius: 8,
|
||||||
|
},
|
||||||
|
tabBarActiveTintColor: COLORS.accent,
|
||||||
|
tabBarInactiveTintColor: COLORS.muted,
|
||||||
tabBarShowLabel: false,
|
tabBarShowLabel: false,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -14,12 +14,18 @@ interface Stats {
|
|||||||
recent_tasks?: any[]
|
recent_tasks?: any[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Variant 스타일 StatCard — screenshot9 패턴 */
|
||||||
function StatCard({ icon, label, value, color }: { icon: string; label: string; value: number | string; color: string }) {
|
function StatCard({ icon, label, value, color }: { icon: string; label: string; value: number | string; color: string }) {
|
||||||
return (
|
return (
|
||||||
<View style={[s.statCard, { borderLeftColor: color, borderLeftWidth: 3 }]}>
|
<View style={[s.statCard, { borderTopColor: color, borderTopWidth: 3 }]}>
|
||||||
|
{/* 아이콘 박스 — 연파랑 컨테이너 */}
|
||||||
|
<View style={[s.statIconBox, { backgroundColor: color + '18' }]}>
|
||||||
<Text style={s.statIcon}>{icon}</Text>
|
<Text style={s.statIcon}>{icon}</Text>
|
||||||
<Text style={s.statValue}>{value}</Text>
|
</View>
|
||||||
|
{/* 라벨 (위) */}
|
||||||
<Text style={s.statLabel}>{label}</Text>
|
<Text style={s.statLabel}>{label}</Text>
|
||||||
|
{/* 수치 (아래) */}
|
||||||
|
<Text style={[s.statValue, { color }]}>{value}</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -126,34 +132,62 @@ export default function Dashboard() {
|
|||||||
const s = StyleSheet.create({
|
const s = StyleSheet.create({
|
||||||
scroll: { flex: 1, backgroundColor: COLORS.bg },
|
scroll: { flex: 1, backgroundColor: COLORS.bg },
|
||||||
center: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: COLORS.bg },
|
center: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: COLORS.bg },
|
||||||
header: { backgroundColor: COLORS.primary, padding: 24, paddingTop: 16 },
|
/* 헤더 — Variant 딥네이비 그라디언트 */
|
||||||
greeting: { fontSize: 20, fontWeight: '700', color: '#fff' },
|
header: {
|
||||||
subGreet: { fontSize: 13, color: '#aac4e8', marginTop: 4 },
|
backgroundColor: '#001530',
|
||||||
|
padding: 24, paddingTop: 20,
|
||||||
|
borderBottomLeftRadius: 20, borderBottomRightRadius: 20,
|
||||||
|
},
|
||||||
|
greeting: { fontSize: 20, fontWeight: '800', color: '#fff', letterSpacing: -0.5 },
|
||||||
|
subGreet: { fontSize: 13, color: 'rgba(0,160,200,.85)', marginTop: 4 },
|
||||||
licenseBanner: { backgroundColor: '#fff3cd', padding: 12, marginHorizontal: 16, marginTop: 12,
|
licenseBanner: { backgroundColor: '#fff3cd', padding: 12, marginHorizontal: 16, marginTop: 12,
|
||||||
borderRadius: 8, borderLeftWidth: 3, borderLeftColor: COLORS.warning },
|
borderRadius: 10, borderLeftWidth: 3, borderLeftColor: COLORS.warning },
|
||||||
licenseBannerText: { fontSize: 12, color: '#856404' },
|
licenseBannerText: { fontSize: 12, color: '#856404' },
|
||||||
licenseBar: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center',
|
licenseBar: {
|
||||||
backgroundColor: COLORS.light, marginHorizontal: 16, marginTop: 8,
|
flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center',
|
||||||
paddingHorizontal: 14, paddingVertical: 8, borderRadius: 8 },
|
backgroundColor: COLORS.light, marginHorizontal: 16, marginTop: 10,
|
||||||
|
paddingHorizontal: 14, paddingVertical: 8, borderRadius: 10,
|
||||||
|
borderWidth: 1, borderColor: 'rgba(0,160,200,.2)',
|
||||||
|
},
|
||||||
licenseEdition: { fontSize: 12, fontWeight: '700', color: COLORS.accent },
|
licenseEdition: { fontSize: 12, fontWeight: '700', color: COLORS.accent },
|
||||||
licenseDays: { fontSize: 12, color: COLORS.muted },
|
licenseDays: { fontSize: 12, color: COLORS.muted },
|
||||||
statsGrid: { flexDirection: 'row', flexWrap: 'wrap', padding: 12, gap: 8 },
|
/* 통계 그리드 */
|
||||||
statCard: { width: '47%', backgroundColor: '#fff', borderRadius: 10, padding: 14,
|
statsGrid: { flexDirection: 'row', flexWrap: 'wrap', padding: 14, gap: 10 },
|
||||||
shadowColor: '#000', shadowOffset: { width: 0, height: 2 },
|
/* Variant StatCard — 상단 컬러 바 + 아이콘 박스 */
|
||||||
shadowOpacity: .06, shadowRadius: 6, elevation: 2 },
|
statCard: {
|
||||||
statIcon: { fontSize: 22, marginBottom: 6 },
|
width: '47%', backgroundColor: '#fff', borderRadius: 12, padding: 14,
|
||||||
statValue: { fontSize: 26, fontWeight: '800', color: COLORS.text },
|
shadowColor: '#003366', shadowOffset: { width: 0, height: 2 },
|
||||||
statLabel: { fontSize: 11, color: COLORS.muted, marginTop: 2 },
|
shadowOpacity: .08, shadowRadius: 8, elevation: 3,
|
||||||
section: { backgroundColor: '#fff', marginHorizontal: 16, marginTop: 12,
|
},
|
||||||
borderRadius: 12, padding: 16, elevation: 1 },
|
statIconBox: { width: 40, height: 40, borderRadius: 10, marginBottom: 10,
|
||||||
sectionTitle: { fontSize: 14, fontWeight: '700', color: COLORS.text, marginBottom: 12 },
|
alignItems: 'center', justifyContent: 'center' },
|
||||||
|
statIcon: { fontSize: 20 },
|
||||||
|
statValue: { fontSize: 28, fontWeight: '900', letterSpacing: -0.5 },
|
||||||
|
statLabel: { fontSize: 11, fontWeight: '600', color: COLORS.muted,
|
||||||
|
letterSpacing: 0.3, textTransform: 'uppercase', marginBottom: 4 },
|
||||||
|
/* 섹션 */
|
||||||
|
section: {
|
||||||
|
backgroundColor: '#fff', marginHorizontal: 16, marginTop: 12,
|
||||||
|
borderRadius: 14, padding: 16,
|
||||||
|
shadowColor: '#003366', shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: .05, shadowRadius: 6, elevation: 2,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 14, fontWeight: '800', color: COLORS.primary,
|
||||||
|
marginBottom: 12, letterSpacing: -0.3,
|
||||||
|
},
|
||||||
srItem: { flexDirection: 'row', alignItems: 'center', gap: 10,
|
srItem: { flexDirection: 'row', alignItems: 'center', gap: 10,
|
||||||
paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#f1f5f9' },
|
paddingVertical: 9, borderBottomWidth: 1, borderBottomColor: '#f1f5f9' },
|
||||||
priorityDot: { width: 8, height: 8, borderRadius: 4 },
|
priorityDot: { width: 8, height: 8, borderRadius: 4 },
|
||||||
srTitle: { fontSize: 13, fontWeight: '500', color: COLORS.text },
|
srTitle: { fontSize: 13, fontWeight: '600', color: COLORS.text },
|
||||||
srMeta: { fontSize: 11, color: COLORS.muted, marginTop: 2 },
|
srMeta: { fontSize: 11, color: COLORS.muted, marginTop: 2 },
|
||||||
|
/* 빠른 실행 */
|
||||||
quickRow: { flexDirection: 'row', justifyContent: 'space-around' },
|
quickRow: { flexDirection: 'row', justifyContent: 'space-around' },
|
||||||
quickBtn: { alignItems: 'center', padding: 12 },
|
quickBtn: {
|
||||||
quickIcon: { fontSize: 28, marginBottom: 4 },
|
alignItems: 'center', padding: 12,
|
||||||
quickLabel: { fontSize: 11, color: COLORS.muted },
|
backgroundColor: COLORS.bg, borderRadius: 12,
|
||||||
|
flex: 1, marginHorizontal: 3,
|
||||||
|
},
|
||||||
|
quickIcon: { fontSize: 26, marginBottom: 5 },
|
||||||
|
quickLabel: { fontSize: 11, fontWeight: '600', color: COLORS.primary },
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,26 +2,28 @@ import Constants from 'expo-constants'
|
|||||||
|
|
||||||
export const API_BASE = Constants.expoConfig?.extra?.guardiaApiUrl ?? 'https://zioinfo.co.kr:8443'
|
export const API_BASE = Constants.expoConfig?.extra?.guardiaApiUrl ?? 'https://zioinfo.co.kr:8443'
|
||||||
|
|
||||||
|
/* Variant 디자인 토큰 (#003366 딥네이비 / #005A8C 미드블루 / #00A0C8 시안) */
|
||||||
export const COLORS = {
|
export const COLORS = {
|
||||||
primary: '#1a3a6b',
|
primary: '#003366', /* 딥네이비 */
|
||||||
accent: '#4f6ef7',
|
blue: '#005A8C', /* 미드블루 */
|
||||||
light: '#e8ecff',
|
accent: '#00A0C8', /* 시안 포인트 */
|
||||||
bg: '#f0f2f5',
|
light: '#E8F7FB', /* 연시안 배경 */
|
||||||
|
bg: '#F8FAFC', /* 페이지 배경 */
|
||||||
card: '#ffffff',
|
card: '#ffffff',
|
||||||
border: '#e2e8f0',
|
border: '#E2E8F0',
|
||||||
text: '#1e293b',
|
text: '#1E293B',
|
||||||
muted: '#64748b',
|
muted: '#64748B',
|
||||||
success: '#22c55e',
|
success: '#22c55e',
|
||||||
warning: '#f59e0b',
|
warning: '#f59e0b',
|
||||||
danger: '#ef4444',
|
danger: '#ef4444',
|
||||||
gnbBg: '#1a1d2e',
|
gnbBg: '#001530', /* 딥네이비 헤더 */
|
||||||
white: '#ffffff',
|
white: '#ffffff',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export const PRIORITY_COLOR: Record<string, string> = {
|
export const PRIORITY_COLOR: Record<string, string> = {
|
||||||
CRITICAL: '#ef4444',
|
CRITICAL: '#ef4444',
|
||||||
HIGH: '#f59e0b',
|
HIGH: '#f59e0b',
|
||||||
MEDIUM: '#4f6ef7',
|
MEDIUM: '#00A0C8', /* 시안으로 변경 */
|
||||||
LOW: '#22c55e',
|
LOW: '#22c55e',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user