UNPKG

@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
/* 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;