181 lines
4.5 KiB
TypeScript
181 lines
4.5 KiB
TypeScript
import { Colors } from '@/constants/Colors';
|
||
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 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}>
|
||
{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}>体重:</Text>
|
||
<Text style={styles.recordWeightValue}>{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,
|
||
shadowColor: '#000',
|
||
shadowOffset: { width: 0, height: 1 },
|
||
shadowOpacity: 0.06,
|
||
shadowRadius: 8,
|
||
elevation: 2,
|
||
},
|
||
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: 18,
|
||
fontWeight: '700',
|
||
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,
|
||
},
|
||
}); |