diff --git a/client/src/resources/equipment-type/EquipmentTypeShow.tsx b/client/src/resources/equipment-type/EquipmentTypeShow.tsx index d81b0a3..f96ec96 100644 --- a/client/src/resources/equipment-type/EquipmentTypeShow.tsx +++ b/client/src/resources/equipment-type/EquipmentTypeShow.tsx @@ -1,13 +1,13 @@ -import { Show, SimpleShowLayout, TextField } from 'react-admin'; +import { Show, SimpleShowLayout, TextField, NumberField } from 'react-admin'; export const EquipmentTypeShow = () => ( - - - - - + + + + + ); diff --git a/client/src/resources/equipment/EquipmentShow.tsx b/client/src/resources/equipment/EquipmentShow.tsx index 10dfd4d..fc099e4 100644 --- a/client/src/resources/equipment/EquipmentShow.tsx +++ b/client/src/resources/equipment/EquipmentShow.tsx @@ -1,20 +1,28 @@ -import { Show, SimpleShowLayout, TextField } from 'react-admin'; +import { Show, SimpleShowLayout, TextField, NumberField, DateField, SelectField, ReferenceField } from 'react-admin'; +const statusChoices = [ + { id: 'Active', name: 'В эксплуатации' }, + { id: 'Repair', name: 'В ремонте' }, + { id: 'Reserve', name: 'В резерве' }, + { id: 'WriteOff', name: 'Списано' }, +]; export const EquipmentShow = () => ( - - - - - - - - - - - + + + + + + + + + + + + + ); diff --git a/client/src/resources/repair-order/RepairOrderShow.tsx b/client/src/resources/repair-order/RepairOrderShow.tsx index 10c6769..78f2a79 100644 --- a/client/src/resources/repair-order/RepairOrderShow.tsx +++ b/client/src/resources/repair-order/RepairOrderShow.tsx @@ -1,20 +1,38 @@ -import { Show, SimpleShowLayout, TextField } from 'react-admin'; +import { Show, SimpleShowLayout, TextField, NumberField, DateField, SelectField, ReferenceField } from 'react-admin'; +const repairKindChoices = [ + { id: 'TO', name: 'Техническое обслуживание' }, + { id: 'TR', name: 'Текущий ремонт' }, + { id: 'TRE', name: 'Текущий расширенный ремонт' }, + { id: 'KR', name: 'Капитальный ремонт' }, + { id: 'AR', name: 'Аварийный ремонт' }, + { id: 'MP', name: 'Метрологическая поверка' }, +]; + +const statusChoices = [ + { id: 'Draft', name: 'Черновик' }, + { id: 'Approved', name: 'Утверждена' }, + { id: 'InWork', name: 'В работе' }, + { id: 'Done', name: 'Выполнена' }, + { id: 'Cancelled', name: 'Отменена' }, +]; export const RepairOrderShow = () => ( - - - - - - - - - - - + + + + + + + + + + + + + ); diff --git a/generation/generate.mjs b/generation/generate.mjs index 595797f..c37046d 100644 --- a/generation/generate.mjs +++ b/generation/generate.mjs @@ -550,7 +550,42 @@ function renderFrontendResource(entityName, entity, resourceName, pk, enums, all const editImports = ['Edit', ...Array.from(formImportSet)].join(', '); const edit = `import { ${editImports} } from 'react-admin';\n\n${choiceConsts.join('\n')}\nexport const ${className}Edit = () => (\n \n \n ${entity.attributes.map((a) => formField(a, 'edit')).filter(Boolean).join('\n ')}\n \n \n);\n`; - const show = `import { Show, SimpleShowLayout, TextField } from 'react-admin';\n\nexport const ${className}Show = () => (\n \n \n ${entity.attributes.map((a) => ``).join('\n ')}\n \n \n);\n`; + const showImportSet = new Set(['Show', 'SimpleShowLayout', 'TextField']); + if (hasNumber) showImportSet.add('NumberField'); + if (hasDate) showImportSet.add('DateField'); + if (enumAttrs.length) showImportSet.add('SelectField'); + if (hasFK) showImportSet.add('ReferenceField'); + + const showFields = []; + for (const a of entity.attributes) { + const label = getAttributeLabel(a, allEntities); + if (a.foreign) { + const referenceEntity = allEntities[a.foreign.entity]; + const referenceAttrs = getEntityAttrNames(referenceEntity); + const fieldSource = referenceAttrs.has('inventoryNumber') + ? 'inventoryNumber' + : referenceAttrs.has('code') + ? 'code' + : referenceAttrs.has('number') + ? 'number' + : 'name'; + showFields.push( + `\n \n ` + ); + continue; + } + if (a.type === 'date') { + showFields.push(``); + } else if (['integer', 'decimal'].includes(a.type)) { + showFields.push(``); + } else if (!['string', 'text', 'uuid', 'integer', 'decimal', 'date'].includes(a.type)) { + showFields.push(``); + } else { + showFields.push(``); + } + } + + const show = `import { ${Array.from(showImportSet).join(', ')} } from 'react-admin';\n\n${choiceConsts.join('\n')}export const ${className}Show = () => (\n \n \n ${showFields.join('\n ')}\n \n \n);\n`; return { files: { diff --git a/prompts/frontend-rules.md b/prompts/frontend-rules.md index 65071b5..82b068c 100644 --- a/prompts/frontend-rules.md +++ b/prompts/frontend-rules.md @@ -25,6 +25,7 @@ The frontend stays a React Admin SPA generated from `domain/*.dsl` and anchored - Each entity becomes a React Admin resource with list/create/edit/show views. - Resource names must stay aligned with backend path segments. - Foreign keys must use `ReferenceInput` / `ReferenceField`. +- Foreign keys shown in list/show views must stay clickable via `ReferenceField link="show"` to open full details of the related resource. - Lists must expose filters through `List` `filters` and an actions toolbar with `FilterButton`. - For enum fields where multi-select is required (for example `status`), use `SelectArrayInput` in list filters. - For foreign key filters and form selection use `ReferenceInput` + `AutocompleteInput` with `filterToQuery={(searchText) => ({ q: searchText })}`. @@ -50,6 +51,7 @@ The frontend stays a React Admin SPA generated from `domain/*.dsl` and anchored - Natural-key resources must preserve route, update, and sort compatibility with React Admin contracts. - Frontend requests must continue to work when the real primary key is not named `id`. - `dataProvider` query serialization must preserve repeated query params for array filters (for example enum multi-select). +- `Resource` wiring in `App.tsx` must keep `show={...}` registration for all generated resources. ## Reproducibility invariants diff --git a/prompts/validation-rules.md b/prompts/validation-rules.md index a26249d..a071be5 100644 --- a/prompts/validation-rules.md +++ b/prompts/validation-rules.md @@ -52,6 +52,8 @@ Validation is now a lightweight automated gate instead of a prose-only checklist - typed form mapping is preserved: - `integer` / `decimal` -> `NumberInput` - `date` -> `DateInput` +- reference fields intended for navigation keep `ReferenceField link="show"` +- resources keep `show={...}` registration in `App.tsx` ### Natural-key checks