← back to Govarbitrage
apps/mobile/components/ScoreBadge.tsx
65 lines
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { Colors, Radius, Spacing, Typography } from "../constants/theme";
import { fmtScore } from "../lib/format";
interface Props {
label: string;
score: number | null | undefined;
size?: "sm" | "md" | "lg";
}
function scoreColor(score: number | null | undefined): string {
if (score == null || !Number.isFinite(score)) return Colors.neutral;
if (score >= 70) return Colors.scoreHigh;
if (score >= 40) return Colors.scoreMid;
return Colors.scoreLow;
}
export function ScoreBadge({ label, score, size = "md" }: Props) {
const color = scoreColor(score);
const sz = size === "lg" ? 44 : size === "md" ? 36 : 28;
const fontSize = size === "lg" ? Typography.sizes.lg : size === "md" ? Typography.sizes.base : Typography.sizes.xs;
return (
<View style={styles.container}>
<View
style={[
styles.circle,
{ width: sz, height: sz, borderRadius: sz / 2, borderColor: color },
]}
>
<Text style={[styles.value, { fontSize, color }]}>{fmtScore(score)}</Text>
</View>
<Text style={[styles.label, size === "sm" && styles.labelSm]}>{label}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
alignItems: "center",
gap: Spacing.xs,
},
circle: {
borderWidth: 2,
alignItems: "center",
justifyContent: "center",
backgroundColor: Colors.surface,
},
value: {
fontWeight: "700",
fontVariant: ["tabular-nums"],
},
label: {
fontSize: Typography.sizes.xs,
color: Colors.textMuted,
textAlign: "center",
textTransform: "uppercase",
letterSpacing: 0.5,
},
labelSm: {
fontSize: 9,
},
});