import { Ionicons } from '@expo/vector-icons';
import { useRouter } from 'expo-router';
import { useEffect, useState } from 'react';
import {
ActivityIndicator,
Pressable,
ScrollView,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { colors } from '../src/theme';
import { useAuth } from '../src/context/AuthContext';
import { useJobPreference } from '../src/hooks';
import type { JobPreference } from '../src/types';
/** 各维度可选项(用于岗位推荐匹配) */
const CITIES = ['北京', '上海', '广州', '深圳', '杭州', '成都', '武汉', '南京', '西安', '苏州'];
const SALARIES = ['不限', '5-10K', '10-20K', '20-30K', '30-50K', '50K以上'];
const WORK_TYPES = ['全职', '兼职', '实习', '远程'];
const STATUSES = ['积极求职中', '观望好机会', '在职暂不考虑'];
/* ===================== 子组件:单选项 chips ===================== */
function ChipGroup({
title,
options,
value,
onSelect,
}: {
title: string;
options: string[];
value: string;
onSelect: (v: string) => void;
}) {
return (
{title}
{options.map((opt) => {
const selected = opt === value;
return (
onSelect(opt)}
>
{opt}
);
})}
);
}
/* ===================== 子组件:四态 ===================== */
function Loading() {
return (
正在加载求职意向…
);
}
function ErrorState({ onRetry }: { onRetry: () => void }) {
return (
加载失败
点击重试
);
}
/* ===================== 页面 ===================== */
export default function JobPreferenceScreen() {
const router = useRouter();
const { completeCandidateSetup } = useAuth();
const { preference, loading, error, refresh, save } = useJobPreference();
const [form, setForm] = useState(null);
const [saving, setSaving] = useState(false);
useEffect(() => {
if (preference && !form) setForm(preference);
}, [preference, form]);
if (loading || !form) {
return (
);
}
if (error) {
return (
);
}
const canSave = form.position.trim().length > 0;
const update = (field: K, value: JobPreference[K]) => {
setForm((prev) => (prev ? { ...prev, [field]: value } : prev));
};
const handleSave = async () => {
if (!canSave || saving) return;
setSaving(true);
try {
await save(form);
completeCandidateSetup();
router.replace('/(tabs)/jobs');
} finally {
setSaving(false);
}
};
const handleSkip = () => {
router.replace('/(tabs)/jobs');
};
return (
设置求职意向
告诉我们你的期望,才能推荐更匹配的岗位
期望职位
update('position', v)}
placeholder="如:前端开发工程师"
placeholderTextColor={colors.textHint}
/>
update('city', v)}
/>
update('salary', v)}
/>
update('workType', v)}
/>
update('status', v)}
/>
{saving ? '保存中…' : '保存并进入求职端'}
稍后设置
);
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: colors.pageBg },
body: { padding: 20, paddingBottom: 24 },
center: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12 },
tip: { fontSize: 14, color: colors.textSecondary },
retryBtn: {
paddingHorizontal: 18,
paddingVertical: 8,
borderRadius: 16,
backgroundColor: colors.primaryLight,
},
retryText: { fontSize: 13, fontWeight: '600', color: colors.primaryText },
header: { marginBottom: 20 },
headerTitle: { fontSize: 22, fontWeight: '800', color: colors.textPrimary },
headerDesc: { fontSize: 13, color: colors.textSecondary, marginTop: 6 },
section: { marginBottom: 20 },
sectionTitle: { fontSize: 15, fontWeight: '700', color: colors.textPrimary, marginBottom: 10 },
input: {
height: 50,
borderRadius: 12,
borderWidth: 1,
borderColor: colors.border,
backgroundColor: colors.white,
paddingHorizontal: 14,
fontSize: 16,
color: colors.textPrimary,
},
chips: { flexDirection: 'row', flexWrap: 'wrap', gap: 10 },
chip: {
paddingHorizontal: 14,
paddingVertical: 9,
borderRadius: 18,
backgroundColor: colors.white,
borderWidth: 1,
borderColor: colors.border,
},
chipSelected: { backgroundColor: colors.primaryLight, borderColor: colors.primary },
chipText: { fontSize: 13, color: colors.textSecondary },
chipTextSelected: { color: colors.primaryText, fontWeight: '600' },
footer: {
paddingHorizontal: 20,
paddingVertical: 14,
backgroundColor: colors.white,
borderTopWidth: 1,
borderTopColor: colors.borderLight,
},
saveBtn: {
height: 50,
borderRadius: 25,
backgroundColor: colors.primaryBtn,
alignItems: 'center',
justifyContent: 'center',
},
saveBtnDisabled: { backgroundColor: colors.border, opacity: 0.7 },
saveText: { fontSize: 16, fontWeight: '700', color: colors.textInverse },
skipBtn: { alignItems: 'center', paddingVertical: 14 },
skipText: { fontSize: 14, color: colors.textHint },
});