Skip to content

Commit

Permalink
Merge pull request #50 from marciosamuel/feature/promocoes-admin
Browse files Browse the repository at this point in the history
Feature/promocoes admin
  • Loading branch information
mateusgs29 committed Jul 3, 2021
2 parents 108adc6 + 913a43b commit 57fe9c4
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 65 deletions.
2 changes: 1 addition & 1 deletion PWA/src/components/Admin/FormPromotion/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ function FormPromotionAdmin(props) {
<TablePromotionProducts
readOnly={readOnly}
updateProducts={handleUpdateProducts}
values={values.products}
promotion={values}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@
vertical-align: middle;
text-align: center;
}

.promotion-products-admin{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 0.5rem;
border-radius: 5px;
color: var(--dark-grey);
background-color: var(--light-grey);
}
152 changes: 97 additions & 55 deletions PWA/src/components/Admin/TablePromotionProducts/index.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
import React, { useEffect, useState } from 'react';
import { Button, Dropdown, FormControl, Table, Spinner } from 'react-bootstrap';
import React, { useContext, useEffect, useMemo, useState } from 'react';
import { Button, Dropdown, FormControl, Table } from 'react-bootstrap';
import { Trash2 } from 'react-feather';
import LoadingPage from '../../Shared/LoadingPage';
import ProductAdminApiService from '../../../services/api/ProductAdminApiService';
import formatFloat from '../../../services/utils/formatFloat';
import './TablePromotionProducts.css';
import PromotionValidationContext from '../../../context/PromotionValidationContext';

