Частичная реализация (front)
This commit is contained in:
parent
19473c157c
commit
ab6afea43b
52
front/src/components/Catalog.jsx
Normal file
52
front/src/components/Catalog.jsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import Button from 'react-bootstrap/Button';
|
||||||
|
import Table from "../commons/Table.jsx";
|
||||||
|
import { useState} from 'react';
|
||||||
|
import styles from './Catalog.module.css';
|
||||||
|
import ModalForm from '../commons/ModalForm.jsx';
|
||||||
|
import { Container } from 'react-bootstrap';
|
||||||
|
// это абстрактный компонент для всех справочников
|
||||||
|
export default function Catalog(props) {
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
|
const [modalTitle, setModalTitle] = useState("");
|
||||||
|
|
||||||
|
const handleClose = () => setShow(false);
|
||||||
|
const handleShow = () => setShow(true);
|
||||||
|
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
setModalTitle("Добавление");
|
||||||
|
props.onBtnAdd();
|
||||||
|
handleShow();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEdit(itemId) {
|
||||||
|
setModalTitle("Редактирование");
|
||||||
|
props.onEdit(itemId);
|
||||||
|
handleShow();
|
||||||
|
}
|
||||||
|
function handleRemove(item) {
|
||||||
|
props.onDelete(item);
|
||||||
|
}
|
||||||
|
function changeData(event) {
|
||||||
|
props.onFormChanged(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div className={`${styles.catalogName}`}>{props.name}</div>
|
||||||
|
<Button variant="success" onClick={handleAdd}>Добавить</Button>
|
||||||
|
<Table
|
||||||
|
headers={props.headers}
|
||||||
|
items={props.items}
|
||||||
|
onEdit={handleEdit}
|
||||||
|
onDelete={handleRemove}
|
||||||
|
/>
|
||||||
|
<ModalForm
|
||||||
|
show={show}
|
||||||
|
onClose={handleClose}
|
||||||
|
modalTitle={modalTitle}
|
||||||
|
// onSubmit={submitForm}
|
||||||
|
onChange={changeData}
|
||||||
|
form={props.form}
|
||||||
|
/></>
|
||||||
|
|
||||||
|
}
|
101
front/src/components/Employees.jsx
Normal file
101
front/src/components/Employees.jsx
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import Employee from "../models/Employee";
|
||||||
|
|
||||||
|
export default function Employees(props) {
|
||||||
|
const headers = [
|
||||||
|
{name: 'surname', label: "Фамилия"},
|
||||||
|
{name: 'name', label: "Имя"},
|
||||||
|
{name: 'phoneNumber', label: "Номер телефона"},
|
||||||
|
];
|
||||||
|
const nameCatalog = "Сотрудники";
|
||||||
|
const [items, setItems] = useState([]);
|
||||||
|
const url = 'employee/';
|
||||||
|
const [data, setData] = useState(new Employee());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadItems();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
function loadItems() {
|
||||||
|
DataService.readAll(url, (data) => new Employee(data))
|
||||||
|
.then(data => setItems(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
DataService.create(url, data).then(() => loadItems());
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEdit(editedId) {
|
||||||
|
DataService.read(url + editedId, (e) => new Employee(e))
|
||||||
|
.then(data => {
|
||||||
|
setData(new Employee(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
function handleEditIsDone() {
|
||||||
|
DataService.update(url + data.id, data).then(() => loadItems());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDelete(item) {
|
||||||
|
if (window.confirm('Удалить выбранный элемент?')) {
|
||||||
|
const promises = [];
|
||||||
|
promises.push(DataService.delete(url + item));
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
loadItems();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// при каждом изменении поля формы происходит вызов этого метода, обновляя данные объекта
|
||||||
|
function handleFormChange(event) {
|
||||||
|
setData({ ...data, [event.target.id]: event.target.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
// определяет действия формы по нажатию Отправить
|
||||||
|
function submitForm() {
|
||||||
|
if (!isEditing) {
|
||||||
|
// если добавление элемента
|
||||||
|
handleAdd();
|
||||||
|
} else {
|
||||||
|
// если редактирование элемента;
|
||||||
|
handleEditIsDone();
|
||||||
|
setEditing(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// вызывается при закрытии модального окна или по нажатию кнопки Добавить и очищает данные объекта
|
||||||
|
function reset() {
|
||||||
|
console.log("Очистка формыыы");
|
||||||
|
setData(new Employee());
|
||||||
|
setEditing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// для каждого типа сущности своя форма,
|
||||||
|
// которая передается дальше в абстрактный компонент Catalog в качестве props.form
|
||||||
|
const form = <Form onSubmit={submitForm}>
|
||||||
|
<Form.Group className="mb-3" controlId="name">
|
||||||
|
<Form.Label>Фамилия</Form.Label>
|
||||||
|
<Form.Control value={data.surname} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
|
||||||
|
<Form.Label>Имя</Form.Label>
|
||||||
|
<Form.Control value={data.name} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
|
||||||
|
<Form.Label>Номер телефона</Form.Label>
|
||||||
|
<Form.Control value={data.phoneNumber} type="input" placeholder="Enter text" onChange={handleFormChange} required/>
|
||||||
|
</Form.Group>
|
||||||
|
<Button variant="primary" type="submit">
|
||||||
|
Отправить
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
return <div className="container-lg pt-5 min-vh-100">
|
||||||
|
<Catalog name={nameCatalog}
|
||||||
|
headers={headers}
|
||||||
|
items={items}
|
||||||
|
onAdd={handleAdd}
|
||||||
|
onEdit={handleEdit}
|
||||||
|
onDelete={handleDelete}
|
||||||
|
onClose={reset}
|
||||||
|
onBtnAdd={reset}
|
||||||
|
form={form}>
|
||||||
|
</Catalog>
|
||||||
|
</div>
|
||||||
|
}
|
0
front/src/components/EntitiesList.jsx
Normal file
0
front/src/components/EntitiesList.jsx
Normal file
25
front/src/components/commons/Header.jsx
Normal file
25
front/src/components/commons/Header.jsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { NavLink } from 'react-router-dom';
|
||||||
|
import Container from 'react-bootstrap/Container';
|
||||||
|
import Nav from 'react-bootstrap/Nav';
|
||||||
|
import Navbar from 'react-bootstrap/Navbar';
|
||||||
|
|
||||||
|
export default function Header(props) {
|
||||||
|
return (
|
||||||
|
<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
|
||||||
|
<Container className='lg justify-content-center'>
|
||||||
|
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
|
||||||
|
<Navbar.Collapse id="responsive-navbar-nav">
|
||||||
|
<Nav className="me-auto">
|
||||||
|
{
|
||||||
|
props.links.map(route =>
|
||||||
|
<NavLink key={route.path} className="nav-link" to={route.path}>
|
||||||
|
<div>{route.label}</div>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Nav>
|
||||||
|
</Navbar.Collapse>
|
||||||
|
</Container>
|
||||||
|
</Navbar>
|
||||||
|
);
|
||||||
|
}
|
18
front/src/components/commons/ItemTable.jsx
Normal file
18
front/src/components/commons/ItemTable.jsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Button from 'react-bootstrap/Button';
|
||||||
|
export default function ItemTable(props) {
|
||||||
|
function edit() {
|
||||||
|
props.onEdit(props.item.id);
|
||||||
|
}
|
||||||
|
function remove() {
|
||||||
|
props.onDelete(props.item.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <tr key={props.item.id}>
|
||||||
|
{
|
||||||
|
props.headers.map((header) => <td key={`${header.name}_${props.item.id}`}>{props.item[header.name]}</td>)
|
||||||
|
}
|
||||||
|
{props.isOnlyView || <td key={`controls_${props.item.id}`}>
|
||||||
|
<Button variant="info" onClick={edit}>Редактировать</Button>
|
||||||
|
<Button variant="danger" onClick={remove}>Удалить</Button></td>}
|
||||||
|
</tr>
|
||||||
|
}
|
36
front/src/components/commons/Table.jsx
Normal file
36
front/src/components/commons/Table.jsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import ItemTable from './ItemTable';
|
||||||
|
import styles from './Table.module.css';
|
||||||
|
export default function Table(props) {
|
||||||
|
function edit(itemId) {
|
||||||
|
props.onEdit(itemId)
|
||||||
|
}
|
||||||
|
function remove(itemId) {
|
||||||
|
props.onDelete(itemId);
|
||||||
|
}
|
||||||
|
console.log(props.items);
|
||||||
|
return <div className={`${styles.wrapper}`}>
|
||||||
|
<table className={`table table-hover ${styles.table}`}>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{
|
||||||
|
props.headers.map((header) => <th key={header.name}>{header.label}</th>)
|
||||||
|
}
|
||||||
|
{props.isOnlyView || <th key='controls'>Элементы управления</th>}
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{
|
||||||
|
props.items.map((item, index) =>
|
||||||
|
<ItemTable
|
||||||
|
key={index}
|
||||||
|
headers={props.headers}
|
||||||
|
item={item}
|
||||||
|
onDelete={remove}
|
||||||
|
onEdit={edit}
|
||||||
|
isOnlyView={props.isOnlyView}/>)
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
}
|
8
front/src/models/Employee.js
Normal file
8
front/src/models/Employee.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default class Employee {
|
||||||
|
constructor(data) {
|
||||||
|
this.id = data?.id;
|
||||||
|
this.surname = data?.surname || '';
|
||||||
|
this.name = data?.name || '';
|
||||||
|
this.phoneNumber = data?.phoneNumber || '';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user