usePagination.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { computed, reactive, readonly, ref } from 'vue'
  3. import type { QueryHandler } from '#shared/server/apollo/handler/index.ts'
  4. import type {
  5. BaseConnection,
  6. OperationQueryResult,
  7. PaginationVariables,
  8. } from '#shared/types/server/apollo/handler.ts'
  9. import type { OperationVariables } from '@apollo/client/core'
  10. export default function usePagination<
  11. TQueryResult extends OperationQueryResult = OperationQueryResult,
  12. TQueryVariables extends OperationVariables = OperationVariables,
  13. >(
  14. query: QueryHandler<TQueryResult, TQueryVariables>,
  15. resultKey: string,
  16. pageSize: number,
  17. ) {
  18. const pageInfo = computed(() => {
  19. const result: OperationQueryResult = query.result().value || {}
  20. return (result[resultKey] as BaseConnection)?.pageInfo
  21. })
  22. const hasNextPage = computed(() => {
  23. return pageInfo.value?.hasNextPage ?? false
  24. })
  25. const hasPreviousPage = computed(() => {
  26. return pageInfo.value?.hasPreviousPage ?? false
  27. })
  28. const getInitialCurrentPage = (): number => {
  29. const result: OperationQueryResult = query.result().value || {}
  30. const data = result[resultKey] as BaseConnection
  31. if (!data) return 1
  32. const currentLength = data.edges?.length || 0
  33. if (!currentLength) return 1
  34. return Math.ceil(currentLength / pageSize)
  35. }
  36. const loadingNewPage = ref(false)
  37. const currentPage = ref(getInitialCurrentPage())
  38. return reactive({
  39. pageInfo: readonly(pageInfo),
  40. hasNextPage: readonly(hasNextPage),
  41. hasPreviousPage: readonly(hasPreviousPage),
  42. loadingNewPage: readonly(loadingNewPage),
  43. currentPage: readonly(currentPage),
  44. async fetchPreviousPage() {
  45. try {
  46. loadingNewPage.value = true
  47. await query.fetchMore({
  48. variables: {
  49. pageSize,
  50. cursor: pageInfo.value?.startCursor,
  51. } as Partial<TQueryVariables & PaginationVariables>,
  52. })
  53. } finally {
  54. currentPage.value -= 1
  55. loadingNewPage.value = false
  56. }
  57. },
  58. async fetchNextPage() {
  59. try {
  60. loadingNewPage.value = true
  61. await query.fetchMore({
  62. variables: {
  63. pageSize,
  64. cursor: pageInfo.value?.endCursor,
  65. } as Partial<TQueryVariables & PaginationVariables>,
  66. })
  67. } finally {
  68. currentPage.value += 1
  69. loadingNewPage.value = false
  70. }
  71. },
  72. })
  73. }