function TablePromotionProductsAdmin(props) {
const { readOnly, values, updateProducts } = props;
const { readOnly, updateProducts, promotion } = props;
const [productsDropdown, setProductsDropdown] = useState([]);
const [productsTable, setProductsTable] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const productsIds = values;

const promotionContext = useContext(PromotionValidationContext);

const productValueMin = useMemo(() => {
const valueMin = productsTable.reduce(
(min, product) =>
min === 0
? product.unitary_value
: Math.min(min, product.unitary_value),
0
);
return valueMin;
}, [productsTable]);

useEffect(() => {
promotionContext({
productValueMin,
error: '',
});
}, [productValueMin]);

const getProducts = async () => {
setIsLoading(true);
Expand All @@ -30,7 +51,7 @@ function TablePromotionProductsAdmin(props) {

const setProducts = () => {
const productsPromotion = productsDropdown.filter((p) =>
productsIds.includes(p.id)
promotion.products.includes(p.id)
);
setProductsTable(productsPromotion);
};
Expand All @@ -44,23 +65,34 @@ function TablePromotionProductsAdmin(props) {
}, [productsDropdown]);

const productAddTable = (productId) => {
productsIds.push(Number(productId));
const productSelected = productsDropdown.filter(
(p) => p.id === Number(productId)
);

setProductsTable([...productsTable, ...productSelected]);
updateProducts(productsIds);
if (
promotion.type === 1 &&
productSelected[0].unitary_value <= promotion.value
) {
promotionContext({
productValueMin,
error:
'Valor do produto não pode ser menor que o valor do desconto da promoção',
});
} else {
setProductsTable([...productsTable, ...productSelected]);
updateProducts([...promotion.products, productId]);
}
};

const productRemoveTable = (productId) => {
productsIds.splice(productsIds.indexOf(Number(productId)), 1);
const productsNotSelected = productsTable.filter(
(p) => p.id !== Number(productId)
);

setProductsTable([...productsNotSelected]);
updateProducts(productsIds);

const newProducts = promotion.products;
newProducts.splice(newProducts.indexOf(Number(productId)), 1);
updateProducts(newProducts);
};

const CustomMenu = React.forwardRef(({ children, className }, ref) => {
Expand All @@ -85,8 +117,18 @@ function TablePromotionProductsAdmin(props) {
);
});

const setDiscount = (productValue) => {
let newValue;
if (promotion.type === 1) {
newValue = productValue - promotion.value;
} else {
newValue = productValue - (productValue * promotion.value) / 100;
}
return `R$ ${formatFloat(newValue)}`;
};

return (
<div className="form-promotion-admin container">
<div className="promotion-products-admin">
<Dropdown
onSelect={(productId) => productAddTable(productId)}
className="my-2"
Expand All @@ -95,52 +137,52 @@ function TablePromotionProductsAdmin(props) {
Selecione um produto
</Dropdown.Toggle>
<Dropdown.Menu as={CustomMenu}>
{isLoading ? (
<Spinner animation="border" variant="dark" />
) : (
productsDropdown.map((product) => (
<Dropdown.Item
eventKey={product.id}
key={product.id}
disabled={
readOnly || !!productsTable.find((p) => p.id === product.id)
}
>
{product.name}
</Dropdown.Item>
))
)}
{productsDropdown.map((product) => (
<Dropdown.Item
eventKey={product.id}
key={product.id}
disabled={
readOnly || !!productsTable.find((p) => p.id === product.id)
}
>
{product.name}
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
<Table hover className="mt-2 table-promotion-products">
<thead>
<tr>
<th>Nome</th>
<th>Preço</th>
<th>Preço com desconto</th>
<th>Deletar</th>
</tr>
</thead>
<tbody>
{productsTable.map((product) => (
<tr key={product.id}>
<td>{product.name}</td>
<td>{`R$ ${formatFloat(product.unitary_value)}`}</td>
<td>50</td>
<td>
<Button
variant="outline-danger"
size="sm"
onClick={() => productRemoveTable(product.id)}
disabled={readOnly}
>
<Trash2 />
</Button>
</td>
{isLoading ? (
<LoadingPage />
) : (
<Table hover className="mt-2 table-promotion-products">
<thead>
<tr>
<th>Nome</th>
<th>Preço</th>
<th>Preço com desconto</th>
<th>Deletar</th>
</tr>
))}
</tbody>
</Table>
</thead>
<tbody>
{productsTable.map((product) => (
<tr key={product.id}>
<td>{product.name}</td>
<td>{`R$ ${formatFloat(product.unitary_value)}`}</td>
<td>{setDiscount(product.unitary_value)}</td>
<td>
<Button
variant="outline-danger"
size="sm"
onClick={() => productRemoveTable(product.id)}
disabled={readOnly}
>
<Trash2 />
</Button>
</td>
</tr>
))}
</tbody>
</Table>
)}
</div>
);
}
Expand Down
5 changes: 3 additions & 2 deletions PWA/src/components/Shared/ValidationErrorsContainer/index.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable react/no-array-index-key */
import React from 'react';
import { Alert, ListGroup } from 'react-bootstrap';
import './ValidationErrorsContainer.css';
Expand All @@ -13,11 +14,11 @@ function ValidationErrorsContainer(props) {
className="validation-errors container"
>
<ListGroup className="validation-errors list">
{errors.map((value) => (
{errors.map((value, index) => (
<ListGroup.Item
variant="warning"
className="validation-errors list-item"
key={value}
key={index}
>
{value};
</ListGroup.Item>
Expand Down
5 changes: 5 additions & 0 deletions PWA/src/context/PromotionValidationContext.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createContext } from 'react';

const PromotionValidationContext = createContext({});

export default PromotionValidationContext;
28 changes: 21 additions & 7 deletions PWA/src/pages/admin/Promotions/PromotionsPage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ButtonsForm from '../../../../components/Admin/ButtonsForm';
import ValidationErrorsContainer from '../../../../components/Shared/ValidationErrorsContainer';
import validationSchema from '../../../../services/validations/validationPromotionAdmin';
import PromotionAdminApiService from '../../../../services/api/PromotionAdminApiService';
import PromotionValidationContext from '../../../../context/PromotionValidationContext';

function PromotionsPage(props) {
const { match } = props;
Expand All @@ -15,6 +16,12 @@ function PromotionsPage(props) {
const [isReadOnly, setIsReadOnly] = useState(true);
const [isSaving, setIsSaving] = useState(false);
const [errors, setErrors] = useState([]);
const [valueProductMin, setValueProductMin] = useState({});

const handleSetContext = (obj) => {
setValueProductMin(obj.productValueMin);
if (obj.error) setErrors([...errors, obj.error]);
};

const getPromotion = async () => {
try {
Expand Down Expand Up @@ -50,10 +57,15 @@ function PromotionsPage(props) {
return true;
})
.catch((err) => {
setErrors([...err.errors]);
setErrors([...errors, ...err.errors]);
return undefined;
});
if (isValid !== undefined) {
if (form.type === 1 && form.value >= valueProductMin) {
setErrors([
...errors,
'Você possui um produto com o valor menor que o desconto, altere o valor ou remova o produto',
]);
} else if (isValid !== undefined) {
const resp = await PromotionAdminApiService.update(
values.id,
form
Expand Down Expand Up @@ -108,11 +120,13 @@ function PromotionsPage(props) {
errors={[...errors]}
clear={handleClearErrors}
/>
<FormPromotionAdmin
values={values}
update={setValues}
readOnly={isReadOnly}
/>
<PromotionValidationContext.Provider value={handleSetContext}>
<FormPromotionAdmin
values={values}
update={setValues}
readOnly={isReadOnly}
/>
</PromotionValidationContext.Provider>
</AdminContainer>
);
}
Expand Down

1 comment on commit 57fe9c4

@vercel
Copy link

@vercel vercel bot commented on 57fe9c4 Jul 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

bee – ./PWA

bee-web2.vercel.app
bee-marciosamuel.vercel.app
bee-git-develop-marciosamuel.vercel.app

Please sign in to comment.