fix(reminders): keine Dauermeldung ohne localStorage, Mail nach Zeitaenderung, null-Pruefung
- Merkliste zusaetzlich im Arbeitsspeicher (sonst alle 10 s dieselbe Meldung) - Aendern der Faelligkeit atomar gegen gleichzeitiges Faelligwerden, setzt Mail-Spur zurueck - UpdateReminderDto lehnt null ab (400 statt 500) - keine Mails an deaktivierte Benutzer - Spaeter erinnern beschriftet heute/morgen nach dem berechneten Zeitpunkt - Bearbeiten schickt dueAt nur bei geaenderter Zeit Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,15 +3,15 @@
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { browserPermissionState } from '@/lib/reminder-notify';
|
||||
import { type SnoozePreset, snoozeTarget } from '@/lib/reminder-time';
|
||||
import { isSameLocalDay, type SnoozePreset, snoozeTarget } from '@/lib/reminder-time';
|
||||
import {
|
||||
deleteReminder,
|
||||
getReminderEmailStatus,
|
||||
listReminders,
|
||||
REMINDERS_CHANGED_EVENT,
|
||||
type Reminder,
|
||||
type ReminderEmailStatus,
|
||||
ReminderRequestError,
|
||||
deleteReminder,
|
||||
getReminderEmailStatus,
|
||||
listReminders,
|
||||
snoozeReminder,
|
||||
} from '@/lib/reminders-api';
|
||||
import type { WidgetProps } from '../widget-registry';
|
||||
@@ -107,7 +107,9 @@ export function ReminderWidget(_props: WidgetProps) {
|
||||
/** Fehler einer Zeilenaktion: 409 heisst, der Stand war veraltet — Text zeigen und neu laden. */
|
||||
const handleFailure = (err: unknown, conflictKey: string) => {
|
||||
setNotice(
|
||||
err instanceof ReminderRequestError && err.status === 409 ? t(conflictKey) : t('reminder.saveError'),
|
||||
err instanceof ReminderRequestError && err.status === 409
|
||||
? t(conflictKey)
|
||||
: t('reminder.saveError'),
|
||||
);
|
||||
void refetch();
|
||||
};
|
||||
@@ -134,6 +136,16 @@ export function ReminderWidget(_props: WidgetProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// „Heute“ oder „Morgen“ aus dem tatsaechlich berechneten Zeitpunkt: kurz nach
|
||||
// Mitternacht liegt das naechste Vorkommen der Uhrzeit noch heute.
|
||||
const tomorrowLabel = (r: Reminder) => {
|
||||
const target = snoozeTarget('tomorrow', new Date(r.dueAt), new Date(now));
|
||||
const time = timeOnly.format(target);
|
||||
return isSameLocalDay(target, new Date(now))
|
||||
? t('reminder.snoozeToday', { time })
|
||||
: t('reminder.snoozeTomorrow', { time });
|
||||
};
|
||||
|
||||
const remove = async (id: string) => {
|
||||
setNotice(null);
|
||||
setConfirmDeleteId(null);
|
||||
@@ -177,7 +189,9 @@ export function ReminderWidget(_props: WidgetProps) {
|
||||
}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<p className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">{r.title}</p>
|
||||
<p className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">
|
||||
{r.title}
|
||||
</p>
|
||||
{r.emailEnabled && (
|
||||
<span
|
||||
className="shrink-0 text-muted-foreground"
|
||||
@@ -244,8 +258,7 @@ export function ReminderWidget(_props: WidgetProps) {
|
||||
>
|
||||
{preset === '10m' && t('reminder.snooze10m')}
|
||||
{preset === '1h' && t('reminder.snooze1h')}
|
||||
{preset === 'tomorrow' &&
|
||||
t('reminder.snoozeTomorrow', { time: timeOnly.format(new Date(r.dueAt)) })}
|
||||
{preset === 'tomorrow' && tomorrowLabel(r)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user