Files
digital-pilates/components/weight/WeightRecordCard.tsx
richarjiang bca6670390 Add Chinese translations for medication management and personal settings
- Introduced new translation files for medication, personal, and weight management in Chinese.
- Updated the main index file to include the new translation modules.
- Enhanced the medication type definitions to include 'ointment'.
- Refactored workout type labels to utilize i18n for better localization support.
- Improved sleep quality descriptions and recommendations with i18n integration.
2025-11-28 17:29:51 +08:00

231 lines
5.9 KiB
TypeScript

import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useI18n } from '@/hooks/useI18n';
import { WeightHistoryItem } from '@/store/userSlice';
import { Ionicons } from '@expo/vector-icons';
import dayjs from 'dayjs';
import React, { useRef } from 'react';
import { Alert, Image, 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 { t } = useI18n();
const swipeableRef = useRef<Swipeable>(null);
const colorScheme = useColorScheme();
const themeColors = Colors[colorScheme ?? 'light'];
// 处理删除操作
const handleDelete = () => {
Alert.alert(
t('weightRecords.card.deleteConfirmTitle'),
t('weightRecords.card.deleteConfirmMessage'),
[
{
text: t('weightRecords.card.cancelButton'),
style: 'cancel',
},
{
text: t('weightRecords.card.deleteButton'),
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" />
</TouchableOpacity>
);
};
return (
<View style={styles.cardContainer}>
<Swipeable
ref={swipeableRef}
renderRightActions={renderRightActions}
rightThreshold={40}
overshootRight={false}
>
<View style={styles.recordCard}>
<View style={styles.leftContent}>
<View style={styles.iconContainer}>
<Image
source={require('@/assets/images/icons/iconWeight.png')}
style={styles.icon}
/>
</View>
<View style={styles.textContent}>
<View style={styles.dateTimeContainer}>
<Text style={styles.dateText}>
{dayjs(record.createdAt).format('MM-DD')}
</Text>
<Text style={styles.timeText}>
{dayjs(record.createdAt).format('HH:mm')}
</Text>
</View>
<View style={styles.weightInfo}>
<Text style={styles.weightValue}>{record.weight}<Text style={styles.unitText}>{t('weightRecords.modal.unit')}</Text></Text>
</View>
</View>
</View>
<View style={styles.rightContent}>
{Math.abs(weightChange) > 0 && (
<View style={[
styles.changeTag,
{ backgroundColor: weightChange < 0 ? '#E8F5E8' : '#FFF2E8' }
]}>
<Ionicons
name={weightChange < 0 ? "arrow-down" : "arrow-up"}
size={10}
color={weightChange < 0 ? '#22C55E' : '#FF9500'}
/>
<Text style={[
styles.changeText,
{ color: weightChange < 0 ? '#22C55E' : '#FF9500' }
]}>
{Math.abs(weightChange).toFixed(1)}
</Text>
</View>
)}
<TouchableOpacity
style={styles.editButton}
onPress={() => onPress?.(record)}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
<Ionicons name="ellipsis-vertical" size={16} color="#9ba3c7" />
</TouchableOpacity>
</View>
</View>
</Swipeable>
</View>
);
};
const styles = StyleSheet.create({
cardContainer: {
shadowColor: 'rgba(30, 41, 59, 0.08)',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.12,
shadowRadius: 12,
elevation: 4,
},
recordCard: {
backgroundColor: '#ffffff',
borderRadius: 24,
padding: 16,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
leftContent: {
flexDirection: 'row',
alignItems: 'center',
flex: 1,
},
iconContainer: {
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#F0F2F5',
alignItems: 'center',
justifyContent: 'center',
marginRight: 16,
},
icon: {
width: 24,
height: 24,
tintColor: '#4F5BD5',
},
textContent: {
justifyContent: 'center',
},
dateTimeContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 4,
},
dateText: {
fontSize: 14,
fontWeight: '600',
color: '#1c1f3a',
marginRight: 8,
fontFamily: 'AliBold',
},
timeText: {
fontSize: 12,
color: '#6f7ba7',
fontFamily: 'AliRegular',
},
weightInfo: {
flexDirection: 'row',
alignItems: 'baseline',
},
weightValue: {
fontSize: 18,
fontWeight: '700',
color: '#1c1f3a',
fontFamily: 'AliBold',
},
unitText: {
fontSize: 13,
fontWeight: '500',
color: '#6f7ba7',
marginLeft: 2,
fontFamily: 'AliRegular',
},
rightContent: {
flexDirection: 'row',
alignItems: 'center',
gap: 12,
},
changeTag: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 6,
paddingVertical: 2,
borderRadius: 8,
},
changeText: {
fontSize: 11,
fontWeight: '700',
marginLeft: 2,
fontFamily: 'AliBold',
},
editButton: {
padding: 4,
},
deleteButton: {
backgroundColor: '#FF6B6B',
justifyContent: 'center',
alignItems: 'center',
width: 70,
borderRadius: 24,
marginLeft: 12,
height: '100%',
},
});