feat(history): HistoryScreen with TrackRow + EmptyState
This commit is contained in:
1 parent
cd278aa2b1
commit
139294a6bd
1 file changed
+38
-75
@@ -16,6 +16,8 @@ import {
|
||||
type ContinuousUsageBlock,
|
||||
} from '../training/continuousUsage';
|
||||
import { TrainingChart } from '../components/TrainingChart';
|
||||
import { TrackRow } from '../components/TrackRow';
|
||||
import { EmptyState } from '../components/EmptyState';
|
||||
import { colors, spacing, typography } from '../theme';
|
||||
|
||||
type HistoryMode = 'windows' | 'continuous' | 'range';
|
||||
@@ -360,46 +362,25 @@ function WindowHistory({
|
||||
</View>
|
||||
|
||||
<View style={styles.timeline}>
|
||||
{sessions.map(session => {
|
||||
{sessions.map((session, index) => {
|
||||
const isOpen = selectedId === session.id;
|
||||
return (
|
||||
<View key={session.id} style={styles.timelineNode}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => onOpenSession(session)}
|
||||
style={({ pressed }) => [
|
||||
styles.sessionStrip,
|
||||
pressed ? styles.pressed : null,
|
||||
<TrackRow
|
||||
accessibilityLabel={`Janela ${formatSessionDay(session.startedAt)} ${formatSessionHour(session.startedAt)}`}
|
||||
day={formatSessionDay(session.startedAt)}
|
||||
hour={formatSessionHour(session.startedAt)}
|
||||
isOpen={isOpen}
|
||||
meta={`${formatDuration(session.durationMs)} · ${session.sampleCount} amostras`}
|
||||
metrics={[
|
||||
{ label: `MÉD ${session.averageBpm}` },
|
||||
{ label: `PICO ${session.peakBpm}`, tone: 'hot' as const },
|
||||
{ label: `MIN ${session.minBpm}` },
|
||||
]}
|
||||
onPress={() => onOpenSession(session)}
|
||||
title={session.deviceName || 'Cinta cardíaca BLE'}
|
||||
trackNumber={index + 1}
|
||||
>
|
||||
<View style={styles.dateBlock}>
|
||||
<Text style={styles.sessionDay}>
|
||||
{formatSessionDay(session.startedAt)}
|
||||
</Text>
|
||||
<Text style={styles.sessionHour}>
|
||||
{formatSessionHour(session.startedAt)}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.sessionBody}>
|
||||
<Text style={styles.sessionTitle}>
|
||||
{session.deviceName || 'Cinta cardíaca BLE'}
|
||||
</Text>
|
||||
<Text style={styles.sessionMeta}>
|
||||
{formatDuration(session.durationMs)} · {session.sampleCount}{' '}
|
||||
amostras · toque para detalhes
|
||||
</Text>
|
||||
<View style={styles.metricLine}>
|
||||
<Text style={styles.metricText}>
|
||||
MÉD {session.averageBpm}
|
||||
</Text>
|
||||
<Text style={styles.metricTextHot}>
|
||||
PICO {session.peakBpm}
|
||||
</Text>
|
||||
<Text style={styles.metricText}>MIN {session.minBpm}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{isOpen ? <OpenIcon /> : <ClosedIcon />}
|
||||
</Pressable>
|
||||
|
||||
{isOpen ? (
|
||||
<WindowDetail
|
||||
@@ -409,6 +390,7 @@ function WindowHistory({
|
||||
zones={zones}
|
||||
/>
|
||||
) : null}
|
||||
</TrackRow>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
@@ -465,50 +447,30 @@ function ContinuousHistory({
|
||||
</View>
|
||||
|
||||
<View style={styles.timeline}>
|
||||
{blocks.map(block => {
|
||||
{blocks.map((block, index) => {
|
||||
const isOpen = selectedUsageId === block.id;
|
||||
return (
|
||||
<View key={block.id} style={styles.timelineNode}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => onOpenBlock(block)}
|
||||
style={({ pressed }) => [
|
||||
styles.sessionStrip,
|
||||
pressed ? styles.pressed : null,
|
||||
<TrackRow
|
||||
accessibilityLabel={`Uso contínuo ${formatSessionDay(block.startedAt)}`}
|
||||
day={formatSessionDay(block.startedAt)}
|
||||
hour={formatSessionHour(block.startedAt)}
|
||||
isOpen={isOpen}
|
||||
meta={`${formatUsageRange(block)} · ${block.sampleCount} amostras`}
|
||||
metrics={[
|
||||
{ label: `MÉD ${block.averageBpm}` },
|
||||
{ label: `PICO ${block.peakBpm}`, tone: 'hot' as const },
|
||||
{ label: `MIN ${block.minBpm}` },
|
||||
]}
|
||||
onPress={() => onOpenBlock(block)}
|
||||
title={block.deviceName || 'Uso contínuo'}
|
||||
trackNumber={index + 1}
|
||||
>
|
||||
<View style={styles.dateBlock}>
|
||||
<Text style={styles.sessionDay}>
|
||||
{formatSessionDay(block.startedAt)}
|
||||
</Text>
|
||||
<Text style={styles.sessionHour}>
|
||||
{formatSessionHour(block.startedAt)}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.sessionBody}>
|
||||
<Text style={styles.sessionTitle}>
|
||||
{block.deviceName || 'Uso contínuo'}
|
||||
</Text>
|
||||
<Text style={styles.sessionMeta}>
|
||||
{formatUsageRange(block)} · {block.sampleCount} amostras ·
|
||||
toque para detalhes
|
||||
</Text>
|
||||
<View style={styles.metricLine}>
|
||||
<Text style={styles.metricText}>
|
||||
MÉD {block.averageBpm}
|
||||
</Text>
|
||||
<Text style={styles.metricTextHot}>
|
||||
PICO {block.peakBpm}
|
||||
</Text>
|
||||
<Text style={styles.metricText}>MIN {block.minBpm}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{isOpen ? <OpenIcon /> : <ClosedIcon />}
|
||||
</Pressable>
|
||||
|
||||
{isOpen && selectedBlock ? (
|
||||
<UsageDetail block={selectedBlock} />
|
||||
) : null}
|
||||
</TrackRow>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
@@ -591,11 +553,12 @@ function EmptyHistory({
|
||||
readonly title: string;
|
||||
}) {
|
||||
return (
|
||||
<View style={styles.emptyBlock}>
|
||||
<Text style={styles.eyebrow}>{eyebrow}</Text>
|
||||
<Text style={styles.emptyTitle}>{title}</Text>
|
||||
<Text style={styles.copy}>{copy}</Text>
|
||||
</View>
|
||||
<EmptyState
|
||||
copy={copy}
|
||||
eyebrow={eyebrow}
|
||||
title={title}
|
||||
tone={eyebrow === 'ANÁLISE BLOQUEADA' ? 'red' : 'amber'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user