diff --git a/src/components/reminder/ReminderCard.tsx b/src/components/reminder/ReminderCard.tsx
index cdda94a..59e935f 100644
--- a/src/components/reminder/ReminderCard.tsx
+++ b/src/components/reminder/ReminderCard.tsx
@@ -1,4 +1,23 @@
-import { Card, Text, Checkbox, Group, Stack } from '@mantine/core';
+import { useMemo, useState } from 'react';
+import {
+ Card,
+ Text,
+ Checkbox,
+ Group,
+ Stack,
+ ThemeIcon,
+ Tooltip,
+ ActionIcon,
+ Menu,
+} from '@mantine/core';
+import {
+ IconBell,
+ IconCheck,
+ IconDots,
+ IconTrash,
+ IconEdit,
+ IconClock,
+} from '@tabler/icons-react';
import type { Event } from '../../types';
interface ReminderCardProps {
@@ -9,6 +28,34 @@ interface ReminderCardProps {
export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
const isCompleted = event.is_completed ?? false;
+ const [isHovered, setIsHovered] = useState(false);
+
+ // 计算距离提醒时间的相关显示
+ const timeInfo = useMemo(() => {
+ const now = new Date();
+ const eventDate = new Date(event.date);
+ const diff = eventDate.getTime() - now.getTime();
+ const isPast = diff < 0;
+ const isToday = eventDate.toDateString() === now.toDateString();
+
+ // 格式化时间显示
+ const timeStr = eventDate.toLocaleString('zh-CN', {
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ });
+
+ return { isPast, isToday, timeStr, diff };
+ }, [event.date]);
+
+ // 颜色主题
+ const getThemeColor = () => {
+ if (isCompleted) return 'gray';
+ if (timeInfo.isPast) return 'red';
+ if (timeInfo.isToday) return 'orange';
+ return 'blue';
+ };
return (
setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
style={{
cursor: 'pointer',
- opacity: isCompleted ? 0.6 : 1,
- transition: 'transform 0.2s',
- textDecoration: isCompleted ? 'line-through' : 'none',
+ opacity: isCompleted ? 0.5 : 1,
+ transition: 'all 0.2s ease',
+ transform: isHovered ? 'translateY(-2px)' : 'translateY(0)',
+ borderLeft: `3px solid var(--mantine-color-${getThemeColor()}-6)`,
}}
- onMouseEnter={(e) => (e.currentTarget.style.transform = 'translateY(-2px)')}
- onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
>
-
-
- {event.title}
-
-
- {new Date(event.date).toLocaleString('zh-CN')}
-
- {event.content && (
-
- {event.content}
-
- )}
-
+
+ {/* Checkbox */}
+ {
+ e.stopPropagation();
+ onToggle();
+ }}
+ onClick={(e) => e.stopPropagation()}
+ color="green"
+ size="sm"
+ />
- {
- e.stopPropagation();
- onToggle();
- }}
- onClick={(e) => e.stopPropagation()}
- />
+
+ {/* Title */}
+
+ {event.title}
+
+
+ {/* Time and content */}
+
+
+
+
+
+ {timeInfo.timeStr}
+
+
+
+ {/* Content preview */}
+ {event.content && !isCompleted && (
+
+ {event.content}
+
+ )}
+
+
+
+ {/* Quick actions */}
+
+ {isHovered && !isCompleted && (
+
+ {
+ e.stopPropagation();
+ onToggle();
+ }}
+ >
+
+
+
+ )}
+
+
+
);
diff --git a/src/components/reminder/ReminderList.tsx b/src/components/reminder/ReminderList.tsx
index 586bb58..1696b5b 100644
--- a/src/components/reminder/ReminderList.tsx
+++ b/src/components/reminder/ReminderList.tsx
@@ -1,6 +1,6 @@
import { useMemo } from 'react';
-import { Stack, Text, Paper, Group, Button } from '@mantine/core';
-import { IconPlus } from '@tabler/icons-react';
+import { Stack, Text, Paper, Group, Button, Badge, ThemeIcon, Alert } from '@mantine/core';
+import { IconPlus, IconBell, IconAlertCircle } from '@tabler/icons-react';
import { ReminderCard } from './ReminderCard';
import type { Event } from '../../types';
@@ -22,52 +22,76 @@ export function ReminderList({
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
+ const nextWeek = new Date(today);
+ nextWeek.setDate(nextWeek.getDate() + 7);
const reminders = events.filter((e) => e.type === 'reminder');
const result = {
today: [] as Event[],
tomorrow: [] as Event[],
+ thisWeek: [] as Event[],
later: [] as Event[],
missed: [] as Event[],
+ completed: [] as Event[],
};
reminders.forEach((event) => {
const eventDate = new Date(event.date);
- if (event.is_completed) return;
+ // 已完成的放最后
+ if (event.is_completed) {
+ result.completed.push(event);
+ return;
+ }
+ // 未完成的按时间分组
if (eventDate < today) {
result.missed.push(event);
} else if (eventDate < tomorrow) {
result.today.push(event);
+ } else if (eventDate < nextWeek) {
+ result.thisWeek.push(event);
} else {
result.later.push(event);
}
});
- // Sort by date
- Object.keys(result).forEach((key) => {
- result[key as keyof typeof result].sort(
- (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
- );
- });
+ // 按时间排序
+ const sortByDate = (a: Event, b: Event) =>
+ new Date(a.date).getTime() - new Date(b.date).getTime();
+
+ result.today.sort(sortByDate);
+ result.tomorrow.sort(sortByDate);
+ result.thisWeek.sort(sortByDate);
+ result.later.sort(sortByDate);
+ result.missed.sort(sortByDate);
+ result.completed.sort(sortByDate);
return result;
}, [events]);
- const hasReminders =
+ const hasActiveReminders =
grouped.today.length > 0 ||
grouped.tomorrow.length > 0 ||
+ grouped.thisWeek.length > 0 ||
grouped.later.length > 0 ||
grouped.missed.length > 0;
- if (!hasReminders) {
+ // 空状态
+ if (!hasActiveReminders) {
return (
-
+
+
+
+
暂无提醒
+
+
+ 记得添加提醒事项哦
+