All files / layers / L2R / slots Crud.tsx

73.72% Statements 87/118
55.66% Branches 59/106
86.66% Functions 13/15
80.23% Lines 69/86

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99          137x   137x 137x   2538x 2538x 2538x 2538x 11990x 11990x 2538x 2538x 2538x 2820x     66x     66x   66x   66x 5x 2x 1x   1x   2x   3x 2x 2x   1x     2538x 12x 12x 12x 66x 12x 12x 12x 6x 2x 6x 6x 6x 2x 1x 10x 10x 1x 1x   4x 6x   3x 2x 2x   1x 1x 9x 1x           66x     2538x                            
import { useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { CrudSurface } from '../surfaces/CrudSurface'
import { useEntityCoordinator } from '../../L2W/coordinatorResolver'
import { useRouteContext } from '../../L2W/routes/routeContextStore'
import type { CrudConfig, CrudFieldConfig, CrudVisualOverrides } from '../../interfaces'
 
export interface CrudProps {
  config: CrudConfig
}
 
const FALLBACK_CONTEXT = { page: 'collection' } as const
 
export function Crud({ config }: CrudProps) {
  const navigate = useNavigate()
  const rawContext = useRouteContext()
  const routeContext = rawContext ?? FALLBACK_CONTEXT
  const fieldNames = config.fieldSet.map(f => f.field)
  const fieldConfigMap = Object.fromEntries(
    config.fieldSet.map(fc => [fc.field, fc]),
  ) as Record<string, CrudFieldConfig>

  const { snapshot, updateField, cancel } =
    useEntityCoordinator(config.entityPath, fieldNames, routeContext, config.entitySelectSources)

  const { cancelTarget, onCancel, successTarget, onSuccess } = config

  const titleOverride = config.title ? { labels: { title: config.title } } : undefined

  const handleClose = useCallback(() => {
    if (cancelTarget) {
      if (snapshot.activeCrud?.mode === 'edit' && routeContext.page === 'detail') {
        navigate(cancelTarget.replace(':id', routeContext.id), { replace: true })
      } else {
        navigate(cancelTarget, { replace: true })
      }
      return
    }
    if (onCancel) {
      onCancel()
      return
    }
    Iif (routeContext.page === 'detail' && routeContext.id) {
      navigate('/' + config.entityPath + '/' + routeContext.id, { replace: true })
    } else {
      navigate(-1)
  E  }
  }, [cancelTarget, onCancel, navigate, snapshot.activeCrud, routeContext, config.entityPath])
 
  const handleSuccess = useCallback(() => {
    if (successTarget) {
      const result = snapshot.lastMutationData as Record<string, unknown> | null
      const resultId = typeof result?.id === 'string' ? result.id : undefined
    E  const routeId = routeContext.page === 'detail' ? routeContext.id : undefined
      const resolvedId =
        snapshot.activeCrud?.mode === 'edit' ? (routeId ?? resultId) : resultId
      const needsId = successTarget.includes(':id')
      if (needsId && !resolvedId) {
        if (cancelTarget) {
          navigate(cancelTarget, { replace: true })
          return
        }
        navigate('/' + config.entityPath, { replace: true })
        return
      }
      navigate(successTarget.replace(':id', resolvedId ?? ''), { replace: true })
      return
    }
    if (onSuccess) {
      onSuccess()
      return
    }
    const mutationResult = snapshot.lastMutationData as Record<string, unknown> | null
    const mutationResultId = typeof mutationResult?.id === 'string' ? mutationResult.id : undefined
    if (snapshot.activeCrud?.mode === 'add' && mutationResultId) {
      navigate('/' + config.entityPath + '/' + mutationResultId, { replace: true })
    } else Eif (snapshot.activeCrud?.mode === 'edit' && routeContext.page === 'detail' && routeContext.id) {
      navigate('/' + config.entityPath + '/' + routeContext.id, { replace: true })
    }
  }, [successTarget, cancelTarget, onSuccess, navigate, snapshot.lastMutationData, snapshot.activeCrud, routeContext, config.entityPath])
 
  return (
    <CrudSurface
      coordinatorSnapshot={snapshot}
      routeContext={routeContext}
      onClose={handleClose}
      onSuccess={handleSuccess}
      updateField={updateField}
      cancel={cancel}
      fieldTypes={config.fieldTypes}
      fieldLints={config.fieldLints}
      fieldHelp={config.fieldHelp}
      fieldConfigs={fieldConfigMap}
      entitySelectData={snapshot.entitySelectData}
      overrides={titleOverride as CrudVisualOverrides | undefined}
    />
  )
}