All files / layers / L2R / slots Crud.tsx

93.75% Statements 45/48
76.59% Branches 36/47
100% Functions 5/5
93.61% Lines 44/47

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                      7x     58x 58x 58x 202x 58x 202x     58x     58x   58x   58x 5x 2x 1x   1x   2x   3x 2x 2x   1x     1x       58x 9x 6x 6x 6x   6x 6x 6x 2x 1x 1x   1x 1x   4x 6x   3x 2x 2x   1x 1x 9x 1x           58x                                  
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)
    }
  }, [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
      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}
    />
  )
}