@rnga/orders
Version:
## Get schema from @prisma-cms 1. yarn get-api-schema -e http://localhost:4000 2. yarn build-api-fragments
1,208 lines (841 loc) • 26.8 kB
JavaScript
/* eslint-disable react/forbid-foreign-prop-types */
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import PrismaCmsComponent from "@prisma-cms/component";
import moment from 'moment';
import SlabLink from "./SlabLink";
import Modal from "../../../../Modal";
import {
updateServiceOrderProcessor,
} from "query";
import TarifSelect from "./TarifSelect";
import NumberFormat from "react-number-format";
import { CircularProgress } from 'material-ui/Progress';
import SlabDenyPinalty from "./SlabDenyPinalty";
class OrderItem extends PrismaCmsComponent {
static propTypes = {
...PrismaCmsComponent.propTypes,
item: PropTypes.object.isRequired,
updateItem: PropTypes.func.isRequired,
services: PropTypes.array.isRequired,
amount: PropTypes.number.isRequired,
classes: PropTypes.object.isRequired,
/**
* Заказ может быть в статусе Архивный.
* Элементы такого заказа нельзя редактировать.
*/
canEdit: PropTypes.func.isRequired,
canOrderSlab: PropTypes.func.isRequired,
notGradable: PropTypes.func.isRequired,
getDirty: PropTypes.func.isRequired,
setService: PropTypes.func.isRequired,
isSlabServiceOrdered: PropTypes.func.isRequired,
};
constructor(props) {
super(props);
this.state = {
...this.state,
tarifsSelectionOpen: false,
confirmRejectModalOpened: false,
confirmAcceptModalOpened: false,
};
}
componentDidMount() {
this.initListeners();
super.componentDidMount && super.componentDidMount();
}
initListeners() {
const {
document,
} = window;
// return;
/**
* Навешиваем на документ событие, чтобы отловить клики вне селекта выбора тарифа, чтобы при клике в другом месте он закрывался.
*/
this.closeEvent = document.addEventListener("click", (event) => {
// if (event.defaultPrevented) {
// return;
// }
const path = event.path || (event.composedPath && event.composedPath());
// const path = event.path;
if (path) {
if (path.indexOf(this.selectTarifWrapper) !== -1) {
// event.stopImmediatePropagation();
// return;
}
else {
this.setState({
tarifsSelectionOpen: false,
});
}
}
else {
if (event.defaultPrevented) {
return;
}
this.setState({
tarifsSelectionOpen: false,
});
}
});
}
getSlabService() {
let {
services,
} = this.props;
return (services && services.find(n => n.code === "slab")) || null;
}
// isSlabServiceOrdered() {
// const {
// selectedServices,
// } = this.getDirty() || {};
// const slabServiceSelected = (selectedServices && selectedServices.find(n => n.code === "slab" && n._selected === true)) ? true : false;
// const {
// ServiceOrders,
// } = this.getItem();
// let SlabServiceOrder = ServiceOrders.find(n => n.Service.code === "slab");
// /**
// * Определяем выбран ли заказ на слаб.
// * Если да, но не выбран тариф, надо подсветить тариф
// */
// // let SlabServiceOrdered = true;
// // let SlabServiceOrdered = slabServiceSelected ? true : false;
// let SlabServiceOrdered = SlabServiceOrder || slabServiceSelected ? true : false;
// return SlabServiceOrdered;
// }
isSlabServiceOrdered() {
const {
selectedServices,
} = this.getDirty() || {};
const slabServiceSelected = (selectedServices && selectedServices.find(n => n.code === "slab" && n._selected === true)) ? true : false;
const {
ServiceOrders,
} = this.getItem();
let SlabServiceOrder = ServiceOrders.find(n => n.Service.code === "slab");
/**
* Определяем выбран ли заказ на слаб.
* Если да, но не выбран тариф, надо подсветить тариф
*/
// let SlabServiceOrdered = true;
// let SlabServiceOrdered = slabServiceSelected ? true : false;
let SlabServiceOrdered = SlabServiceOrder || slabServiceSelected ? true : false;
return SlabServiceOrdered;
}
/**
* Выбран тариф
*/
setTarif(tarif) {
// console.log("setTarif", tarif);
const canEdit = this.canEdit();
if (!canEdit) {
return false;
}
const {
id: serviceTarifId,
} = tarif;
if (!this.canOrderSlab()) {
return false;
}
this.updateItem({
slabTarif: serviceTarifId,
});
const slabService = this.getSlabService();
// slabService._selected = false;
/**
* Если не была выбрана услуга слабирования, автоматически назначаем
*/
let {
selectedServices,
} = this.getDirty() || {}
selectedServices = selectedServices || [];
const dirtySlabSelected = selectedServices.find(n => n.id === slabService.id && n._selected ? true : false);
if (!this.isSlabServiceOrdered() || !dirtySlabSelected) {
setTimeout(() => {
this.setService(slabService);
}, 100);
}
// else {
// }
this.setState({
tarifsSelectionOpen: false,
});
// const slabServiceSelected = this.isSlabServiceSelected();
}
rejectSlabOrder = data => {
// this.updateItem(data);
// eslint-disable-next-line no-unreachable
this.setState({
confirmRejectModalOpened: true,
tarifsSelectionOpen: false,
});
}
canEdit() {
const {
canEdit,
} = this.props;
return canEdit();
}
// /**
// * Выбираем услугу
// */
// setService(service) {
// const canEdit = this.canEdit();
// // console.log("canEdit", canEdit);
// if (!canEdit) {
// return;
// }
// /**
// * Когда пользователь отменяет выбор тарифа,
// * удаляем его из массива
// */
// // if (!selectedService._selected) {
// // selectedServices.splice(selectedServices.indexOf(selectedService), 1);
// // }
// const {
// id: serviceId,
// code,
// } = service;
// let {
// selectedServices,
// } = this.getDirty() || {}
// selectedServices = selectedServices || [];
// // const index = selectedServices.findIndex(n => n.id === serviceId);
// let selectedService = selectedServices.find(n => n.id === serviceId);
// if (!selectedService) {
// selectedService = {
// ...service,
// };
// /**
// * Проверяем если выбирает слабирование, то должен быть указан прегрейд
// */
// switch (code) {
// case "slab":
// if (!this.canOrderSlab()) {
// return false;
// }
// break;
// }
// selectedServices.push(selectedService);
// }
// selectedService._selected = selectedService._selected ? false : true;
// this.updateItem({
// selectedServices,
// });
// }
/**
* Выбираем услугу
*/
setService(service) {
const {
setService,
} = this.props;
return setService(this.getItem(), service);
}
// canOrderSlab() {
// const {
// preGrade,
// sheldon_grade,
// } = this.getItem();
// if (this.notGradable()) {
// return this.addError("Нельзя заказать услугу для этой монеты");
// }
// if (!preGrade) {
// return this.addError("Дождитесь получения прегрейда.");
// }
// return true;
// }
// notGradable() {
// const {
// preGrade,
// sheldon_grade,
// } = this.getItem() || {};
// console.log("notGradable item", this.getItem());
// return (
// preGrade === "NOTGENUINE"
// || preGrade === "NOTGRADABLE"
// || sheldon_grade === "NOTGENUINE"
// || sheldon_grade === "NOTGRADABLE"
// );
// }
canOrderSlab() {
// const {
// preGrade,
// sheldon_grade,
// } = this.getItem();
// if (this.notGradable()) {
// return this.addError("Нельзя заказать услугу для этой монеты");
// }
// if (!preGrade) {
// return this.addError("Дождитесь получения прегрейда.");
// }
// return true;
const {
canOrderSlab,
} = this.props;
return canOrderSlab(this.getItem()) === true;
}
notGradable() {
// const {
// preGrade,
// sheldon_grade,
// } = this.getItem() || {};
// return (
// preGrade === "NOTGENUINE"
// || preGrade === "NOTGRADABLE"
// || sheldon_grade === "NOTGENUINE"
// || sheldon_grade === "NOTGRADABLE"
// );
const {
notGradable,
} = this.props;
return notGradable(this.getItem()) === true;
}
updateItem(data) {
const {
updateItem,
} = this.props;
const item = this.getItem();
return updateItem(item, data);
}
getItem() {
const {
item,
} = this.props;
return item;
}
// getDirty() {
// const {
// _dirty,
// } = this.getItem();
// return _dirty;
// }
getDirty() {
const {
getDirty,
} = this.props;
return getDirty(this.getItem());
}
async confirmService(serviceOrderId) {
await this.updateServiceOrder(serviceOrderId, {
confirm: true,
});
}
async rejectService(serviceOrderId) {
await this.updateServiceOrder(serviceOrderId, {
reject: true,
})
.then(r => {
// console.log("rejectSlabOrder _dirty", this);
let {
selectedServices,
} = this.getDirty() || {}
selectedServices = selectedServices || [];
// const dirtySlabSelected = selectedServices.find(n => n.code === "slab" ? true : false);
const dirtySlabSelectedIndex = selectedServices.findIndex(n => n.code === "slab" ? true : false);
if (dirtySlabSelectedIndex !== -1) {
const selectedServicesNew = selectedServices.slice(0);
selectedServicesNew.splice(dirtySlabSelectedIndex, 1);
this.updateItem({
selectedServices: selectedServicesNew,
slabTarif: undefined,
});
// console.log("dirtySlabSelected", dirtySlabSelected);
return;
}
return r;
});
}
/**
* Обновление заказа услуг с записью в БД
*/
async updateServiceOrder(serviceOrderId, data) {
const {
loading,
} = this.state;
// const {
// item: {
// id: serviceOrderId,
// },
// } = this.props;
if (!serviceOrderId || loading) {
return;
}
this.setState({
loading: true,
});
let params = {
mutation: updateServiceOrderProcessor,
variables: {
data,
where: {
id: serviceOrderId,
},
},
};
const result = await this.mutate(params)
.catch(error => error);
this.setState({
loading: false,
});
if (result && result instanceof Error) {
throw result;
}
return result;
}
translitGrade(grade) {
return grade ? grade.replace("DET", " DET") : null;
}
render() {
const {
item,
services,
amount,
classes,
} = this.props;
const {
tarifsSelectionOpen,
loading,
confirmRejectModalOpened,
confirmAcceptModalOpened,
} = this.state;
if (!item || !services) {
return null;
}
const canEdit = this.canEdit() && !this.notGradable();
const {
// id: itemId,
number,
title,
year,
metal,
price,
sheldon_grade,
sheldon_grade_details,
// date,
preGrade,
ServiceOrders,
slab,
} = item;
const preGradeStr = this.translitGrade(preGrade);
const sheldon_gradeStr = this.translitGrade(sheldon_grade);
const dirty = this.getDirty()
let {
selectedServices,
slabTarif,
rejectSlabService,
} = dirty || {}
let servicesList = [];
let slabService = services.find(n => n.code === "slab");
// const slabServiceSelected = (selectedServices && selectedServices.find(n => n.code === "slab" && n._selected === true)) ? true : false;
let slabTarifs = (slabService && slabService.Tarifs) || [];
let SlabServiceOrder = ServiceOrders.find(n => n.Service.code === "slab");
const {
id: slabServiceOrderId,
// createdAt: slabServiceOrderCreatedAt,
// rejectDate: slabServiceOrderRejectDate,
confirmDate: slabServiceOrderConfirmDate,
// readyDate: slabServiceOrderReadyDate,
// Service: SlabService,
} = SlabServiceOrder || {};
// const {
// rejectCost: slabServiceRejectCost,
// } = SlabService || {}
// Выбранный слаб-тариф
if (!slabTarif) {
if (SlabServiceOrder && SlabServiceOrder.Tarif) {
slabTarif = SlabServiceOrder.Tarif.id;
}
}
let selectedSlabTarif = slabTarif ? slabTarifs.find(n => n.id === slabTarif) : null;
let slabServiceConfirmActions;
let slabServiceModals = <Fragment>
{confirmRejectModalOpened
?
<Modal
opened={true}
handleClose={event => {
this.setState({
confirmRejectModalOpened: false,
});
}}
title={"Подтверждение отказа от услуги"}
>
<div
className="window"
style={{
width: "auto",
padding: 0,
}}
>
<div
className="accept-deny-text"
>
Вы отказываетесь от услуги?
</div>
{/* {slabServiceRejectCost ?
<div>
{`Будет удержано ${slabServiceRejectCost} рублей.`}
</div>
: null
} */}
{slabServiceOrderId ?
<SlabDenyPinalty
where={{
id: slabServiceOrderId,
}}
/>
: null}
<div className="confirm-send-wrapper" style={{
display: "block",
}}>
<div className="confirm-send-cansel-wrapper">
<div
className="confirm-button confirm_cansel"
onClick={event => {
event.preventDefault();
event.stopPropagation();
this.setState({
confirmRejectModalOpened: false,
});
}}
>Отмена</div>
<div
className={classes.buttonWrapper}
>
<div
className="confirm-button confirm_send"
onClick={async event => {
event.preventDefault();
event.stopPropagation();
this.rejectService(slabServiceOrderId)
.then(r => {
this.setState({
confirmRejectModalOpened: false,
});
return r;
})
}}
>
Подтверждаю
</div>
{loading ? <CircularProgress size={24} className={classes.buttonProgress} /> : null}
</div>
</div>
</div>
</div>
</Modal>
:
null
}
{
confirmAcceptModalOpened
?
<Modal
opened={true}
handleClose={event => {
this.setState({
confirmAcceptModalOpened: false,
});
}}
title={"Подтверждение заказа услуги"}
>
<div
className="window"
style={{
width: "auto",
padding: 0,
}}
>
<div
className="accept-deny-text"
>
Вы подтверждаете заказ услуги?
</div>
<div className="confirm-send-wrapper" style={{
display: "block",
}}>
<div className="confirm-send-cansel-wrapper">
<div
className="confirm-button confirm_cansel"
onClick={event => {
event.preventDefault();
event.stopPropagation();
this.setState({
confirmAcceptModalOpened: false,
});
}}
>Отмена</div>
<div
className="confirm-button confirm_send"
onClick={async event => {
event.preventDefault();
event.stopPropagation();
this.confirmService(slabServiceOrderId)
.then(r => {
this.setState({
confirmAcceptModalOpened: false,
});
return r;
})
}}
>
Подтверждаю
</div>
</div>
</div>
</div>
</Modal>
:
null
}
</Fragment>
/**
* Если было заказано слабирование
*/
// if (slabServiceOrderId) {
// // console.log("slabServiceOrderId", slabServiceOrderId, !dirty && !slabServiceOrderRejectDate && !slabServiceOrderConfirmDate && sheldon_grade ? true : false,
// // dirty, slabServiceOrderRejectDate, slabServiceOrderConfirmDate, sheldon_grade
// // );
// /**
// * Пользовательские действия со слабированием
// */
// // if (!dirty && !slabServiceOrderRejectDate && !slabServiceOrderConfirmDate && sheldon_grade) {
// if (!slabServiceOrderRejectDate && !slabServiceOrderConfirmDate && sheldon_grade) {
// slabServiceConfirmActions = <Fragment>
// <button
// className="btn btn-xs btn-success"
// onClick={event => {
// event.preventDefault();
// event.stopPropagation();
// this.setState({
// confirmAcceptModalOpened: true,
// })
// }}
// // onClick={event => this.confirmService(slabServiceOrderId)}
// disabled={loading ? true : false}
// >
// Подт.
// </button>
// <button
// className="btn btn-xs btn-danger"
// onClick={event => {
// event.preventDefault();
// event.stopPropagation();
// this.setState({
// confirmRejectModalOpened: true,
// })
// }}
// // onClick={event => this.rejectService(slabServiceOrderId)}
// disabled={loading ? true : false}
// >
// Отк.
// </button>
// </Fragment>
// }
// }
/**
* Определяем выбран ли заказ на слаб.
* Если да, но не выбран тариф, надо подсветить тариф
*/
// let SlabServiceOrdered = true;
// let SlabServiceOrdered = slabServiceSelected ? true : false;
// let SlabServiceOrdered = SlabServiceOrder || slabServiceSelected ? true : false;
const SlabServiceOrdered = this.isSlabServiceOrdered();
let tarifSelect;
services.map(service => {
const {
id: serviceId,
code,
name,
short_name,
} = service;
const selectedService = (selectedServices && selectedServices.find(n => n.id === serviceId));
const ServiceOrder = ServiceOrders.find(i => i.Service.id === serviceId)
let label = <label
onClick={!ServiceOrder ? event => {
event.preventDefault();
event.stopPropagation();
this.setService(service);
} : undefined}
style={{
width: "100%",
textAlign: "center",
cursor: "pointer",
}}
>
{short_name || name}
</label>
let selected = selectedService ? selectedService._selected : ServiceOrder ? true : false;
// let className;
switch (code) {
case "slab":
// if (selected && slabServiceOrderConfirmDate) {
if (selected && slabServiceOrderId && sheldon_grade) {
tarifSelect = <div
ref={node => {
this.selectTarifWrapper = node;
}}
>
<TarifSelect
tarifsSelectionOpen={tarifsSelectionOpen}
selectedSlabTarif={selectedSlabTarif}
SlabServiceOrder={SlabServiceOrder}
SlabServiceOrdered={SlabServiceOrdered}
slabTarif={slabTarif}
slabTarifs={slabTarifs}
price={price}
onSlabClick={event => {
this.setState({
tarifsSelectionOpen: !tarifsSelectionOpen,
// tarifsSelectionOpen: true,
})
}}
setTarif={tarif => this.setTarif(tarif)}
resetOrder={event => {
this.setService(service);
this.updateItem({
slabTarif: undefined,
});
}}
updateObject={data => {
this.updateItem(data);
this.setState({
tarifsSelectionOpen: false,
});
}}
rejectSlabOrder={this.rejectSlabOrder}
slabRejected={rejectSlabService ? true : false}
canEdit={canEdit}
/>
</div>
// label = tarifSelect;
}
// className = "tariff-td";
break;
default: ;
}
servicesList.push(<div
key={serviceId}
title={name}
// className={[className, "service_accept", selected ? "checked-item" : ""].join(" ")}
className={["service_accept", selected ? "checked-item" : ""].join(" ")}
>
{/* <input className="slab-chek" type="checkbox" value="1" /> */}
{label}
</div>);
return null;
});
let slabDate;
if (slabServiceOrderConfirmDate) {
slabDate = moment(slabServiceOrderConfirmDate).format('DD.MM.YY')
}
return super.render(
<tr>
<td>
{number}
{/*
Modals
*/}
{slabServiceConfirmActions}
{slabServiceModals}
{/*
Eof Modals
*/}
</td>
<td><span
className="text-block text-ellipsis item-title"
title={title}
>{title}</span></td>
<td><span className="text-block">{year}</span></td>
<td><span className="text-block">{metal}</span></td>
<td><span className="text-block no-wrap-block">
<NumberFormat
value={price || 0}
displayType="text"
thousandSeparator=" "
/>
</span></td>
{/* <td>
<div className="tab-block services">
{servicesList}
</div>
</td> */}
<td>{preGradeStr}</td>
<td>
<div
className="tab-block services ready-service"
>
{servicesList}
</div>
</td>
{/* <td>
<div className="">{slabServiceOrderCreatedAt && moment(slabServiceOrderCreatedAt).format('DD.MM.YY') || null}</div>
</td> */}
<td>
<span
className="text-block-grade"
>
{sheldon_gradeStr} {sheldon_grade_details ? <span
className="order-item--sheldon_grade_details"
>
{sheldon_grade_details}
</span> : null}
</span>
</td>
<td className="tariff-td"
>
{tarifSelect}
</td>
<td>
{slabDate}
</td>
<td>
<div className="tab-block services ready-service">
{services.map(n => {
const {
id: serviceId,
name,
code,
} = n;
// const ready = ServiceOrders.find(i => i.Service.id === serviceId && i.readyDate)
const serviceOrder = ServiceOrders.find(i => i.Service.id === serviceId);
const {
readyDate,
} = serviceOrder || {}
let label = <label>
{/* {readyDate ? moment(readyDate).format('DD.MM.YY') : short_name || name} */}
{readyDate ? moment(readyDate).format('DD.MM.YY') : "Дата"}
</label>
return <div
key={serviceId}
title={name}
className={["service_accept", readyDate ? "checked-item" : ""].join(" ")}
>
{(code === "slab" && slab && readyDate)
?
<SlabLink
slab={slab}
>
{label}
</SlabLink>
:
label
}
</div>
})}
</div>
</td>
<td>
<span className="text-block">
<NumberFormat
value={amount || 0}
displayType="text"
thousandSeparator=" "
/>
</span>
</td>
</tr>
);
}
}
export default OrderItem;