Таблицы, добавление, редактирование, удаление, удаление выделенного.
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.idea
|
||||
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
Generated
+24
@@ -24,5 +24,29 @@
|
||||
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
|
||||
</formatting-settings>
|
||||
</DBN-SQL>
|
||||
<DBN-PSQL>
|
||||
<case-options enabled="true">
|
||||
<option name="KEYWORD_CASE" value="lower" />
|
||||
<option name="FUNCTION_CASE" value="lower" />
|
||||
<option name="PARAMETER_CASE" value="lower" />
|
||||
<option name="DATATYPE_CASE" value="lower" />
|
||||
<option name="OBJECT_CASE" value="preserve" />
|
||||
</case-options>
|
||||
<formatting-settings enabled="false" />
|
||||
</DBN-PSQL>
|
||||
<DBN-SQL>
|
||||
<case-options enabled="true">
|
||||
<option name="KEYWORD_CASE" value="lower" />
|
||||
<option name="FUNCTION_CASE" value="lower" />
|
||||
<option name="PARAMETER_CASE" value="lower" />
|
||||
<option name="DATATYPE_CASE" value="lower" />
|
||||
<option name="OBJECT_CASE" value="preserve" />
|
||||
</case-options>
|
||||
<formatting-settings enabled="false">
|
||||
<option name="STATEMENT_SPACING" value="one_line" />
|
||||
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
|
||||
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
|
||||
</formatting-settings>
|
||||
</DBN-SQL>
|
||||
</code_scheme>
|
||||
</component>
|
||||
Generated
+158
-1
@@ -1,12 +1,169 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="3c1f5459-12ab-4427-89ae-be4c0e341eb6" name="Default Changelist" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Button/Button.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Button/button.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Checkbox/Checkbox.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Checkbox/checkbox.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Checkbox/selected.svg" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Input/Input.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Input/input.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Loader/Loader.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Loader/loader.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Select/Select.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Common/Select/select.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Form/Form.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Form/form.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Modal/Modal.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Modal/modal.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Sidebar/Sidebar.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Sidebar/sidebar.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/Table.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableCell/TableCell.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableCell/tableCell.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableEmpty/TableEmpty.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableEmpty/tableEmpty.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableHead/TableHead.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableHead/tableHead.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableHeadItem/TableHeadItem.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableHeadItem/tableHeadItem.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableRow/TableRow.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/TableRow/tableRow.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Table/table.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Template/TableCompany/TableCompany.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Template/TableCompany/tableCompany.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Template/TableWorkers/TableWorkers.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/Components/Template/TableWorkers/tableWorkers.scss" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/helpers/array.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/mock/mockTable.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/store/store.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/store/tableCompanySlice.js" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/store/tableWorkersSlice.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/codeStyles/Project.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/codeStyles/Project.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/App.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.scss" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/App.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/logo.svg" beforeDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="JavaScript File" />
|
||||
<option value="SCSS File" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectId" id="2J35rc74r3VojkFeH4ngbLhp6ge" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showExcludedFiles" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$/../IRI" />
|
||||
<property name="list.type.of.created.stylesheet" value="SCSS" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.detected.package.standard" value="true" />
|
||||
<property name="node.js.path.for.package.eslint" value="project" />
|
||||
<property name="node.js.path.for.package.standard" value="project" />
|
||||
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
||||
<property name="node.js.selected.package.standard" value="" />
|
||||
<property name="nodejs_package_manager_path" value="npm" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/src/Components/Table" />
|
||||
</key>
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/src/Components/Common" />
|
||||
<recent name="$PROJECT_DIR$/src/Components/Table" />
|
||||
<recent name="$PROJECT_DIR$/src" />
|
||||
<recent name="$PROJECT_DIR$/src/Components/Common/Checkbox" />
|
||||
<recent name="$PROJECT_DIR$/src/Components" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="SvnConfiguration">
|
||||
<configuration />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="3c1f5459-12ab-4427-89ae-be4c0e341eb6" name="Default Changelist" comment="" />
|
||||
<created>1671294125199</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1671294125199</updated>
|
||||
<workItem from="1671294127387" duration="5598000" />
|
||||
<workItem from="1671299757432" duration="6341000" />
|
||||
<workItem from="1671365091146" duration="14875000" />
|
||||
<workItem from="1671388144305" duration="15952000" />
|
||||
<workItem from="1671448137631" duration="41117000" />
|
||||
<workItem from="1671524387598" duration="275000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="WindowStateProjectService">
|
||||
<state x="555" y="181" width="800" height="671" key="#ESLint" timestamp="1671294406686">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="555" y="181" width="800" height="671" key="#ESLint/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671294406686" />
|
||||
<state x="627" y="325" width="655" height="382" key="#com.intellij.fileTypes.FileTypeChooser" timestamp="1671390741373">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="627" y="325" width="655" height="382" key="#com.intellij.fileTypes.FileTypeChooser/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671390741373" />
|
||||
<state x="693" y="269" width="524" height="494" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1671375945131">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="693" y="269" width="524" height="494" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671375945131" />
|
||||
<state x="561" y="118" width="788" height="796" key="CommitChangelistDialog2" timestamp="1671524816158">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="561" y="118" width="788" height="796" key="CommitChangelistDialog2/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671524816158" />
|
||||
<state x="743" y="277" width="424" height="478" key="FileChooserDialogImpl" timestamp="1671486080118">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="743" y="277" width="424" height="478" key="FileChooserDialogImpl/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671486080118" />
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.bottom" timestamp="1671299466029">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.bottom/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671299466029" />
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.center" timestamp="1671299466029">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.center/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671299466029" />
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.left" timestamp="1671299466029">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.left/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671299466029" />
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.right" timestamp="1671299466029">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state width="1899" height="276" key="GridCell.Tab.0.right/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671299466029" />
|
||||
<state x="624" y="238" key="run.anything.popup" timestamp="1671472733814">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="624" y="238" key="run.anything.popup/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671472733814" />
|
||||
<state x="623" y="228" width="672" height="678" key="search.everywhere.popup" timestamp="1671389871175">
|
||||
<screen x="0" y="0" width="1920" height="1040" />
|
||||
</state>
|
||||
<state x="623" y="228" width="672" height="678" key="search.everywhere.popup/0.0.1920.1040/0.0.1920.1040@0.0.1920.1040" timestamp="1671389871175" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+2995
-25
File diff suppressed because it is too large
Load Diff
@@ -6,9 +6,12 @@
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"node-sass": "^7.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"redux-devtools-extension": "^2.13.9",
|
||||
"uuid": "^9.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -34,5 +37,9 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@reduxjs/toolkit": "^1.9.1",
|
||||
"react-redux": "^8.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
+71
-18
@@ -1,24 +1,77 @@
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {useDispatch, useSelector} from 'react-redux'
|
||||
|
||||
import TableWorkers from "./Components/Template/TableWorkers/TableWorkers";
|
||||
import TableCompany from "./Components/Template/TableCompany/TableCompany";
|
||||
|
||||
import {companyRecords} from "./mock/mockTable";
|
||||
import {companyWorkers} from "./mock/mockTable";
|
||||
import {tableCompanySlice} from "./store/tableCompanySlice";
|
||||
|
||||
|
||||
import {tableWorkersSlice} from "./store/tableWorkersSlice";
|
||||
import './App.scss'
|
||||
|
||||
function App() {
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const tableCompanyData = useSelector((state) => state.table);
|
||||
const tableWorkersData = useSelector((state) => state.tableWorkers);
|
||||
|
||||
|
||||
const {
|
||||
setInitialCompany, calculateWorkersInCompany
|
||||
} = tableCompanySlice.actions;
|
||||
|
||||
|
||||
const {setInitialWorkers, showCompanyWorkers, setColorActiveWorker,} = tableWorkersSlice.actions;
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
dispatch(setInitialCompany(companyRecords));
|
||||
setIsLoading(false);
|
||||
dispatch(setInitialWorkers(companyWorkers))
|
||||
|
||||
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (tableCompanyData.data.data) {
|
||||
dispatch(showCompanyWorkers(tableCompanyData.activeCompanyId))
|
||||
}
|
||||
|
||||
}, [tableCompanyData.activeCompanyId]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
dispatch(setColorActiveWorker(tableWorkersData.activeWorkersId));
|
||||
|
||||
}, [tableWorkersData.activeWorkersId]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(tableWorkersData.workers)
|
||||
dispatch(calculateWorkersInCompany(tableWorkersData.workers))
|
||||
|
||||
}, [tableWorkersData.workers]);
|
||||
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.js</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
<div className="App">
|
||||
<TableCompany
|
||||
tableData={tableCompanyData}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<TableWorkers
|
||||
companyData={tableCompanyData.data.data}
|
||||
tableData={tableWorkersData}
|
||||
/>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
background: #131826;
|
||||
}
|
||||
body {
|
||||
background: #131826;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
import './button.scss';
|
||||
|
||||
export const Button = ({text, onClick, styles = {}, containerStyles = {}, children, disabled = false}) => {
|
||||
return (
|
||||
<div className='button' style={containerStyles}>
|
||||
<button onClick={onClick} style={styles} disabled={!!disabled}>
|
||||
{text || children}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 10px 15px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #219FE6;
|
||||
border-radius: 4px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
color: #FFFFFF;
|
||||
outline: none;
|
||||
border: none;
|
||||
transition: all ease 0.3s;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: #0F8ACF;
|
||||
box-shadow: 0 0 33px #276B92;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: #3F3F3F;
|
||||
color: #ACACAC;
|
||||
box-shadow: none;
|
||||
cursor: alias;
|
||||
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 33px #276B92, inset 0 0 10px rgba(14, 89, 131, 0.43);
|
||||
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #0F8ACF;
|
||||
|
||||
&:before {
|
||||
background: none;
|
||||
border: 1px solid #0F8ACF;
|
||||
content: "";
|
||||
display: block;
|
||||
border-radius: 6px;
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
left: -4px;
|
||||
right: -4px;
|
||||
bottom: -4px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
import selectedIcon from './selected.svg'
|
||||
|
||||
import './checkbox.scss'
|
||||
|
||||
export const Checkbox = ({ isActive, onChange = () => {} }) => {
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div onClick={onChange} className='checkbox__input'>
|
||||
{isActive && <img src={selectedIcon} alt="iconChecked"/>}
|
||||
</div>
|
||||
|
||||
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
.checkbox__input {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid #898A98;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.66659 0.333328C2.78253 0.333328 1.93468 0.684518 1.30956 1.30964C0.684441 1.93476 0.333252 2.78261 0.333252 3.66666V10.3333C0.333252 11.2174 0.684441 12.0652 1.30956 12.6904C1.93468 13.3155 2.78253 13.6667 3.66659 13.6667H10.3333C11.2173 13.6667 12.0652 13.3155 12.6903 12.6904C13.3154 12.0652 13.6666 11.2174 13.6666 10.3333V3.66666C13.6666 2.78261 13.3154 1.93476 12.6903 1.30964C12.0652 0.684518 11.2173 0.333328 10.3333 0.333328H3.66659ZM9.48659 6.12266C9.54647 6.05875 9.59318 5.98367 9.62404 5.90171C9.65491 5.81975 9.66933 5.73251 9.66648 5.64498C9.66364 5.55744 9.64358 5.47133 9.60745 5.39154C9.57132 5.31176 9.51983 5.23988 9.45592 5.18C9.39201 5.12011 9.31693 5.0734 9.23497 5.04254C9.15301 5.01167 9.06577 4.99725 8.97823 5.0001C8.8907 5.00294 8.80458 5.023 8.7248 5.05913C8.64502 5.09526 8.57314 5.14675 8.51325 5.21066L6.45792 7.404L5.44258 6.502C5.30956 6.39141 5.13875 6.33686 4.96625 6.34987C4.79375 6.36289 4.63306 6.44245 4.51813 6.57174C4.4032 6.70104 4.34303 6.86994 4.35033 7.04278C4.35763 7.21562 4.43183 7.37885 4.55725 7.49799L6.05725 8.83133C6.18704 8.94662 6.35669 9.00674 6.53011 8.99889C6.70354 8.99105 6.86706 8.91587 6.98592 8.78933L9.48592 6.12266H9.48659Z" fill="#219FE6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,39 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
|
||||
import './input.scss';
|
||||
|
||||
export const Input = ({ required, name, type = 'text', value, placeholder, isNotChangeable=false, onChange=()=>{}, onChangeValue=(value)=>value, fieldData={},}) => {
|
||||
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
|
||||
useEffect( ()=>{
|
||||
setInputValue(value)
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className={`customInput ${required && !inputValue ? ' customInput--required':''}`}>
|
||||
<div className='customInput__field'>
|
||||
<input
|
||||
name={name}
|
||||
className='customInput__input'
|
||||
type={type}
|
||||
placeholder={placeholder}
|
||||
disabled={isNotChangeable}
|
||||
value={inputValue}
|
||||
{...fieldData}
|
||||
onChange={e => {
|
||||
const res = onChangeValue(e.target.value);
|
||||
setInputValue(res);
|
||||
fieldData.onChange && fieldData.onChange({...e, target: {...e.target, value: res}})
|
||||
}}
|
||||
onBlur={(e)=>{
|
||||
onChange(inputValue);
|
||||
fieldData.onBlur && fieldData.onBlur(e)
|
||||
}}
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
.customInput {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
&--required {
|
||||
border: 1px solid #b21;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&__field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #2D313D;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #2D313D;
|
||||
border-radius: 4px;
|
||||
padding: 0 10px;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
border: 1px solid #2D313D;
|
||||
color: #898A98;
|
||||
transition: all ease 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: #3A3F4F;
|
||||
|
||||
}
|
||||
|
||||
&:focus {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
border: 1px solid #219FE6
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: #3F3F3F;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
import './loader.scss';
|
||||
|
||||
export const Loader = () => {
|
||||
return (
|
||||
<div className='loader'/>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
.loader {
|
||||
--clock-color: #007affbb;
|
||||
--white-color: #fff;
|
||||
--clock-width: 2.5rem;
|
||||
--clock-radius: calc(var(--clock-width) / 2);
|
||||
--clock-minute-length: calc(var(--clock-width) * 0.4);
|
||||
--clock-hour-length: calc(var(--clock-width) * 0.2);
|
||||
--clock-thickness: 0.2rem;
|
||||
|
||||
margin-left: 12px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: var(--clock-width);
|
||||
height: var(--clock-width);
|
||||
border: 2px solid var(--clock-color);
|
||||
border-radius: 50%;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
top: calc(var(--clock-radius) * 0.25);
|
||||
width: var(--clock-thickness);
|
||||
background: var(--clock-color);
|
||||
border-radius: 10px;
|
||||
transform-origin: center calc(100% - calc(var(--clock-thickness) / 2));
|
||||
animation: spin infinite linear;
|
||||
}
|
||||
|
||||
&::before {
|
||||
height: var(--clock-minute-length);
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
&::after {
|
||||
top: calc(var(--clock-radius) * 0.25 + var(--clock-hour-length));
|
||||
height: var(--clock-hour-length);
|
||||
animation-duration: 15s;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from "react";
|
||||
import './select.scss'
|
||||
|
||||
export const Select = ({options, onChange}) => {
|
||||
|
||||
return (
|
||||
<select className='select' defaultValue={'DEFAULT'} onChange={(e) => {
|
||||
|
||||
onChange(e.target.value)
|
||||
}}>
|
||||
<option disabled value='DEFAULT'>Выберите компанию</option>
|
||||
{
|
||||
options.map((item, key) => {
|
||||
return <option key={key} value={item[Object.keys(item)[0]]}>{item[Object.keys(item)[1]]}</option>
|
||||
})
|
||||
}
|
||||
|
||||
</select>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
.select {
|
||||
background: #2D313D;
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
color: white;
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import React, {useState} from "react";
|
||||
|
||||
import {Input} from "../Common/Input/Input";
|
||||
import {Button} from "../Common/Button/Button";
|
||||
|
||||
import './form.scss'
|
||||
import {Select} from "../Common/Select/Select";
|
||||
|
||||
|
||||
export const Form = ({
|
||||
data, config, onClick = () => {
|
||||
}
|
||||
}) => {
|
||||
|
||||
const [formData, setFormData] = useState(data);
|
||||
|
||||
const inputs = config.filter((item) => item.editable === true);
|
||||
const inputsIdRender = inputs.map((item) => item.columnId);
|
||||
|
||||
return (
|
||||
<form className='form'>
|
||||
{
|
||||
Object.entries(formData || {}).map((item, key) => {
|
||||
|
||||
const rowName = inputs.find((i) =>
|
||||
i.columnId === item[0]
|
||||
);
|
||||
|
||||
if (inputsIdRender.indexOf(item[0]) + 1) {
|
||||
if (Array.isArray(item[1])) {
|
||||
return <div key={key} className='form__row'>
|
||||
<label>{rowName.columnName}</label>
|
||||
<Select options={item[1]}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
[item[0]]: [...item[1]].map((i) => {
|
||||
if (i.companyId === parseInt(e)) {
|
||||
return {...i, active: true}
|
||||
} else {
|
||||
return {...i, active: false}
|
||||
}
|
||||
})
|
||||
})}/>
|
||||
</div>
|
||||
}
|
||||
return (
|
||||
<div className='form__row' key={key}>
|
||||
<label>{rowName.columnName}</label>
|
||||
<Input name={item[0]}
|
||||
onChange={(e) => setFormData({...formData, [item[0]]: e})} type="text"
|
||||
isNotChangeable={!rowName.editable}
|
||||
value={item[1]}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
)}
|
||||
|
||||
<div className='form__buttons'>
|
||||
<Button onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onClick(formData);
|
||||
}}>Сохранить</Button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
.form {
|
||||
background: #1c2a41;
|
||||
|
||||
&__row {
|
||||
label {
|
||||
color: white;
|
||||
}
|
||||
|
||||
margin-bottom: 10px;
|
||||
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
import ReactDom from 'react-dom'
|
||||
|
||||
import './modal.scss'
|
||||
|
||||
export default React.memo(function Modal({isOpen, children, onClose = ()=> {}}) {
|
||||
|
||||
const body = document.querySelector('body');
|
||||
|
||||
return ReactDom.createPortal(
|
||||
<div className={`modal ${isOpen ? ' active' : ''}`} onClick={() => onClose()}>
|
||||
<div className='modal__content' onClick={(e) => e.stopPropagation()}>
|
||||
<button className='modal__close' onClick={() => onClose()}>Х</button>
|
||||
{children}
|
||||
</div>
|
||||
</div>, body)
|
||||
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
.modal {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(0);
|
||||
|
||||
&__content {
|
||||
background-color: #1c2a41;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
|
||||
}
|
||||
|
||||
&__close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal.active {
|
||||
transform: scale(1)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
|
||||
|
||||
import './sidebar.scss'
|
||||
|
||||
export const Sidebar = () => {
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
import React from "react";
|
||||
|
||||
import {TableRow} from "./TableRow/TableRow";
|
||||
import {TableHead} from "./TableHead/TableHead";
|
||||
import {TableEmpty} from "./TableEmpty/TableEmpty";
|
||||
import {Button} from "../Common/Button/Button";
|
||||
import {Loader} from "../Common/Loader/Loader";
|
||||
|
||||
import './table.scss'
|
||||
|
||||
export const Table = ({groups, tableConfig, data, emptyTable, fetchMore, isFetching, hasMore, isLoading, onChange}) => {
|
||||
|
||||
if(isLoading) {
|
||||
return (
|
||||
<div className='table'>
|
||||
<TableEmpty {...emptyTable} text='Загрузка' loader={Loader} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='table'>
|
||||
{
|
||||
data && data.length > 0 ?
|
||||
|
||||
<div className='table__data'>
|
||||
|
||||
<TableHead tableConfig={tableConfig} groups={groups}/>
|
||||
|
||||
<div className='table__rowList'>
|
||||
|
||||
{
|
||||
data.map((row, key) => {
|
||||
return (
|
||||
<TableRow row={row} onChange={onChange} key={`TableRow${key}`} tableConfig={tableConfig}/>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
{ hasMore && <div className='table__load'>
|
||||
{
|
||||
isFetching
|
||||
? <Button><Loader /></Button>
|
||||
: <Button onClick={()=>fetchMore()}>Load more</Button>
|
||||
}
|
||||
</div> }
|
||||
</div>
|
||||
: <TableEmpty {...emptyTable}/>
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
import './tableCell.scss';
|
||||
|
||||
export const TableCell = ({ row, tableConfig, onChange, item, columnWidth, renderRowItem = (item => item), isGroupEnd, onClick = ()=> {}}) => {
|
||||
return (
|
||||
<div onClick={onClick} className={`tableCell${isGroupEnd ? " tableCell--last" : ""}`}
|
||||
style={{minWidth: columnWidth}}>
|
||||
{
|
||||
renderRowItem(item, row, tableConfig, onChange)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
.tableCell {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #FFFFFF;
|
||||
height: 100%;
|
||||
|
||||
|
||||
&--last {
|
||||
border-right: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
&>p {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-bottom: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
|
||||
import './tableEmpty.scss';
|
||||
|
||||
export const TableEmpty = ({icon, text, button, link, loader: Loader}) => {
|
||||
return (
|
||||
<div className='tableEmpty'>
|
||||
{ icon && <div className='tableEmpty__icon'>
|
||||
<img src={icon} alt={'icon'}/>
|
||||
</div> }
|
||||
<div className='tableEmpty__text'>
|
||||
<p>{text}</p>
|
||||
{ Loader && <Loader /> }
|
||||
</div>
|
||||
|
||||
{/*{button && <div className='tableEmpty__button'>*/}
|
||||
{/* {*/}
|
||||
{/* button.link*/}
|
||||
{/* ? <Link to={button.link}>{button.text}</Link>*/}
|
||||
{/* : <Button {...button} />*/}
|
||||
{/* }*/}
|
||||
|
||||
{/*</div>}*/}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
.tableEmpty {
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 25px 0;
|
||||
background: #131826;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
margin-top: 4px;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
margin-top: 130px;
|
||||
}
|
||||
}
|
||||
|
||||
&__text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 446px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
color: #FFFFFF;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
margin-top: 27px;
|
||||
width: 258px;
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
margin-top: 30px;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
|
||||
width: 135px;
|
||||
height: 42px;
|
||||
|
||||
background: #219FE6;
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
|
||||
import {TableHeadItem} from "../TableHeadItem/TableHeadItem";
|
||||
|
||||
import './tableHead.scss';
|
||||
|
||||
export const TableHead = ({groups, tableConfig, info}) => {
|
||||
return (
|
||||
<div className='tableHead'>
|
||||
{
|
||||
groups
|
||||
? groups.map((groupItem, key) => {
|
||||
return (
|
||||
<div key={key} className='tableHead__group'
|
||||
style={{minWidth: groupItem.width, flex: groupItem.columnCount}}>
|
||||
<TableHeadItem item={{columnName: groupItem.id}} info={groupItem.info} isGroup={true}/>
|
||||
<div className='tableHead__groupItems'>
|
||||
{
|
||||
tableConfig.filter(headItem => headItem.groupId === groupItem.id).map((headItem, key) => {
|
||||
return (
|
||||
<TableHeadItem item={headItem} key={key} info={info && info[headItem.columnId]}/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
: tableConfig.map((headItem, key) => {
|
||||
return (
|
||||
<TableHeadItem key={`tableHeadItem${key}`} item={headItem}/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
.tableHead {
|
||||
display: flex;
|
||||
background-color: #131826;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-bottom: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
// &__item {
|
||||
// height: 38px;
|
||||
// position: relative;
|
||||
// flex: 1;
|
||||
|
||||
// &:after {
|
||||
// content: '';
|
||||
// position: absolute;
|
||||
// width: 100%;
|
||||
// bottom: 0;
|
||||
// left: 0;
|
||||
// border-bottom: 1px solid #282D3A;
|
||||
// }
|
||||
// }
|
||||
|
||||
&__groupItems {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&__group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 1px solid #282D3A;
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
|
||||
import './tableHeadItem.scss';
|
||||
|
||||
export const TableHeadItem = ({item, isGroup}) => {
|
||||
|
||||
return (
|
||||
<div className={`tableHeadItem${isGroup ? ' tableHeadItem--group' : ''}`}
|
||||
style={{minWidth: item.columnWidth, width: '100%'}}>
|
||||
<div className='tableHeadItem__text'>
|
||||
{
|
||||
typeof item.columnName === "function" ?
|
||||
item.columnName() : item.columnName
|
||||
}
|
||||
</div>
|
||||
{
|
||||
item.info
|
||||
&& (
|
||||
<div className='tableHeadItem__info'>
|
||||
<div className='tableHeadItem__message'>
|
||||
{item.info.message}
|
||||
</div>
|
||||
{item.info.message ? 'i' : ''}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
.tableHeadItem {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 38px;
|
||||
flex: 1;
|
||||
//padding: 10px 0;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-bottom: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
|
||||
&--group {
|
||||
height: 50px;
|
||||
padding: 18px 27px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
//border-left: 1px solid #282D3A;
|
||||
|
||||
.tableHeadItem__text {
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tableHeadItem__info {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-left: 8px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
font-size: 8px;
|
||||
|
||||
&--highlighted {
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 0 20px #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__text {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 13px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #898A98;
|
||||
}
|
||||
|
||||
&__info {
|
||||
margin-left: 5px;
|
||||
position: relative;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: #898A98;
|
||||
border-radius: 50%;
|
||||
font-size: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 0 20px #FFFFFF;
|
||||
.tableHeadItem__message {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__message {
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: max-content;
|
||||
max-width: 420px;
|
||||
padding: 10px;
|
||||
background-color: #131826;
|
||||
color: #FFFFFF;
|
||||
font-size: 12px;
|
||||
z-index: 2;
|
||||
top: initial;
|
||||
bottom: 16px;
|
||||
left: initial;
|
||||
right: -50%;
|
||||
transform: translate(20%, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
|
||||
import {TableCell} from "../TableCell/TableCell";
|
||||
|
||||
import './tableRow.scss';
|
||||
|
||||
export const TableRow = ({tableConfig, row, onChange}) => {
|
||||
return (
|
||||
<div className={`tableRow ${row.active ? "tableRow--active" : ""}`}>
|
||||
{
|
||||
tableConfig.map(({columnId, columnWidth, renderRowItem, isGroupEnd}, key) => {
|
||||
return (
|
||||
<TableCell
|
||||
key={`cell${row.id}${key}`}
|
||||
row={row}
|
||||
onChange={onChange}
|
||||
item={row[columnId]}
|
||||
columnWidth={columnWidth}
|
||||
renderRowItem={renderRowItem}
|
||||
isGroupEnd={isGroupEnd}
|
||||
tableConfig={tableConfig}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
.tableRow {
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
background-color: #131826;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-bottom: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
// &__cell {
|
||||
// height: 100%;
|
||||
// border-bottom: 1px solid #282D3A;
|
||||
// flex: 1;
|
||||
// }
|
||||
|
||||
}
|
||||
.tableRow--active {
|
||||
background-color: #23324f;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.table {
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
&__data {
|
||||
background-color: #131826;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
&__head {
|
||||
border-bottom: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
&__row {
|
||||
border-bottom: 1px solid #282D3A;
|
||||
}
|
||||
|
||||
&__load {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
import React, {useState} from "react";
|
||||
import {useDispatch} from "react-redux";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
|
||||
import {Checkbox} from "../../Common/Checkbox/Checkbox";
|
||||
import {Button} from "../../Common/Button/Button";
|
||||
import {Table} from "../../Table/Table";
|
||||
import {Form} from "../../Form/Form";
|
||||
import Modal from "../../Modal/Modal";
|
||||
|
||||
import {tableCompanySlice} from "../../../store/tableCompanySlice";
|
||||
import {tableWorkersSlice} from "../../../store/tableWorkersSlice";
|
||||
|
||||
import './tableCompany.scss'
|
||||
|
||||
export default React.memo(function TableCompany({isLoading, tableData}) {
|
||||
|
||||
const [modalData, setModalData] = useState({});
|
||||
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
const [modalCreateOpen, setModalCreateOpen] = useState(false);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const {
|
||||
setActiveCompany, setActiveAllCompany, removeSelectedCompany,
|
||||
setUnActiveWorkers, removeCompany, editCompanyData, createCompany
|
||||
} = tableCompanySlice.actions;
|
||||
|
||||
const {removeWorkersByIdCompany} = tableWorkersSlice.actions;
|
||||
|
||||
const companyTableConfig = [
|
||||
{
|
||||
columnId: 'check',
|
||||
columnName: () =>
|
||||
<Checkbox
|
||||
isActive={tableData.data.data.length === tableData.activeCompanyId.length}
|
||||
onChange={() => {
|
||||
dispatch(setUnActiveWorkers());
|
||||
dispatch(setActiveAllCompany());
|
||||
}}
|
||||
/>,
|
||||
columnWidth: '40px',
|
||||
renderRowItem: (item, row) =>
|
||||
<Checkbox
|
||||
id={row.id}
|
||||
isActive={tableData.activeCompanyId.includes(row.id)}
|
||||
onChange={() => {
|
||||
dispatch(setUnActiveWorkers());
|
||||
dispatch(setActiveCompany(row.id))
|
||||
}}
|
||||
/>,
|
||||
},
|
||||
{
|
||||
columnId: 'company_name',
|
||||
columnName: 'Название компании',
|
||||
columnWidth: '110px',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'number_of_employees',
|
||||
columnName: 'Количество сотрудников',
|
||||
columnWidth: '90px',
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
columnId: 'address',
|
||||
columnName: 'Адрес',
|
||||
columnWidth: '110px',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: "handlers",
|
||||
columnName: () => <Button
|
||||
styles={{padding: '1px', background: '#881818', maxWidth: '98px'}}
|
||||
onClick={() => {
|
||||
dispatch(removeSelectedCompany(tableData.activeCompanyId))
|
||||
}}
|
||||
>Удалить выбранные</Button>,
|
||||
renderRowItem: (item, row) =>
|
||||
<div>
|
||||
<Button styles={{padding: '3px', marginBottom: '3px'}} onClick={() => {
|
||||
dispatch(removeCompany(row.id));
|
||||
dispatch(removeWorkersByIdCompany(row.id))
|
||||
}
|
||||
}> Удалить
|
||||
</Button>
|
||||
<Button styles={{padding: '3px'}} onClick={
|
||||
() => {
|
||||
setModalData({...row});
|
||||
setModalOpen(true);
|
||||
}
|
||||
}>Редактировать
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
}
|
||||
];
|
||||
const createCompanyConfig = [
|
||||
{
|
||||
columnId: 'id',
|
||||
columnName: 'Фамилия',
|
||||
},
|
||||
{
|
||||
columnId: 'company_name',
|
||||
columnName: 'Название компании',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'address',
|
||||
columnName: 'Адрес',
|
||||
editable: true,
|
||||
},
|
||||
|
||||
];
|
||||
return (
|
||||
<div className='tableWrapper'>
|
||||
<div className='tableWrapper__title'>
|
||||
<Button styles={{background: "#3dda0c87", maxWidth: '200px'}} onClick={() => {
|
||||
setModalCreateOpen(true)
|
||||
}}>
|
||||
Добавить компанию
|
||||
</Button>
|
||||
</div>
|
||||
<Table
|
||||
// hasMore={tableData.has_more_pages}
|
||||
// fetchMore={() => {
|
||||
// setCursor(tableData.next_page_cursor_param);
|
||||
// setPushTableData(true)
|
||||
// }}
|
||||
isLoading={isLoading}
|
||||
tableConfig={companyTableConfig}
|
||||
emptyTable={{
|
||||
text: "Пусто...",
|
||||
}}
|
||||
data={tableData.data.data}
|
||||
|
||||
/>
|
||||
{modalOpen &&
|
||||
<Modal isOpen={modalOpen} onClose={() => setModalOpen(false)}>
|
||||
<Form data={modalData} onClick={(formData) => {
|
||||
dispatch(editCompanyData(formData));
|
||||
setModalOpen(false)
|
||||
}} config={companyTableConfig}/>
|
||||
</Modal>}
|
||||
|
||||
{modalCreateOpen &&
|
||||
<Modal isOpen={modalCreateOpen} onClose={() => {
|
||||
setModalCreateOpen(false)
|
||||
}}>
|
||||
<Form data={{
|
||||
company_name: '',
|
||||
address: "",
|
||||
|
||||
}} onClick={(formData) => {
|
||||
|
||||
const newFormData = {
|
||||
...formData,
|
||||
id: Math.floor(Math.random() * 10000),
|
||||
};
|
||||
dispatch(createCompany(newFormData));
|
||||
setModalCreateOpen(false)
|
||||
}} config={createCompanyConfig}/>
|
||||
</Modal>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,173 @@
|
||||
import React, {useState} from "react";
|
||||
import {useDispatch} from "react-redux";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
import {Table} from "../../Table/Table";
|
||||
import {Button} from "../../Common/Button/Button";
|
||||
import {Checkbox} from "../../Common/Checkbox/Checkbox";
|
||||
import {Form} from "../../Form/Form";
|
||||
import Modal from "../../Modal/Modal";
|
||||
|
||||
import {tableWorkersSlice} from "../../../store/tableWorkersSlice";
|
||||
|
||||
import './tableWorkers.scss'
|
||||
|
||||
export default React.memo(function TableWorkers({tableData, companyData}) {
|
||||
|
||||
const [modalData, setModalData] = useState({});
|
||||
const [modalEditOpen, setModalEditOpen] = useState(false);
|
||||
const [modalCreateOpen, setModalCreateOpen] = useState(false);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const {removeWorker, editWorkersData, removeSelectedWorkers, setActiveWorker, setActiveAllWorkers, createWorker} = tableWorkersSlice.actions;
|
||||
const arrCompany = companyData?.map((item) => {
|
||||
return {companyId: item.id, company_name: item.company_name}
|
||||
});
|
||||
|
||||
const companyWorkersTableConfig = [
|
||||
{
|
||||
columnId: 'checkWorkers',
|
||||
columnName: () =>
|
||||
<Checkbox
|
||||
isActive={tableData.visibleWorkers.length === tableData.activeWorkersId.length}
|
||||
onChange={() => {
|
||||
dispatch(setActiveAllWorkers());
|
||||
}}
|
||||
/>,
|
||||
columnWidth: '40px',
|
||||
renderRowItem: (item, row) =>
|
||||
<Checkbox
|
||||
id={row.id}
|
||||
isActive={tableData.activeWorkersId.includes(row.id)}
|
||||
onChange={() => {
|
||||
dispatch(setActiveWorker(row.id))
|
||||
}}
|
||||
/>,
|
||||
},
|
||||
{
|
||||
columnId: 'last_name',
|
||||
columnName: 'Фамилия',
|
||||
columnWidth: '100px',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'first_name',
|
||||
columnName: 'Имя',
|
||||
columnWidth: '100px',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'position',
|
||||
columnName: 'Должность',
|
||||
columnWidth: '110px',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: "handlers",
|
||||
columnName: () => <Button
|
||||
onClick={() => {
|
||||
dispatch(removeSelectedWorkers(tableData.activeWorkersId))
|
||||
}}
|
||||
styles={{padding: '1px', background: '#881818', maxWidth: '98px'}}
|
||||
>Удалить выбранные</Button>,
|
||||
renderRowItem: (item, row) =>
|
||||
<div>
|
||||
<Button styles={{padding: '3px', marginBottom: '3px'}} onClick={() =>
|
||||
dispatch(removeWorker(row.id))
|
||||
}> Удалить
|
||||
</Button>
|
||||
<Button styles={{padding: '3px'}} onClick={
|
||||
() => {
|
||||
setModalData({...row});
|
||||
setModalEditOpen(true);
|
||||
}
|
||||
}>Редактировать
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
},
|
||||
];
|
||||
|
||||
const createWorkerConfig = [
|
||||
{
|
||||
columnId: 'last_name',
|
||||
columnName: 'Фамилия',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'first_name',
|
||||
columnName: 'Имя',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'position',
|
||||
columnName: 'Должность',
|
||||
editable: true,
|
||||
},
|
||||
{
|
||||
columnId: 'companyId',
|
||||
columnName: 'Компания',
|
||||
editable: true,
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className='tableWrapper'>
|
||||
<div className='tableWrapper__title'>
|
||||
<Button styles={{background: "#3dda0c87", maxWidth: '200px'}} onClick={() => {
|
||||
setModalCreateOpen(true)
|
||||
}}>
|
||||
Добавить работника
|
||||
</Button>
|
||||
</div>
|
||||
<Table
|
||||
// hasMore={tableData.has_more_pages}
|
||||
// fetchMore={() => {
|
||||
// setCursor(tableData.next_page_cursor_param);
|
||||
// setPushTableData(true)
|
||||
// }}
|
||||
|
||||
tableConfig={companyWorkersTableConfig}
|
||||
emptyTable={{
|
||||
text: "Пусто...",
|
||||
}}
|
||||
data={tableData.visibleWorkers}
|
||||
onChange={editWorkersData}
|
||||
/>
|
||||
{modalEditOpen &&
|
||||
<Modal isOpen={modalEditOpen} onClose={() => {
|
||||
setModalEditOpen(false)
|
||||
}}>
|
||||
<Form data={modalData} onClick={(formData) => {
|
||||
dispatch(editWorkersData(formData));
|
||||
setModalEditOpen(false)
|
||||
}} config={companyWorkersTableConfig}/>
|
||||
</Modal>
|
||||
}
|
||||
|
||||
{modalCreateOpen &&
|
||||
<Modal isOpen={modalCreateOpen} onClose={() => {
|
||||
setModalCreateOpen(false)
|
||||
}}>
|
||||
<Form data={{
|
||||
last_name: '',
|
||||
first_name: "",
|
||||
position: "",
|
||||
companyId: arrCompany
|
||||
}} onClick={(formData) => {
|
||||
|
||||
const newFormData = {
|
||||
...formData,
|
||||
id: uuidv4(),
|
||||
companyId: formData.companyId.find((item) => item.active).companyId
|
||||
|
||||
};
|
||||
dispatch(createWorker(newFormData));
|
||||
setModalCreateOpen(false)
|
||||
}} config={createWorkerConfig}/>
|
||||
</Modal>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
.tableWorkers {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&__title {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
export function flat(arr) {
|
||||
const newArr = [];
|
||||
arr.forEach(i =>
|
||||
Array.isArray(i) ? newArr.push(...flat(i)) : newArr.push(i)
|
||||
);
|
||||
return newArr;
|
||||
}
|
||||
+12
-7
@@ -1,17 +1,22 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import {Provider} from "react-redux";
|
||||
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
import store from "./store/store";
|
||||
|
||||
import './index.css';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<App/>
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
|
||||
reportWebVitals();
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,73 @@
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
id: 1111,
|
||||
company_name: "Sber Bank",
|
||||
address: 'asfd asd',
|
||||
},
|
||||
{
|
||||
id: 2222,
|
||||
company_name: "alfa Bank",
|
||||
address: 'asfdasd',
|
||||
|
||||
},
|
||||
{
|
||||
id: 3333,
|
||||
company_name: "Tinkoff Bank",
|
||||
address: 'asfd ',
|
||||
},
|
||||
|
||||
];
|
||||
const workers= [
|
||||
{
|
||||
id: uuidv4(),
|
||||
companyId: 1111,
|
||||
last_name: "Karpenko",
|
||||
first_name: "sergey",
|
||||
position: "Front End developer",
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
companyId: 1111,
|
||||
last_name: "Ne karp",
|
||||
first_name: "Ne",
|
||||
position: "Ne Front End developer",
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
companyId: 1111,
|
||||
last_name: "Sasuke",
|
||||
first_name: "Kakashi",
|
||||
position: "Коллектор",
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
companyId: 2222,
|
||||
last_name: "Кактов",
|
||||
first_name: "ктото",
|
||||
position: "буздельник",
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
companyId: 3333,
|
||||
last_name: "Savenko",
|
||||
first_name: "Dima",
|
||||
position: "Front End developer",
|
||||
},
|
||||
{
|
||||
id: uuidv4(),
|
||||
companyId: 3333,
|
||||
last_name: "Ne Savenko",
|
||||
first_name: "Ne Dima",
|
||||
position: "Ne Front End developer",
|
||||
},
|
||||
];
|
||||
|
||||
export const companyRecords = {
|
||||
data: tableData,
|
||||
totalRecords: tableData.length,
|
||||
pages: (tableData.length + 1) / 10
|
||||
};
|
||||
|
||||
export const companyWorkers = workers
|
||||
@@ -0,0 +1,18 @@
|
||||
import {configureStore, combineReducers} from "@reduxjs/toolkit";
|
||||
|
||||
import tableCompanySlice from './tableCompanySlice'
|
||||
import tableWorkersSlice from "./tableWorkersSlice";
|
||||
|
||||
import {composeWithDevTools} from "redux-devtools-extension";
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
table: tableCompanySlice,
|
||||
tableWorkers: tableWorkersSlice,
|
||||
|
||||
});
|
||||
|
||||
const store = configureStore({
|
||||
reducer: rootReducer,
|
||||
}, composeWithDevTools());
|
||||
|
||||
export default store
|
||||
@@ -0,0 +1,89 @@
|
||||
import {createSlice} from "@reduxjs/toolkit";
|
||||
|
||||
|
||||
export const tableCompanySlice = createSlice({
|
||||
name: "tableCompany",
|
||||
initialState: {
|
||||
data: [],
|
||||
activeCompanyId: [],
|
||||
|
||||
},
|
||||
|
||||
reducers: {
|
||||
setInitialCompany(state, {payload}) {
|
||||
|
||||
state.data = payload
|
||||
},
|
||||
|
||||
calculateWorkersInCompany(state, {payload}) {
|
||||
const countWorkersInCompany = payload.reduce((acc, el) => {
|
||||
acc[el.companyId] = (acc[el.companyId] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
|
||||
if (Array.isArray(state.data.data)) {
|
||||
state.data.data = state.data?.data.map((i) => {
|
||||
return {
|
||||
...i,
|
||||
number_of_employees: countWorkersInCompany[i.id]
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
setActiveCompany(state, {payload}) {
|
||||
|
||||
const index = state.activeCompanyId.indexOf(payload);
|
||||
if (index > -1) {
|
||||
state.activeCompanyId.splice(index, 1)
|
||||
} else {
|
||||
state.activeCompanyId.push(payload)
|
||||
}
|
||||
},
|
||||
|
||||
setActiveAllCompany(state) {
|
||||
if (state.activeCompanyId.length && state.activeCompanyId.length === state.data.data.length) {
|
||||
state.activeCompanyId = []
|
||||
} else {
|
||||
state.activeCompanyId = state.data.data.map(item => item.id)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setUnActiveWorkers(state) {
|
||||
state.activeWorkersId = []
|
||||
},
|
||||
|
||||
removeCompany(state, {payload}) {
|
||||
state.data.data = state.data.data.filter((item) => item.id !== payload)
|
||||
},
|
||||
|
||||
removeSelectedCompany(state, {payload}) {
|
||||
|
||||
state.data.data = state.data.data.filter((item) => !payload.includes(item.id))
|
||||
},
|
||||
|
||||
editCompanyData(state, action) {
|
||||
state.data.data = state.data.data.map((i) => {
|
||||
if (i.id === action.payload.id) {
|
||||
return action.payload
|
||||
}
|
||||
return i
|
||||
})
|
||||
},
|
||||
createCompany(state, {payload}) {
|
||||
state.data.data = [...state.data.data, payload]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default tableCompanySlice.reducer
|
||||
|
||||
export const {
|
||||
setInitialCompany, setActiveCompany, setActiveAllCompany, createCompany,
|
||||
setUnActiveWorkers, removeCompany, editCompanyData, calculateWorkersInCompany
|
||||
} = tableCompanySlice.actions;
|
||||
@@ -0,0 +1,93 @@
|
||||
import {createSlice} from "@reduxjs/toolkit";
|
||||
|
||||
|
||||
export const tableWorkersSlice = createSlice({
|
||||
name: "tableWorkers",
|
||||
initialState: {
|
||||
workers: [],
|
||||
activeWorkersId: [],
|
||||
visibleWorkers: []
|
||||
},
|
||||
|
||||
reducers: {
|
||||
setInitialWorkers(state, {payload}) {
|
||||
state.workers = payload
|
||||
},
|
||||
|
||||
showCompanyWorkers(state, {payload}) {
|
||||
|
||||
state.visibleWorkers = state.workers.filter((item) => payload.includes(item.companyId))
|
||||
},
|
||||
|
||||
setColorActiveWorker(state) {
|
||||
|
||||
state.visibleWorkers = state.visibleWorkers.map((worker) => {
|
||||
if (state.activeWorkersId.includes(worker.id)) {
|
||||
return {...worker, active: true}
|
||||
} else {
|
||||
return {...worker, active: false}
|
||||
}
|
||||
})
|
||||
},
|
||||
setActiveWorker(state, action) {
|
||||
const index = state.activeWorkersId.indexOf(action.payload);
|
||||
if (index > -1) {
|
||||
state.activeWorkersId.splice(index, 1)
|
||||
} else {
|
||||
state.activeWorkersId.push(action.payload)
|
||||
}
|
||||
},
|
||||
|
||||
setActiveAllWorkers(state) {
|
||||
if (state.activeWorkersId.length > 0 && state.activeWorkersId.length === state.visibleWorkers.length) {
|
||||
state.activeWorkersId = []
|
||||
} else {
|
||||
state.activeWorkersId = state.visibleWorkers.map(item => item.id)
|
||||
}
|
||||
},
|
||||
removeWorkersByIdCompany(state, {payload}) {
|
||||
|
||||
state.workers = state.workers.filter((i) => i.companyId !== payload);
|
||||
state.visibleWorkers = state.visibleWorkers.filter((i) => i.companyId !== payload)
|
||||
|
||||
},
|
||||
|
||||
removeWorker(state, action) {
|
||||
state.workers = state.workers.filter((item) => item.id !== action.payload);
|
||||
state.visibleWorkers = state.visibleWorkers.filter((item) => item.id !== action.payload)
|
||||
},
|
||||
|
||||
removeSelectedWorkers(state, {payload}) {
|
||||
state.workers = state.workers.filter((item) => !payload.includes(item.id));
|
||||
state.visibleWorkers = state.visibleWorkers.filter((item) => !payload.includes(item.id))
|
||||
},
|
||||
|
||||
editWorkersData(state, {payload}) {
|
||||
state.workers = state.workers.map((i) => {
|
||||
if (i.id === payload.id) {
|
||||
return payload
|
||||
}
|
||||
return i
|
||||
});
|
||||
state.visibleWorkers = state.visibleWorkers.map((i) => {
|
||||
if (i.id === payload.id) {
|
||||
return payload
|
||||
}
|
||||
return i
|
||||
});
|
||||
},
|
||||
createWorker(state, {payload}) {
|
||||
state.workers = [...state.workers, payload]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default tableWorkersSlice.reducer
|
||||
|
||||
export const {
|
||||
setInitialWorkers, showCompanyWorkers, setColorActiveWorker, removeWorkersByIdCompany, removeWorker,
|
||||
editWorkersData, removeSelectedWorkers, setActiveWorker, createWorker
|
||||
|
||||
} = tableWorkersSlice.actions;
|
||||
Reference in New Issue
Block a user