轻松聘
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.
 
 
 

78 lines
2.1 KiB

/**
* 星级打分 / 星级展示组件。
*
* 岗位评价(app/jobs/[id].tsx)与候选人反馈(app/application-detail.tsx)都要用,
* 所以提到 components 层只留一份 —— 两处各写一份的话,改星色或改最大星数时必然漏改一处。
*
* 只读态用「实心 / 描边」区分而不只靠颜色:色觉障碍用户也要能读出分数(WCAG 1.4.1)。
*/
import { Ionicons } from '@expo/vector-icons';
import { Pressable, StyleSheet, View } from 'react-native';
import { colors } from '../src/theme';
/**
* 星色。候选项详情、岗位评价页此前都用 compareOrange 画星,
* 这里沿用同一语义色,不新造 token。
*/
export const STAR_COLOR = colors.compareOrange;
export function RatingStars({
value,
max = 5,
size = 14,
onChange,
}: {
/** 当前分值,0 表示未评分 */
value: number;
/** 满星数,默认 5 */
max?: number;
size?: number;
/** 传了就是可点打分(编辑器内用),不传即只读展示 */
onChange?: (next: number) => void;
}) {
const readonly = !onChange;
return (
<View style={styles.row}>
{Array.from({ length: max }, (_, i) => {
const starValue = i + 1;
const filled = starValue <= value;
const star = (
<Ionicons
name={filled ? 'star' : 'star-outline'}
size={size}
color={filled ? STAR_COLOR : colors.borderStrong}
/>
);
if (readonly) {
return (
<View key={starValue} style={styles.cell}>
{star}
</View>
);
}
return (
<Pressable
key={starValue}
style={styles.cell}
hitSlop={6}
onPress={() => onChange(starValue)}
accessibilityRole="button"
accessibilityLabel={`打 ${starValue} 分`}
>
{star}
</Pressable>
);
})}
</View>
);
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center',
},
cell: {
paddingHorizontal: 1,
},
});