import { Ionicons } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import {
ActivityIndicator,
Alert,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useOfferCompareData } from '../../src/hooks';
import { colors, headerGradientSolid } from '../../src/theme';
import type { OfferBenefitGroup, OfferItem, OfferScore, WorkLifeBalanceRow } from '../../src/types';
/* ===================== 子组件 ===================== */
/** 顶部导航:返回 + 标题 + 编辑 */
function Header({ onBack, onEdit }: { onBack: () => void; onEdit?: () => void }) {
return (
Offer对比
编辑
);
}
/** 单个 Offer 卡片 */
function OfferCard({ offer, selected }: { offer: OfferItem; selected: boolean }) {
return (
{offer.company}
{selected && }
{offer.position}
{offer.salary}
);
}
/** 添加 Offer */
function AddOfferCard({ onPress }: { onPress: () => void }) {
return (
添加Offer
);
}
/** 星级评分 */
function StarRating({ stars }: { stars: number }) {
return (
{[1, 2, 3, 4, 5].map((i) => (
))}
);
}
/** 综合评分对比 */
function ScoreComparison({ offers, scores }: { offers: OfferItem[]; scores: OfferScore[] }) {
return (
综合评分对比
{offers.map((offer, index) => {
const score = scores[index];
if (!score) return null;
const isWinner = score.score === Math.max(...scores.map((s) => s.score));
return (
{score.score}
{score.level}
推荐指数
);
})}
);
}
/** 分组对比表格 */
function BenefitComparison({ offers, groups }: { offers: OfferItem[]; groups: OfferBenefitGroup[] }) {
return (
薪资福利对比
{/* 表头:公司名 */}
{offers.map((offer) => (
{offer.company}
))}
{groups.map((group) => (
{group.title}
{group.rows.map((row) => (
{row.label}
{row.values.map((value, colIndex) => {
const highlight = row.highlights?.[colIndex];
return (
{value ?? '-'}
);
})}
))}
))}
);
}
/** 工作生活平衡 */
function WorkLifeBalance({ offers, rows }: { offers: OfferItem[]; rows: WorkLifeBalanceRow[] }) {
return (
工作生活平衡
{offers.map((offer) => (
{offer.company}
))}
{rows.map((row) => (
{row.label}
{row.values.map((value, colIndex) => {
const highlight = row.highlights?.[colIndex];
return (
{value}
);
})}
))}
);
}
/** AI 智能建议 */
function AISuggestionCard({ summary, detail, reportAction }: { summary: string; detail: string; reportAction: string }) {
return (
AI智能建议
{summary}
{detail}
Alert.alert('AI智能建议', '完整建议报告功能开发中,敬请期待')}
>
{reportAction}
);
}
/* ===================== 页面 ===================== */
/**
* Offer 对比页:对比已收到 Offer 的薪资、福利、工作生活平衡与 AI 建议
*/
export default function OfferCompareScreen() {
const router = useRouter();
const { data, offers, scores, benefitGroups, workLifeBalance, aiSuggestion, actions, loading, error, refresh } =
useOfferCompareData();
if (error) {
return (
router.back()} />
加载失败,请重试
重试
);
}
if (loading || !data) {
return (
router.back()} />
正在加载 Offer 对比…
);
}
return (
router.back()} />
{/* Offer 卡片头部 */}
{offers.map((offer) => (
))}
Alert.alert('添加Offer', 'Offer添加功能开发中,敬请期待')}
/>
{/* 综合评分对比 */}
{/* 薪资福利对比 */}
{/* 工作生活平衡 */}
{/* AI 智能建议 */}
{aiSuggestion && (
)}
{/* 底部操作栏 */}
Alert.alert('导出对比报告', '报告导出功能开发中,敬请期待')}
>
{actions?.exportLabel ?? '导出对比报告'}
Alert.alert('接受Offer', 'Offer确认功能开发中,敬请期待')}
>
{actions?.acceptLabel ?? '接受Offer'}
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: colors.pageBg,
},
/* ---- 顶部导航 ---- */
header: {
height: 48,
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 8,
backgroundColor: colors.pageBg,
},
headerBtn: {
width: 48,
height: 40,
alignItems: 'center',
justifyContent: 'center',
},
headerTitle: {
flex: 1,
textAlign: 'center',
fontSize: 17,
fontWeight: '700',
color: colors.textPrimary,
},
headerEdit: {
fontSize: 14,
color: colors.primary,
fontWeight: '600',
},
/* ---- 状态 ---- */
stateWrap: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 24,
},
stateText: {
marginTop: 12,
fontSize: 14,
color: colors.textSecondary,
textAlign: 'center',
},
retryBtn: {
marginTop: 16,
paddingHorizontal: 24,
paddingVertical: 8,
borderRadius: 18,
backgroundColor: colors.primaryBtn,
},
retryText: {
fontSize: 13,
fontWeight: '600',
color: colors.white,
},
/* ---- 页面内容 ---- */
scroll: {
flex: 1,
},
content: {
paddingHorizontal: 12,
paddingTop: 8,
paddingBottom: 12,
},
bottomGap: {
height: 80,
},
/* ---- Offer 卡片 ---- */
offerList: {
gap: 10,
paddingVertical: 4,
paddingHorizontal: 4,
},
offerCard: {
width: 150,
padding: 14,
borderRadius: 12,
backgroundColor: colors.white,
borderWidth: 1,
borderColor: colors.border,
},
offerCardSelected: {
borderColor: colors.primary,
backgroundColor: colors.primaryLight,
},
offerCardTop: {
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'space-between',
},
offerCompany: {
flex: 1,
fontSize: 14,
fontWeight: '700',
color: colors.textPrimary,
},
checkCircle: {
width: 18,
height: 18,
borderRadius: 9,
borderWidth: 1.5,
borderColor: colors.borderStrong,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 6,
},
checkCircleActive: {
backgroundColor: colors.primary,
borderColor: colors.primary,
},
offerPosition: {
marginTop: 6,
fontSize: 12,
color: colors.textSecondary,
},
offerSalary: {
marginTop: 10,
fontSize: 16,
fontWeight: '800',
},
addOfferCard: {
width: 80,
padding: 12,
borderRadius: 12,
borderWidth: 1,
borderStyle: 'dashed',
borderColor: colors.borderStrong,
alignItems: 'center',
justifyContent: 'center',
},
addOfferText: {
marginTop: 6,
fontSize: 12,
color: colors.textHint,
},
/* ---- 通用卡片与分区标题 ---- */
card: {
backgroundColor: colors.white,
borderRadius: 12,
padding: 16,
marginTop: 12,
},
sectionHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 14,
},
sectionBar: {
width: 4,
height: 16,
borderRadius: 2,
backgroundColor: colors.primary,
marginRight: 8,
},
sectionTitle: {
fontSize: 16,
fontWeight: '700',
color: colors.textPrimary,
},
/* ---- 综合评分对比 ---- */
scoreRow: {
flexDirection: 'row',
justifyContent: 'space-around',
paddingTop: 4,
},
scoreCol: {
alignItems: 'center',
flex: 1,
},
scoreNum: {
fontSize: 44,
fontWeight: '800',
color: colors.textSecondary,
},
scoreNumWinner: {
color: colors.success,
},
scoreMeta: {
flexDirection: 'row',
alignItems: 'center',
marginTop: 6,
gap: 6,
},
scoreLevel: {
fontSize: 13,
fontWeight: '700',
},
starRow: {
flexDirection: 'row',
},
starIcon: {
marginHorizontal: 1,
},
scoreHint: {
marginTop: 6,
fontSize: 11,
color: colors.textHint,
},
/* ---- 表格 ---- */
tableHeaderRow: {
flexDirection: 'row',
alignItems: 'center',
paddingBottom: 10,
borderBottomWidth: 1,
borderBottomColor: colors.borderLight,
},
tableRow: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 10,
borderBottomWidth: 1,
borderBottomColor: colors.borderLight,
},
tableLabelCell: {
width: 88,
},
tableLabelText: {
width: 88,
fontSize: 13,
color: colors.textSecondary,
},
tableValueCell: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 8,
marginHorizontal: 2,
borderRadius: 8,
},
tableHeaderText: {
fontSize: 13,
fontWeight: '600',
color: colors.textPrimary,
textAlign: 'center',
},
tableValueText: {
fontSize: 13,
color: colors.textPrimary,
textAlign: 'center',
},
tableValueTextHighlight: {
color: colors.primaryText,
fontWeight: '700',
},
tableValueTextSuccess: {
color: colors.successText,
fontWeight: '700',
},
offerDot: {
width: 6,
height: 6,
borderRadius: 3,
marginRight: 4,
},
groupTitle: {
marginTop: 14,
marginBottom: 8,
fontSize: 14,
fontWeight: '700',
color: colors.textPrimary,
},
/* ---- AI 建议 ---- */
aiCard: {
marginTop: 12,
borderRadius: 12,
padding: 16,
},
aiHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10,
},
aiTitle: {
marginLeft: 6,
fontSize: 16,
fontWeight: '700',
color: colors.textInverse,
},
aiSummary: {
fontSize: 14,
fontWeight: '700',
color: colors.textInverse,
lineHeight: 20,
},
aiDetail: {
marginTop: 8,
fontSize: 13,
color: colors.textInverse,
opacity: 0.9,
lineHeight: 19,
},
aiReportBtn: {
marginTop: 12,
flexDirection: 'row',
alignItems: 'center',
},
aiReportText: {
fontSize: 13,
color: colors.textInverse,
fontWeight: '600',
},
/* ---- 底部操作栏 ---- */
actionBar: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 12,
paddingTop: 10,
paddingBottom: 16,
backgroundColor: colors.white,
borderTopWidth: 1,
borderTopColor: colors.borderLight,
gap: 10,
},
exportBtn: {
flex: 1,
height: 44,
borderRadius: 22,
borderWidth: 1,
borderColor: colors.border,
alignItems: 'center',
justifyContent: 'center',
},
exportText: {
fontSize: 14,
fontWeight: '600',
color: colors.textPrimary,
},
acceptBtn: {
flex: 1.4,
height: 44,
borderRadius: 22,
backgroundColor: colors.primaryBtn,
alignItems: 'center',
justifyContent: 'center',
},
acceptText: {
fontSize: 14,
fontWeight: '700',
color: colors.white,
},
});