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

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

15
  return {
16
    label: 'Ruim', variant: 'red'
17
  } as const
18
}
19

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

27
type Props = { card: HistoryCard & { raw: SleepRecord } }
28

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

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

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

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