import { Colors } from '@/constants/Colors'; import { useColorScheme } from '@/hooks/useColorScheme'; import { useWaterDataByDate } from '@/hooks/useWaterData'; import { getQuickWaterAmount, setQuickWaterAmount } from '@/utils/userPreferences'; import { Ionicons } from '@expo/vector-icons'; import { Picker } from '@react-native-picker/picker'; import { Image } from 'expo-image'; import { router, useLocalSearchParams } from 'expo-router'; import React, { useEffect, useState } from 'react'; import { Alert, KeyboardAvoidingView, Modal, Platform, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { Swipeable } from 'react-native-gesture-handler'; import { HeaderBar } from '@/components/ui/HeaderBar'; import dayjs from 'dayjs'; interface WaterSettingsProps { selectedDate?: string; } const WaterSettings: React.FC = () => { const { selectedDate } = useLocalSearchParams<{ selectedDate?: string }>(); const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; const colorTokens = Colors[theme]; const [dailyGoal, setDailyGoal] = useState('2000'); const [quickAddAmount, setQuickAddAmount] = useState('250'); // 编辑弹窗状态 const [goalModalVisible, setGoalModalVisible] = useState(false); const [quickAddModalVisible, setQuickAddModalVisible] = useState(false); // 临时选中值 const [tempGoal, setTempGoal] = useState(parseInt(dailyGoal)); const [tempQuickAdd, setTempQuickAdd] = useState(parseInt(quickAddAmount)); // 使用新的 hook 来处理指定日期的饮水数据 const { waterRecords, dailyWaterGoal, updateWaterGoal, removeWaterRecord } = useWaterDataByDate(selectedDate); const goalPresets = [1500, 2000, 2500, 3000, 3500, 4000]; const quickAddPresets = [100, 150, 200, 250, 300, 350, 400, 500]; // 打开饮水目标弹窗时初始化临时值 const openGoalModal = () => { setTempGoal(parseInt(dailyGoal)); setGoalModalVisible(true); }; // 打开快速添加弹窗时初始化临时值 const openQuickAddModal = () => { setTempQuickAdd(parseInt(quickAddAmount)); setQuickAddModalVisible(true); }; // 处理饮水目标确认 const handleGoalConfirm = async () => { setDailyGoal(tempGoal.toString()); setGoalModalVisible(false); try { const success = await updateWaterGoal(tempGoal); if (!success) { Alert.alert('设置失败', '无法保存饮水目标,请重试'); } } catch { Alert.alert('设置失败', '无法保存饮水目标,请重试'); } }; // 处理快速添加默认值确认 const handleQuickAddConfirm = async () => { setQuickAddAmount(tempQuickAdd.toString()); setQuickAddModalVisible(false); try { await setQuickWaterAmount(tempQuickAdd); } catch { Alert.alert('设置失败', '无法保存快速添加默认值,请重试'); } }; // 删除饮水记录 const handleDeleteRecord = async (recordId: string) => { await removeWaterRecord(recordId); }; // 加载用户偏好设置和当前饮水目标 useEffect(() => { const loadUserPreferences = async () => { try { const amount = await getQuickWaterAmount(); setQuickAddAmount(amount.toString()); // 设置当前的饮水目标 if (dailyWaterGoal) { setDailyGoal(dailyWaterGoal.toString()); } } catch (error) { console.error('加载用户偏好设置失败:', error); } }; loadUserPreferences(); }, [dailyWaterGoal]); // 当dailyGoal或quickAddAmount更新时,同步更新临时状态 useEffect(() => { setTempGoal(parseInt(dailyGoal)); }, [dailyGoal]); useEffect(() => { setTempQuickAdd(parseInt(quickAddAmount)); }, [quickAddAmount]); // 新增:饮水记录卡片组件 const WaterRecordCard = ({ record, onDelete }: { record: any; onDelete: () => void }) => { const swipeableRef = React.useRef(null); // 处理删除操作 const handleDelete = () => { Alert.alert( '确认删除', '确定要删除这条饮水记录吗?此操作无法撤销。', [ { text: '取消', style: 'cancel', }, { text: '删除', style: 'destructive', onPress: () => { onDelete(); swipeableRef.current?.close(); }, }, ] ); }; // 渲染右侧删除按钮 const renderRightActions = () => { return ( 删除 ); }; return ( {dayjs(record.recordedAt || record.createdAt).format('HH:mm')} {record.amount}ml {record.note && ( {record.note} )} ); }; return ( { // 这里会通过路由自动处理返回 router.back(); }} /> {/* 第一部分:饮水配置 */} 饮水配置 {/* 设置目标部分 */} 每日饮水目标 {dailyGoal}ml {/* 快速添加默认值设置部分 */} 快速添加默认值 设置点击右上角"+"按钮时添加的默认饮水量 {quickAddAmount}ml {/* 第二部分:饮水记录 */} {selectedDate ? dayjs(selectedDate).format('MM月DD日') : '今日'}饮水记录 {waterRecords && waterRecords.length > 0 ? ( {waterRecords.map((record) => ( handleDeleteRecord(record.id)} /> ))} {/* 总计显示 */} 总计:{waterRecords.reduce((sum, record) => sum + record.amount, 0)}ml 目标:{dailyWaterGoal}ml ) : ( 暂无饮水记录 点击"添加记录"开始记录饮水量 )} {/* 饮水目标编辑弹窗 */} setGoalModalVisible(false)} > setGoalModalVisible(false)} /> 每日饮水目标 setTempGoal(value)} style={styles.picker} > {Array.from({ length: 96 }, (_, i) => 500 + i * 100).map(goal => ( ))} setGoalModalVisible(false)} style={[styles.modalBtn, { backgroundColor: colorTokens.pageBackgroundEmphasis }]} > 取消 确定 {/* 快速添加默认值编辑弹窗 */} setQuickAddModalVisible(false)} > setQuickAddModalVisible(false)} /> 快速添加默认值 setTempQuickAdd(value)} style={styles.picker} > {Array.from({ length: 41 }, (_, i) => 50 + i * 10).map(amount => ( ))} setQuickAddModalVisible(false)} style={[styles.modalBtn, { backgroundColor: colorTokens.pageBackgroundEmphasis }]} > 取消 确定 ); }; const styles = StyleSheet.create({ container: { flex: 1, }, keyboardAvoidingView: { flex: 1, }, scrollView: { flex: 1, }, scrollContent: { padding: 20, }, section: { marginBottom: 32, }, sectionTitle: { fontSize: 20, fontWeight: '600', marginBottom: 20, letterSpacing: -0.5, }, subsectionTitle: { fontSize: 16, fontWeight: '500', marginBottom: 12, letterSpacing: -0.3, }, sectionSubtitle: { fontSize: 14, fontWeight: '400', lineHeight: 18, }, input: { borderRadius: 12, paddingHorizontal: 16, paddingVertical: 14, fontSize: 16, fontWeight: '500', marginBottom: 16, }, settingRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: 16, paddingHorizontal: 16, borderRadius: 12, marginBottom: 16, }, settingLeft: { flex: 1, }, settingTitle: { fontSize: 16, fontWeight: '500', marginBottom: 4, }, settingSubtitle: { fontSize: 14, marginBottom: 8, }, settingValue: { fontSize: 16, }, settingRight: { marginLeft: 12, }, quickAmountsContainer: { marginBottom: 15, }, quickAmountsWrapper: { flexDirection: 'row', gap: 10, paddingRight: 10, }, quickAmountButton: { paddingHorizontal: 20, paddingVertical: 8, borderRadius: 20, minWidth: 70, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.05, shadowRadius: 2, elevation: 1, }, quickAmountText: { fontSize: 15, fontWeight: '500', }, saveButton: { paddingVertical: 14, borderRadius: 12, alignItems: 'center', marginTop: 24, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 3, }, saveButtonText: { fontSize: 16, fontWeight: '700', }, // 饮水记录相关样式 recordsList: { gap: 12, }, recordCardContainer: { // iOS 阴影效果 shadowColor: '#000000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.08, shadowRadius: 4, // Android 阴影效果 elevation: 2, }, recordCard: { borderRadius: 12, padding: 10, }, recordMainContent: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, recordIconContainer: { width: 40, height: 40, borderRadius: 10, alignItems: 'center', justifyContent: 'center', }, recordIcon: { width: 20, height: 20, }, recordInfo: { flex: 1, marginLeft: 12, }, recordLabel: { fontSize: 16, fontWeight: '600', marginBottom: 8, }, recordTimeContainer: { flexDirection: 'row', alignItems: 'center', gap: 4, }, recordAmountContainer: { alignItems: 'flex-end', }, recordAmount: { fontSize: 14, fontWeight: '500', }, deleteSwipeButton: { backgroundColor: '#EF4444', justifyContent: 'center', alignItems: 'center', width: 80, borderRadius: 12, marginLeft: 8, }, deleteSwipeButtonText: { color: '#FFFFFF', fontSize: 12, fontWeight: '600', marginTop: 4, }, recordTimeText: { fontSize: 12, fontWeight: '400', }, recordNote: { marginTop: 8, fontSize: 14, fontStyle: 'italic', lineHeight: 20, }, recordsSummary: { marginTop: 20, padding: 16, borderRadius: 12, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', }, summaryText: { fontSize: 12, fontWeight: '500', }, summaryGoal: { fontSize: 12, fontWeight: '500', }, noRecordsContainer: { alignItems: 'center', justifyContent: 'center', paddingVertical: 40, gap: 12, }, noRecordsText: { fontSize: 16, fontWeight: '600', }, noRecordsSubText: { fontSize: 14, textAlign: 'center', }, modalBackdrop: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(0,0,0,0.4)', }, modalSheet: { position: 'absolute', left: 0, right: 0, bottom: 0, padding: 16, backgroundColor: '#FFFFFF', borderTopLeftRadius: 16, borderTopRightRadius: 16, // iOS 阴影效果 shadowColor: '#000000', shadowOffset: { width: 0, height: -2 }, shadowOpacity: 0.1, shadowRadius: 8, // Android 阴影效果 elevation: 16, }, modalHandle: { width: 36, height: 4, backgroundColor: '#E0E0E0', borderRadius: 2, alignSelf: 'center', marginBottom: 20, }, modalTitle: { fontSize: 20, fontWeight: '600', textAlign: 'center', marginBottom: 20, }, pickerContainer: { height: 200, marginBottom: 20, }, picker: { height: 200, }, modalActions: { flexDirection: 'row', justifyContent: 'flex-end', gap: 12, }, modalBtn: { paddingHorizontal: 14, paddingVertical: 10, borderRadius: 10, minWidth: 80, alignItems: 'center', }, modalBtnPrimary: { // backgroundColor will be set dynamically }, modalBtnText: { fontSize: 16, fontWeight: '600', }, modalBtnTextPrimary: { // color will be set dynamically }, }); export default WaterSettings;