diff --git a/src/components/WeightChart.tsx b/src/components/WeightChart.tsx
index 7ea663f..f2f743d 100644
--- a/src/components/WeightChart.tsx
+++ b/src/components/WeightChart.tsx
@@ -11,50 +11,11 @@ const COLORS = {
muscleMass: '#2196F3',
}
-function SingleChart({
- title,
- data,
- labels,
- color,
- unit,
-}: {
- title: string
- data: number[]
- labels: string[]
- color: string
- unit: string
-}) {
- return (
-
- {title}
- color, strokeWidth: 2 }] }}
- width={Dimensions.get('window').width - 32}
- height={180}
- yAxisSuffix={unit}
- chartConfig={{
- backgroundColor: '#ffffff',
- backgroundGradientFrom: '#ffffff',
- backgroundGradientTo: '#ffffff',
- decimalPlaces: 1,
- color: (opacity = 1) => `rgba(${hexToRgb(color)}, ${opacity})`,
- labelColor: () => '#666',
- propsForDots: { r: '3' },
- }}
- bezier
- style={styles.chart}
- withInnerLines={false}
- fromZero={false}
- />
-
- )
-}
-
-function hexToRgb(hex: string): string {
- const r = parseInt(hex.slice(1, 3), 16)
- const g = parseInt(hex.slice(3, 5), 16)
- const b = parseInt(hex.slice(5, 7), 16)
- return `${r}, ${g}, ${b}`
+function normalize(values: number[]): number[] {
+ const min = Math.min(...values)
+ const max = Math.max(...values)
+ if (max === min) return values.map(() => 50)
+ return values.map(v => ((v - min) / (max - min)) * 100)
}
export default function WeightChart({ measurements }: Props) {
@@ -70,6 +31,8 @@ export default function WeightChart({ measurements }: Props) {
cutoff.setDate(cutoff.getDate() - 30)
const filtered = sorted.filter(m => new Date(m.measuredAt) >= cutoff)
const dataPoints = filtered.length >= 2 ? filtered : sorted
+ const latest = dataPoints[dataPoints.length - 1]
+ const previous = dataPoints.length > 1 ? dataPoints[dataPoints.length - 2] : null
const labels = dataPoints.map(m => {
const d = new Date(m.measuredAt)
@@ -79,33 +42,96 @@ export default function WeightChart({ measurements }: Props) {
const labelStep = labels.length > 8 ? Math.ceil(labels.length / 8) : 1
const sparseLabels = labels.map((l, i) => (i % labelStep === 0 ? l : ''))
+ const weightData = dataPoints.map(m => m.weight)
+ const fatData = dataPoints.map(m => m.fatMass)
+ const muscleData = dataPoints.map(m => m.muscleMass)
+
return (
Voortgang (30 dagen)
-
- m.weight)}
- labels={sparseLabels}
- color={COLORS.weight}
- unit=" kg"
+ COLORS.weight, strokeWidth: 2 },
+ { data: normalize(fatData), color: () => COLORS.fatMass, strokeWidth: 2 },
+ { data: normalize(muscleData), color: () => COLORS.muscleMass, strokeWidth: 2 },
+ ],
+ }}
+ width={Dimensions.get('window').width - 32}
+ height={220}
+ chartConfig={{
+ backgroundColor: '#ffffff',
+ backgroundGradientFrom: '#ffffff',
+ backgroundGradientTo: '#ffffff',
+ decimalPlaces: 0,
+ color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
+ labelColor: () => 'transparent',
+ propsForDots: { r: '3' },
+ propsForLabels: { fontSize: 9 },
+ }}
+ bezier
+ style={styles.chart}
+ withInnerLines={false}
+ fromZero={false}
/>
- m.fatMass)}
- labels={sparseLabels}
- color={COLORS.fatMass}
- unit=" kg"
- />
+
+
+
+
+
+
+ )
+}
- m.muscleMass)}
- labels={sparseLabels}
- color={COLORS.muscleMass}
- unit=" kg"
- />
+function MetricInfo({
+ color,
+ label,
+ value,
+ prev,
+ unit,
+}: {
+ color: string
+ label: string
+ value: number
+ prev?: number
+ unit: string
+}) {
+ const diff = prev !== undefined ? value - prev : 0
+ const sign = diff > 0 ? '+' : ''
+ return (
+
+
+
+ {label}
+
+
+ {value.toFixed(1)} {unit}
+ {prev !== undefined && (
+
+ {' '}{sign}{diff.toFixed(1)}
+
+ )}
+
)
}
@@ -113,7 +139,12 @@ export default function WeightChart({ measurements }: Props) {
const styles = StyleSheet.create({
container: { marginHorizontal: 16, marginBottom: 16 },
title: { fontSize: 18, fontWeight: '700', marginBottom: 8 },
- chartBlock: { marginBottom: 12 },
- chartTitle: { fontSize: 13, fontWeight: '600', color: '#555', marginBottom: 4, marginLeft: 4 },
chart: { borderRadius: 12 },
+ legend: { flexDirection: 'row', justifyContent: 'space-around', marginTop: 8, gap: 8 },
+ metricItem: { alignItems: 'center', flex: 1 },
+ metricRow: { flexDirection: 'row', alignItems: 'center', gap: 4, marginBottom: 2 },
+ dot: { width: 8, height: 8, borderRadius: 4 },
+ metricLabel: { fontSize: 11, color: '#888' },
+ metricValue: { fontSize: 13, fontWeight: '600', color: '#333' },
+ metricDiff: { fontSize: 11, color: '#999' },
})