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 | 68x 68x 68x 1336x 1336x 1336x 1336x 5588x 5588x 1336x 1336x 1336x 1570x 66x 66x 66x 66x 5x 2x 1x 1x 2x 3x 2x 2x 1x 1336x 8x 8x 8x 66x 9x 8x 8x 6x 1x 6x 6x 6x 2x 1x 7x 7x 1x 1x 4x 6x 3x 2x 2x 1x 1x 9x 1x 66x 1336x | 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}
/>
)
}
|