Skip to content

Commit abe756a

Browse files
fix(ux): add toast feedback to 5 silent success operations
Add consistent toast notifications for operations that previously completed silently: move-to-maintenance success, comment delete/color error handling with Sentry, undo via sonner replacing custom floating div, and CommentInlineEdit error catch.
1 parent 32d932f commit abe756a

File tree

3 files changed

+20
-21
lines changed

3 files changed

+20
-21
lines changed

src/app/board/[id]/BoardPageClient.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export const BoardPageClient = memo(function BoardPageClient({
148148
executeCardAction(cardId, moveToMaintenance, {
149149
actionName: 'moveToMaintenance',
150150
errorMessage: 'Failed to move to maintenance',
151+
successMessage: 'Moved to maintenance',
151152
}),
152153
[executeCardAction],
153154
)

src/components/Board/CommentInlineEdit.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ export const CommentInlineEdit = memo<CommentInlineEditProps>(
129129
if (closeOnSave) {
130130
toast.success('Comment saved')
131131
}
132+
} catch {
133+
toast.error('Failed to save comment')
132134
} finally {
133135
setIsSaving(false)
134136
}

src/components/Board/KanbanBoard.tsx

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ export const KanbanBoard = memo<KanbanBoardProps>(
172172
// Note: _boardId is no longer used for data fetching (Phase 4 refactoring)
173173
// Data is now fetched by Server Component and passed via props/Redux
174174
// Kept for backwards compatibility and potential future use (e.g., refresh)
175-
const prefersReducedMotion = useReducedMotion()
176175
// Redux state (auto-synced to LocalStorage)
177176
const dispatch = useAppDispatch()
178177
const statuses = useAppSelector(selectStatusLists)
@@ -193,7 +192,6 @@ export const KanbanBoard = memo<KanbanBoardProps>(
193192
// Uses useSyncExternalStore-based hook for proper SSR support
194193
const isMounted = useMounted()
195194
const [columnHistory, setColumnHistory] = useState<StatusListDomain[][]>([])
196-
const [undoMessage, setUndoMessage] = useState<string | null>(null)
197195

198196
// Memoized sorted statuses for consistent rendering (by gridRow, then gridCol)
199197
const sortedStatuses = useMemo(
@@ -325,7 +323,14 @@ export const KanbanBoard = memo<KanbanBoardProps>(
325323
}))
326324

327325
// Persist to database
328-
await updateCommentColor(cardId, color)
326+
try {
327+
await updateCommentColor(cardId, color)
328+
} catch (error) {
329+
Sentry.captureException(error, {
330+
tags: { action: 'updateCommentColor' },
331+
})
332+
toast.error('Failed to update comment color')
333+
}
329334
},
330335
[],
331336
)
@@ -347,7 +352,13 @@ export const KanbanBoard = memo<KanbanBoardProps>(
347352
}))
348353

349354
// Persist to database
350-
await deleteComment(cardId)
355+
try {
356+
await deleteComment(cardId)
357+
toast.success('Comment deleted')
358+
} catch (error) {
359+
Sentry.captureException(error, { tags: { action: 'deleteComment' } })
360+
toast.error('Failed to delete comment')
361+
}
351362
}, [])
352363

353364
/**
@@ -362,8 +373,7 @@ export const KanbanBoard = memo<KanbanBoardProps>(
362373
if (previousState) {
363374
dispatch(setStatusLists(previousState))
364375
setColumnHistory((prev) => prev.slice(0, -1))
365-
setUndoMessage('Column order restored')
366-
setTimeout(() => setUndoMessage(null), 2000)
376+
toast.success('Column order restored')
367377

368378
// P1-8: Sync reverted column positions to DB
369379
const updates = previousState.map((s) => ({
@@ -386,8 +396,7 @@ export const KanbanBoard = memo<KanbanBoardProps>(
386396
if (previousState) {
387397
dispatch(setRepoCards(previousState))
388398
setHistory((prev) => prev.slice(0, -1))
389-
setUndoMessage('Card operation undone')
390-
setTimeout(() => setUndoMessage(null), 2000)
399+
toast.success('Card operation undone')
391400

392401
// P1-8: Sync reverted card positions to DB
393402
const updates = previousState.map((c, index) => ({
@@ -708,19 +717,6 @@ export const KanbanBoard = memo<KanbanBoardProps>(
708717

709718
return (
710719
<div className="relative w-fit min-w-full p-6">
711-
{/* Undo message display */}
712-
{undoMessage && (
713-
<motion.div
714-
initial={prefersReducedMotion ? false : { opacity: 0, y: -20 }}
715-
animate={{ opacity: 1, y: 0 }}
716-
exit={{ opacity: 0 }}
717-
transition={{ duration: prefersReducedMotion ? 0 : undefined }}
718-
className="bg-primary text-primary-foreground absolute top-4 left-1/2 z-50 -translate-x-1/2 transform rounded-lg px-4 py-2 shadow-lg"
719-
>
720-
{undoMessage}
721-
</motion.div>
722-
)}
723-
724720
<DndContext
725721
sensors={sensors}
726722
collisionDetection={forgivingCollisionDetection}

0 commit comments

Comments
 (0)