P8PanelsCEMROS/repair_anl_atc/repair_anl_atc.js
Dollerino 261f2cf490 init
2026-04-02 13:44:02 +03:00

234 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Парус 8 - Панели мониторинга - ТОиР - Аналитика по ремонтам АТС
Панель мониторинга: Корневая панель аналитики по ремонтам АТС
*/
//---------------------
//Подключение библиотек
//---------------------
import React, { useState, useEffect, useMemo } from "react"; //Классы React
import { Box, Grid, Paper, Fab, Icon } from "@mui/material"; //Интерфейсные компоненты
import { APP_BAR_HEIGHT } from "../../components/p8p_app_workspace"; //Заголовок страницы
import { P8PChart } from "../../components/p8p_chart"; //График
import { APP_STYLES } from "../../../app.styles"; //Типовые стили
import { P8PDataGrid, P8P_DATA_GRID_SIZE, P8P_DATA_GRID_MORE_HEIGHT, P8P_DATA_GRID_FILTERS_HEIGHT } from "../../components/p8p_data_grid"; //Таблица данных
import { P8P_DATA_GRID_CONFIG_PROPS } from "../../config_wrapper"; //Подключение компонентов к настройкам приложения
import { FilterDialog } from "./filter_dialog"; //Диалог фильтра
import { Filter } from "./filter"; //Фильтры
import { useFilters } from "./hooks/filter_hooks"; //Хуки фильтров
import { useChartStatuses, useChartSpendings, useTableRepairs } from "./hooks/hooks";
import { useDictionary } from "./hooks/dict_hooks";
import { dataCellRender, valueFormatter, formatFilterValues } from "./layouts";
import { ChartFilter } from "./chart_filter";
import { hasValue } from "../../core/utils";
//---------
//Константы
//---------
//Высота графиков
const CHART_HEIGHT = "300px";
//Стили
const STYLES = {
TABLE_PROJECTS: (showCharts, morePages, filters, isChartsFiltered) => ({
height: `calc(100vh - ${APP_BAR_HEIGHT} - ${showCharts ? CHART_HEIGHT : "0px"} - ${morePages ? P8P_DATA_GRID_MORE_HEIGHT : "0px"} - ${
filters ? P8P_DATA_GRID_FILTERS_HEIGHT : "0px"
} - ${showCharts && isChartsFiltered ? "53px" : "0px"} - 90px)`,
maxWidth: `calc(100vw - 16px)`,
...APP_STYLES.SCROLL
}),
CHART: { maxHeight: CHART_HEIGHT, display: "flex", justifyContent: "center" },
CHART_PAPER: { height: "100%", paddingBottom: "5px" },
CHART_FAB: { position: "absolute", top: 80, left: 16 }
};
//Графики страницы
const CHART_NAMES = {
repairs: "REPAIRS",
spendings: "SPENDINGS"
};
//-----------
//Тело модуля
//-----------
//Корневая панель аналитики по ремонтам АТС
const RepairAnlATC = () => {
//Собственное состояние - признак отображения фильтров
const [isFilterOpen, setIsFilterOpen] = useState(true);
//Состояния графиков
const [showCharts, setShowCharts] = useState(true);
//Собственное состояние - общие фильтры
const [filterValues, isFiltersLoaded, filtersInit, handleFilterChange] = useFilters();
//Собственное состояние - фильтры ремонтов
const [filterRepairs, setFilterRepairs] = useState({ nState: null });
//Собственное состояние - фильтры затрат
const [filterSpendings, setFilterSpendings] = useState({ nType: null });
//Общие фильтры панели
const allFilters = useMemo(() => {
return { ...filterValues, nState: filterRepairs.nState, nType: filterSpendings.nType };
}, [filterRepairs.nState, filterSpendings.nType, filterValues]);
//Состояние графика статусов
const { chartStatuses, handleReload: handleChartStatusesReload } = useChartStatuses({ storedArgs: allFilters });
//Состояние графика трудовых затрат
const { chartSpendings, handleReload: handleChartSpendingsReload } = useChartSpendings({ storedArgs: allFilters });
//Состояние таблицы ремонтных ведомостей
const {
dataGrid,
handleReload: handleTableRepairsReload,
handleFilterChanged,
handleOrderChanged,
handlePagesCountChanged
} = useTableRepairs({
storedArgs: formatFilterValues(allFilters)
});
//Вспомогательные функции открытия раздела
const { handleEquipRepairSheetsOpen } = useDictionary();
//При изменении фильтра в диалоге
const handleFilterOk = filter => {
//Обновляем фильтры
handleFilterChange({ filter });
//Закрываем диалог фильтра
setIsFilterOpen(false);
};
//При закрытии диалога фильтра
const handleFilterCancel = () => setIsFilterOpen(false);
//При открытии диалога фильтра
const handleFilterDialogOpen = () => setIsFilterOpen(true);
//При нажатии на элемент графика "Ремонты"
const handleChartStatusesClick = ({ item }) => {
setFilterRepairs({ nState: item.NSTATE });
};
//При нажатии на элемент графика "Трудовые затраты"
const handleChartSpendingsClick = ({ item }) => {
//Если тип не соответствует текущему
if (item.NTYPE !== filterSpendings.nType) setFilterSpendings({ nType: item.NTYPE });
};
//При изменении фильтра графика
const handleChartFilterChange = ({ chartName, filter }) => {
//При изменении фильтров графика "Ремонты"
if (chartName === CHART_NAMES.repairs) {
setFilterRepairs({ ...filter });
}
//При изменении фильтров графика "Трудовые затраты"
if (chartName === CHART_NAMES.spendings) setFilterSpendings({ ...filter });
};
//При изменении фильтра
useEffect(() => {
//Если фильтр установлен
if (!filtersInit) {
handleChartStatusesReload();
handleChartSpendingsReload();
handleTableRepairsReload();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allFilters, filtersInit]);
//Генерация содержимого
return (
<Box p={1}>
{!filtersInit ? <Filter filter={filterValues} onFilterOpen={handleFilterDialogOpen} /> : null}
<Grid container spacing={1}>
{showCharts ? (
<>
<Grid item xs={6}>
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
{hasValue(filterRepairs.nState) ? (
<ChartFilter chartName={CHART_NAMES.repairs} filter={filterRepairs} onFilterChange={handleChartFilterChange} />
) : null}
{chartStatuses.loaded ? (
<P8PChart {...chartStatuses} style={STYLES.CHART} onClick={handleChartStatusesClick} legendPosition={"top"} />
) : null}
</Paper>
</Grid>
<Grid item xs={6}>
<Paper elevation={3} sx={STYLES.CHART_PAPER}>
{hasValue(filterSpendings.nType) ? (
<ChartFilter
chartName={CHART_NAMES.spendings}
filter={filterSpendings}
onFilterChange={handleChartFilterChange}
/>
) : null}
{chartSpendings.loaded ? (
<P8PChart
{...chartSpendings}
style={STYLES.CHART}
options={{
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
}
}}
legendPosition={"top"}
onClick={handleChartSpendingsClick}
/>
) : null}
</Paper>
</Grid>
</>
) : null}
<Grid item xs={12}>
{dataGrid.dataLoaded ? (
<P8PDataGrid
{...P8P_DATA_GRID_CONFIG_PROPS}
{...dataGrid}
size={P8P_DATA_GRID_SIZE.LARGE}
containerComponentProps={{
sx: STYLES.TABLE_PROJECTS(
showCharts,
dataGrid.morePages,
(dataGrid.filters || []).length > 0,
hasValue(filterRepairs.nState) || hasValue(filterSpendings.nType)
)
}}
filtersInitial={dataGrid.filters}
onOrderChanged={handleOrderChanged}
onFilterChanged={handleFilterChanged}
onPagesCountChanged={handlePagesCountChanged}
dataCellRender={prms => dataCellRender({ ...prms, showEquipRepairSheets: handleEquipRepairSheetsOpen })}
valueFormatter={valueFormatter}
/>
) : null}
</Grid>
</Grid>
{chartStatuses.loaded && chartSpendings.loaded ? (
<Fab size="small" color="secondary" sx={STYLES.CHART_FAB} onClick={() => setShowCharts(!showCharts)}>
<Icon>{showCharts ? "expand_less" : "expand_more"}</Icon>
</Fab>
) : null}
{isFilterOpen && isFiltersLoaded ? (
<FilterDialog initial={filterValues} isFiltersInit={filtersInit} onOk={handleFilterOk} onCancel={handleFilterCancel} />
) : null}
</Box>
);
};
//----------------
//Интерфейс модуля
//----------------
export { RepairAnlATC };