ExportAllRows.progress.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { useCallback, useRef, type ReactNode } from 'react'
  2. import { toast } from 'sonner'
  3. import { SonnerProgress } from 'ui'
  4. export const useProgressToasts = () => {
  5. const toastIdsRef = useRef(new Map<number, string | number>())
  6. const startProgressTracker = useCallback(
  7. ({
  8. id,
  9. name,
  10. trackPercentage = false,
  11. }: {
  12. id: number
  13. name: string
  14. trackPercentage?: boolean
  15. }) => {
  16. if (toastIdsRef.current.has(id)) return
  17. if (trackPercentage) {
  18. toastIdsRef.current.set(
  19. id,
  20. toast(<SonnerProgress progress={0} message={`Exporting ${name}...`} />, {
  21. closeButton: false,
  22. duration: Infinity,
  23. })
  24. )
  25. } else {
  26. toastIdsRef.current.set(id, toast.loading(`Exporting ${name}...`))
  27. }
  28. },
  29. []
  30. )
  31. const trackPercentageProgress = useCallback(
  32. ({
  33. id,
  34. name,
  35. value,
  36. totalRows,
  37. }: {
  38. id: number
  39. name: string
  40. value: number
  41. totalRows: number
  42. }) => {
  43. const savedToastId = toastIdsRef.current.get(id)
  44. const progress = Math.min((value / totalRows) * 100, 100)
  45. const newToastId = toast(
  46. <SonnerProgress progress={progress} message={`Exporting ${name}...`} />,
  47. {
  48. id: savedToastId,
  49. closeButton: false,
  50. duration: Infinity,
  51. }
  52. )
  53. if (!savedToastId) toastIdsRef.current.set(id, newToastId)
  54. },
  55. []
  56. )
  57. const stopTrackerWithError = useCallback(
  58. (id: number, name: string, customMessage?: ReactNode) => {
  59. const savedToastId = toastIdsRef.current.get(id)
  60. if (savedToastId) {
  61. toast.dismiss(savedToastId)
  62. toastIdsRef.current.delete(id)
  63. }
  64. toast.error(customMessage ?? `There was an error exporting ${name}`)
  65. },
  66. []
  67. )
  68. const dismissTrackerSilently = useCallback((id: number) => {
  69. const savedToastId = toastIdsRef.current.get(id)
  70. if (savedToastId) {
  71. toast.dismiss(savedToastId)
  72. toastIdsRef.current.delete(id)
  73. }
  74. }, [])
  75. const markTrackerComplete = useCallback((id: number, totalRows: number) => {
  76. const savedToastId = toastIdsRef.current.get(id)
  77. const deleteSavedToastId = () => toastIdsRef.current.delete(id)
  78. toast.success(`Successfully exported ${totalRows} rows`, {
  79. id: savedToastId,
  80. duration: 4000,
  81. onAutoClose: deleteSavedToastId,
  82. onDismiss: deleteSavedToastId,
  83. })
  84. }, [])
  85. return {
  86. startProgressTracker,
  87. trackPercentageProgress,
  88. stopTrackerWithError,
  89. dismissTrackerSilently,
  90. markTrackerComplete,
  91. }
  92. }