готово #78
@ -68,7 +68,9 @@ const INTEGER_COLUMN_IDS = new Set([
|
|||||||
const getColorBrightness = (hexColor) => {
|
const getColorBrightness = (hexColor) => {
|
||||||
if (!hexColor) return 255;
|
if (!hexColor) return 255;
|
||||||
const color = hexColor.replace('#', '');
|
const color = hexColor.replace('#', '');
|
||||||
let r, g, b;
|
let r;
|
||||||
|
let g;
|
||||||
|
let b;
|
||||||
if (color.length === 3) {
|
if (color.length === 3) {
|
||||||
r = Number.parseInt(color[0] + color[0], 16);
|
r = Number.parseInt(color[0] + color[0], 16);
|
||||||
g = Number.parseInt(color[1] + color[1], 16);
|
g = Number.parseInt(color[1] + color[1], 16);
|
||||||
@ -86,7 +88,7 @@ const getColorBrightness = (hexColor) => {
|
|||||||
const formatNumber = (value, asInteger = false) => {
|
const formatNumber = (value, asInteger = false) => {
|
||||||
if (value === null || value === undefined || value === '') return String(value || '');
|
if (value === null || value === undefined || value === '') return String(value || '');
|
||||||
const num = Number(value);
|
const num = Number(value);
|
||||||
if (isNaN(num)) return String(value);
|
if (Number.isNaN(num)) return String(value);
|
||||||
return num.toLocaleString('ru-RU', {
|
return num.toLocaleString('ru-RU', {
|
||||||
minimumFractionDigits: asInteger ? 0 : 1,
|
minimumFractionDigits: asInteger ? 0 : 1,
|
||||||
maximumFractionDigits: asInteger ? 0 : 1,
|
maximumFractionDigits: asInteger ? 0 : 1,
|
||||||
@ -146,7 +148,7 @@ const CellComponent = ({
|
|||||||
// Мемоизация значения
|
// Мемоизация значения
|
||||||
const { rawValue, displayValue, isNumeric } = useMemo(() => {
|
const { rawValue, displayValue, isNumeric } = useMemo(() => {
|
||||||
const value = cell.getValue();
|
const value = cell.getValue();
|
||||||
const isNum = !isNaN(Number(value)) && value !== null && value !== undefined && value !== '';
|
const isNum = value !== null && value !== undefined && value !== '' && !Number.isNaN(Number(value));
|
||||||
let display = String(value || '');
|
let display = String(value || '');
|
||||||
|
|
||||||
if (isNum) {
|
if (isNum) {
|
||||||
@ -191,7 +193,8 @@ const CellComponent = ({
|
|||||||
}, [isLocked, onClick]);
|
}, [isLocked, onClick]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='cell' style={cellStyles} onClick={handleClick}>
|
// biome-ignore lint/a11y/useKeyWithClickEvents: <explanation>
|
||||||
|
<div type="button" className='cell' style={cellStyles} onClick={handleClick}>
|
||||||
<span style={CONTAINER_STYLES}>{highlightedContent}</span>
|
<span style={CONTAINER_STYLES}>{highlightedContent}</span>
|
||||||
{lockBadge}
|
{lockBadge}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,10 @@
|
|||||||
|
import { blueColumn, greenColumn, orangeColumn } from "./columnColors";
|
||||||
|
|
||||||
export const columnPinningDefault = {
|
export const columnPinningDefault = {
|
||||||
left: ['mrt-row-expand', 'sort_order'],
|
left: ['mrt-row-expand', 'sort_order'],
|
||||||
right: [],
|
right: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const columnVisibilityDefault = { 'mrt-row-select': false };
|
export const columnVisibilityDefault = { 'mrt-row-select': false };
|
||||||
|
|
||||||
|
export const sectionCodeColor = { 1: greenColumn, 3: orangeColumn, 4: blueColumn}
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react'
|
|||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import { useRealtime } from './contexts/RealtimeContext';
|
import { useRealtime } from './contexts/RealtimeContext';
|
||||||
|
import { sectionCodeColor } from './constants/columnConfig';
|
||||||
|
import { blueColumn, greenColumn } from './constants/columnColors';
|
||||||
|
|
||||||
const EditCellPortal = React.memo(({
|
const EditCellPortal = React.memo(({
|
||||||
cell,
|
cell,
|
||||||
@ -76,6 +78,13 @@ const EditCellPortal = React.memo(({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getColorCell(colors, column, row) {
|
||||||
|
if (row.original.data.section_code){
|
||||||
|
const section_code = row.original.data.section_code[0];
|
||||||
|
return (sectionCodeColor[section_code] || blueColumn)[row.original?.row_type || row.row_type];
|
||||||
|
}
|
||||||
|
return colors[column.id]?.color_type?.[row.original?.row_type || row.row_type];
|
||||||
|
}
|
||||||
|
|
||||||
export const getTableColumns = ({
|
export const getTableColumns = ({
|
||||||
Cell,
|
Cell,
|
||||||
@ -121,7 +130,7 @@ export const getTableColumns = ({
|
|||||||
globalFilter,
|
globalFilter,
|
||||||
columnFilter,
|
columnFilter,
|
||||||
isEditable: row.original?.row_type === 'INPUT' || false,
|
isEditable: row.original?.row_type === 'INPUT' || false,
|
||||||
backgroundColor: columnColors[column.id]?.color_type?.[row.original?.row_type || row.row_type],
|
backgroundColor: getColorCell(columnColors, column, row),
|
||||||
isUpdating: table.options.meta?.updatingCells?.[`${row.id}_${column.id}`],
|
isUpdating: table.options.meta?.updatingCells?.[`${row.id}_${column.id}`],
|
||||||
isInvalid,
|
isInvalid,
|
||||||
value,
|
value,
|
||||||
@ -154,7 +163,7 @@ export const getTableColumns = ({
|
|||||||
|
|
||||||
// Оптимизированная функция processColumns
|
// Оптимизированная функция processColumns
|
||||||
const processColumns = (columns) => {
|
const processColumns = (columns) => {
|
||||||
columns.forEach((col) => {
|
for (const col of columns) {
|
||||||
col.Cell = ({ cell, table, column, row }) => {
|
col.Cell = ({ cell, table, column, row }) => {
|
||||||
const props = getCachedCellProps(row, column, table);
|
const props = getCachedCellProps(row, column, table);
|
||||||
|
|
||||||
@ -163,7 +172,7 @@ export const getTableColumns = ({
|
|||||||
column,
|
column,
|
||||||
cell,
|
cell,
|
||||||
...props,
|
...props,
|
||||||
}), [row.id, column.id, cell.getValue(), props._hash]);
|
}), [row, column, cell, props]);
|
||||||
|
|
||||||
return <Cell {...cellProps} />;
|
return <Cell {...cellProps} />;
|
||||||
};
|
};
|
||||||
@ -187,7 +196,7 @@ export const getTableColumns = ({
|
|||||||
if (col.columns?.length) {
|
if (col.columns?.length) {
|
||||||
processColumns(col.columns);
|
processColumns(col.columns);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
processColumns(columns);
|
processColumns(columns);
|
||||||
@ -201,8 +210,7 @@ export const getTableColumns = ({
|
|||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
onCellNumberClick(row.id);
|
onCellNumberClick(row.id);
|
||||||
}, [row.id, onCellNumberClick]);
|
}, [row.id, onCellNumberClick]);
|
||||||
|
return <button type="button" onClick={handleClick}>{`${cell.getValue()} `}</button>;
|
||||||
return <button onClick={handleClick}>{cell.getValue() + ' '}</button>;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Box, Button, Divider, FormControl, FormLabel, IconButton, MenuItem, Select, Stack, TextField } from '@mui/material';
|
import { Box, Button, Divider, FormControl, FormLabel, IconButton, MenuItem, Select, Stack, TextField } from '@mui/material';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { STAGE_ROLE_RUSSIAN_NAME } from '../../constants/constants';
|
import { STAGE_ROLE_RUSSIAN_NAME, DIRECTION_TRANSLATE } from '../../constants/constants';
|
||||||
import { formatDateForApi } from '../../utils/formatDate';
|
import { formatDateForApi } from '../../utils/formatDate';
|
||||||
import { collectLeafColumns } from '../RealtimeTable/utils/columnUtils';
|
import { collectLeafColumns } from '../RealtimeTable/utils/columnUtils';
|
||||||
import CollapsibleTree from '../common/CollapsibleTree';
|
import CollapsibleTree from '../common/CollapsibleTree';
|
||||||
@ -27,6 +27,7 @@ export const AddStagesModal = ({
|
|||||||
const [endDate, setEndDate] = useState(null);
|
const [endDate, setEndDate] = useState(null);
|
||||||
const [stageName, setStageName] = useState('');
|
const [stageName, setStageName] = useState('');
|
||||||
const [selectedSheet, setSelectedSheet] = useState(defaultSheet);
|
const [selectedSheet, setSelectedSheet] = useState(defaultSheet);
|
||||||
|
const [selectedDirection, setSelectedDirection] = useState('');
|
||||||
const [selectedRole, setSelectedRole] = useState();
|
const [selectedRole, setSelectedRole] = useState();
|
||||||
const [columnsConfig, setColumnsConfig] = useState({ columns: [], colors: {} });
|
const [columnsConfig, setColumnsConfig] = useState({ columns: [], colors: {} });
|
||||||
const [selectedColumns, setSelectedColumns] = useState([]);
|
const [selectedColumns, setSelectedColumns] = useState([]);
|
||||||
@ -34,7 +35,7 @@ export const AddStagesModal = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadColumnsConfig = async () => {
|
const loadColumnsConfig = async () => {
|
||||||
if (!selectedSheet) return;
|
if (!selectedSheet) return;
|
||||||
const sheetObj = sheetOptions.find((s) => s.value == selectedSheet);
|
const sheetObj = sheetOptions.find((s) => s.value === selectedSheet);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { config } = await import(`../RealtimeTable/constants/${formType}/${sheetObj.sheet}.js`);
|
const { config } = await import(`../RealtimeTable/constants/${formType}/${sheetObj.sheet}.js`);
|
||||||
@ -54,13 +55,15 @@ export const AddStagesModal = ({
|
|||||||
setEndDate(stage.closes_at ?? null);
|
setEndDate(stage.closes_at ?? null);
|
||||||
setStageName(stage.phase_code ?? '');
|
setStageName(stage.phase_code ?? '');
|
||||||
setSelectedSheet(stage.sheet ?? null);
|
setSelectedSheet(stage.sheet ?? null);
|
||||||
|
setSelectedDirection(stage.direction ?? '');
|
||||||
setSelectedRole(stage.role ?? null);
|
setSelectedRole(stage.role ?? null);
|
||||||
setSelectedColumns(stage.column_keys.map((c) => 'data.' + c));
|
setSelectedColumns(stage.column_keys.map((c) => `data.${c}`));
|
||||||
} else {
|
} else {
|
||||||
setStartDate(null);
|
setStartDate(null);
|
||||||
setEndDate(null);
|
setEndDate(null);
|
||||||
setStageName('');
|
setStageName('');
|
||||||
setSelectedSheet(defaultSheet);
|
setSelectedSheet(defaultSheet);
|
||||||
|
setSelectedDirection('');
|
||||||
setSelectedRole();
|
setSelectedRole();
|
||||||
setSelectedColumns([]);
|
setSelectedColumns([]);
|
||||||
}
|
}
|
||||||
@ -69,12 +72,12 @@ export const AddStagesModal = ({
|
|||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const opensAt = formatDateForApi(startDate);
|
const opensAt = formatDateForApi(startDate);
|
||||||
const closesAt = formatDateForApi(endDate);
|
const closesAt = formatDateForApi(endDate);
|
||||||
const sheetObj = sheetOptions.find((s) => s.value == selectedSheet);
|
const sheetObj = sheetOptions.find((s) => s.value === selectedSheet);
|
||||||
|
|
||||||
const stageData = {
|
const stageData = {
|
||||||
phase_code: stageName,
|
phase_code: stageName,
|
||||||
sheet: sheetObj.sheet,
|
sheet: sheetObj.sheet,
|
||||||
direction: sheetObj.direction,
|
direction: selectedDirection,
|
||||||
role: selectedRole,
|
role: selectedRole,
|
||||||
opens_at: opensAt,
|
opens_at: opensAt,
|
||||||
closes_at: closesAt,
|
closes_at: closesAt,
|
||||||
@ -101,6 +104,7 @@ export const AddStagesModal = ({
|
|||||||
setEndDate(null);
|
setEndDate(null);
|
||||||
setStageName('');
|
setStageName('');
|
||||||
setSelectedSheet(defaultSheet);
|
setSelectedSheet(defaultSheet);
|
||||||
|
setSelectedDirection('');
|
||||||
setSelectedRole();
|
setSelectedRole();
|
||||||
setSelectedColumns([]);
|
setSelectedColumns([]);
|
||||||
onClose();
|
onClose();
|
||||||
@ -115,6 +119,7 @@ export const AddStagesModal = ({
|
|||||||
const handleSheetChange = (event) => {
|
const handleSheetChange = (event) => {
|
||||||
setSelectedSheet(event.target.value);
|
setSelectedSheet(event.target.value);
|
||||||
setSelectedColumns([]);
|
setSelectedColumns([]);
|
||||||
|
setSelectedDirection(''); // Сбрасываем direction при смене листа
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleColumnsSelect = (column, isSelect) => {
|
const handleColumnsSelect = (column, isSelect) => {
|
||||||
@ -129,7 +134,7 @@ export const AddStagesModal = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isFormValid = startDate && endDate && stageName.trim() && selectedSheet;
|
const isFormValid = startDate && endDate && stageName.trim() && selectedSheet && selectedDirection;
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
@ -138,6 +143,10 @@ export const AddStagesModal = ({
|
|||||||
|
|
||||||
const columnTree = columnsConfig.columns || [];
|
const columnTree = columnsConfig.columns || [];
|
||||||
|
|
||||||
|
// Проверяем, нужно ли показывать выбор направления (для AHR CAP)
|
||||||
|
const sheetObj = sheetOptions.find((s) => s.value === selectedSheet);
|
||||||
|
const showDirectionSelect = sheetObj?.direction;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalBackdrop isOpen={isOpen} onClick={handleBackdropClick}>
|
<ModalBackdrop isOpen={isOpen} onClick={handleBackdropClick}>
|
||||||
<ModalContainer>
|
<ModalContainer>
|
||||||
@ -187,6 +196,31 @@ export const AddStagesModal = ({
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
|
{/* Выбор направления (только для AHR CAP) */}
|
||||||
|
{showDirectionSelect && (
|
||||||
|
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<FormLabel>Направление</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={selectedDirection}
|
||||||
|
onChange={(e) => setSelectedDirection(e.target.value)}
|
||||||
|
displayEmpty
|
||||||
|
size='small'
|
||||||
|
>
|
||||||
|
<MenuItem value='' disabled>
|
||||||
|
Выберите направление
|
||||||
|
</MenuItem>
|
||||||
|
{Object.entries(DIRECTION_TRANSLATE).map(([key, label]) => (
|
||||||
|
<MenuItem key={key} value={key}>
|
||||||
|
{label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
|
||||||
{selectedSheet && columnTree.length > 0 && (
|
{selectedSheet && columnTree.length > 0 && (
|
||||||
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
<Stack sx={{ marginBottom: '0.75rem', width: '100%' }}>
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
|
|||||||
@ -7,5 +7,5 @@ export const stageColumnsHiddenFromPicker = [
|
|||||||
'data.header.internal_order',
|
'data.header.internal_order',
|
||||||
'data.header.vsp_id',
|
'data.header.vsp_id',
|
||||||
'data.header.section_code',
|
'data.header.section_code',
|
||||||
'data.header.justification',
|
// 'data.header.justification',
|
||||||
];
|
];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user