import { Ionicons } from '@expo/vector-icons';
import { useRouter } from 'expo-router';
import {
ActivityIndicator,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useGameData } from '../src/hooks';
import { colors } from '../src/theme';
import type { GameLevel, GameLevelStatus, GameProgress } from '../src/types';
/** 关卡状态 → 样式配置 */
const LEVEL_STATUS_STYLE: Record<
GameLevelStatus,
{ bg: string; border: string; icon: string; text: string }
> = {
locked: {
bg: colors.borderLight,
border: colors.border,
icon: colors.textHint,
text: colors.textHint,
},
available: {
bg: colors.primaryLight,
border: colors.primaryBorder,
icon: colors.primary,
text: colors.primaryText,
},
completed: {
bg: colors.successLight,
border: colors.successBorder,
icon: colors.success,
text: colors.successText,
},
};
/** 根据进度计算关卡状态 */
function getLevelStatus(level: GameLevel, progress: GameProgress | null): GameLevelStatus {
if (!progress) return 'locked';
if (progress.results.some((r) => r.levelId === level.id && r.completed)) return 'completed';
if (progress.unlockedLevels.includes(level.id)) return 'available';
return 'locked';
}
/* ===================== 子组件:顶部导航 ===================== */
function Header({ onBack }: { onBack: () => void }) {
return (
求职通关
);
}
/* ===================== 子组件:进度条 ===================== */
function ProgressBar({ percent }: { percent: number }) {
return (
通关进度
{percent}%
);
}
/* ===================== 子组件:关卡卡片 ===================== */
function LevelCard({
level,
status,
onPress,
}: {
level: GameLevel;
status: GameLevelStatus;
onPress: () => void;
}) {
const theme = LEVEL_STATUS_STYLE[status];
const disabled = status === 'locked';
return (
第 {level.order} 关
{level.title}
{level.subtitle}
{status === 'completed' ? (
) : status === 'available' ? (
) : (
)}
);
}
/* ===================== 页面 ===================== */
export default function GameScreen() {
const router = useRouter();
const { levels, progress, loading, error, refresh } = useGameData();
return (
router.back()} />
{loading ? (
) : error ? (
加载失败,请重试
重试
) : levels.length === 0 ? (
暂无关卡数据
) : (
{levels.map((level) => {
const status = getLevelStatus(level, progress);
return (
router.push(`/game/level?id=${level.id}`)}
/>
);
})}
)}
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: colors.pageBg,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 8,
height: 48,
backgroundColor: colors.white,
borderBottomWidth: 1,
borderBottomColor: colors.borderLight,
},
headerBtn: {
width: 40,
height: 40,
alignItems: 'center',
justifyContent: 'center',
},
headerTitle: {
fontSize: 17,
fontWeight: '700',
color: colors.textPrimary,
},
scroll: {
flex: 1,
},
content: {
padding: 8,
paddingBottom: 24,
},
progressCard: {
backgroundColor: colors.white,
borderRadius: 8,
padding: 16,
marginBottom: 8,
},
progressHead: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 10,
},
progressLabel: {
fontSize: 15,
fontWeight: '700',
color: colors.textPrimary,
},
progressValue: {
fontSize: 15,
fontWeight: '700',
color: colors.primary,
},
progressTrack: {
height: 8,
borderRadius: 4,
backgroundColor: colors.border,
},
progressFill: {
height: 8,
borderRadius: 4,
backgroundColor: colors.primary,
},
levelsSection: {
gap: 8,
},
levelCard: {
flexDirection: 'row',
alignItems: 'center',
padding: 14,
borderRadius: 8,
borderWidth: 1,
backgroundColor: colors.white,
},
levelIconWrap: {
width: 44,
height: 44,
borderRadius: 22,
alignItems: 'center',
justifyContent: 'center',
},
levelBody: {
flex: 1,
marginLeft: 12,
},
levelOrder: {
fontSize: 12,
fontWeight: '600',
marginBottom: 2,
},
levelTitle: {
fontSize: 16,
fontWeight: '700',
},
levelSubtitle: {
marginTop: 2,
fontSize: 13,
},
levelRight: {
width: 36,
alignItems: 'center',
justifyContent: 'center',
},
stateBox: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
stateText: {
marginTop: 12,
fontSize: 14,
color: colors.textSecondary,
},
retryBtn: {
marginTop: 16,
paddingHorizontal: 24,
paddingVertical: 8,
borderRadius: 18,
backgroundColor: colors.primaryBtn,
},
retryText: {
fontSize: 13,
fontWeight: '600',
color: colors.white,
},
});