Rework menu for different statuses of equip

This commit is contained in:
Первов Артем
2026-04-30 04:40:42 +03:00
parent fea773bb15
commit 376b4a6a57
7 changed files with 77 additions and 5 deletions

View File

@@ -15,6 +15,7 @@ import { EquipmentStatusChangeCreate } from './resources/equipment-status-change
import { EquipmentStatusChangeEdit } from './resources/equipment-status-change/EquipmentStatusChangeEdit';
import { EquipmentStatusChangeList } from './resources/equipment-status-change/EquipmentStatusChangeList';
import { EquipmentStatusChangeShow } from './resources/equipment-status-change/EquipmentStatusChangeShow';
import { ToirLayout } from './layout/ToirLayout';
function ToirAdmin() {
const paletteMode = useEmbeddedParentTheme();
@@ -32,6 +33,7 @@ function ToirAdmin() {
return (
<Admin
layout={ToirLayout}
dataProvider={dataProvider}
authProvider={authProvider}
theme={theme}
@@ -47,7 +49,7 @@ function ToirAdmin() {
/>
<Resource
name="status-changes"
options={{ label: 'Акты' }}
options={{ label: 'Журнал актов' }}
list={EquipmentStatusChangeList}
create={EquipmentStatusChangeCreate}
edit={EquipmentStatusChangeEdit}

View File

@@ -14,7 +14,7 @@ const customRu = {
},
},
'status-changes': {
name: 'Акт |||| Акты',
name: 'Акт |||| Журнал актов',
fields: {
id: 'ID',
equipmentId: 'Оборудование',

View File

@@ -0,0 +1,7 @@
import type { ComponentProps, ReactElement } from 'react';
import { Layout } from 'react-admin';
import { ToirMenu } from './ToirMenu';
export function ToirLayout(props: ComponentProps<typeof Layout>): ReactElement {
return <Layout {...props} menu={ToirMenu} />;
}

View File

@@ -0,0 +1,23 @@
import { Menu, MenuItemLink } from 'react-admin';
import {
EQUIPMENT_SIDEBAR_ARCHIVE_FILTER,
EQUIPMENT_SIDEBAR_IN_WORK_FILTER,
equipmentListSearch,
} from './toirMenuLinks';
export function ToirMenu() {
return (
<Menu>
<MenuItemLink to="/equipment" primaryText="Оборудование" />
<MenuItemLink
to={`/equipment?${equipmentListSearch(EQUIPMENT_SIDEBAR_IN_WORK_FILTER)}`}
primaryText="В работе"
/>
<MenuItemLink
to={`/equipment?${equipmentListSearch(EQUIPMENT_SIDEBAR_ARCHIVE_FILTER)}`}
primaryText="Архив"
/>
<MenuItemLink to="/status-changes" primaryText="Журнал актов" />
</Menu>
);
}

View File

@@ -0,0 +1,13 @@
/** Параметры списка оборудования в формате react-admin (как при сохранённом фильтре в URL). */
export function equipmentListSearch(filter: Record<string, unknown>): string {
const params = new URLSearchParams();
params.set('filter', JSON.stringify(filter));
params.set('displayedFilters', JSON.stringify({ status: true }));
return params.toString();
}
/** «В работе» → статус Active (в эксплуатации). См. `equipmentStatusChoices`. */
export const EQUIPMENT_SIDEBAR_IN_WORK_FILTER = { status: ['Active'] };
/** «Архив» → списанное оборудование (WriteOff). */
export const EQUIPMENT_SIDEBAR_ARCHIVE_FILTER = { status: ['WriteOff'] };

View File

@@ -1,3 +1,5 @@
import { useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import {
CreateButton,
Datagrid,
@@ -5,13 +7,26 @@ import {
FilterButton,
List,
SelectArrayInput,
SelectField,
TextField,
TextInput,
TopToolbar,
} from 'react-admin';
import { equipmentStatusChoices } from './shared';
function parseListFilterFromSearch(search: string): Record<string, unknown> | undefined {
const params = new URLSearchParams(search);
const raw = params.get('filter');
if (!raw) {
return undefined;
}
try {
const parsed = JSON.parse(raw) as Record<string, unknown>;
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : undefined;
} catch {
return undefined;
}
}
const equipmentFilters = [
<TextInput key="q" source="q" label="Поиск" alwaysOn />,
<SelectArrayInput key="status" source="status" label="Статус" choices={equipmentStatusChoices} />,
@@ -25,14 +40,23 @@ const ListActions = () => (
);
export function EquipmentList() {
const location = useLocation();
const filterDefaultValues = useMemo(() => parseListFilterFromSearch(location.search), [location.search]);
const listKey = `${location.pathname}${location.search}`;
return (
<List filters={equipmentFilters} actions={<ListActions />} sort={{ field: 'name', order: 'ASC' }}>
<List
key={listKey}
filters={equipmentFilters}
actions={<ListActions />}
sort={{ field: 'name', order: 'ASC' }}
filterDefaultValues={filterDefaultValues}
>
<Datagrid rowClick="show">
<TextField source="name" />
<TextField source="serialNumber" />
<DateField source="dateOfInspection" />
<DateField source="commissionedAt" />
<SelectField source="status" choices={equipmentStatusChoices} />
</Datagrid>
</List>
);

View File

@@ -82,9 +82,12 @@ export function buildToirMuiTheme(mode: Mode): Theme {
styleOverrides: {
head: {
fontWeight: 700,
fontSize: '0.9rem',
borderBottom: `1px solid ${t.border}`,
},
root: {
fontSize: '0.95rem',
lineHeight: 1.35,
borderBottom: `1px solid ${t.divider}`,
},
},