feat(scheduling): add 近期已干预 summary card (last 7 days)
Restore 替换建议 card and add a new emerald 近期已干预 card. Clicking opens the history modal pre-filtered to the last 7 days (excluding cancelled) via a toggle chip users can switch off. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -8,8 +8,12 @@ import Blur from '../../components/Blur';
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
onChange?: () => void;
|
||||
/** When true, pre-filter to the last 7 days (excluding cancelled). */
|
||||
recentOnly?: boolean;
|
||||
}
|
||||
|
||||
const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
|
||||
type StatusTab = 'all' | NotificationStatus;
|
||||
|
||||
const STATUS_TABS: { key: StatusTab; label: string }[] = [
|
||||
@@ -36,15 +40,23 @@ function fmtDateTime(iso: string): string {
|
||||
return `${y}-${m}-${day} ${hh}:${mm}`;
|
||||
}
|
||||
|
||||
export default function NotificationHistory({ onClose, onChange }: Props) {
|
||||
export default function NotificationHistory({ onClose, onChange, recentOnly = false }: Props) {
|
||||
const [records, setRecords] = useState<NotificationRecord[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [tab, setTab] = useState<StatusTab>('all');
|
||||
const [recent7d, setRecent7d] = useState(recentOnly);
|
||||
const [mutatingId, setMutatingId] = useState<number | null>(null);
|
||||
const [executeTarget, setExecuteTarget] = useState<NotificationRecord | null>(null);
|
||||
const [afterMileageInput, setAfterMileageInput] = useState('');
|
||||
const [notesInput, setNotesInput] = useState('');
|
||||
|
||||
const visibleRecords = recent7d
|
||||
? records.filter(r => {
|
||||
const t = Date.parse(r.createdAt);
|
||||
return Number.isFinite(t) && Date.now() - t <= SEVEN_DAYS_MS && r.status !== 'cancelled';
|
||||
})
|
||||
: records;
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
@@ -117,7 +129,7 @@ export default function NotificationHistory({ onClose, onChange }: Props) {
|
||||
</div>
|
||||
|
||||
{/* Status tabs */}
|
||||
<div className="border-b border-slate-100 px-4 py-2 flex gap-1.5 flex-shrink-0">
|
||||
<div className="border-b border-slate-100 px-4 py-2 flex gap-1.5 flex-shrink-0 flex-wrap items-center">
|
||||
{STATUS_TABS.map(t => (
|
||||
<button
|
||||
key={t.key}
|
||||
@@ -129,6 +141,17 @@ export default function NotificationHistory({ onClose, onChange }: Props) {
|
||||
{t.label}
|
||||
</button>
|
||||
))}
|
||||
<div className="ml-auto">
|
||||
<button
|
||||
onClick={() => setRecent7d(v => !v)}
|
||||
className={`text-[11px] px-3 py-1 rounded-full font-medium cursor-pointer transition-colors ${
|
||||
recent7d ? 'bg-emerald-600 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'
|
||||
}`}
|
||||
title="仅看最近 7 天(不含已取消)"
|
||||
>
|
||||
近 7 天
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
@@ -137,14 +160,14 @@ export default function NotificationHistory({ onClose, onChange }: Props) {
|
||||
<div className="py-16 text-center text-slate-400 text-xs flex items-center justify-center gap-2">
|
||||
<Loader2 size={14} className="animate-spin" /> 加载中
|
||||
</div>
|
||||
) : records.length === 0 ? (
|
||||
) : visibleRecords.length === 0 ? (
|
||||
<div className="py-16 text-center text-slate-400">
|
||||
<Clock className="w-8 h-8 text-slate-200 mx-auto mb-2" />
|
||||
<p className="text-sm">暂无记录</p>
|
||||
<p className="text-sm">{recent7d ? '最近 7 天暂无干预记录' : '暂无记录'}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y divide-slate-50">
|
||||
{records.map(rec => {
|
||||
{visibleRecords.map(rec => {
|
||||
const badge = statusBadge(rec.status);
|
||||
const busy = mutatingId === rec.id;
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user