diff --git a/src/components/reminder/ReminderCard.tsx b/src/components/reminder/ReminderCard.tsx
index cccd632..7b1c28a 100644
--- a/src/components/reminder/ReminderCard.tsx
+++ b/src/components/reminder/ReminderCard.tsx
@@ -1,4 +1,4 @@
-import { useMemo, useState } from 'react';
+import { useMemo, useState, useEffect } from 'react';
import { Paper, Text, Checkbox, Group, Stack, ActionIcon } from '@mantine/core';
import { IconDots } from '@tabler/icons-react';
import type { Event } from '../../types';
@@ -8,13 +8,15 @@ interface ReminderCardProps {
onToggle: () => void;
onClick: () => void;
onDelete?: () => void;
+ isMissed?: boolean;
}
-export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
+export function ReminderCard({ event, onToggle, onClick, isMissed = false }: ReminderCardProps) {
const isCompleted = event.is_completed ?? false;
const [isHovered, setIsHovered] = useState(false);
+ const [isAnimating, setIsAnimating] = useState(false);
- // 计算距离提醒时间的相关显示
+ // 计算时间信息
const timeInfo = useMemo(() => {
const now = new Date();
const eventDate = new Date(event.date);
@@ -22,7 +24,6 @@ export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
const isPast = diff < 0;
const isToday = eventDate.toDateString() === now.toDateString();
- // 格式化时间显示
const timeStr = eventDate.toLocaleString('zh-CN', {
month: 'numeric',
day: 'numeric',
@@ -33,12 +34,32 @@ export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
return { isPast, isToday, timeStr, diff };
}, [event.date]);
- // 颜色主题
- const getThemeColor = () => {
+ // 获取文字颜色
+ const getTextColor = () => {
if (isCompleted) return '#999';
+ if (timeInfo.isPast) return '#666';
+ return '#1a1a1a';
+ };
+
+ // 获取时间颜色
+ const getTimeColor = () => {
+ if (isCompleted) return '#bbb';
if (timeInfo.isPast) return '#c41c1c';
- if (timeInfo.isToday) return '#666';
- return '#888';
+ return '#666';
+ };
+
+ // 获取背景色
+ const getBackground = () => {
+ if (isCompleted) return 'rgba(0, 0, 0, 0.02)';
+ if (isMissed) return 'rgba(196, 28, 28, 0.03)';
+ return 'rgba(0, 0, 0, 0.02)';
+ };
+
+ // 获取边框颜色
+ const getBorderColor = () => {
+ if (isCompleted) return 'rgba(0, 0, 0, 0.06)';
+ if (isMissed) return 'rgba(196, 28, 28, 0.15)';
+ return 'rgba(0, 0, 0, 0.06)';
};
return (
@@ -49,26 +70,55 @@ export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
onMouseLeave={() => setIsHovered(false)}
style={{
cursor: 'pointer',
- opacity: isCompleted ? 0.4 : 1,
- transition: 'all 0.2s ease',
+ opacity: isAnimating ? 0 : isCompleted ? 0.4 : 1,
transform: isHovered ? 'translateY(-1px)' : 'translateY(0)',
- borderLeft: `2px solid ${getThemeColor()}`,
- background: 'rgba(0, 0, 0, 0.02)',
- border: '1px solid rgba(0, 0, 0, 0.04)',
+ background: getBackground(),
+ border: `1px solid ${getBorderColor()}`,
+ borderLeft: isMissed && !isCompleted ? '3px solid #c41c1c' : undefined,
+ transition: 'all 0.3s ease',
+ animation: isAnimating ? 'reminder-card-fadeOut 0.3s ease-out forwards' : 'none',
}}
>
+
- {/* Checkbox - 点击切换完成状态 */}
- {
- e.stopPropagation();
- onToggle();
+ {/* Checkbox */}
+
+ >
+ {
+ e.stopPropagation();
+ if (isMissed && !isCompleted) {
+ // 已过期提醒:先播放动画,动画结束后再触发 toggle
+ setIsAnimating(true);
+ setTimeout(() => {
+ setIsAnimating(false);
+ onToggle();
+ }, 300);
+ } else {
+ onToggle();
+ }
+ }}
+ size="xs"
+ color="#1a1a1a"
+ />
+
{/* Title */}
@@ -78,23 +128,34 @@ export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
lineClamp={1}
style={{
textDecoration: isCompleted ? 'line-through' : 'none',
- color: isCompleted ? '#bbb' : '#1a1a1a',
+ color: getTextColor(),
letterSpacing: '0.03em',
+ transition: 'color 0.2s ease',
}}
>
{event.title}
- {/* Time and content */}
-
-
- {timeInfo.timeStr}
-
-
+ {/* Time */}
+
+ {timeInfo.timeStr}
+
- {/* Content preview */}
- {event.content && !isCompleted && (
-
+ {/* Content preview - 始终显示 */}
+ {event.content && (
+
{event.content}
)}
@@ -111,7 +172,11 @@ export function ReminderCard({ event, onToggle, onClick }: ReminderCardProps) {
e.stopPropagation();
onClick();
}}
- style={{ color: '#999' }}
+ style={{
+ color: '#999',
+ opacity: isHovered ? 1 : 0,
+ transition: 'all 0.2s ease',
+ }}
title="编辑"
>
diff --git a/src/components/reminder/ReminderList.tsx b/src/components/reminder/ReminderList.tsx
index 8807ac7..d328c85 100644
--- a/src/components/reminder/ReminderList.tsx
+++ b/src/components/reminder/ReminderList.tsx
@@ -83,8 +83,8 @@ export function ReminderList({
result.today.sort(sortByDate);
result.tomorrow.sort(sortByDate);
result.later.sort(sortByDate);
- // 已过期按时间倒序(最近的在上面)
- result.missed.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
+ // 已过期按时间正序(最早的在前)
+ result.missed.sort(sortByDate);
return result;
}, [events]);
@@ -176,6 +176,7 @@ export function ReminderList({
onClick={() => onEventClick(event)}
onToggle={() => onToggleComplete(event)}
onDelete={onDelete ? () => onDelete(event) : undefined}
+ isMissed={true}
/>
))}
{grouped.missed.length > 3 && (
diff --git a/src/pages/ArchivePage.tsx b/src/pages/ArchivePage.tsx
index f1c1c34..bce8ed4 100644
--- a/src/pages/ArchivePage.tsx
+++ b/src/pages/ArchivePage.tsx
@@ -8,6 +8,7 @@ import {
Group,
Button,
ActionIcon,
+ Box,
} from '@mantine/core';
import { IconArrowLeft, IconRotateClockwise, IconTrash, IconArchive } from '@tabler/icons-react';
import { useNavigate } from 'react-router-dom';
@@ -17,21 +18,27 @@ import type { Event } from '../types';
export function ArchivePage() {
const navigate = useNavigate();
const events = useAppStore((state) => state.events);
+ const fetchEvents = useAppStore((state) => state.fetchEvents);
const updateEventById = useAppStore((state) => state.updateEventById);
const deleteEventById = useAppStore((state) => state.deleteEventById);
- // 页面加载时检查登录状态
+ // 页面加载时获取数据
useEffect(() => {
const isAuthenticated = useAppStore.getState().isAuthenticated;
if (!isAuthenticated) {
navigate('/login', { replace: true });
+ } else {
+ fetchEvents();
}
- }, [navigate]);
+ }, [navigate, fetchEvents]);
// 获取已归档的提醒(已过期且已勾选的)
- const archivedReminders = events.filter(
- (e) => e.type === 'reminder' && e.is_completed
- ).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
+ const archivedReminders = events.filter((e) => {
+ if (e.type !== 'reminder' || !e.is_completed) return false;
+ const eventDate = new Date(e.date);
+ const now = new Date();
+ return eventDate < now; // 仅已过期的
+ }).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
const handleRestore = async (event: Event) => {
await updateEventById(event.id, { is_completed: false });
@@ -42,15 +49,17 @@ export function ArchivePage() {
};
return (
-
-
+
{/* Header */}
-
+
-
+
);
}
diff --git a/tmpclaude-a0eb-cwd b/tmpclaude-a0eb-cwd
deleted file mode 100644
index 094e142..0000000
--- a/tmpclaude-a0eb-cwd
+++ /dev/null
@@ -1 +0,0 @@
-/e/qia/client
diff --git a/tmpclaude-bde2-cwd b/tmpclaude-bde2-cwd
deleted file mode 100644
index 094e142..0000000
--- a/tmpclaude-bde2-cwd
+++ /dev/null
@@ -1 +0,0 @@
-/e/qia/client