PoliciesDataContext.tsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import type { PropsWithChildren } from 'react'
  2. import { createContext, useCallback, useContext, useMemo } from 'react'
  3. import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
  4. import type { ResponseError } from '@/types'
  5. type TableKey = `${string}.${string}`
  6. type PoliciesDataContextValue = {
  7. getPoliciesForTable: (schema: string, table: string) => Array<Policy>
  8. isPoliciesLoading: boolean
  9. isPoliciesError: boolean
  10. policiesError?: ResponseError | Error
  11. exposedSchemas: Set<string>
  12. }
  13. const PoliciesDataContext = createContext<PoliciesDataContextValue | null>(null)
  14. export const usePoliciesData = () => {
  15. const context = useContext(PoliciesDataContext)
  16. if (!context) throw new Error('usePoliciesData must be used within PoliciesDataProvider')
  17. return context
  18. }
  19. type PoliciesDataProviderProps = {
  20. policies: Array<Policy>
  21. isPoliciesLoading: boolean
  22. isPoliciesError: boolean
  23. policiesError?: ResponseError | Error
  24. exposedSchemas: string[]
  25. }
  26. export const PoliciesDataProvider = ({
  27. children,
  28. policies,
  29. isPoliciesLoading,
  30. isPoliciesError,
  31. policiesError,
  32. exposedSchemas,
  33. }: PropsWithChildren<PoliciesDataProviderProps>) => {
  34. const policiesByTable = useMemo(() => {
  35. const map = new Map<TableKey, Array<Policy>>()
  36. for (const policy of policies) {
  37. const key = `${policy.schema}.${policy.table}` satisfies TableKey
  38. const existing = map.get(key)
  39. if (existing) {
  40. existing.push(policy)
  41. } else {
  42. map.set(key, [policy])
  43. }
  44. }
  45. for (const list of map.values()) {
  46. list.sort((a, b) => a.name.localeCompare(b.name))
  47. }
  48. return map
  49. }, [policies])
  50. const getPoliciesForTable = useCallback(
  51. (schema: string, table: string) => policiesByTable.get(`${schema}.${table}`) ?? [],
  52. [policiesByTable]
  53. )
  54. const exposedSchemasSet = useMemo(() => new Set(exposedSchemas), [exposedSchemas])
  55. const contextValue = useMemo(
  56. () => ({
  57. getPoliciesForTable,
  58. isPoliciesLoading,
  59. isPoliciesError,
  60. policiesError,
  61. exposedSchemas: exposedSchemasSet,
  62. }),
  63. [getPoliciesForTable, isPoliciesLoading, isPoliciesError, policiesError, exposedSchemasSet]
  64. )
  65. return (
  66. <PoliciesDataContext.Provider value={contextValue}>{children}</PoliciesDataContext.Provider>
  67. )
  68. }