@@ -16,9 +16,12 @@ import toast from "react-hot-toast";
1616 */
1717
1818import { Skeleton } from "@/components/ui/Skeleton" ;
19+ import { useQueryClient } from "@tanstack/react-query" ;
1920import {
2021 getDashboardAnalytics ,
2122 fetchDashboardData ,
23+ useDashboard ,
24+ dashboardQueryKey ,
2225 type DashboardSnapshot ,
2326 type Stream ,
2427} from "@/lib/dashboard" ;
@@ -440,13 +443,13 @@ function renderRecentActivity(snapshot: DashboardSnapshot | null, onCreateStream
440443// ─── Main Component ───────────────────────────────────────────────────────────
441444
442445export function DashboardView ( { session, onDisconnect } : DashboardViewProps ) {
446+ const queryClient = useQueryClient ( ) ;
443447 const [ activeTab , setActiveTab ] = React . useState ( "overview" ) ;
444448 const [ showWizard , setShowWizard ] = React . useState ( false ) ;
445449 const [ modal , setModal ] = React . useState < ModalState > ( null ) ;
446450
447- const [ snapshot , setSnapshot ] = React . useState < DashboardSnapshot | null > ( null ) ;
448- const [ isSnapshotLoading , setIsSnapshotLoading ] = React . useState ( true ) ;
449- const [ snapshotError , setSnapshotError ] = React . useState < string | null > ( null ) ;
451+ const { data : snapshot = null , isLoading : isSnapshotLoading , error : queryError , refetch } = useDashboard ( session . publicKey ) ;
452+ const snapshotError = queryError ? ( queryError as Error ) . message : null ;
450453
451454 const { events : streamEvents , connected, reconnecting, error } = useStreamEvents ( {
452455 userPublicKeys : [ session . publicKey ] ,
@@ -459,15 +462,11 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
459462 if ( latestEvent ) {
460463 const relevantTypes = [ "created" , "topped_up" , "withdrawn" , "cancelled" , "completed" , "paused" , "resumed" ] ;
461464 if ( relevantTypes . includes ( latestEvent . type ) ) {
462- fetchDashboardData ( session . publicKey )
463- . then ( setSnapshot )
464- . catch ( ( err ) => {
465- setSnapshotError ( err instanceof Error ? err . message : "Failed to refresh dashboard" ) ;
466- } ) ;
465+ queryClient . invalidateQueries ( { queryKey : dashboardQueryKey ( session . publicKey ) } ) ;
467466 }
468467 }
469468 }
470- } , [ streamEvents , session . publicKey ] ) ;
469+ } , [ streamEvents , session . publicKey , queryClient ] ) ;
471470
472471 const [ streamForm , setStreamForm ] = React . useState < StreamFormValues > ( EMPTY_STREAM_FORM ) ;
473472 const [ templates , setTemplates ] = React . useState < StreamTemplate [ ] > ( [ ] ) ;
@@ -524,42 +523,7 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
524523 persistTemplates ( templates ) ;
525524 } , [ templates , templatesHydrated ] ) ;
526525
527- // ── Load dashboard snapshot ───────────────────────────────────────────────
528-
529- const loadSnapshot = React . useCallback ( async ( ) => {
530- setIsSnapshotLoading ( true ) ;
531- setSnapshotError ( null ) ;
532- try {
533- const next = await fetchDashboardData ( session . publicKey ) ;
534- setSnapshot ( next ) ;
535- } catch ( err ) {
536- setSnapshot ( null ) ;
537- setSnapshotError ( err instanceof Error ? err . message : "Failed to fetch dashboard data." ) ;
538- } finally {
539- setIsSnapshotLoading ( false ) ;
540- }
541- } , [ session . publicKey , setIsSnapshotLoading , setSnapshotError , setSnapshot ] ) ;
542-
543- React . useEffect ( ( ) => {
544- let cancelled = false ;
545- const run = async ( ) => {
546- setIsSnapshotLoading ( true ) ;
547- setSnapshotError ( null ) ;
548- try {
549- const next = await fetchDashboardData ( session . publicKey ) ;
550- if ( ! cancelled ) setSnapshot ( next ) ;
551- } catch ( err ) {
552- if ( ! cancelled ) {
553- setSnapshot ( null ) ;
554- setSnapshotError ( err instanceof Error ? err . message : "Failed to fetch dashboard data." ) ;
555- }
556- } finally {
557- if ( ! cancelled ) setIsSnapshotLoading ( false ) ;
558- }
559- } ;
560- void run ( ) ;
561- return ( ) => { cancelled = true ; } ;
562- } , [ session . publicKey ] ) ;
526+ const loadSnapshot = ( ) => refetch ( ) ;
563527
564528 // ── Template handlers ─────────────────────────────────────────────────────
565529
@@ -619,19 +583,19 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
619583 // ── Optimistic helpers ────────────────────────────────────────────────────
620584
621585 const removeStreamLocally = ( streamId : string ) => {
622- setSnapshot ( ( prev ) => {
586+ queryClient . setQueryData < DashboardSnapshot | undefined > ( dashboardQueryKey ( session . publicKey ) , ( prev ) => {
623587 if ( ! prev ) return prev ;
624588 return { ...prev , outgoingStreams : prev . outgoingStreams . map ( ( s ) => s . id === streamId ? { ...s , status : "Cancelled" , isActive : false } : s ) , activeStreamsCount : Math . max ( 0 , prev . activeStreamsCount - 1 ) } ;
625589 } ) ;
626590 } ;
627591
628592 const topUpStreamLocally = ( streamId : string , amount : number ) => {
629- setSnapshot ( ( prev ) => { if ( ! prev ) return prev ; return { ...prev , outgoingStreams : prev . outgoingStreams . map ( ( s ) => s . id === streamId ? { ...s , deposited : s . deposited + amount } : s ) } ; } ) ;
593+ queryClient . setQueryData < DashboardSnapshot | undefined > ( dashboardQueryKey ( session . publicKey ) , ( prev ) => { if ( ! prev ) return prev ; return { ...prev , outgoingStreams : prev . outgoingStreams . map ( ( s ) => s . id === streamId ? { ...s , deposited : s . deposited + amount } : s ) } ; } ) ;
630594 } ;
631595
632596 const addStreamLocally = ( data : StreamFormData ) => {
633597 const newStream : Stream = { id : `stream-${ Date . now ( ) } ` , date : new Date ( ) . toISOString ( ) . split ( "T" ) [ 0 ] ?? "" , recipient : shortenPublicKey ( data . recipient ) , amount : parseFloat ( data . amount ) , token : data . token , status : "Active" , deposited : parseFloat ( data . amount ) , withdrawn : 0 , ratePerSecond : 0 , lastUpdateTime : Math . floor ( Date . now ( ) / 1000 ) , isActive : true } ;
634- setSnapshot ( ( prev ) => { if ( ! prev ) return prev ; return { ...prev , outgoingStreams : [ newStream , ...prev . outgoingStreams ] , activeStreamsCount : prev . activeStreamsCount + 1 } ; } ) ;
598+ queryClient . setQueryData < DashboardSnapshot | undefined > ( dashboardQueryKey ( session . publicKey ) , ( prev ) => { if ( ! prev ) return prev ; return { ...prev , outgoingStreams : [ newStream , ...prev . outgoingStreams ] , activeStreamsCount : prev . activeStreamsCount + 1 } ; } ) ;
635599 } ;
636600
637601 // ── Contract handlers ─────────────────────────────────────────────────────
@@ -685,8 +649,7 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) {
685649 setWithdrawingIncomingStreamId ( stream . id ) ;
686650 try {
687651 await sorobanWithdraw ( session , { streamId : BigInt ( stream . id . replace ( / \D / g, "" ) || "0" ) } ) ;
688- const refreshed = await fetchDashboardData ( session . publicKey ) ;
689- setSnapshot ( refreshed ) ;
652+ await queryClient . invalidateQueries ( { queryKey : dashboardQueryKey ( session . publicKey ) } ) ;
690653 toast . success ( "Withdrawal successful!" , { id : toastId } ) ;
691654 } catch ( err ) {
692655 toast . error ( toSorobanErrorMessage ( err ) , { id : toastId } ) ;
0 commit comments