&_&
This commit is contained in:
parent
07bd46c0ac
commit
2babc111b9
23
1/.gitignore
vendored
23
1/.gitignore
vendored
@ -1,23 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
70
1/README.md
70
1/README.md
@ -1,70 +0,0 @@
|
||||
# Getting Started with Create React App
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
||||
|
||||
The page will reload when you make changes.\
|
||||
You may also see any lint errors in the console.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
||||
|
||||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
||||
|
||||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||
|
||||
### `npm run build` fails to minify
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
19
1/data.json
19
1/data.json
@ -1,19 +0,0 @@
|
||||
{
|
||||
"posts": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "json-server",
|
||||
"author": "typicode"
|
||||
}
|
||||
],
|
||||
"comments": [
|
||||
{
|
||||
"id": 1,
|
||||
"body": "some comment",
|
||||
"postId": 1
|
||||
}
|
||||
],
|
||||
"profile": {
|
||||
"name": "typicode"
|
||||
}
|
||||
}
|
10117
1/package-lock.json
generated
10117
1/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "front",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"web-vitals": "^2.1.4",
|
||||
"axios": "^1.1.3",
|
||||
"bootstrap": "^5.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>
|
||||
<title>Front for spring</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,40 +0,0 @@
|
||||
import { useRoutes, Outlet, BrowserRouter } from 'react-router-dom';
|
||||
import Header from './components/common/Header';
|
||||
import Catalogs from './components/catalogs/Catalogs';
|
||||
import CatalogProducts from './components/catalogs/CatalogProducts';
|
||||
import CatalogSuppliers from './components/catalogs/CatalogSuppliers';
|
||||
|
||||
|
||||
function Router(props) {
|
||||
return useRoutes(props.rootRoute);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const routes = [
|
||||
{ index: true, element: <Catalogs /> },
|
||||
{ path: 'catalogs', element: <Catalogs />, label: 'Справочники' },
|
||||
{ path: 'catalogs/products', element: <CatalogProducts/> },
|
||||
{ path: 'catalogs/suppliers', element: <CatalogSuppliers /> }
|
||||
];
|
||||
const links = routes.filter(route => route.hasOwnProperty('label'));
|
||||
const rootRoute = [
|
||||
{ path: '/', element: render(links), children: routes }
|
||||
];
|
||||
|
||||
function render(links) {
|
||||
return (
|
||||
<>
|
||||
<Header links={links} />
|
||||
<div className="container-fluid">
|
||||
<Outlet />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Router rootRoute={ rootRoute } />
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
import axios from "axios";
|
||||
|
||||
function toJSON(data) {
|
||||
const jsonObj = {};
|
||||
const fields = Object.getOwnPropertyNames(data);
|
||||
for (const field of fields) {
|
||||
if (data[field] === undefined) {
|
||||
continue;
|
||||
}
|
||||
jsonObj[field] = data[field];
|
||||
}
|
||||
return jsonObj;
|
||||
}
|
||||
|
||||
export default class DataService {
|
||||
static dataUrlPrefix = 'http://localhost:8080/';
|
||||
|
||||
static async readAll(url, transformer) {
|
||||
const response = await axios.get(this.dataUrlPrefix + url);
|
||||
return response.data.map(item => transformer(item));
|
||||
}
|
||||
|
||||
static async read(url, transformer) {
|
||||
const response = await axios.get(this.dataUrlPrefix + url);
|
||||
return transformer(response.data);
|
||||
}
|
||||
|
||||
static async create(url, data) {
|
||||
const response = await axios.post(this.dataUrlPrefix + url, toJSON(data));
|
||||
return true;
|
||||
}
|
||||
|
||||
static async update(url, data) {
|
||||
const response = await axios.put(this.dataUrlPrefix + url, toJSON(data));
|
||||
return true;
|
||||
}
|
||||
|
||||
static async delete(url) {
|
||||
const response = await axios.delete(this.dataUrlPrefix + url);
|
||||
return response.data.id;
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
import React, {useState} from 'react';
|
||||
|
||||
const productModel ={
|
||||
name: '',
|
||||
cost: ''
|
||||
}
|
||||
|
||||
export default function ProductPage(){
|
||||
const mainUrl = 'http://localhost:8080/product/'
|
||||
|
||||
const [product, setProduct] = useState(productModel)
|
||||
|
||||
const [products, setProducts] = useState([])
|
||||
|
||||
const addProduct = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
setProducts((prevState) => [...prevState, product])
|
||||
setProduct(productModel)
|
||||
}
|
||||
|
||||
const getAllProducts = () =>{
|
||||
fetch(`${mainUrl}`)
|
||||
.then((res) => {
|
||||
return res.json();
|
||||
})
|
||||
.then((arr) => {
|
||||
setProducts(arr);
|
||||
})
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="container">
|
||||
<form id="form" onSubmit={addProduct}>
|
||||
<div className="row mt-3">
|
||||
<div className="col-sm-6">
|
||||
<label for="lastName" className="form-label">Наименование</label>
|
||||
<input type="text" className="form-control" id="productName" required
|
||||
onChange={(e) => setProduct((prevState => (
|
||||
{
|
||||
...prevState, name: e.target.value
|
||||
}
|
||||
)))} value={product.name} />
|
||||
</div>
|
||||
<div className="col-sm-6">
|
||||
<label for="firstName" className="form-label">Цена</label>
|
||||
<input type="text" className="form-control" id="productCost" required
|
||||
onChange={(e) => setProduct((prevState => (
|
||||
{
|
||||
...prevState, cost: e.target.value
|
||||
}
|
||||
)))} value={product.cost}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row mt-3">
|
||||
<div className="d-grid col-sm-4 mx-auto">
|
||||
<button type="submit" className="btn btn-success">Добавить</button>
|
||||
</div>
|
||||
<div className="d-grid col-sm-4 mx-auto mt-3 mt-sm-0">
|
||||
<button type="reset" className="btn btn-danger">Очистить инпуты</button>
|
||||
</div>
|
||||
<div className="d-grid col-sm-4 mx-auto mt-3 mt-sm-0">
|
||||
<button id="testNormal" type="button" className="btn btn-secondary">Test</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div className="row table-responsive">
|
||||
<table className="table mt-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Наименование</th>
|
||||
<th scope="col">Цена</th>
|
||||
<th scope="col">Действие</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
{products.map((product, index) =>
|
||||
|
||||
<tr>
|
||||
<td>{index + 1}</td>
|
||||
<td>{product.name}</td>
|
||||
<td>{product.cost}</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import Toolbar from "../common/Toolbar";
|
||||
import Table from "../common/Table";
|
||||
import Modal from "../common/Modal";
|
||||
import DataService from '../DataService';
|
||||
|
||||
export default function Catalog(props) {
|
||||
const [items, setItems] = useState([]);
|
||||
const [modalHeader, setModalHeader] = useState('');
|
||||
const [modalConfirm, setModalConfirm] = useState('');
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [isEdit, setEdit] = useState(false);
|
||||
|
||||
let selectedItems = [];
|
||||
|
||||
useEffect(() => {
|
||||
loadItems();
|
||||
}, []);
|
||||
|
||||
function loadItems() {
|
||||
DataService.readAll(props.getAllUrl, props.transformer)
|
||||
.then(data => setItems(data));
|
||||
}
|
||||
|
||||
function saveItem() {
|
||||
if (!isEdit) {
|
||||
DataService.create(props.url, props.data).then(() => loadItems());
|
||||
} else {
|
||||
DataService.update(props.url + props.data.id, props.data).then(() => loadItems());
|
||||
}
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
setEdit(false);
|
||||
setModalHeader('Добавление элемента');
|
||||
setModalConfirm('Добавить');
|
||||
setModalVisible(true);
|
||||
props.onAdd();
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
if (selectedItems.length === 0) {
|
||||
return;
|
||||
}
|
||||
edit(selectedItems[0]);
|
||||
}
|
||||
|
||||
function edit(editedId) {
|
||||
DataService.read(props.url + editedId, props.transformer)
|
||||
.then(data => {
|
||||
setEdit(true);
|
||||
setModalHeader('Редактирование элемента');
|
||||
setModalConfirm('Сохранить');
|
||||
setModalVisible(true);
|
||||
props.onEdit(data);
|
||||
});
|
||||
}
|
||||
|
||||
function handleRemove() {
|
||||
if (selectedItems.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (confirm('Удалить выбранные элементы?')) {
|
||||
const promises = [];
|
||||
selectedItems.forEach(item => {
|
||||
promises.push(DataService.delete(props.url + item));
|
||||
});
|
||||
Promise.all(promises).then((results) => {
|
||||
selectedItems.length = 0;
|
||||
loadItems();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleTableClick(tableSelectedItems) {
|
||||
selectedItems = tableSelectedItems;
|
||||
}
|
||||
|
||||
function handleTableDblClick(tableSelectedItem) {
|
||||
edit(tableSelectedItem);
|
||||
}
|
||||
|
||||
function handleModalHide() {
|
||||
setModalVisible(false);
|
||||
}
|
||||
|
||||
function handleModalDone() {
|
||||
saveItem();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Toolbar
|
||||
onAdd={handleAdd}
|
||||
onEdit={handleEdit}
|
||||
onRemove={handleRemove}/>
|
||||
<Table
|
||||
headers={props.headers}
|
||||
items={items}
|
||||
selectable={true}
|
||||
onClick={handleTableClick}
|
||||
onDblClick={handleTableDblClick}/>
|
||||
<Modal
|
||||
header={modalHeader}
|
||||
confirm={modalConfirm}
|
||||
visible={modalVisible}
|
||||
onHide={handleModalHide}
|
||||
onDone={handleModalDone}>
|
||||
{props.children}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import Catalog from './Catalog';
|
||||
import Discipline from '../../models/Discipline';
|
||||
|
||||
export default function CatalogOrders(props) {
|
||||
const url = 'product/';
|
||||
const transformer = (data) => new Discipline(data);
|
||||
const catalogProductHeaders = [
|
||||
{ name: 'name', label: 'Продукт' }
|
||||
];
|
||||
|
||||
const [data, setData] = useState(new Discipline());
|
||||
|
||||
function handleOnAdd() {
|
||||
setData(new Discipline());
|
||||
}
|
||||
|
||||
function handleOnEdit(data) {
|
||||
setData(new Discipline(data));
|
||||
}
|
||||
|
||||
function handleFormChange(event) {
|
||||
setData({ ...data, [event.target.id]: event.target.value })
|
||||
}
|
||||
|
||||
return (
|
||||
<Catalog headers={catalogProductHeaders}
|
||||
getAllUrl={url}
|
||||
url={url}
|
||||
transformer={transformer}
|
||||
data={data}
|
||||
onAdd={handleOnAdd}
|
||||
onEdit={handleOnEdit}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="name" className="form-label">Название продукта</label>
|
||||
<input type="text" id="name" className="form-control" required
|
||||
value={data.name} onChange={handleFormChange}/>
|
||||
</div>
|
||||
</Catalog>
|
||||
);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import Catalog from './Catalog';
|
||||
import Product from '../models/Product';
|
||||
|
||||
export default function CatalogProducts(props) {
|
||||
const url = 'product/';
|
||||
|
||||
const transformer = (data) => new Product(data);
|
||||
|
||||
const catalogProductHeaders = [
|
||||
{ name: 'name', label: 'Продукт' },
|
||||
{ name: 'cost', label: 'Цена' }
|
||||
];
|
||||
|
||||
const [data, setData] = useState(new Product());
|
||||
|
||||
function handleOnAdd() {
|
||||
setData(new Product());
|
||||
}
|
||||
|
||||
function handleOnEdit(data) {
|
||||
setData(new Product(data));
|
||||
}
|
||||
|
||||
function handleFormChange(event) {
|
||||
setData({ ...data, [event.target.id]: event.target.value })
|
||||
}
|
||||
|
||||
return (
|
||||
<Catalog headers={catalogProductHeaders}
|
||||
getAllUrl={url}
|
||||
url={url}
|
||||
transformer={transformer}
|
||||
data={data}
|
||||
onAdd={handleOnAdd}
|
||||
onEdit={handleOnEdit}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="name" className="form-label">Наименование</label>
|
||||
<input type="text" id="name" className="form-control" required
|
||||
value={data.name} onChange={handleFormChange}/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="cost" className="form-label">Цена</label>
|
||||
<input type="number" id="cost" className="form-control" required
|
||||
value={data.cost} onChange={handleFormChange}/>
|
||||
</div>
|
||||
</Catalog>
|
||||
);
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import Catalog from './Catalog';
|
||||
import Supplier from '../models/Supplier';
|
||||
|
||||
export default function CatalogSuppliers(props) {
|
||||
const url = 'supplier/';
|
||||
const transformer = (data) => new Supplier(data);
|
||||
const catalogSupplierHeaders = [
|
||||
{ name: 'name', label: 'Название организации' },
|
||||
{ name: 'license', label: 'Номер лицензии' }
|
||||
];
|
||||
|
||||
const [data, setData] = useState(new Supplier());
|
||||
|
||||
function handleOnAdd() {
|
||||
setData(new Supplier());
|
||||
}
|
||||
|
||||
function handleOnEdit(data) {
|
||||
setData(new Supplier(data));
|
||||
}
|
||||
|
||||
function handleFormChange(event) {
|
||||
setData({ ...data, [event.target.id]: event.target.value })
|
||||
}
|
||||
|
||||
return (
|
||||
<Catalog headers={catalogSupplierHeaders}
|
||||
getAllUrl={url}
|
||||
url={url}
|
||||
transformer={transformer}
|
||||
data={data}
|
||||
onAdd={handleOnAdd}
|
||||
onEdit={handleOnEdit}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="name" className="form-label">Название организаци</label>
|
||||
<input type="text" id="name" className="form-control" required
|
||||
value={data.name} onChange={handleFormChange}/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="license" className="form-label">Номер лицензии</label>
|
||||
<input type="text" id="license" className="form-control" required
|
||||
value={data.license} onChange={handleFormChange}/>
|
||||
</div>
|
||||
</Catalog>
|
||||
);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import LinksList from '../common/LinksList';
|
||||
|
||||
export default function Catalogs(props) {
|
||||
const catalogs = [
|
||||
{ name: 'products', label: 'Продукты' },
|
||||
{ name: 'suppliers', label: 'Поставщики' },
|
||||
// { name: 'orders', label: 'Заказы' }
|
||||
];
|
||||
|
||||
return (
|
||||
<LinksList items={catalogs} />
|
||||
);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
export default function Header(props) {
|
||||
return (
|
||||
<nav className="navbar navbar-expand-lg bg-light">
|
||||
<div className="container-fluid">
|
||||
<h1 className="navbar-brand">Поставки</h1>
|
||||
<button className="navbar-toggler" type="button"
|
||||
data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarNav">
|
||||
<ul className="navbar-nav">
|
||||
{
|
||||
props.links.map(route =>
|
||||
<li key={route.path}
|
||||
className="nav-item">
|
||||
<NavLink className="nav-link" to={route.path}>
|
||||
{route.label}
|
||||
</NavLink>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav >
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default function LinksList(props) {
|
||||
return (
|
||||
<div className="list-group">
|
||||
{
|
||||
props.items.map(catalog =>
|
||||
<Link key={catalog.name} to={catalog.name}
|
||||
className="list-group-item list-group-item-action">
|
||||
{catalog.label}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
</div >
|
||||
);
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
export default function Modal(props) {
|
||||
const formRef = React.createRef();
|
||||
|
||||
function hide() {
|
||||
props.onHide();
|
||||
}
|
||||
|
||||
function done(e) {
|
||||
e.preventDefault();
|
||||
if (formRef.current.checkValidity()) {
|
||||
props.onDone();
|
||||
hide();
|
||||
} else {
|
||||
formRef.current.reportValidity();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal fade show" tabIndex="-1" aria-hidden="true"
|
||||
style={{ display: props.visible ? 'block' : 'none' }}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="modal-title fs-5" id="exampleModalLabel">{props.header}</h1>
|
||||
<button className="btn-close" type="button" aria-label="Close"
|
||||
onClick={hide}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<form ref={formRef} onSubmit={done}>
|
||||
{props.children}
|
||||
</form>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-secondary" type="button" onClick={hide}>Закрыть</button>
|
||||
<button className="btn btn-primary" type="button" onClick={done}>
|
||||
{props.confirm}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import styles from './Table.module.css';
|
||||
|
||||
export default function Table(props) {
|
||||
const [tableUpdate, setTableUpdate] = useState(false);
|
||||
const [selectedItems, setSelectedItems] = useState([]);
|
||||
|
||||
function isSelected(id) {
|
||||
if (!props.selectable) {
|
||||
return false;
|
||||
}
|
||||
return selectedItems.includes(id);
|
||||
}
|
||||
|
||||
function click(id) {
|
||||
if (!props.selectable) {
|
||||
return;
|
||||
}
|
||||
if (isSelected(id)) {
|
||||
var index = selectedItems.indexOf(id);
|
||||
if (index !== -1) {
|
||||
selectedItems.splice(index, 1);
|
||||
setSelectedItems(selectedItems);
|
||||
setTableUpdate(!tableUpdate);
|
||||
}
|
||||
} else {
|
||||
selectedItems.push(id);
|
||||
setSelectedItems(selectedItems);
|
||||
setTableUpdate(!tableUpdate);
|
||||
}
|
||||
props.onClick(selectedItems);
|
||||
}
|
||||
|
||||
function dblClick(id) {
|
||||
if (!props.selectable) {
|
||||
return;
|
||||
}
|
||||
props.onDblClick(id);
|
||||
}
|
||||
|
||||
return (
|
||||
<table className={`table table-hover ${styles.table} ${props.selectable ? styles.selectable : ''}`}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
{
|
||||
props.headers.map(header =>
|
||||
<th key={header.name} scope="col">
|
||||
{header.label}
|
||||
</th>
|
||||
)
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
props.items.map((item, index) =>
|
||||
<tr key={item.id}
|
||||
className={isSelected(item.id) ? styles.selected : ''}
|
||||
onClick={(e) => click(item.id, e)} onDoubleClick={(e) => dblClick(item.id, e)}>
|
||||
<th scope="row">{index + 1}</th>
|
||||
{
|
||||
props.headers.map(header =>
|
||||
<td key={item.id + header.name}>{item[header.name]}</td>
|
||||
)
|
||||
}
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
</tbody >
|
||||
</table >
|
||||
);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
.table tbody tr {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.selectable tbody tr:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-color: #0d6efd;
|
||||
opacity: 80%;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import styles from './Toolbar.module.css';
|
||||
|
||||
export default function Toolbar(props) {
|
||||
function add() {
|
||||
props.onAdd();
|
||||
}
|
||||
|
||||
function edit() {
|
||||
props.onEdit();
|
||||
}
|
||||
|
||||
function remove() {
|
||||
props.onRemove();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="btn-group mt-2" role="group">
|
||||
<button type="button" className={`btn btn-success ${styles.btn}`} onClick={add}>
|
||||
Добавить
|
||||
</button>
|
||||
<button type="button" className={`btn btn-warning ${styles.btn}`} onClick={edit} >
|
||||
Изменить
|
||||
</button >
|
||||
<button type="button" className={`btn btn-danger ${styles.btn}`} onClick={remove}>
|
||||
Удалить
|
||||
</button >
|
||||
</div >
|
||||
);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
.btn {
|
||||
min-width: 140px;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export default class Order {
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.date = data?.date || '';
|
||||
this.supplierId = data?.supplierId || '';
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export default class Product {
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.name = data?.name || '';
|
||||
this.cost = data?.cost || '';
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export default class Supplier {
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.name = data?.name || '';
|
||||
this.license = data?.license || '';
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App'
|
||||
import ProductPage from './components/ProductPage';
|
||||
import './style.css'
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<ProductPage />
|
||||
</React.StrictMode>
|
||||
);
|
@ -35,12 +35,11 @@ public class OrderController {
|
||||
return new OrderDto(orderService.addProduct(id, productId));
|
||||
}
|
||||
|
||||
// @PatchMapping("/{id}")
|
||||
// public Orders updateOrder(@PathVariable Long id,
|
||||
// @RequestParam() String name,
|
||||
// @RequestParam() int license) {
|
||||
// return orderService.updateOrder(id, name, license);
|
||||
// }
|
||||
@PatchMapping("/{id}")
|
||||
public Orders updateOrder(@PathVariable Long id,
|
||||
@RequestParam() Long supplierId) {
|
||||
return orderService.updateOrder(id, supplierId);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public OrderDto deleteOrder(@PathVariable Long id) {
|
||||
|
@ -3,6 +3,7 @@ package com.example.demo.supply.Order;
|
||||
import com.example.demo.supply.Product.Product;
|
||||
import com.example.demo.supply.Supplier.Supplier;
|
||||
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -69,9 +69,9 @@ public class OrderService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Orders updateOrder(Long id, Date date) {
|
||||
public Orders updateOrder(Long id, Long supplierId) {
|
||||
final Orders currentOrder = findOrder(id);
|
||||
currentOrder.setDateOfOrder(date);
|
||||
currentOrder.setSupplier(supplierService.findSupplier(supplierId));
|
||||
return orderRepository.save(currentOrder);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.example.demo.supply.Supplier.Supplier;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
8
front/package-lock.json
generated
8
front/package-lock.json
generated
@ -11,7 +11,7 @@
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"axios": "^1.3.5",
|
||||
"axios": "^1.3.6",
|
||||
"bootstrap": "^5.2.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@ -5078,9 +5078,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz",
|
||||
"integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==",
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.6.tgz",
|
||||
"integrity": "sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
|
@ -5,7 +5,7 @@
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"axios": "^1.3.5",
|
||||
"axios": "^1.3.6",
|
||||
"bootstrap": "^5.2.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -1,11 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
|
||||
<meta charset="utf-8" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="path/to/font-awesome/css/font-awesome.min.css">
|
||||
<title>React App</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
|
||||
|
||||
<title>Поставки</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { BrowserRouter, Route, Routes} from "react-router-dom";
|
||||
import CatalogProducts from "./Catalogs/CatalogProducts";
|
||||
import CatalogSuppliers from "./Catalogs/CatalogSuppliers";
|
||||
import CatalogOrders from "./Catalogs/CatalogOrders";
|
||||
import Header from "./general/Header";
|
||||
|
||||
function App() {
|
||||
@ -12,7 +13,7 @@ function App() {
|
||||
<Route path="/" Component={CatalogProducts}/>
|
||||
<Route path="/products" Component={CatalogProducts} />
|
||||
<Route path="/suppliers" Component={CatalogSuppliers} />
|
||||
<Route path="/orders" Component={CatalogSuppliers} />
|
||||
<Route path="/orders" Component={CatalogOrders} />
|
||||
</Routes>
|
||||
|
||||
</BrowserRouter>
|
||||
|
@ -1,9 +1,15 @@
|
||||
import { useState } from 'react';
|
||||
import { React, useState, useEffect } from 'react';
|
||||
import Catalog from '../general/Catalog'
|
||||
import Order from '../models/Order';
|
||||
import Supplier from '../models/Supplier';
|
||||
import Product from '../models/Product';
|
||||
import DataService from '../DataService';
|
||||
import Modal from '../general/Modal';
|
||||
|
||||
export default function CatalogOrders(props) {
|
||||
const url = 'order/'
|
||||
const supplierUrl = 'supplier/'
|
||||
const productUrl = 'product/'
|
||||
|
||||
const transformer = (data) => new Order(data)
|
||||
|
||||
@ -14,45 +20,88 @@ export default function CatalogOrders(props) {
|
||||
];
|
||||
|
||||
const [data, setData] = useState(new Order());
|
||||
const [suppliers, setSuppliers] = useState([]);
|
||||
const [products, setProducts] = useState([]);
|
||||
|
||||
const add = () => setData(new Order());
|
||||
const edit = (data) => setData(new Order(data))
|
||||
|
||||
useEffect(() => {
|
||||
DataService.readAll(supplierUrl, (data) => new Supplier(data)).then(data => setSuppliers(data));
|
||||
DataService.readAll(productUrl, (data) => new Product(data)).then(data => setProducts(data));
|
||||
}, [])
|
||||
|
||||
const add = () =>{
|
||||
setData(new Order())
|
||||
console.log(data)
|
||||
}
|
||||
const edit = (data) => {
|
||||
console.log(data)
|
||||
setData(new Order(data))
|
||||
}
|
||||
|
||||
const addProduct = (data) => {
|
||||
setData(new Order(data))
|
||||
}
|
||||
|
||||
function handleFormChange(event) {
|
||||
console.log(data)
|
||||
setData({ ...data, [event.target.id]: event.target.value })
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
return (
|
||||
<Catalog headers={catalogOrderHeaders}
|
||||
getAllUrl={url}
|
||||
<>
|
||||
<Catalog headers={catalogOrderHeaders}
|
||||
url={url}
|
||||
transformer={transformer}
|
||||
data={data}
|
||||
add={add}
|
||||
edit={edit}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="data" className="form-label" value={`Дата ${data.date}`}>Дата ${data.date}</label>
|
||||
edit={edit}
|
||||
isOrder={true}
|
||||
addProduct={edit}
|
||||
modalAddProduct={
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">Поставщик</label>
|
||||
<select id="product" className="form-select" required
|
||||
value={data.product} onChange={handleFormChange}>
|
||||
<option disabled value="">Укажите продукт</option>
|
||||
{
|
||||
products.map(product =>
|
||||
<option key={product.id} value={product.id}>{product.name}</option>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
}>
|
||||
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="data" className="form-label">Дата {data.date}</label>
|
||||
</div> */}
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="cost" className="form-label">Цена</label>
|
||||
<input type="number" id="cost" className="form-control" required
|
||||
value={data.cost} onChange={handleFormChange}/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="supplier" className="form-label">Поставщик</label>
|
||||
<select id="supplier" className="form-select" required
|
||||
value={data.supplier} onChange={handleFormChange}>
|
||||
<label htmlFor="supplierId" className="form-label">Поставщик</label>
|
||||
<select id="supplierId" className="form-select" required
|
||||
value={data.supplierId} onChange={handleFormChange}>
|
||||
<option disabled value="">Укажите поставщика</option>
|
||||
{
|
||||
groups.map(group =>
|
||||
<option key={group.id} value={group.id}>{group.name}</option>
|
||||
suppliers.map(supplier =>
|
||||
<option key={supplier.id} value={supplier.id}>{supplier.name}</option>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">Поставщик</label>
|
||||
<select id="product" className="form-select" required
|
||||
value={data.product} onChange={handleFormChange}>
|
||||
<option disabled value="">Укажите продукт</option>
|
||||
{
|
||||
products.map(product =>
|
||||
<option key={product.id} value={product.id}>{product.name}</option>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</Catalog>
|
||||
</>
|
||||
);
|
||||
}
|
@ -29,7 +29,8 @@ export default function CatalogProducts(props) {
|
||||
transformer={transformer}
|
||||
data={data}
|
||||
add={add}
|
||||
edit={edit}>
|
||||
edit={edit}
|
||||
isOrder={false}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="name" className="form-label">Наименование</label>
|
||||
<input type="text" id="name" className="form-control" required
|
||||
|
@ -28,7 +28,8 @@ export default function CatalogSuppliers(props) {
|
||||
transformer={transformer}
|
||||
data={data}
|
||||
add={add}
|
||||
edit={edit}>
|
||||
edit={edit}
|
||||
isOrder={false}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="name" className="form-label">Поставщик</label>
|
||||
<input type="text" id="name" className="form-control" required
|
||||
|
@ -6,9 +6,12 @@ function getFullUrl(url, data) {
|
||||
const fields = Object.getOwnPropertyNames(data);
|
||||
//проходимся по каждому полю
|
||||
for (const field of fields) {
|
||||
if (data[field] === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field === undefined) continue
|
||||
if (field === 'id') continue
|
||||
if (field === 'date') continue
|
||||
if (field === 'countProducts') continue
|
||||
if (field === 'products') continue
|
||||
currentUrl.searchParams.append(field, data[field])
|
||||
}
|
||||
|
||||
@ -20,6 +23,7 @@ export default class DataService {
|
||||
|
||||
static async readAll(url, transformer) {
|
||||
const response = await axios.get(this.mainUrl + url);
|
||||
// console.log(response)
|
||||
return response.data.map(item => transformer(item));
|
||||
}
|
||||
|
||||
@ -29,14 +33,21 @@ export default class DataService {
|
||||
}
|
||||
|
||||
static async create(url, data) {
|
||||
console.log(data)
|
||||
await fetch(getFullUrl(this.mainUrl + url, data), {
|
||||
method: 'POST',
|
||||
}).catch(e => console.log(e))
|
||||
return true;
|
||||
}
|
||||
|
||||
static async addProduct(url) {
|
||||
await fetch(url, {
|
||||
method: 'PATCH',
|
||||
}).catch(e => console.log(e))
|
||||
return true;
|
||||
}
|
||||
|
||||
static async update(url, data) {
|
||||
data.id = undefined
|
||||
await fetch(getFullUrl(this.mainUrl + url, data), {
|
||||
method: 'PATCH',
|
||||
}).catch(e => console.log(e))
|
||||
|
54
front/src/general/AddsToOrder.jsx
Normal file
54
front/src/general/AddsToOrder.jsx
Normal file
@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
|
||||
export default function AddsToOrder(props){
|
||||
const formRef = React.createRef();
|
||||
|
||||
const hide = () => props.onHide()
|
||||
|
||||
const done = (e) => {
|
||||
e.preventDefault()
|
||||
if (formRef.current.checkValidity()) {
|
||||
props.onDone()
|
||||
hide()
|
||||
} else
|
||||
formRef.current.reportValidity()
|
||||
}
|
||||
return(
|
||||
<div className="modal fade show" tabIndex="-1" aria-hidden="true"
|
||||
style={{ display: props.visible ? 'block' : 'none' }}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="modal-title fs-5" id="exampleModalLabel">{props.header}</h1>
|
||||
<button className="btn-close" type="button" aria-label="Close"
|
||||
onClick={hide}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<form ref={formRef} onSubmit={done}>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="product" className="form-label">Поставщик</label>
|
||||
<select id="product" className="form-select" required
|
||||
value={data.product} onChange={handleFormChange}>
|
||||
<option disabled value="">Укажите продукт</option>
|
||||
{
|
||||
props.products.map(product =>
|
||||
<option key={product.id} value={product.id}>{product.name}</option>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-secondary" type="button" onClick={hide}>Закрыть</button>
|
||||
<button className="btn btn-primary" type="button" onClick={done}>
|
||||
{props.confirm}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -10,7 +10,10 @@ function Catalog(props) {
|
||||
const [modalHeader, setModalHeader] = useState('')
|
||||
const [modalConfirm, setModalConfirm] = useState('')
|
||||
const [modalVisible, setModalVisible] = useState(false)
|
||||
const [addProdVisible, setAddProdVisible] = useState(false)
|
||||
const [isEdit, setEdit] = useState(false)
|
||||
const [isAddProd, setIsAddProd] = useState(false)
|
||||
|
||||
|
||||
let selectedItems = [];
|
||||
|
||||
@ -20,15 +23,22 @@ function Catalog(props) {
|
||||
}, []);
|
||||
|
||||
const loadItems = () => {
|
||||
DataService.readAll(props.getAllUrl, props.transformer)
|
||||
.then(data => setItems(data))
|
||||
DataService.readAll(props.url, props.transformer)
|
||||
.then(data =>
|
||||
setItems(data))
|
||||
}
|
||||
|
||||
const saveItem = () => {
|
||||
if(isAddProd){
|
||||
DataService.addProduct(`${props.url}addProduct/${props.data.id}`).then(() => loadItems())
|
||||
return
|
||||
}
|
||||
|
||||
if (!isEdit) {
|
||||
DataService.create(props.url, props.data).then(() => loadItems());
|
||||
} else {
|
||||
DataService.update(props.url + props.data.id, props.data).then(() => loadItems());
|
||||
DataService.create(props.url, props.data).then(() => loadItems())
|
||||
if()
|
||||
} else{
|
||||
DataService.update(props.url + props.data.id, props.data).then(() => loadItems())
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +54,16 @@ function Catalog(props) {
|
||||
if (selectedItems.length === 0) {
|
||||
return;
|
||||
}
|
||||
editItem(selectedItems[0])
|
||||
//editItem(selectedItems[0])
|
||||
|
||||
DataService.read(props.url + selectedItems[0], props.transformer)
|
||||
.then(data => {
|
||||
setEdit(true);
|
||||
setModalHeader('Редактирование элемента');
|
||||
setModalConfirm('Сохранить');
|
||||
setModalVisible(true);
|
||||
props.edit(data);
|
||||
});
|
||||
}
|
||||
|
||||
const editItem = (editedId) => {
|
||||
@ -75,12 +94,24 @@ function Catalog(props) {
|
||||
}
|
||||
}
|
||||
|
||||
const addProduct = () => {
|
||||
if (selectedItems.length === 0)
|
||||
return
|
||||
|
||||
DataService.read(props.url + selectedItems[0], props.transformer)
|
||||
.then(data => {
|
||||
setEdit(false)
|
||||
isAddProd(true)
|
||||
setModalHeader('Добавление продукта к заказу')
|
||||
setModalConfirm('Сохранить')
|
||||
setAddProdVisible(true)
|
||||
props.edit(data)
|
||||
});
|
||||
}
|
||||
|
||||
const handleTableClick = (tableSelectedItems) => selectedItems = tableSelectedItems;
|
||||
|
||||
const handleTableDblClick = (tableSelectedItem) => editItem(tableSelectedItem);
|
||||
|
||||
const hideModal = () => setModalVisible(false)
|
||||
//после принятия в модальном окне идет создание, либо изменение объекта
|
||||
const modalDone = () => saveItem()
|
||||
|
||||
return (
|
||||
@ -88,7 +119,10 @@ function Catalog(props) {
|
||||
<ToolBar
|
||||
add={add}
|
||||
edit={edit}
|
||||
remove={remove}/>
|
||||
remove={remove}
|
||||
addProduct={addProduct}
|
||||
// removeProduct
|
||||
addsVisible={props.isOrder}/>
|
||||
<Table
|
||||
headers={props.headers}
|
||||
items={items}
|
||||
@ -103,6 +137,14 @@ function Catalog(props) {
|
||||
onDone={modalDone}>
|
||||
{props.children}
|
||||
</Modal>
|
||||
<Modal
|
||||
header={modalHeader}
|
||||
confirm={modalConfirm}
|
||||
visible={addProdVisible}
|
||||
onHide={hideModal}
|
||||
onDone={modalDone}>
|
||||
{props.modalAddProduct}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -19,28 +19,28 @@ function Modal(props) {
|
||||
|
||||
return (
|
||||
<div className="modal fade show" tabIndex="-1" aria-hidden="true"
|
||||
style={{ display: props.visible ? 'block' : 'none' }}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="modal-title fs-5" id="exampleModalLabel">{props.header}</h1>
|
||||
<button className="btn-close" type="button" aria-label="Close"
|
||||
onClick={hide}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<form ref={formRef} onSubmit={done}>
|
||||
{props.children}
|
||||
</form>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-secondary" type="button" onClick={hide}>Закрыть</button>
|
||||
<button className="btn btn-primary" type="button" onClick={done}>
|
||||
{props.confirm}
|
||||
</button>
|
||||
</div>
|
||||
style={{ display: props.visible ? 'block' : 'none' }}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h1 className="modal-title fs-5" id="exampleModalLabel">{props.header}</h1>
|
||||
<button className="btn-close" type="button" aria-label="Close"
|
||||
onClick={hide}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<form ref={formRef} onSubmit={done}>
|
||||
{props.children}
|
||||
</form>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-secondary" type="button" onClick={hide}>Закрыть</button>
|
||||
<button className="btn btn-primary" type="button" onClick={done}>
|
||||
{props.confirm}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,30 +4,34 @@ import styles from './Toolbar.module.css';
|
||||
//кнопочки
|
||||
function ToolBar(props) {
|
||||
|
||||
const add = () => {
|
||||
props.add()
|
||||
}
|
||||
|
||||
const edit = () => {
|
||||
props.edit()
|
||||
}
|
||||
|
||||
const remove = () => {
|
||||
props.remove()
|
||||
}
|
||||
const add = () => props.add()
|
||||
const edit = () => props.edit()
|
||||
const remove = () => props.remove()
|
||||
const addProduct = () => props.addProduct()
|
||||
const removeProduct = () => props.removeProduct()
|
||||
|
||||
return (
|
||||
<div className="btn-group mt-2" role="group">
|
||||
<button type="button" className={`btn btn-success ${styles.btn}`} onClick={add}>
|
||||
Добавить
|
||||
</button>
|
||||
<button type="button" className={`btn btn-warning ${styles.btn}`} onClick={edit} >
|
||||
Изменить
|
||||
</button >
|
||||
<button type="button" className={`btn btn-danger ${styles.btn}`} onClick={remove}>
|
||||
Удалить
|
||||
</button >
|
||||
</div >
|
||||
<button type="button" className={`btn btn-success ${styles.btn}`} onClick={add}>
|
||||
Добавить
|
||||
</button>
|
||||
<button type="button" className={`btn btn-warning ${styles.btn}`} onClick={edit} >
|
||||
Изменить
|
||||
</button >
|
||||
<button type="button" className={`btn btn-danger ${styles.btn}`} onClick={remove}>
|
||||
Удалить
|
||||
</button >
|
||||
|
||||
<button type="button" className={`btn btn-success ${styles.btn}`} onClick={addProduct}
|
||||
style={{ display: props.addsVisible ? 'block' : 'none' }}>
|
||||
Добавить продукт
|
||||
</button>
|
||||
<button type="button" className={`btn btn-danger ${styles.btn}`} onClick={removeProduct}
|
||||
style={{ display: props.addsVisible ? 'block' : 'none' }}>
|
||||
Удалить продукт
|
||||
</button >
|
||||
</div >
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
.btn {
|
||||
min-width: 140px;
|
||||
margin: 5px;
|
||||
}
|
@ -3,13 +3,8 @@ import Product from "./Product";
|
||||
export default class Order {
|
||||
constructor(data) {
|
||||
this.id = data?.id;
|
||||
this.date = data?.date || '';
|
||||
this.supplier = data?.supplier || '';
|
||||
this.supplierId = data?.supplierId || '';
|
||||
this.products = data?.products.map(product => new Product(product)) || '';
|
||||
this.countProducts = '';
|
||||
if(this.countProducts !== ''){
|
||||
this.countProducts = this.products.length
|
||||
}
|
||||
this.date = data?.dateOfOrder || '';
|
||||
this.supplierId = data?.supplier.id || '';
|
||||
this.supplier = data?.supplier.name || '';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user