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 | 134x 134x 134x 2580x 2580x 2580x 2580x 12092x 12092x 2580x 2580x 2580x 2862x 66x 66x 66x 66x 5x 2x 1x 1x 2x 3x 2x 2x 1x 2580x 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 2580x | 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}
/>
)
}
|