You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
7.1 KiB
181 lines
7.1 KiB
import { useEffect, useState } from 'react';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { StatusBar } from 'expo-status-bar';
|
|
import { colors } from '../../../src/theme';
|
|
import { Illustration } from '../ui/Illustration';
|
|
import { Modal } from '../ui/Modal';
|
|
|
|
type Step = 'guide' | 'location' | 'notify' | null;
|
|
|
|
const JOBS = [
|
|
{ company: '巴适伙伴', pos: '前端开发工程师', salary: '12-18K', city: '上海' },
|
|
{ company: '星河科技', pos: '鸿蒙开发工程师', salary: '15-22K', city: '上海' },
|
|
{ company: '云图网络', pos: '全栈工程师', salary: '13-20K', city: '杭州' },
|
|
{ company: '启明软件', pos: '数据分析师', salary: '10-16K', city: '深圳' },
|
|
];
|
|
|
|
const TABS = [
|
|
{ key: 'home', icon: 'home', label: '首页' },
|
|
{ key: 'msg', icon: 'chatbubble', label: '消息' },
|
|
{ key: 'me', icon: 'person', label: '我的' },
|
|
] as const;
|
|
|
|
export function P23Home() {
|
|
const [tab, setTab] = useState<(typeof TABS)[number]['key']>('home');
|
|
const [step, setStep] = useState<Step>('guide');
|
|
|
|
useEffect(() => {
|
|
setStep('guide');
|
|
}, []);
|
|
|
|
return (
|
|
<SafeAreaView style={styles.screen} edges={['top']}>
|
|
<StatusBar style="dark" />
|
|
|
|
<View style={styles.topBar}>
|
|
<Text style={styles.topTitle}>推荐职位</Text>
|
|
<Ionicons name="location" size={16} color={colors.primary} />
|
|
<Text style={styles.topCity}>上海</Text>
|
|
</View>
|
|
|
|
<ScrollView style={styles.list} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false}>
|
|
{JOBS.map((j) => (
|
|
<View key={j.company} style={styles.card}>
|
|
<Illustration name="logo" size={44} radius={10} />
|
|
<View style={styles.cardBody}>
|
|
<Text style={styles.pos}>{j.pos}</Text>
|
|
<Text style={styles.company}>{j.company}</Text>
|
|
</View>
|
|
<View style={styles.cardRight}>
|
|
<Text style={styles.salary}>{j.salary}</Text>
|
|
<View style={styles.cityTag}>
|
|
<Text style={styles.cityText}>{j.city}</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
))}
|
|
</ScrollView>
|
|
|
|
<View style={styles.tabBar}>
|
|
{TABS.map((t) => (
|
|
<Pressable key={t.key} style={styles.tab} onPress={() => setTab(t.key)}>
|
|
<Ionicons name={t.icon} size={22} color={tab === t.key ? colors.primary : colors.textHint} />
|
|
<Text style={[styles.tabLabel, tab === t.key && styles.tabLabelActive]}>{t.label}</Text>
|
|
</Pressable>
|
|
))}
|
|
</View>
|
|
|
|
{step === 'guide' && (
|
|
<View style={styles.guide}>
|
|
<View style={styles.guideCard}>
|
|
<Ionicons name="arrow-down" size={20} color={colors.primary} />
|
|
<Text style={styles.guideText}>点击查看职位详情</Text>
|
|
</View>
|
|
<Pressable style={styles.guideBtn} onPress={() => setStep('location')}>
|
|
<Text style={styles.guideBtnText}>知道了</Text>
|
|
</Pressable>
|
|
</View>
|
|
)}
|
|
|
|
<Modal
|
|
visible={step === 'location'}
|
|
title="允许获取位置"
|
|
onClose={() => setStep('notify')}
|
|
footer={
|
|
<View style={styles.modalBtns}>
|
|
<Pressable style={[styles.modalBtn, styles.modalBtnGhost]} onPress={() => setStep('notify')}>
|
|
<Text style={styles.modalBtnGhostText}>暂不</Text>
|
|
</Pressable>
|
|
<Pressable style={[styles.modalBtn, styles.modalBtnPrimary]} onPress={() => setStep('notify')}>
|
|
<Text style={styles.modalBtnPrimaryText}>允许</Text>
|
|
</Pressable>
|
|
</View>
|
|
}
|
|
>
|
|
<Text style={styles.modalBody}>开启定位可为你推荐附近的职位与机会。</Text>
|
|
</Modal>
|
|
|
|
<Modal
|
|
visible={step === 'notify'}
|
|
title="开启通知"
|
|
onClose={() => setStep(null)}
|
|
footer={
|
|
<View style={styles.modalBtns}>
|
|
<Pressable style={[styles.modalBtn, styles.modalBtnGhost]} onPress={() => setStep(null)}>
|
|
<Text style={styles.modalBtnGhostText}>暂不</Text>
|
|
</Pressable>
|
|
<Pressable style={[styles.modalBtn, styles.modalBtnPrimary]} onPress={() => setStep(null)}>
|
|
<Text style={styles.modalBtnPrimaryText}>允许</Text>
|
|
</Pressable>
|
|
</View>
|
|
}
|
|
>
|
|
<Text style={styles.modalBody}>开启通知可及时接收面试邀请与 Boss 消息。</Text>
|
|
</Modal>
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
screen: { flex: 1, backgroundColor: colors.pageBg },
|
|
topBar: { flexDirection: 'row', alignItems: 'center', gap: 6, paddingHorizontal: 20, paddingVertical: 12, backgroundColor: colors.white },
|
|
topTitle: { fontSize: 18, fontWeight: '800', color: colors.textPrimary, marginRight: 'auto' },
|
|
topCity: { fontSize: 13, color: colors.primary, fontWeight: '600' },
|
|
list: { flex: 1 },
|
|
listContent: { padding: 16, gap: 12 },
|
|
card: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 12,
|
|
backgroundColor: colors.white,
|
|
borderRadius: 14,
|
|
padding: 14,
|
|
borderWidth: 1,
|
|
borderColor: colors.border,
|
|
},
|
|
cardBody: { flex: 1, gap: 4 },
|
|
pos: { fontSize: 15, fontWeight: '700', color: colors.textPrimary },
|
|
company: { fontSize: 12, color: colors.textSecondary },
|
|
cardRight: { alignItems: 'flex-end', gap: 6 },
|
|
salary: { fontSize: 15, fontWeight: '700', color: colors.info },
|
|
cityTag: { backgroundColor: colors.primaryLight, paddingHorizontal: 8, paddingVertical: 2, borderRadius: 8 },
|
|
cityText: { fontSize: 11, color: colors.primaryText },
|
|
tabBar: {
|
|
flexDirection: 'row',
|
|
borderTopWidth: 1,
|
|
borderColor: colors.borderLight,
|
|
backgroundColor: colors.white,
|
|
paddingVertical: 8,
|
|
},
|
|
tab: { flex: 1, alignItems: 'center', gap: 2 },
|
|
tabLabel: { fontSize: 11, color: colors.textHint },
|
|
tabLabelActive: { color: colors.primary, fontWeight: '700' },
|
|
guide: {
|
|
...StyleSheet.absoluteFill,
|
|
backgroundColor: colors.scrim,
|
|
alignItems: 'center',
|
|
justifyContent: 'flex-start',
|
|
paddingTop: 150,
|
|
},
|
|
guideCard: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 6,
|
|
backgroundColor: colors.white,
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 10,
|
|
borderRadius: 12,
|
|
},
|
|
guideText: { fontSize: 14, fontWeight: '600', color: colors.textPrimary },
|
|
guideBtn: { marginTop: 16, backgroundColor: colors.primary, paddingHorizontal: 28, paddingVertical: 10, borderRadius: 20 },
|
|
guideBtnText: { color: colors.textInverse, fontWeight: '700' },
|
|
modalBtns: { flexDirection: 'row', gap: 12 },
|
|
modalBtn: { flex: 1, height: 44, borderRadius: 22, alignItems: 'center', justifyContent: 'center' },
|
|
modalBtnGhost: { backgroundColor: colors.borderLight },
|
|
modalBtnGhostText: { color: colors.textSecondary, fontWeight: '600' },
|
|
modalBtnPrimary: { backgroundColor: colors.primary },
|
|
modalBtnPrimaryText: { color: colors.textInverse, fontWeight: '700' },
|
|
modalBody: { fontSize: 14, color: colors.textSecondary, lineHeight: 22, textAlign: 'center' },
|
|
});
|
|
|