All files / layers / L2R / slots Crud.tsx

72.03% Statements 85/118
50% Branches 53/106
86.66% Functions 13/15
79.06% Lines 68/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          46x   46x 46x   676x 676x 676x 676x 1864x 1864x 676x 676x 676x 750x     42x     42x   42x   42x 5x 2x 1x   1x   2x   3x 2x 2x   1x     676x 1x 1x 1x 42x 7x 4x 4x 4x 1x 4x 4x 4x 2x 1x 1x   1x 1x   2x 4x   3x 2x 2x   1x 1x 7x 1x           42x     676x                        
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
   E   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}
      fieldConfigs={fieldConfigMap}
      entitySelectData={snapshot.entitySelectData}
      overrides={titleOverride as CrudVisualOverrides | undefined}
    />
  )
}