5_2
This commit is contained in:
parent
efc2bd6e7d
commit
f49f0d234c
File diff suppressed because one or more lines are too long
69
Lab5/Bookfill/package-lock.json
generated
69
Lab5/Bookfill/package-lock.json
generated
@ -15,6 +15,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.9.1",
|
||||
"react-bootstrap-icons": "^1.10.3",
|
||||
"react-custom-scrollbars": "^4.2.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-icons": "^4.12.0",
|
||||
@ -1160,6 +1161,11 @@
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/add-px-to-style": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/add-px-to-style/-/add-px-to-style-1.0.0.tgz",
|
||||
"integrity": "sha512-YMyxSlXpPjD8uWekCQGuN40lV4bnZagUwqa2m/uFv1z/tNImSk9fnXVMUI5qwME/zzI3MMQRvjZ+69zyfSSyew=="
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
@ -1864,6 +1870,16 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-css": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-css/-/dom-css-2.1.0.tgz",
|
||||
"integrity": "sha512-w9kU7FAbaSh3QKijL6n59ofAhkkmMJ31GclJIz/vyQdjogfyxcB6Zf8CZyibOERI5o0Hxz30VmJS7+7r5fEj2Q==",
|
||||
"dependencies": {
|
||||
"add-px-to-style": "1.0.0",
|
||||
"prefix-style": "2.0.1",
|
||||
"to-camel-case": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
@ -4507,6 +4523,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
@ -4580,6 +4601,11 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prefix-style": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prefix-style/-/prefix-style-2.0.1.tgz",
|
||||
"integrity": "sha512-gdr1MBNVT0drzTq95CbSNdsrBDoHGlb2aDJP/FoY+1e+jSDPOb1Cv554gH2MGiSr2WTcXi/zu+NaFzfcHQkfBQ=="
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@ -4673,6 +4699,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"dependencies": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
@ -4748,6 +4782,20 @@
|
||||
"react": ">=16.8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/react-custom-scrollbars": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz",
|
||||
"integrity": "sha512-VtJTUvZ7kPh/auZWIbBRceGPkE30XBYe+HktFxuMWBR2eVQQ+Ur6yFJMoaYcNpyGq22uYJ9Wx4UAEcC0K+LNPQ==",
|
||||
"dependencies": {
|
||||
"dom-css": "^2.0.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"raf": "^3.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^0.14.0 || ^15.0.0 || ^16.0.0",
|
||||
"react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
||||
@ -5432,6 +5480,14 @@
|
||||
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-camel-case": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz",
|
||||
"integrity": "sha512-nD8pQi5H34kyu1QDMFjzEIYqk0xa9Alt6ZfrdEMuHCFOfTLhDG5pgTu/aAM9Wt9lXILwlXmWP43b8sav0GNE8Q==",
|
||||
"dependencies": {
|
||||
"to-space-case": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
@ -5441,6 +5497,19 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/to-no-case": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz",
|
||||
"integrity": "sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg=="
|
||||
},
|
||||
"node_modules/to-space-case": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz",
|
||||
"integrity": "sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==",
|
||||
"dependencies": {
|
||||
"to-no-case": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
|
@ -19,6 +19,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.9.1",
|
||||
"react-bootstrap-icons": "^1.10.3",
|
||||
"react-custom-scrollbars": "^4.2.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-icons": "^4.12.0",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button, ButtonGroup, Card } from 'react-bootstrap';
|
||||
import { DashLg, PlusLg, XLg } from 'react-bootstrap-icons';
|
||||
import { DashLg, XLg } from 'react-bootstrap-icons';
|
||||
import imgPlaceholder from '../../assets/200.png';
|
||||
import './Cart.css';
|
||||
import useCart from './CartHook';
|
||||
@ -7,8 +7,6 @@ import useCart from './CartHook';
|
||||
const Cart = () => {
|
||||
const {
|
||||
cart,
|
||||
getCartSum,
|
||||
addToCart,
|
||||
removeFromCart,
|
||||
clearCart,
|
||||
} = useCart();
|
||||
@ -27,20 +25,10 @@ const Cart = () => {
|
||||
<Card.Body className='p-2 d-flex flex-column flex-sm-row align-items-center'>
|
||||
<div className='cart-item flex-fill'>
|
||||
<img className='cart-image' src={cartItem.image || imgPlaceholder} alt="Cart Image" />
|
||||
{cartItem.type.name}
|
||||
{cartItem.book_name}
|
||||
</div>
|
||||
<div className='cart-item mt-2 mt-sm-0 d-flex flex-column align-items-center align-items-sm-end'>
|
||||
<div>
|
||||
{cartItem.price}
|
||||
{' * '}
|
||||
{cartItem.count}
|
||||
{' = '}
|
||||
{parseFloat(cartItem.price * cartItem.count).toFixed(2)}
|
||||
</div>
|
||||
<ButtonGroup className='mt-2 mt-sm-1' aria-label="Cart counter">
|
||||
<Button variant="primary" onClick={() => addToCart(cartItem)}>
|
||||
<PlusLg />
|
||||
</Button>
|
||||
<Button variant="danger" onClick={() => removeFromCart(cartItem)}>
|
||||
<DashLg />
|
||||
</Button>
|
||||
@ -49,9 +37,6 @@ const Cart = () => {
|
||||
</Card.Body>
|
||||
</Card>)
|
||||
}
|
||||
<div className='mb-2 col-12 col-md-8 col-lg-6 d-flex justify-content-end'>
|
||||
<strong>Итого: {getCartSum()} ₽</strong>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -10,7 +10,7 @@ const setCartCount = (cart, item, value) => {
|
||||
const addToCart = (cart, item) => {
|
||||
const existsItem = cart.find((cartItem) => cartItem.id === item.id);
|
||||
if (existsItem !== undefined) {
|
||||
return setCartCount(cart, item, 1);
|
||||
return cart;
|
||||
}
|
||||
return [...cart, { ...item, count: 1 }];
|
||||
};
|
||||
|
@ -14,7 +14,6 @@ const Input = ({
|
||||
|
||||
Input.propTypes = {
|
||||
name: PropTypes.string,
|
||||
book_name: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
|
@ -20,7 +20,6 @@ const Select = ({
|
||||
Select.propTypes = {
|
||||
values: PropTypes.array,
|
||||
name: PropTypes.string,
|
||||
book_name: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
|
@ -30,10 +30,10 @@ const LinesForm = ({ id }) => {
|
||||
<LinesItemForm item={item} handleChange={handleChange} />
|
||||
<Form.Group className='row justify-content-center m-0 mt-3'>
|
||||
<Button className='col-5 col-lg-2 m-0 me-2' variant='secondary' onClick={() => onBack()}>
|
||||
Назад
|
||||
Back
|
||||
</Button>
|
||||
<Button className='col-5 col-lg-2 m-0 ms-2' type='submit' variant='primary'>
|
||||
Сохранить
|
||||
Save
|
||||
</Button>
|
||||
</Form.Group>
|
||||
</Form>
|
||||
|
@ -14,16 +14,18 @@ const LinesItemForm = ({ item, handleChange }) => {
|
||||
<img id='image-preview' className='rounded' alt='placeholder'
|
||||
src={item.image || imgPlaceholder} />
|
||||
</div>
|
||||
<Input name='book_name' label='Name' value={item.book_name} onChange={handleChange}
|
||||
type='text' required />
|
||||
<Select values={types} name='typeId' label='Type' value={item.typeId} onChange={handleChange}
|
||||
required />
|
||||
<Input name='price' label='Price' value={item.price} onChange={handleChange}
|
||||
type='number' min='50.0' step='1.0' required />
|
||||
<Input name='count' label='Количество' value={item.count} onChange={handleChange}
|
||||
type='number' min='1' step='1' required />
|
||||
<Input name='image' label='Изображение' onChange={handleChange}
|
||||
type='file' accept='image/*' />
|
||||
<div style={{ height: 300, overflow: 'auto' }}>
|
||||
<Input name='book_name' label='Name' value={item.book_name} onChange={handleChange}
|
||||
type='text' required />
|
||||
<Select values={types} name='typeId' label='Type' value={item.typeId} onChange={handleChange}
|
||||
required />
|
||||
<Input name='author_name' label='Author' value={item.author_name} onChange={handleChange}
|
||||
type='text' required />
|
||||
<Input name='price' label='Price' value={item.price} onChange={handleChange}
|
||||
type='number' min='50.0' step='1.0' required />
|
||||
<Input name='image' label='Image' onChange={handleChange}
|
||||
type='file' accept='image/*' />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable prefer-destructuring */
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import getBase64FromFile from '../../utils/Base64';
|
||||
@ -16,17 +15,15 @@ const useLinesItemForm = (id, linesChangeHandle) => {
|
||||
|
||||
const getLineObject = (formData) => {
|
||||
const typeId = parseInt(formData.typeId, 10);
|
||||
// eslint-disable-next-line camelcase
|
||||
const book_name = formData.book_name;
|
||||
const bookname = formData.book_name;
|
||||
const authorname = formData.author_name;
|
||||
const price = parseFloat(formData.price).toFixed(2);
|
||||
const count = parseInt(formData.count, 10);
|
||||
const image = formData.image.startsWith('data:image') ? formData.image : '';
|
||||
return {
|
||||
typeId: typeId.toString(),
|
||||
// eslint-disable-next-line object-shorthand, camelcase
|
||||
book_name: book_name,
|
||||
book_name: bookname,
|
||||
author_name: authorname,
|
||||
price: price.toString(),
|
||||
count: count.toString(),
|
||||
image,
|
||||
};
|
||||
};
|
||||
|
@ -5,6 +5,7 @@ const useLinesItem = (id) => {
|
||||
const emptyItem = {
|
||||
id: '',
|
||||
book_name: '',
|
||||
author_name: '',
|
||||
typeId: '',
|
||||
price: '0',
|
||||
count: '0',
|
||||
|
@ -7,10 +7,10 @@ const LinesTable = ({ children }) => {
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope='col'>№</th>
|
||||
<th scope='col' className='w-25'>Товар</th>
|
||||
<th scope='col' className='w-25'>Цена</th>
|
||||
<th scope='col' className='w-25'>Колич.</th>
|
||||
<th scope='col' className='w-25'>Сумма</th>
|
||||
<th scope='col' className='w-25'>Name</th>
|
||||
<th scope='col' className='w-25'>Category</th>
|
||||
<th scope='col' className='w-25'>Author</th>
|
||||
<th scope='col' className='w-25'>Price</th>
|
||||
<th scope='col'></th>
|
||||
<th scope='col'></th>
|
||||
<th scope='col'></th>
|
||||
|
@ -0,0 +1,4 @@
|
||||
#image {
|
||||
max-width: 200px;
|
||||
max-height: 100;
|
||||
}
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||
import {
|
||||
PencilFill, Trash3, Heart,
|
||||
} from 'react-bootstrap-icons';
|
||||
import './LinesTableRow.css';
|
||||
|
||||
const LinesTableRow = ({
|
||||
index, line, onAddCart, onDelete, onEdit,
|
||||
@ -16,8 +17,9 @@ const LinesTableRow = ({
|
||||
<th scope="row">{index + 1}</th>
|
||||
<td>{line.book_name}</td>
|
||||
<td>{line.type.name}</td>
|
||||
<td>{line.author_name}</td>
|
||||
<td>{parseFloat(line.price).toFixed(2)}</td>
|
||||
<td>{line.count}</td>
|
||||
<td><img src={line.image} id='image' alt={line.book_name} /></td>
|
||||
<td><a href="#" onClick={(event) => handleAnchorClick(event, onAddCart)}><Heart /></a></td>
|
||||
<td><a href="#" onClick={(event) => handleAnchorClick(event, onEdit)}><PencilFill /></a></td>
|
||||
<td><a href="#" onClick={(event) => handleAnchorClick(event, onDelete)}><Trash3 /></a></td>
|
||||
|
@ -19,10 +19,10 @@ const ModalForm = ({
|
||||
<Modal.Footer className='m-0 pt-2 pb-2 ps-3 pe-3 row justify-content-center'>
|
||||
<Button variant='secondary' className='col-5 m-0 me-2'
|
||||
onClick={() => onClose()}>
|
||||
Отмена
|
||||
Close
|
||||
</Button>
|
||||
<Button variant='primary' className='col-5 m-0 ms-2' type='submit'>
|
||||
Сохранить
|
||||
Save
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
|
Loading…
Reference in New Issue
Block a user