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 dayjs from 'dayjs'; import { Image } from 'expo-image'; import React, { useEffect, useState } from 'react'; import { Alert, KeyboardAvoidingView, Modal, Platform, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native'; import { Swipeable } from 'react-native-gesture-handler'; interface AddWaterModalProps { visible: boolean; onClose: () => void; selectedDate?: string; // 新增:选中的日期,格式为 YYYY-MM-DD } const AddWaterModal: React.FC = ({ visible, onClose, selectedDate }) => { const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; const colorTokens = Colors[theme]; const [activeTab, setActiveTab] = useState<'manage' | 'records'>('manage'); const [waterAmount, setWaterAmount] = useState('250'); const [note, setNote] = useState(''); const [dailyGoal, setDailyGoal] = useState('2000'); const [quickAddAmount, setQuickAddAmount] = useState('250'); // 快速添加默认值 // 使用新的 hook 来处理指定日期的饮水数据 const { waterRecords, dailyWaterGoal, addWaterRecord, updateWaterGoal, removeWaterRecord } = useWaterDataByDate(selectedDate); const quickAmounts = [100, 150, 200, 250, 300, 350, 400, 500]; const goalPresets = [1500, 2000, 2500, 3000, 3500, 4000]; const quickAddPresets = [100, 150, 200, 250, 300, 350, 400, 500]; // 快速添加默认值选项 const handleAddWater = async () => { const amount = parseInt(waterAmount); if (amount > 0) { // 如果有选中日期,则为该日期添加记录;否则为今天添加记录 const recordedAt = selectedDate ? dayjs(selectedDate).toISOString() : dayjs().toISOString(); const success = await addWaterRecord(amount, recordedAt); if (success) { setWaterAmount('250'); setNote(''); onClose(); } } }; const handleUpdateGoal = async () => { const goal = parseInt(dailyGoal); if (goal >= 500 && goal <= 10000) { const success = await updateWaterGoal(goal); if (success) { setDailyGoal('2000'); onClose(); } } }; // 处理保存所有设置(饮水目标 + 快速添加默认值) const handleSaveSettings = async () => { const goal = parseInt(dailyGoal); const amount = parseInt(quickAddAmount); let hasError = false; // 验证饮水目标 if (goal < 500 || goal > 10000) { Alert.alert('输入错误', '每日饮水目标应在500ml到10000ml之间'); return; } // 验证快速添加默认值 if (amount < 50 || amount > 1000) { Alert.alert('输入错误', '快速添加默认值应在50ml到1000ml之间'); return; } try { // 保存饮水目标 const goalSuccess = await updateWaterGoal(goal); if (!goalSuccess) { hasError = true; } // 保存快速添加默认值 await setQuickWaterAmount(amount); if (!hasError) { onClose(); } } catch (error) { 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); } }; if (visible) { loadUserPreferences(); } }, [visible, dailyWaterGoal]); // 渲染Tab切换器 - 参照营养记录页面的实现 const renderTabToggle = () => ( setActiveTab('manage')} > 饮水配置 setActiveTab('records')} > 饮水记录 ); // 合并后的管理Tab,包含添加记录和设置目标 const renderManageTab = () => ( {/* 设置目标部分 */} 每日饮水目标 (ml) 推荐目标 {goalPresets.map((goal) => ( setDailyGoal(goal.toString())} > {goal}ml ))} {/* 快速添加默认值设置部分 */} 快速添加默认值 (ml) 设置点击右上角"+"按钮时添加的默认饮水量 推荐设置 {quickAddPresets.map((amount) => ( setQuickAddAmount(amount.toString())} > {amount}ml ))} 取消 保存设置 ); // 新增:饮水记录卡片组件 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} )} ); }; // 新增:饮水记录Tab内容 const renderRecordsTab = () => ( {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 ) : ( 暂无饮水记录 点击"添加记录"开始记录饮水量 )} ); return ( 配置饮水 {renderTabToggle()} {activeTab === 'manage' ? renderManageTab() : renderRecordsTab()} ); }; const styles = StyleSheet.create({ centeredView: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(0, 0, 0, 0.5)', }, modalView: { width: '90%', maxWidth: 400, height: 650, // 固定高度 borderRadius: 24, paddingTop: 24, paddingHorizontal: 20, paddingBottom: 20, shadowColor: '#000000', shadowOffset: { width: 0, height: 8, }, shadowOpacity: 0.12, shadowRadius: 20, elevation: 8, }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, }, modalTitle: { fontSize: 16, fontWeight: '600', letterSpacing: -0.5, }, closeButton: { padding: 5, }, tabContainer: { flexDirection: 'row', borderRadius: 20, padding: 2, marginBottom: 24, }, tabButton: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 18, minWidth: 80, alignItems: 'center', flex: 1, }, tabButtonText: { fontSize: 14, fontWeight: '600', }, contentScrollView: { flex: 1, }, tabContent: { paddingVertical: 10, }, sectionTitle: { fontSize: 14, 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, }, remarkInput: { height: 80, textAlignVertical: 'top', }, 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', }, buttonContainer: { flexDirection: 'row', gap: 10, marginTop: 20, }, button: { flex: 1, paddingVertical: 14, borderRadius: 12, alignItems: 'center', }, cancelButton: { }, confirmButton: { shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 3, }, cancelButtonText: { fontSize: 16, fontWeight: '600', }, confirmButtonText: { 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', }, }); export default AddWaterModal;