Files
digital-pilates/components/weight/WeightRecordCard.tsx
richarjiang 91df01bd79 feat(auth): 预加载用户数据并优化登录状态同步
- 在启动屏预加载用户 token 与资料,避免首页白屏
- 新增 rehydrateUserSync 同步注入 Redux,减少异步等待
- 登录页兼容 ERR_REQUEST_CANCELED 取消场景
- 各页面统一依赖 isLoggedIn 判断,移除冗余控制台日志
- 步数卡片与详情页改为实时拉取健康数据,不再缓存至 Redux
- 后台任务注册移至顶层,防止重复定义
- 体重记录、HeaderBar 等 UI 细节样式微调
2025-09-15 09:56:42 +08:00

179 lines
4.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { WeightHistoryItem } from '@/store/userSlice';
import { Ionicons } from '@expo/vector-icons';
import dayjs from 'dayjs';
import React, { useRef } from 'react';
import { Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { Swipeable } from 'react-native-gesture-handler';
interface WeightRecordCardProps {
record: WeightHistoryItem;
onPress?: (record: WeightHistoryItem) => void;
onDelete?: (recordId: string) => void;
weightChange?: number;
}
export const WeightRecordCard: React.FC<WeightRecordCardProps> = ({
record,
onPress,
onDelete,
weightChange = 0
}) => {
const swipeableRef = useRef<Swipeable>(null);
const colorScheme = useColorScheme();
const themeColors = Colors[colorScheme ?? 'light'];
// 处理删除操作
const handleDelete = () => {
Alert.alert(
'确认删除',
`确定要删除这条体重记录吗?此操作无法撤销。`,
[
{
text: '取消',
style: 'cancel',
},
{
text: '删除',
style: 'destructive',
onPress: () => {
const recordId = record.id || record.createdAt;
onDelete?.(recordId);
swipeableRef.current?.close();
},
},
]
);
};
// 渲染删除按钮
const renderRightActions = () => {
return (
<TouchableOpacity
style={styles.deleteButton}
onPress={handleDelete}
activeOpacity={0.8}
>
<Ionicons name="trash" size={20} color="#FFFFFF" />
<Text style={styles.deleteButtonText}></Text>
</TouchableOpacity>
);
};
return (
<Swipeable
ref={swipeableRef}
renderRightActions={renderRightActions}
rightThreshold={40}
overshootRight={false}
>
<View
style={[styles.recordCard]}
>
<View style={styles.recordHeader}>
<Text style={[styles.recordDateTime, { color: themeColors.textSecondary }]}>
{dayjs(record.createdAt).format('MM月DD日 HH:mm')}
</Text>
<TouchableOpacity
style={styles.recordEditButton}
onPress={() => onPress?.(record)}
>
<Ionicons name="create-outline" size={16} color="#FF9500" />
</TouchableOpacity>
</View>
<View style={styles.recordContent}>
<Text style={[styles.recordWeightLabel, { color: themeColors.textSecondary }]}></Text>
<Text style={[styles.recordWeightValue, { color: themeColors.text }]}>{record.weight}kg</Text>
{Math.abs(weightChange) > 0 && (
<View style={[
styles.weightChangeTag,
{ backgroundColor: weightChange < 0 ? '#E8F5E8' : '#FFF2E8' }
]}>
<Ionicons
name={weightChange < 0 ? "arrow-down" : "arrow-up"}
size={12}
color={weightChange < 0 ? Colors.light.accentGreen : '#FF9500'}
/>
<Text style={[
styles.weightChangeText,
{ color: weightChange < 0 ? Colors.light.accentGreen : '#FF9500' }
]}>
{Math.abs(weightChange).toFixed(1)}
</Text>
</View>
)}
</View>
</View>
</Swipeable>
);
};
const styles = StyleSheet.create({
recordCard: {
backgroundColor: '#ffffff',
borderRadius: 16,
padding: 20,
marginBottom: 12,
},
recordHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 12,
},
recordDateTime: {
fontSize: 14,
color: '#687076',
fontWeight: '500',
},
recordEditButton: {
padding: 6,
borderRadius: 8,
backgroundColor: 'rgba(255, 149, 0, 0.1)',
},
recordContent: {
flexDirection: 'row',
alignItems: 'center',
},
recordWeightLabel: {
fontSize: 16,
color: '#687076',
fontWeight: '500',
},
recordWeightValue: {
fontSize: 16,
fontWeight: '600',
color: '#192126',
marginLeft: 4,
flex: 1,
},
weightChangeTag: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
marginLeft: 12,
},
weightChangeText: {
fontSize: 12,
fontWeight: '600',
marginLeft: 2,
},
deleteButton: {
backgroundColor: '#EF4444',
justifyContent: 'center',
alignItems: 'center',
width: 80,
borderRadius: 16,
marginBottom: 12,
marginLeft: 8,
},
deleteButtonText: {
color: '#FFFFFF',
fontSize: 12,
fontWeight: '600',
marginTop: 4,
},
});