import { useEffect, useState } from 'react'; import { Container, Title, Button, Group, Text, Modal, TextInput, Textarea, Switch, Select, Stack, } from '@mantine/core'; import { DatePickerInput, TimeInput } from '@mantine/dates'; import { IconLogout, IconSettings } from '@tabler/icons-react'; import { useDisclosure } from '@mantine/hooks'; import { useNavigate } from 'react-router-dom'; import { useAppStore } from '../stores'; import { AnniversaryList } from '../components/anniversary/AnniversaryList'; import { ReminderList } from '../components/reminder/ReminderList'; import { NoteEditor } from '../components/note/NoteEditor'; import { FloatingAIChat } from '../components/ai/FloatingAIChat'; import type { Event, EventType, RepeatType } from '../types'; import { calculateNextReminderDate } from '../utils/repeatCalculator'; export function HomePage() { const navigate = useNavigate(); const user = useAppStore((state) => state.user); const logout = useAppStore((state) => state.logout); const checkAuth = useAppStore((state) => state.checkAuth); const events = useAppStore((state) => state.events); const fetchEvents = useAppStore((state) => state.fetchEvents); const createEvent = useAppStore((state) => state.createEvent); const updateEventById = useAppStore((state) => state.updateEventById); const deleteEventById = useAppStore((state) => state.deleteEventById); const [opened, { open, close }] = useDisclosure(false); const [selectedEvent, setSelectedEvent] = useState(null); const [isEdit, setIsEdit] = useState(false); // Form state const [formType, setFormType] = useState('anniversary'); const [formTitle, setFormTitle] = useState(''); const [formContent, setFormContent] = useState(''); const [formDate, setFormDate] = useState(null); const [formTime, setFormTime] = useState(''); const [formIsLunar, setFormIsLunar] = useState(false); const [formRepeatType, setFormRepeatType] = useState('none'); const [formIsHoliday, setFormIsHoliday] = useState(false); // Initialize auth and data on mount useEffect(() => { checkAuth(); fetchEvents().catch(console.error); }, []); // eslint-disable-line react-hooks/exhaustive-deps const handleLogout = async () => { await logout(); navigate('/landing'); }; const handleEventClick = (event: Event) => { setSelectedEvent(event); setIsEdit(true); setFormType(event.type); setFormTitle(event.title); setFormContent(event.content || ''); setFormDate(new Date(event.date)); setFormIsLunar(event.is_lunar); setFormRepeatType(event.repeat_type); setFormIsHoliday(event.is_holiday || false); // 提取时间(如果日期中包含时间信息) const eventDate = new Date(event.date); const hours = eventDate.getHours(); const minutes = eventDate.getMinutes(); setFormTime(hours === 0 && minutes === 0 ? '' : `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`); open(); }; const handleAddClick = (type: EventType) => { setSelectedEvent(null); setIsEdit(false); setFormType(type); setFormTitle(''); setFormContent(''); setFormDate(null); setFormTime(''); setFormIsLunar(false); setFormRepeatType('none'); setFormIsHoliday(type === 'anniversary'); open(); }; const handleSubmit = async () => { if (!formTitle.trim() || !formDate) return; // 确保 date 是 Date 对象 const dateObj = formDate instanceof Date ? formDate : new Date(formDate as unknown as string); let dateStr: string; const year = dateObj.getFullYear(); const month = String(dateObj.getMonth() + 1).padStart(2, '0'); const day = String(dateObj.getDate()).padStart(2, '0'); if (formTime) { // 有时间:构建本地时间格式 const hours = String(parseInt(formTime.split(':')[0])).padStart(2, '0'); const minutes = String(parseInt(formTime.split(':')[1])).padStart(2, '0'); dateStr = `${year}-${month}-${day}T${hours}:${minutes}:00`; } else { // 无时间:只保存日期部分 dateStr = `${year}-${month}-${day}T00:00:00`; } // 构建事件数据,确保不包含 undefined 值 const eventData: Record = { type: formType, title: formTitle, date: dateStr, is_lunar: formIsLunar, repeat_type: formRepeatType, // 计算下一次提醒日期 next_reminder_date: calculateNextReminderDate(dateStr, formRepeatType, undefined), is_holiday: formIsHoliday ?? false, }; // 只有当 content 有值时才包含 if (formContent.trim()) { eventData.content = formContent; } if (isEdit && selectedEvent) { await updateEventById(selectedEvent.id, eventData); } else { await createEvent(eventData); } close(); resetForm(); fetchEvents(); }; const handleDeleteFromModal = async () => { if (!selectedEvent) return; await deleteEventById(selectedEvent.id); close(); resetForm(); }; const handleToggleComplete = async (event: Event) => { if (event.type !== 'reminder') return; // 使用当前期望的状态(取反) const newCompleted = !event.is_completed; const result = await updateEventById(event.id, { is_completed: newCompleted, }); if (result.error) { console.error('更新失败:', result.error); } // 乐观更新已处理 UI 响应,无需 fetchEvents }; const handleDelete = async (event: Event) => { if (event.type !== 'reminder') return; await deleteEventById(event.id); fetchEvents(); }; const handlePostpone = async (event: Event) => { if (event.type !== 'reminder') return; // 将日期顺延到今天,保留原事件的时间 const today = new Date(); const originalDate = new Date(event.date); // 提取原时间的小时和分钟 const hours = originalDate.getHours(); const minutes = originalDate.getMinutes(); // 构建新的本地时间字符串 const newDateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}T${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00`; const result = await updateEventById(event.id, { date: newDateStr, }); if (result.error) { console.error('顺延失败:', result.error); } }; const resetForm = () => { setFormType('anniversary'); setFormTitle(''); setFormContent(''); setFormDate(null); setFormTime(''); setFormIsLunar(false); setFormRepeatType('none'); setFormIsHoliday(false); setSelectedEvent(null); setIsEdit(false); }; const handleAIEventCreated = () => { fetchEvents(); }; return (
{/* Header */} 掐日子 {/* 设置入口 */} {user?.nickname || user?.email} {/* Main Content - 3 column horizontal layout */}
{/* Left column - Anniversary */}
handleAddClick('anniversary')} />
{/* Middle column - Reminder */}
handleAddClick('reminder')} onDelete={handleDelete} onPostpone={handlePostpone} />
{/* Right column - Note */}
{/* AI Chat - Floating */} {/* Add/Edit Event Modal */} {isEdit ? '编辑事件' : '添加事件'} } size="md" styles={{ header: { borderBottom: '1px solid rgba(0,0,0,0.06)', }, body: { paddingTop: 20, }, }} > {/* Event type */}