feat: add fat mass + muscle mass curves to chart, limit to last 30 days
This commit is contained in:
parent
b9b800f628
commit
1275a229f2
1 changed files with 55 additions and 7 deletions
|
|
@ -5,6 +5,12 @@ import { Measurement } from '../types'
|
||||||
|
|
||||||
type Props = { measurements: Measurement[] }
|
type Props = { measurements: Measurement[] }
|
||||||
|
|
||||||
|
const COLORS = {
|
||||||
|
weight: '#4CAF50',
|
||||||
|
fatMass: '#FF9800',
|
||||||
|
muscleMass: '#2196F3',
|
||||||
|
}
|
||||||
|
|
||||||
export default function WeightChart({ measurements }: Props) {
|
export default function WeightChart({ measurements }: Props) {
|
||||||
if (measurements.length < 2) {
|
if (measurements.length < 2) {
|
||||||
return null
|
return null
|
||||||
|
|
@ -14,34 +20,72 @@ export default function WeightChart({ measurements }: Props) {
|
||||||
(a, b) => new Date(a.measuredAt).getTime() - new Date(b.measuredAt).getTime()
|
(a, b) => new Date(a.measuredAt).getTime() - new Date(b.measuredAt).getTime()
|
||||||
)
|
)
|
||||||
|
|
||||||
const labels = sorted.map(m => {
|
const cutoff = new Date(sorted[sorted.length - 1].measuredAt)
|
||||||
|
cutoff.setDate(cutoff.getDate() - 30)
|
||||||
|
const filtered = sorted.filter(m => new Date(m.measuredAt) >= cutoff)
|
||||||
|
const dataPoints = filtered.length >= 2 ? filtered : sorted
|
||||||
|
|
||||||
|
const labels = dataPoints.map(m => {
|
||||||
const d = new Date(m.measuredAt)
|
const d = new Date(m.measuredAt)
|
||||||
return `${d.getDate()}/${d.getMonth() + 1}`
|
return `${d.getDate()}/${d.getMonth() + 1}`
|
||||||
})
|
})
|
||||||
const data = sorted.map(m => m.weight)
|
|
||||||
|
const labelStep = labels.length > 8 ? Math.ceil(labels.length / 8) : 1
|
||||||
|
const sparseLabels = labels.map((l, i) => (i % labelStep === 0 ? l : ''))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.title}>Gewichtsgrafiek</Text>
|
<Text style={styles.title}>Gewicht & Lichaamssamenstelling</Text>
|
||||||
<LineChart
|
<LineChart
|
||||||
data={{
|
data={{
|
||||||
labels: labels.length > 10 ? labels.filter((_, i) => i % Math.ceil(labels.length / 10) === 0) : labels,
|
labels: sparseLabels,
|
||||||
datasets: [{ data }],
|
datasets: [
|
||||||
|
{
|
||||||
|
data: dataPoints.map(m => m.weight),
|
||||||
|
color: () => COLORS.weight,
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: dataPoints.map(m => m.fatMass),
|
||||||
|
color: () => COLORS.fatMass,
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: dataPoints.map(m => m.muscleMass),
|
||||||
|
color: () => COLORS.muscleMass,
|
||||||
|
strokeWidth: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
}}
|
}}
|
||||||
width={Dimensions.get('window').width - 32}
|
width={Dimensions.get('window').width - 32}
|
||||||
height={220}
|
height={240}
|
||||||
yAxisSuffix=" kg"
|
yAxisSuffix=" kg"
|
||||||
chartConfig={{
|
chartConfig={{
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#ffffff',
|
||||||
backgroundGradientFrom: '#ffffff',
|
backgroundGradientFrom: '#ffffff',
|
||||||
backgroundGradientTo: '#ffffff',
|
backgroundGradientTo: '#ffffff',
|
||||||
decimalPlaces: 1,
|
decimalPlaces: 1,
|
||||||
color: (opacity = 1) => `rgba(76, 175, 80, ${opacity})`,
|
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
|
||||||
labelColor: () => '#666',
|
labelColor: () => '#666',
|
||||||
|
propsForDots: { r: '3' },
|
||||||
}}
|
}}
|
||||||
bezier
|
bezier
|
||||||
style={styles.chart}
|
style={styles.chart}
|
||||||
/>
|
/>
|
||||||
|
<View style={styles.legend}>
|
||||||
|
<View style={styles.legendItem}>
|
||||||
|
<View style={[styles.legendDot, { backgroundColor: COLORS.weight }]} />
|
||||||
|
<Text style={styles.legendLabel}>Gewicht</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.legendItem}>
|
||||||
|
<View style={[styles.legendDot, { backgroundColor: COLORS.fatMass }]} />
|
||||||
|
<Text style={styles.legendLabel}>Vetmassa</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.legendItem}>
|
||||||
|
<View style={[styles.legendDot, { backgroundColor: COLORS.muscleMass }]} />
|
||||||
|
<Text style={styles.legendLabel}>Spiermassa</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -50,4 +94,8 @@ const styles = StyleSheet.create({
|
||||||
container: { marginHorizontal: 16, marginBottom: 16 },
|
container: { marginHorizontal: 16, marginBottom: 16 },
|
||||||
title: { fontSize: 18, fontWeight: '700', marginBottom: 8 },
|
title: { fontSize: 18, fontWeight: '700', marginBottom: 8 },
|
||||||
chart: { borderRadius: 12 },
|
chart: { borderRadius: 12 },
|
||||||
|
legend: { flexDirection: 'row', justifyContent: 'center', gap: 16, marginTop: 8 },
|
||||||
|
legendItem: { flexDirection: 'row', alignItems: 'center', gap: 4 },
|
||||||
|
legendDot: { width: 10, height: 10, borderRadius: 5 },
|
||||||
|
legendLabel: { fontSize: 12, color: '#666' },
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue