/* * 홈/대시보드 — 활성 행사 헤더(D-데이) + 역할별 진입 카드. * 워크스페이스(행사)는 로그인 응답에서 수신. 역할에 따라 진입 동선 분기. */ import { Ionicons } from '@expo/vector-icons'; import { router } from 'expo-router'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'; import { Banner } from '../../components/Banner'; import { Card } from '../../components/Card'; import { DdayChip } from '../../components/DdayChip'; import { useAuth } from '../../context/AuthContext'; import type { EventRole, WorkspaceDto } from '../../lib/types'; import { colors, radius, spacing, type } from '../../theme'; export default function HomeScreen() { const { t } = useTranslation(); const { user, workspaces, activeWorkspace, selectWorkspace } = useAuth(); return ( {t('home.hello', { name: user?.displayName ?? t('common.user') })} {workspaces.length === 0 ? ( {t('home.noEvent')} ) : null} {/* 행사 선택 */} {workspaces.length > 1 ? ( {workspaces.map((w) => ( selectWorkspace(w.eventId)} style={[ styles.eventChip, activeWorkspace?.eventId === w.eventId && styles.eventChipOn, ]} > {w.eventName} ))} ) : null} {activeWorkspace ? : null} {/* 진행 스테퍼 */} {t('home.progress')} {/* 역할별 진입 */} {activeWorkspace ? : null} ); } function EventHeader({ ws }: { ws: WorkspaceDto }) { const { t } = useTranslation(); return ( {ws.eventName} {ws.hallLabel} · {ws.startDate} ~ {ws.endDate} {t(`roles.${ws.myRole}` as const)} ); } function RoleActions({ role }: { role: EventRole }) { const { t } = useTranslation(); const actions: { label: string; icon: keyof typeof Ionicons.glyphMap; onPress: () => void }[] = []; if (role === 'CONTRACTOR') { actions.push({ label: t('home.actionChecklist'), icon: 'clipboard-outline', onPress: () => router.push('/checklist') }); } if (role === 'HALL_MANAGER') { actions.push({ label: t('home.actionInspection'), icon: 'shield-checkmark-outline', onPress: () => router.push('/inspection') }); } actions.push({ label: t('home.actionGallery'), icon: 'images-outline', onPress: () => router.push('/(tabs)/gallery') }); return ( {actions.map((a) => ( {a.label} ))} ); } function Stepper({ steps, active }: { steps: string[]; active: number }) { return ( {steps.map((s, i) => ( {i + 1} {s} ))} ); } const styles = StyleSheet.create({ scroll: { padding: spacing.md, gap: spacing.md }, hello: { fontSize: type.h2.fontSize, fontWeight: '700', color: colors.neutral900 }, eventPicker: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 }, eventChip: { paddingHorizontal: 12, paddingVertical: 8, borderRadius: radius.pill, borderWidth: 1, borderColor: colors.neutral200, maxWidth: 220, }, eventChipOn: { backgroundColor: colors.primary100, borderColor: colors.primary600 }, eventChipText: { color: colors.neutral700, fontSize: type.caption.fontSize }, eventChipTextOn: { color: colors.primary700, fontWeight: '700' }, eventHeaderTop: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 8 }, eventName: { flex: 1, fontSize: type.h3.fontSize, fontWeight: '700', color: colors.neutral900 }, eventMeta: { marginTop: 4, color: colors.neutral500, fontSize: type.caption.fontSize }, roleBadge: { alignSelf: 'flex-start', marginTop: 10, backgroundColor: colors.primary050, borderRadius: radius.pill, paddingHorizontal: 10, paddingVertical: 3, }, roleBadgeText: { color: colors.primary700, fontSize: type.caption.fontSize, fontWeight: '600' }, cardTitle: { fontSize: type.h3.fontSize, fontWeight: '600', color: colors.neutral900, marginBottom: 12 }, actions: { flexDirection: 'row', flexWrap: 'wrap', gap: spacing.md }, actionCard: { flexGrow: 1, flexBasis: '45%', backgroundColor: colors.white, borderWidth: 1, borderColor: colors.neutral200, borderRadius: radius.md, padding: spacing.md, gap: 8, minHeight: 96, justifyContent: 'center', }, actionLabel: { fontSize: type.body.fontSize, fontWeight: '600', color: colors.neutral700 }, stepper: { flexDirection: 'row', justifyContent: 'space-between' }, step: { alignItems: 'center', flex: 1, gap: 6 }, stepDot: { width: 28, height: 28, borderRadius: 14, backgroundColor: colors.neutral200, alignItems: 'center', justifyContent: 'center', }, stepDotText: { color: colors.white, fontWeight: '700', fontSize: type.caption.fontSize }, stepLabel: { fontSize: type.caption.fontSize, color: colors.neutral500 }, });