169 lines
6.8 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 } from "react"; //Классы React
import PropTypes from "prop-types"; //Контроль свойств компонента
import { Box, Icon, Input, InputAdornment, FormControl, Select, InputLabel, MenuItem, IconButton, Typography, Switch, Stack } from "@mui/material"; //Интерфейсные компоненты
//---------
//Константы
//---------
//Стили
const STYLES = {
STATE: value => ({ color: value === 1 ? "green" : "black" }),
COST_STATUS: color => ({ color, verticalAlign: "middle" }),
COST_READY: value => ({ color: value <= 30 ? "red" : value >= 80 ? "green" : "#e2af00" }),
TOGGLE_COLOR: checked => ({ color: checked ? "#006dd9" : "lightgrey" })
};
//-----------
//Тело модуля
//-----------
//Поле ввода формы
const FormField = ({ elementCode, elementValue, labelText, onChange, dictionary, list, type, ...other }) => {
//Значение элемента
const [value, setValue] = useState(elementValue);
//При получении нового значения из вне
useEffect(() => {
setValue(elementValue);
}, [elementValue]);
//Выбор значения из словаря
const handleDictionaryClick = () =>
dictionary ? dictionary(res => (res ? res.map(i => handleChange({ target: { name: i.name, value: i.value } })) : null)) : null;
//Изменение значения элемента (по событию)
const handleChange = e => {
setValue(e.target.value);
if (onChange) onChange(e.target.name, e.target.value);
};
//Генерация содержимого
return (
<Box p={1}>
<FormControl variant="standard" fullWidth {...other}>
{list ? (
<>
<InputLabel id={`${elementCode}Lable`} shrink>
{labelText}
</InputLabel>
<Select
labelId={`${elementCode}Lable`}
id={elementCode}
name={elementCode}
label={labelText}
value={value || value == 0 ? value : ""}
onChange={handleChange}
displayEmpty
>
{list.map((item, i) => (
<MenuItem key={i} value={item.value || item.value == 0 ? item.value : ""}>
{item.name}
</MenuItem>
))}
</Select>
</>
) : (
<>
<InputLabel {...(type == "date" ? { shrink: true } : {})} htmlFor={elementCode}>
{labelText}
</InputLabel>
<Input
id={elementCode}
name={elementCode}
value={value || value == 0 ? value : ""}
endAdornment={
dictionary ? (
<InputAdornment position="end">
<IconButton aria-label={`${elementCode} select`} onClick={handleDictionaryClick} edge="end">
<Icon>list</Icon>
</IconButton>
</InputAdornment>
) : null
}
{...(type ? { type } : {})}
onChange={handleChange}
/>
</>
)}
</FormControl>
</Box>
);
};
//Контроль свойств - Поле ввода формы
FormField.propTypes = {
elementCode: PropTypes.string.isRequired,
elementValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.instanceOf(Date)]),
labelText: PropTypes.string.isRequired,
onChange: PropTypes.func,
dictionary: PropTypes.func,
list: PropTypes.array,
type: PropTypes.string
};
//Переключатель
const Toggle = ({ labels, checked, onChange }) => {
//Обработка переключения
const handleChange = event => (onChange ? onChange(event.target.checked) : null);
//Генерация содержимого
return (
<Stack direction={"row"} spacing={1} alignItems={"center"} justifyContent={"center"}>
<Typography sx={STYLES.TOGGLE_COLOR(!checked)}>{labels[0]}</Typography>
<Switch checked={checked} size="small" onChange={handleChange} />
<Typography sx={STYLES.TOGGLE_COLOR(checked)}>{labels[1]}</Typography>
</Stack>
);
};
//Контроль свойств компонента - Переключатель
Toggle.propTypes = {
labels: PropTypes.arrayOf(PropTypes.string).isRequired,
checked: PropTypes.bool.isRequired,
onChange: PropTypes.func
};
//Формирование значения для колонки "Статус структуры цены"
const formatCostStatusValue = ({ value, onClick, type = 1 }) => {
const [text, color] =
value == 0
? ["Без отклонений", "lightgreen"]
: value == 1
? [type == 1 ? "Есть статьи с расходом более 90%" : "Расход более 90%", "#ffdf71"]
: value == 2
? [type == 1 ? "Есть статьи с перерасходом" : "Перерасход", "#eb6b6b"]
: ["Не определено", "lightgray"];
return onClick ? (
<IconButton onClick={onClick}>
<Icon sx={STYLES.COST_STATUS(color)} title={`${text}\nНажмите для детальной информации`}>
circle
</Icon>
</IconButton>
) : (
<Icon sx={STYLES.COST_STATUS(color)} title={text}>
circle
</Icon>
);
};
//Формирование значения для колонки "Готов (%, зтраты)"
const formatCostReadyValue = value => {
return <span style={STYLES.COST_READY(value)}>{value}</span>;
};
//----------------
//Интерфейс модуля
//----------------
export { STYLES as COMMON_STYLES, FormField, Toggle, formatCostStatusValue, formatCostReadyValue };