import { Colors } from '@/constants/Colors'; import { useColorScheme } from '@/hooks/useColorScheme'; import { CreateGoalRequest, GoalPriority, RepeatType } from '@/types/goals'; import DateTimePicker from '@react-native-community/datetimepicker'; import React, { useState } from 'react'; import { Alert, Modal, Platform, ScrollView, StyleSheet, Switch, Text, TextInput, TouchableOpacity, View, } from 'react-native'; interface CreateGoalModalProps { visible: boolean; onClose: () => void; onSubmit: (goalData: CreateGoalRequest) => void; loading?: boolean; } const REPEAT_TYPE_OPTIONS: { value: RepeatType; label: string }[] = [ { value: 'daily', label: '每日' }, { value: 'weekly', label: '每周' }, { value: 'monthly', label: '每月' }, { value: 'custom', label: '自定义' }, ]; const FREQUENCY_OPTIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; export const CreateGoalModal: React.FC = ({ visible, onClose, onSubmit, loading = false, }) => { const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; const colorTokens = Colors[theme]; // 表单状态 const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [repeatType, setRepeatType] = useState('daily'); const [frequency, setFrequency] = useState(1); const [hasReminder, setHasReminder] = useState(false); const [reminderTime, setReminderTime] = useState('20:00'); const [category, setCategory] = useState(''); const [priority, setPriority] = useState(5); const [showTimePicker, setShowTimePicker] = useState(false); const [tempSelectedTime, setTempSelectedTime] = useState(null); // 重置表单 const resetForm = () => { setTitle(''); setDescription(''); setRepeatType('daily'); setFrequency(1); setHasReminder(false); setReminderTime('19:00'); setCategory(''); setPriority(5); }; // 处理关闭 const handleClose = () => { if (!loading) { resetForm(); onClose(); } }; // 处理提交 const handleSubmit = () => { if (!title.trim()) { Alert.alert('提示', '请输入目标标题'); return; } // 计算startTime:从reminderTime中获取小时和分钟,转换为当天的分钟数 let startTime: number | undefined; if (reminderTime) { const [hours, minutes] = reminderTime.split(':').map(Number); startTime = hours * 60 + minutes; } const goalData: CreateGoalRequest = { title: title.trim(), description: description.trim() || undefined, repeatType, frequency, category: category.trim() || undefined, priority, hasReminder, reminderTime: hasReminder ? reminderTime : undefined, reminderSettings: hasReminder ? { enabled: true, weekdays: [1, 2, 3, 4, 5, 6, 0], // 默认每天 } : undefined, startTime, }; console.log('goalData', goalData); onSubmit(goalData); }; // 时间选择器 const handleTimeChange = (event: any, selectedDate?: Date) => { if (Platform.OS === 'android') { // Android: 用户点击系统确认按钮后自动关闭 if (event.type === 'set' && selectedDate) { const hours = selectedDate.getHours().toString().padStart(2, '0'); const minutes = selectedDate.getMinutes().toString().padStart(2, '0'); setReminderTime(`${hours}:${minutes}`); } setShowTimePicker(false); } else { // iOS: 只在用户点击自定义确认按钮时更新 if (selectedDate) { setTempSelectedTime(selectedDate); } } }; const handleConfirmTime = () => { setShowTimePicker(false); if (tempSelectedTime) { const hours = tempSelectedTime.getHours().toString().padStart(2, '0'); const minutes = tempSelectedTime.getMinutes().toString().padStart(2, '0'); setReminderTime(`${hours}:${minutes}`); } setTempSelectedTime(null); }; const handleCancelTime = () => { setShowTimePicker(false); setTempSelectedTime(null); }; const showTimePickerModal = () => { setShowTimePicker(true); }; // 获取当前时间对应的Date对象 const getCurrentTimeDate = () => { const [hours, minutes] = reminderTime.split(':').map(Number); const date = new Date(); date.setHours(hours, minutes, 0, 0); return date; }; return ( {/* 头部 */} 创建新目标 {/* 目标标题输入 */} 图标 {/* 装饰图案 */} {/* 目标重复周期 */} 🔄 目标重复周期 {REPEAT_TYPE_OPTIONS.find(opt => opt.value === repeatType)?.label} {/* 频率设置 */} 📊 频率 {frequency} {/* 提醒设置 */} 🔔 提醒 {/* 时间设置 */} 时间 {reminderTime} {/* 时间选择器弹窗 */} setShowTimePicker(false)} > {Platform.OS === 'ios' && ( 取消 确定 )} {/* 描述输入(可选) */} {/* 保存按钮 */} {loading ? '保存中...' : '保存'} ); }; const styles = StyleSheet.create({ container: { flex: 1, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 20, paddingTop: 60, paddingBottom: 20, }, cancelButton: { fontSize: 24, fontWeight: '600', }, title: { fontSize: 18, fontWeight: '600', }, content: { flex: 1, paddingHorizontal: 20, }, section: { marginBottom: 24, }, iconTitleContainer: { flexDirection: 'row', alignItems: 'flex-start', backgroundColor: '#FFFFFF', borderRadius: 16, padding: 20, marginBottom: 16, }, iconPlaceholder: { width: 60, height: 60, borderRadius: 30, backgroundColor: '#F3F4F6', alignItems: 'center', justifyContent: 'center', marginRight: 16, }, iconText: { fontSize: 12, color: '#9CA3AF', fontWeight: '500', }, titleInput: { flex: 1, fontSize: 16, fontWeight: '500', minHeight: 60, textAlignVertical: 'top', }, decorationContainer: { alignItems: 'flex-end', paddingRight: 20, }, decoration: { width: 80, height: 60, backgroundColor: '#E0E7FF', borderRadius: 40, opacity: 0.6, }, optionCard: { borderRadius: 16, marginBottom: 12, overflow: 'hidden', }, optionHeader: { flexDirection: 'row', alignItems: 'center', padding: 16, }, optionIcon: { width: 32, height: 32, borderRadius: 16, backgroundColor: '#F3F4F6', alignItems: 'center', justifyContent: 'center', marginRight: 12, }, optionIconText: { fontSize: 16, }, optionLabel: { flex: 1, fontSize: 16, fontWeight: '500', }, optionValue: { flexDirection: 'row', alignItems: 'center', }, optionValueText: { fontSize: 16, fontWeight: '500', marginRight: 8, }, chevron: { fontSize: 20, fontWeight: '300', }, descriptionInput: { padding: 16, fontSize: 16, minHeight: 80, textAlignVertical: 'top', }, footer: { padding: 20, paddingBottom: 40, }, saveButton: { backgroundColor: '#6366F1', borderRadius: 16, paddingVertical: 16, alignItems: 'center', }, saveButtonText: { color: '#FFFFFF', fontSize: 18, fontWeight: '600', }, modalBackdrop: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(0,0,0,0.35)', }, modalSheet: { position: 'absolute', left: 0, right: 0, bottom: 0, padding: 16, backgroundColor: '#FFFFFF', borderTopLeftRadius: 16, borderTopRightRadius: 16, }, modalActions: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 8, gap: 12, }, modalBtn: { paddingHorizontal: 14, paddingVertical: 10, borderRadius: 10, backgroundColor: '#F1F5F9', }, modalBtnPrimary: { backgroundColor: '#6366F1', }, modalBtnText: { color: '#334155', fontWeight: '700', }, modalBtnTextPrimary: { color: '#FFFFFF', fontWeight: '700', }, }); export default CreateGoalModal;