feat: reminder button in list/tabs view, notifications show reminders, trash count live update
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 43s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 43s
- Add reminder action to NoteActions (masonry view) and NoteMetaSidebar (tabs view) - NotificationPanel now fetches and displays upcoming/overdue reminders alongside share requests - Badge count includes overdue reminders; overdue items show mark-as-done toggle - Sidebar trash count refreshes on NoteRefreshContext trigger (no more manual refresh) - Add "Clear completed" button on reminders page with clearCompletedReminders action - Add i18n keys for new features (en/fr) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -50,8 +50,10 @@ import {
|
||||
History,
|
||||
PanelRightClose,
|
||||
PanelRightOpen,
|
||||
Bell,
|
||||
} from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { ReminderDialog } from '@/components/reminder-dialog'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -385,17 +387,20 @@ function NoteMetaSidebar({
|
||||
onArchive,
|
||||
onOpenHistory,
|
||||
onEnableHistory,
|
||||
onUpdateReminder,
|
||||
}: {
|
||||
note: Note
|
||||
onPinToggle: (note: Note) => void
|
||||
onArchive: (note: Note) => void
|
||||
onOpenHistory?: (note: Note) => void
|
||||
onEnableHistory?: (noteId: string) => Promise<void>
|
||||
onUpdateReminder?: (noteId: string, reminder: Date | null) => void
|
||||
}) {
|
||||
const { t } = useLanguage()
|
||||
const { notebooks, moveNoteToNotebookOptimistic } = useNotebooks()
|
||||
const [moveOpen, setMoveOpen] = useState(false)
|
||||
const [isMoving, setIsMoving] = useState(false)
|
||||
const [showReminder, setShowReminder] = useState(false)
|
||||
|
||||
// t() returns the key itself when not found — use this wrapper for safe fallbacks
|
||||
const ts = (key: string, fallback: string) => {
|
||||
@@ -571,6 +576,32 @@ function NoteMetaSidebar({
|
||||
onClick={() => onArchive(note)}
|
||||
/>
|
||||
|
||||
{/* Reminder */}
|
||||
{onUpdateReminder && (
|
||||
<>
|
||||
<SidebarActionBtn
|
||||
icon={<Bell className={cn("h-3.5 w-3.5", note.reminder && "text-primary")} />}
|
||||
label={t('reminder.setReminder')}
|
||||
onClick={() => setShowReminder(true)}
|
||||
/>
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<ReminderDialog
|
||||
open={showReminder}
|
||||
onOpenChange={setShowReminder}
|
||||
currentReminder={note.reminder ? new Date(note.reminder) : null}
|
||||
onSave={(date) => {
|
||||
onUpdateReminder(note.id, date)
|
||||
setShowReminder(false)
|
||||
}}
|
||||
onRemove={() => {
|
||||
onUpdateReminder(note.id, null)
|
||||
setShowReminder(false)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* History */}
|
||||
<SidebarActionBtn
|
||||
icon={<History className="h-3.5 w-3.5" />}
|
||||
@@ -928,6 +959,22 @@ export function NotesTabsView({
|
||||
onArchive={handleArchive}
|
||||
onOpenHistory={onOpenHistory}
|
||||
onEnableHistory={onEnableHistory}
|
||||
onUpdateReminder={async (noteId, reminder) => {
|
||||
try {
|
||||
await updateNote(noteId, { reminder })
|
||||
setItems((prev) =>
|
||||
prev.map((n) => (n.id === noteId ? { ...n, reminder } : n))
|
||||
)
|
||||
if (reminder) {
|
||||
toast.success(t('notes.reminderSet', { datetime: reminder.toLocaleString() }))
|
||||
} else {
|
||||
toast.info(t('reminder.removeReminder'))
|
||||
}
|
||||
triggerRefresh()
|
||||
} catch {
|
||||
toast.error(t('general.error'))
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user