eletrotupi / tcc/ frontend/components/history/SleepRecordCard.tsxca6234de503f574e5e6cd3a52e58f2d5b6c253f2
2.9 KB | 117 lines Raw
1
import { View, Text, StyleSheet } from 'react-native'
2
import { MaterialIcons } from '@expo/vector-icons'
3
import { Card } from '@/components/ui/Cards'
4
import { Badge } from '@/components/ui/Badge'
5
import type { SleepRecord } from '@/lib/api'
6
import { Spacing } from '@/constants/theme';
7
import { router } from 'expo-router'
8

9
function sleepBadge(hours: number) {
10
  if (hours >= 7) return { label: 'Excelente', variant: 'green'  } as const
11
  if (hours >= 5) return { label: 'Regular', variant: 'yellow' } as const
12

13
  return {
14
    label: 'Ruim', variant: 'red'
15
  } as const
16
}
17

18
// TODO: Move this into the time utilities
19
function formatDuration(average: number) {
20
  const h = Math.floor(average)
21
  const m = Math.round((average - h) * 60)
22
  return `${h}h ${m.toString().padStart(2, '0')}min`
23
}
24

25
type Props = { card: HistoryCard & { raw: SleepRecord } }
26

27
export function SleepRecordCard({ card }: Props) {
28
  const badge    = sleepBadge(card.raw.average)
29
  const duration = formatDuration(card.raw.average)
30

31
  const time     = new Date(card.timestamp)
32
    .toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })
33

34
  return (
35
    <Card style={styles.card} onPress={() => router.push(`/sleep/${card.raw.id}`)}>
36
      <View style={styles.row}>
37
        <View style={[styles.iconWrap, { backgroundColor: '#ede9fe' }]}>
38
          <MaterialIcons name="bedtime" size={22} color="#7c3aed" />
39
        </View>
40
        <View style={styles.body}>
41
          <View style={styles.titleRow}>
42
            <Text style={styles.title}>Sono</Text>
43
            <Text style={styles.time}>{time}</Text>
44
          </View>
45
          <View style={styles.durationRow}>
46
            <Text style={styles.duration}>{duration}</Text>
47
          </View>
48
          {card.raw.annotations ? (
49
            <Text style={styles.summary} numberOfLines={2}>
50
              {card.raw.annotations.trim()}
51
            </Text>
52
          ) : null}
53
          <Badge label={badge.label} variant={badge.variant} style={styles.badge} />
54
        </View>
55
      </View>
56
    </Card>
57
  )
58
}
59

60
const styles = StyleSheet.create({
61
  card: {
62
    padding: Spacing.cardGap
63
  },
64
  row:         {
65
    flexDirection: 'row',
66
    alignItems: 'flex-start',
67
    gap: 12
68
  },
69
  iconWrap: {
70
    width: 40,
71
    height: 40,
72
    borderRadius: 20,
73
    alignItems: 'center',
74
    justifyContent: 'center',
75
    marginTop: 1
76
  },
77
  body: {
78
    flex: 1
79
  },
80
  titleRow: {
81
    flexDirection: 'row',
82
    justifyContent: 'space-between',
83
    alignItems: 'center',
84
    marginBottom: 4
85
  },
86
  title: {
87
    fontSize: 15,
88
    fontWeight: '600'
89
  },
90
  time: {
91
    fontSize: 13,
92
    opacity: 0.45
93
  },
94
  durationRow: {
95
    flexDirection: 'row',
96
    alignItems: 'center',
97
    gap: 8,
98
    marginBottom: 4
99
  },
100
  duration: {
101
    fontSize: 13,
102
    fontWeight: '500',
103
    opacity: 0.75
104
  },
105
  summary: {
106
    fontSize: 13,
107
    opacity: 0.6,
108
    lineHeight: 18,
109
    marginTop: 4,
110
    fontStyle: 'italic'
111
  },
112
  badge: {
113
    alignSelf: 'flex-start',
114
    marginTop: 4,
115
    maxWidth: '50%'
116
  },
117
})