@@ -14,6 +14,7 @@ import {
1414import { useLocation } from "@tanstack/react-router" ;
1515import { useCallback , useEffect , useRef , useState } from "react" ;
1616
17+ import { useNotifications } from "@/contexts/NotificationContext" ;
1718import { serializeSearch } from "@/utils/url-decoding" ;
1819
1920const USER_INTERACTIONS_LOGGER_CONTEXT = "user-interactions" ;
@@ -108,6 +109,9 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
108109 // Get router location - must be called unconditionally at top level (React hooks rules)
109110 const location = useLocation ( ) ;
110111
112+ // Get notifications for user feedback
113+ const { showNotification } = useNotifications ( ) ;
114+
111115 // State
112116 const [ recentHistory , setRecentHistory ] = useState < CatalogueEntity [ ] > ( [ ] ) ;
113117 const [ bookmarks , setBookmarks ] = useState < CatalogueEntity [ ] > ( [ ] ) ;
@@ -381,16 +385,28 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
381385 throw new Error ( "Entity ID and type are required to bookmark" ) ;
382386 }
383387
388+ // Optimistic update
389+ const wasBookmarked = isBookmarked ;
390+ setIsBookmarked ( true ) ;
391+
384392 try {
385393 await catalogueService . addBookmark ( {
386394 entityType : entityType as EntityType ,
387395 entityId : entityId ,
388396 notes : tags ? `${ notes || '' } \n\nTags: ${ tags . join ( ', ' ) } ` : notes ,
389397 } ) ;
390398
391- setIsBookmarked ( true ) ;
399+ showNotification ( {
400+ title : "Success" ,
401+ message : "Added to bookmarks" ,
402+ category : "success" ,
403+ } ) ;
404+
392405 await refreshData ( ) ;
393406 } catch ( error ) {
407+ // Rollback optimistic update
408+ setIsBookmarked ( wasBookmarked ) ;
409+
394410 logger . error (
395411 USER_INTERACTIONS_LOGGER_CONTEXT ,
396412 "Failed to bookmark entity" ,
@@ -400,6 +416,13 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
400416 error,
401417 } ,
402418 ) ;
419+
420+ showNotification ( {
421+ title : "Error" ,
422+ message : `Failed to bookmark: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
423+ category : "error" ,
424+ } ) ;
425+
403426 throw error ;
404427 }
405428 } ,
@@ -409,6 +432,8 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
409432 location . pathname ,
410433 location . search ,
411434 refreshData ,
435+ isBookmarked ,
436+ showNotification ,
412437 ] ,
413438 ) ;
414439
@@ -417,6 +442,10 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
417442 throw new Error ( "Entity ID and type are required to unbookmark" ) ;
418443 }
419444
445+ // Optimistic update
446+ const wasBookmarked = isBookmarked ;
447+ setIsBookmarked ( false ) ;
448+
420449 try {
421450 // Find the bookmark record for this entity
422451 const allBookmarks = await catalogueService . getBookmarks ( ) ;
@@ -426,10 +455,19 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
426455
427456 if ( bookmark ?. id ) {
428457 await catalogueService . removeBookmark ( bookmark . id ) ;
429- setIsBookmarked ( false ) ;
458+
459+ showNotification ( {
460+ title : "Success" ,
461+ message : "Removed from bookmarks" ,
462+ category : "success" ,
463+ } ) ;
464+
430465 await refreshData ( ) ;
431466 }
432467 } catch ( error ) {
468+ // Rollback optimistic update
469+ setIsBookmarked ( wasBookmarked ) ;
470+
433471 logger . error (
434472 USER_INTERACTIONS_LOGGER_CONTEXT ,
435473 "Failed to unbookmark entity" ,
@@ -439,9 +477,16 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
439477 error,
440478 } ,
441479 ) ;
480+
481+ showNotification ( {
482+ title : "Error" ,
483+ message : `Failed to remove bookmark: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
484+ category : "error" ,
485+ } ) ;
486+
442487 throw error ;
443488 }
444- } , [ entityId , entityType , refreshData ] ) ;
489+ } , [ entityId , entityType , refreshData , isBookmarked , showNotification ] ) ;
445490
446491 const bookmarkSearch = useCallback (
447492 async ( {
@@ -468,6 +513,13 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
468513 } ) ;
469514
470515 setIsBookmarked ( true ) ;
516+
517+ showNotification ( {
518+ title : "Success" ,
519+ message : "Saved search to bookmarks" ,
520+ category : "success" ,
521+ } ) ;
522+
471523 await refreshData ( ) ;
472524 } catch ( error ) {
473525 logger . error (
@@ -479,10 +531,17 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
479531 error,
480532 } ,
481533 ) ;
534+
535+ showNotification ( {
536+ title : "Error" ,
537+ message : `Failed to save search: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
538+ category : "error" ,
539+ } ) ;
540+
482541 throw error ;
483542 }
484543 } ,
485- [ location . pathname , location . search , refreshData ] ,
544+ [ location . pathname , location . search , refreshData , showNotification ] ,
486545 ) ;
487546
488547 const bookmarkList = useCallback (
@@ -508,6 +567,13 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
508567 } ) ;
509568
510569 setIsBookmarked ( true ) ;
570+
571+ showNotification ( {
572+ title : "Success" ,
573+ message : "Saved list to bookmarks" ,
574+ category : "success" ,
575+ } ) ;
576+
511577 await refreshData ( ) ;
512578 } catch ( error ) {
513579 logger . error (
@@ -518,17 +584,27 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
518584 error,
519585 } ,
520586 ) ;
587+
588+ showNotification ( {
589+ title : "Error" ,
590+ message : `Failed to save list: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
591+ category : "error" ,
592+ } ) ;
593+
521594 throw error ;
522595 }
523596 } ,
524- [ refreshData ] ,
597+ [ refreshData , showNotification ] ,
525598 ) ;
526599
527600 const unbookmarkSearch = useCallback ( async ( ) => {
528601 if ( ! searchQuery ) {
529602 throw new Error ( "Search query is required to unbookmark" ) ;
530603 }
531604
605+ const wasBookmarked = isBookmarked ;
606+ setIsBookmarked ( false ) ;
607+
532608 try {
533609 // Find the bookmark record for this search
534610 const allBookmarks = await catalogueService . getBookmarks ( ) ;
@@ -539,10 +615,19 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
539615
540616 if ( bookmark ?. id ) {
541617 await catalogueService . removeBookmark ( bookmark . id ) ;
542- setIsBookmarked ( false ) ;
618+
619+ showNotification ( {
620+ title : "Success" ,
621+ message : "Removed saved search from bookmarks" ,
622+ category : "success" ,
623+ } ) ;
624+
543625 await refreshData ( ) ;
544626 }
545627 } catch ( error ) {
628+ // Rollback optimistic update
629+ setIsBookmarked ( wasBookmarked ) ;
630+
546631 logger . error (
547632 USER_INTERACTIONS_LOGGER_CONTEXT ,
548633 "Failed to unbookmark search" ,
@@ -552,15 +637,25 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
552637 error,
553638 } ,
554639 ) ;
640+
641+ showNotification ( {
642+ title : "Error" ,
643+ message : `Failed to remove: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
644+ category : "error" ,
645+ } ) ;
646+
555647 throw error ;
556648 }
557- } , [ searchQuery , filters , refreshData ] ) ;
649+ } , [ searchQuery , filters , refreshData , isBookmarked , showNotification ] ) ;
558650
559651 const unbookmarkList = useCallback ( async ( ) => {
560652 if ( ! url ) {
561653 throw new Error ( "URL is required to unbookmark list" ) ;
562654 }
563655
656+ const wasBookmarked = isBookmarked ;
657+ setIsBookmarked ( false ) ;
658+
564659 try {
565660 // Find the bookmark record for this list
566661 const allBookmarks = await catalogueService . getBookmarks ( ) ;
@@ -571,10 +666,19 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
571666
572667 if ( bookmark ?. id ) {
573668 await catalogueService . removeBookmark ( bookmark . id ) ;
574- setIsBookmarked ( false ) ;
669+
670+ showNotification ( {
671+ title : "Success" ,
672+ message : "Removed saved list from bookmarks" ,
673+ category : "success" ,
674+ } ) ;
675+
575676 await refreshData ( ) ;
576677 }
577678 } catch ( error ) {
679+ // Rollback optimistic update
680+ setIsBookmarked ( wasBookmarked ) ;
681+
578682 logger . error (
579683 USER_INTERACTIONS_LOGGER_CONTEXT ,
580684 "Failed to unbookmark list" ,
@@ -583,9 +687,16 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
583687 error,
584688 } ,
585689 ) ;
690+
691+ showNotification ( {
692+ title : "Error" ,
693+ message : `Failed to remove: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
694+ category : "error" ,
695+ } ) ;
696+
586697 throw error ;
587698 }
588- } , [ url , refreshData ] ) ;
699+ } , [ url , refreshData , isBookmarked , showNotification ] ) ;
589700
590701 const updateBookmark = useCallback (
591702 async (
@@ -680,6 +791,12 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
680791 } ) ;
681792 }
682793
794+ showNotification ( {
795+ title : "Success" ,
796+ message : `Removed ${ success } bookmark${ success !== 1 ? 's' : '' } ${ failed > 0 ? ` (${ failed } failed)` : '' } ` ,
797+ category : "success" ,
798+ } ) ;
799+
683800 await refreshData ( ) ; // Refresh data after bulk operation
684801 return { success, failed } ;
685802 } catch ( error ) {
@@ -691,25 +808,46 @@ export const useUserInteractions = (options: UseUserInteractionsOptions = {}): U
691808 error,
692809 } ,
693810 ) ;
811+
812+ showNotification ( {
813+ title : "Error" ,
814+ message : `Bulk remove failed: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
815+ category : "error" ,
816+ } ) ;
817+
694818 throw error ;
695819 }
696820 } ,
697- [ refreshData ] ,
821+ [ refreshData , showNotification ] ,
698822 ) ;
699823
700824 const clearHistory = useCallback ( async ( ) => {
701825 try {
702826 await catalogueService . clearHistory ( ) ;
827+
828+ showNotification ( {
829+ title : "Success" ,
830+ message : "History cleared" ,
831+ category : "success" ,
832+ } ) ;
833+
703834 await refreshData ( ) ;
704835 } catch ( error ) {
705836 logger . error (
706837 USER_INTERACTIONS_LOGGER_CONTEXT ,
707838 "Failed to clear history" ,
708839 { error }
709840 ) ;
841+
842+ showNotification ( {
843+ title : "Error" ,
844+ message : `Failed to clear history: ${ error instanceof Error ? error . message : 'Unknown error' } ` ,
845+ category : "error" ,
846+ } ) ;
847+
710848 throw error ;
711849 }
712- } , [ refreshData ] ) ;
850+ } , [ refreshData , showNotification ] ) ;
713851
714852 return {
715853 // Page visit tracking (now using catalogue history)
0 commit comments