UNPKG

@rnga/orders

Version:

## Get schema from @prisma-cms 1. yarn get-api-schema -e http://localhost:4000 2. yarn build-api-fragments

1,277 lines (882 loc) 27.2 kB
/* eslint-disable no-script-url */ /* eslint-disable jsx-a11y/anchor-is-valid */ import React, { Fragment } from 'react' import PropTypes from 'prop-types' import { graphql, compose } from 'react-apollo'; // import gql from 'graphql-tag'; import moment from "moment"; import OrderItem from "./OrderItem"; import { // order, updateOrderProcessor, // updateUserProcessor, } from 'query'; import EditableView from 'apollo-cms/lib/DataView/Object/Editable'; import Modal from "../../../Modal"; import { withStyles } from 'material-ui'; import { CircularProgress } from 'material-ui/Progress'; import green from 'material-ui/colors/green'; import NumberFormat from 'react-number-format'; const styles = { buttonWrapper: { position: "relative", display: "inline-block", }, buttonLoading: { opacity: 0.2, }, buttonProgress: { color: green[500], position: 'absolute', top: '50%', left: '50%', marginTop: -12, marginLeft: -12, }, link: { cursor: "pointer", }, } export class OrdersOrder extends EditableView { static propTypes = { // eslint-disable-next-line react/forbid-foreign-prop-types ...EditableView.propTypes, services: PropTypes.array, // match: PropTypes.object.isRequired, // View: PropTypes.func.isRequired, // order: PropTypes.object.isRequired, classes: PropTypes.object.isRequired, } static defaultProps = { ...EditableView.defaultProps, // View, } constructor(props) { super(props); const { opened = false, confirmOpened = false, showSuccess = false, // loading = false, } = props; this.state = { ...this.state, opened, confirmOpened, showSuccess, }; } renderHeader() { return null; } updateItem(item, data) { let itemsDirty = this.getItemsDirty() || []; const { id: itemId, } = item; let existsItem = itemsDirty.find(n => n.id === itemId) || itemsDirty[itemsDirty.push({ id: itemId, }) - 1]; Object.assign(existsItem, data); this.updateObject({ itemsDirty, }); } getItemsDirty(activeOnly = false) { let { itemsDirty, } = this.state._dirty || {} // return itemsDirty; return activeOnly === true ? itemsDirty ? itemsDirty.filter(n => { // n.selectedServices && n.selectedServices.findIndex(n => n._selected === true) !== -1 let dirty = false; if (!n) { return false; } const { // id: dirtyItemId, selectedServices, // ...other } = n; // if ( // dirtyItemId === id // ) { if ( (selectedServices && selectedServices.find(n => n._selected === true)) // || (other && Object.keys(other).length) ) { dirty = true; } // } return dirty; }) : [] : itemsDirty; } printOrder() { this.setState({ opened: true, }, () => { setTimeout(() => { // const { // orderTable, // } = this.refs; const { orderTableRef: orderTable, } = this; if (!orderTable) { return; } const clone = orderTable.cloneNode(true); // const wrapper = <div // className={"print-wrapper"} // > // {this.renderOrderTable()} // </div> const wrapper = global.document.querySelector(".print-wrapper"); if (!wrapper) { return; } wrapper.innerHTML = null; wrapper.appendChild(clone) // $(this).closest('.open-tab-wrapper').find('.selection-block').removeClass('open'); // var thisOrder = $(this).closest('.open-tab-wrapper.client-order'); // var userName = $(this).closest('.orders-wrapper').attr('data-login'); // var userFullName = $(this).closest('.orders-wrapper').attr('data-username'); // var orderNum = $(this).closest('.orders-wrapper').find('.open-tab-title').attr('data-order'); // var orderDate = $(this).closest('.orders-wrapper').find('.open-tab-title').attr('data-orderdate'); // $('.print-wrapper').empty(); // $('title').empty(); // $('title').append('Личный кабинет пользователя ' + userName + ' заказ № ' + orderNum + ' от ' + orderDate); // $(thisOrder).clone().appendTo('.print-wrapper'); // window.print(); // $(this).closest('.open-tab-wrapper').find('.selection-block').removeClass('open'); // var thisOrder = $(this).closest('.open-tab-wrapper.client-order'); // var userName = $(this).closest('.orders-wrapper').attr('data-login'); // var userFullName = $(this).closest('.orders-wrapper').attr('data-username'); // var orderNum = $(this).closest('.orders-wrapper').find('.open-tab-title').attr('data-order'); // var orderDate = $(this).closest('.orders-wrapper').find('.open-tab-title').attr('data-orderdate'); // $('.print-wrapper').empty(); // $('title').empty(); // $('title').append('Личный кабинет пользователя ' + userName + ' заказ № ' + orderNum + ' от ' + orderDate); // $(thisOrder).clone().appendTo('.print-wrapper'); window.print(); }, 500) }); } renderEditableView() { return this.renderDefaultView(); } canOrderSlab(item, showErrors = true) { const { preGrade, // sheldon_grade, } = item; if (this.notGradable(item)) { showErrors && this.addError("Нельзя заказать услугу для этой монеты"); return false; } if (!preGrade) { showErrors && this.addError("Дождитесь получения прегрейда."); return false; } return true; } notGradable(item) { const { preGrade, sheldon_grade, } = item || {}; return ( preGrade === "NOTGENUINE" || preGrade === "NOTGRADABLE" || sheldon_grade === "NOTGENUINE" || sheldon_grade === "NOTGRADABLE" ); } addError(error) { super.addError(error); return false; } getDirty(item) { const { _dirty, } = item; return _dirty; } isSlabServiceOrdered(item) { const { selectedServices, } = this.getDirty(item) || {}; const slabServiceSelected = (selectedServices && selectedServices.find(n => n.code === "slab" && n._selected === true)) ? true : false; const { ServiceOrders, } = item; 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; } /** * Выбираем услугу */ setService(item, service) { const canEdit = this.canEdit(); // console.log("setService service", service); // 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(item) || {} 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(item)) { return false; } break; default: ; } selectedServices.push(selectedService); } selectedService._selected = selectedService._selected ? false : true; this.updateItem(item, { selectedServices, }); } canEdit = () => { const order = this.getObjectWithMutations() || {}; const { archived, } = order; let canEdit = archived === false || archived === null ? true : false; return canEdit; } getItems(options = {}) { const order = this.getObjectWithMutations(); if (!order) { return []; } const { services, // classes, } = this.props; const { diffsOnly, } = options; const { // id: orderId, // date, // number, Items, // archived, } = order; let itemsDirty = this.getItemsDirty() || []; return Items && Items.length ? Items.map(n => { const { id, price: itemPrice, ServiceOrders, InvoiceItems = [], } = n; // if(ServiceOrders && ServiceOrders.length) { // dirty = true; // } // else { // } let dirtyItem = itemsDirty.find(n => { let dirty = false; if (!n) { return null; } // if (ServiceOrders && ServiceOrders.length) { // dirty = true; // } // else { const { id: dirtyItemId, selectedServices, ...other } = n; if ( dirtyItemId === id ) { if ( (selectedServices && selectedServices.find(n => n._selected === true)) || (other && Object.keys(other).length) ) { dirty = true; } // } } return dirty; }); if (diffsOnly && (!dirtyItem && (!ServiceOrders || !ServiceOrders.length))) { return null; } let amount = InvoiceItems.reduce((a, { cost: b }) => a + b, 0); const { selectedServices, slabTarif, } = dirtyItem || {} let slabSelected = ServiceOrders && ServiceOrders.find(n => n.Service.code === "slab") ? true : false; let dirtySlab = (selectedServices && selectedServices.find(n => n.code === "slab" && n._selected === true)) || null; // console.log("selectedServices", selectedServices); // console.log("dirtySlab", dirtySlab); if (dirtySlab) { slabSelected = true; } /** * Высчитываем стоимость данного изделия. * Для этого проходим по каждой услуге и проверяем выбранные. * * Считать надо: * - Услугу * - Тариф */ // ServiceOrders services.map(i => { const { id: serviceId, // name, // short_name, // Tarifs, code, } = i; let service; let tarif; let selectedService = (selectedServices && selectedServices.find(s => s.id === serviceId && s._selected === true)); /** * Флаг того, что услуга в отказе */ // let rejected; /** * Надо брать данные из базы данных (самой услуги) */ let serviceOrderAmount; switch (code) { case "photo": /** * Если заказано слабирование, то фото бесплатно */ if (slabSelected) { return null; } break; default: ; } if (selectedService) { service = selectedService; // tarif = selectedService.Tarif; const { code, Tarifs, } = service; if (code === "slab") { tarif = slabTarif ? Tarifs.find(t => t.id === slabTarif) : undefined; } } else { const ServiceOrder = ServiceOrders.find(i => i.Service.id === serviceId); if (ServiceOrder) { let { Service, Tarif, amount, } = ServiceOrder; serviceOrderAmount = amount; service = Service; tarif = Tarif; } } if (serviceOrderAmount !== undefined) { if (serviceOrderAmount) { amount += serviceOrderAmount; } } else if (service) { const { price, priceCooficient, } = service if (tarif) { amount += tarif.price; } if (priceCooficient) { if (itemPrice) { amount += itemPrice * (priceCooficient / 100); } } else if (price) { amount += price; } } return null; }); // total += price ? parseFloat(price) : 0; amount = (amount && parseInt(amount)) || 0; // total += amount; return { item: { ...n, _dirty: dirtyItem, }, services, amount, }; // return <OrderItem // key={id} // item={{ // ...n, // _dirty: dirtyItem, // }} // services={services} // amount={amount} // classes={classes} // updateItem={(item, data) => this.updateItem(item, data)} // canEdit={() => this.canEdit()} // canOrderSlab={item => this.canOrderSlab(item)} // notGradable={item => this.notGradable(item)} // getDirty={item => this.getDirty(item)} // setService={(item, service) => this.setService(item, service)} // /> }).filter(n => n) : []; } renderOrderTable(options = {}) { const { diffsOnly, } = options; const order = this.getObjectWithMutations(); if (!order) { return null; } const { opened, // confirmOpened, } = this.state; const { // services, classes, } = this.props; // let canEdit = archived === false || archived === null ? true : false; // console.log("canEdit", canEdit, archived); let total = 0; let items = this.getItems(options).map(n => { const { item, services, amount, } = n; if (amount) { total += amount; } return <OrderItem key={item.id} item={item} services={services} amount={amount} classes={classes} updateItem={(item, data) => this.updateItem(item, data)} canEdit={() => this.canEdit()} canOrderSlab={item => this.canOrderSlab(item)} notGradable={item => this.notGradable(item)} getDirty={item => this.getDirty(item)} isSlabServiceOrdered={item => this.isSlabServiceOrdered(item)} setService={(item, service) => this.setService(item, service)} /> }); const hasActiveItems = this.getItemsDirty(true).length; // let servicesTitles = services && services.map(n => { // const { // id, // name, // short_name, // } = n; // return <th // key={id} // > // {short_name || name} // </th> // }) || []; const tableServicesTitles = this.getTableServicesTitles("Заказ услуг"); const tableServicesTitles2 = this.getTableServicesTitles("Готовность"); return <div className="client-order" // ref={!diffsOnly ? "orderTable" : undefined} ref={element => { if (!diffsOnly) { this.orderTableRef = element } }} > <div className="open-tab-content" style={{ display: "block", }} > <table className={["order-table", ""].join(" ")} border="0" cellSpacing="0" cellPadding="0" id="103595180" style={{ maxWidth: "100%", minWidth: 1000, }} > <tbody> {opened && items ? <Fragment> <tr> <th className={["num-th", ""].join(" ")}></th> <th className={["name-th", ""].join(" ")}>Предмет</th> <th className={["year-th", ""].join(" ")}>Год</th> <th className={["metal-th", ""].join(" ")}>Металл</th> <th className={["otsenka-th", ""].join(" ")}>Оценка (руб.)</th> {/* <th className={["service-th", ""].join(" ")}>Услуги</th> */} <th className={["pregdare-th", ""].join(" ")}>Прегрейд</th> {/* {servicesTitles} */} {tableServicesTitles} {/* <th className={["tarif-th", ""].join(" ")}>Тариф</th> */} {/* <th>Дата заказа</th> */} <th className={["graid-th", ""].join(" ")}>Грейд по Шелдону</th> <th className={["tarif-th", ""].join(" ")}> Тариф </th> <th className={["order-date-th", ""].join(" ")}> Дата заказа </th> {tableServicesTitles2} <th className={["price-th", ""].join(" ")}>Стоимость (руб.)</th> </tr> {items} <tr className="result-order-row"> <td colSpan="11"><span className="text-block">Итого</span></td> <td><span className="text-block"> <NumberFormat value={total || 0} displayType="text" thousandSeparator=" " /> </span></td> </tr> </Fragment> : null} {!diffsOnly && hasActiveItems ? <tr className="accept-grade-button-wrapper" style={{ display: !this.isDirty() ? "none" : undefined, }}> <td className="accept-grade-block" colSpan="15"> <div className="accept-grade-button confirm_order" title="Подтвердить выбранные позиции" onClick={event => { // this.save(); this.setState({ confirmOpened: true, }); }} > Подтвердить </div> <div className="refuse-accept-grade-button" title="Очистить выбранные позиции" onClick={event => { this.resetEdit(); }} > x </div> </td> </tr> : null} </tbody> </table> </div> </div> ; } getTableServicesTitles(title) { // const { // classes, // } = this.props; return <th className={["service-th service-ready", ""].join(" ")}> <div className="service-ready-title"> {title} </div> <div className="tab-block services ready-service"> <div title="Слабировать все" className={["service_accept "].join(" ")} // className={["service_accept ", classes.link].join(" ")} > <a href="javascript:;" // className={classes.link} style={{ cursor: "pointer", }} onClick={event => { if (window.confirm("Заказать слабирование по всем позициям?")) { this.orderAllSlabs(); } }} > Слаб </a> </div> <div title="Экспертное заключение" className="service_accept "> Эксп </div> <div title="Фото" className="service_accept "> Фото </div> <div title="Оценка" className="service_accept "> Оценка </div> </div> </th> } orderAllSlabs() { // const items = this.getItems().map(({ item }) => item); const items = this.getItems(); // console.log("orderAllSlabs items", items); items.map(n => { const { item, services, } = n; const slabService = services && services.find(n => n.code === "slab"); if (slabService && this.canOrderSlab(item, false) && !this.isSlabServiceOrdered(item)) { // console.log("orderAllSlabs item", item); // console.log("orderAllSlabs services", services); this.setService(item, slabService); } return null; }); } renderDefaultView() { const order = this.getObjectWithMutations(); console.log("renderDefaultView order", order); if (!order) { return null; } const { classes, } = this.props; const { opened, confirmOpened, showSuccess, loading, } = this.state; const { number, date, } = order; // if(!order){ // return null; // } let orderTitle = `Заказ № ${number} ${(date && moment(date).format('DD.MM.YY')) || ""}`; let orderTable = this.renderOrderTable(); let confirmModal; if (confirmOpened) { confirmModal = <div className="order-profile" > <Modal opened={true} handleClose={event => { this.setState({ confirmOpened: false, }); }} title={orderTitle} // className="popup2" > <div className="window" style={{ width: "auto", padding: 0, }} > {this.renderOrderTable({ diffsOnly: true, })} <div className="confirm-send-wrapper" style={{ display: "block", }}> <div className="confirm-send-cansel-wrapper"> <div className="confirm-button confirm_cansel" onClick={event => { event.preventDefault(); this.setState({ confirmOpened: false, }); }} > Отменить </div> <div className={classes.buttonWrapper} > <div className={["confirm-button confirm_send", loading ? classes.buttonLoading : ""].join(" ")} onClick={async event => { event.preventDefault(); await this.save() .then(r => { const { response, } = r.data || {} const { success, } = response || {} if (success) { this.setState({ confirmOpened: false, }); this.setState({ showSuccess: true, }); setTimeout(() => { this.setState({ showSuccess: false, }); }, 3000); } }); }} > Отправить </div> {loading ? <CircularProgress size={24} className={classes.buttonProgress} /> : null} </div> </div> </div> </div> </Modal> </div> } let successMessage; if (showSuccess) { successMessage = <div className="order-profile" > <Modal opened={true} handleClose={event => { this.setState({ confirmOpened: false, }); }} title={"Успешно"} // className="popup2" > <div className="window" // style={{ // width: "auto", // padding: 0, // }} > <div className="insText"> <p>Спасибо за Ваш заказ.<br />Мы с Вами обязательно свяжемся.</p> </div> </div> </Modal> </div> } return <Fragment> <div className="orders-wrapper" > <div className="open-tab-wrapper client-order"> <div className={["open-tab-title", opened ? "open" : ""].join(" ")} onClick={event => { this.setState({ opened: !opened, }); }} > {orderTitle} <i className="menu-expand" ></i> </div> <div className="print_order print-button" title="Распечатать заказ" onClick={event => this.printOrder()} ></div> <div className="open-tab-content" style={{ display: "block", }} > {orderTable} <div className="popup-grade">Подтвердить</div> </div> </div> </div> {confirmModal} {successMessage} </Fragment> // return (<View // // object={order} // // data={data} // // saveObject={this.saveOrder} // // {...other} // data={{ // }} // />) } } export default compose( // graphql(order, { // // name: 'order', // }), graphql(updateOrderProcessor, { // name: 'updateOrder', options: () => { return { variables: { orderGetItems: false, }, } }, }), // graphql(updateUserProcessor, { // name: 'updateUser', // }), )(withStyles(styles)(props => <OrdersOrder {...props} />)); // export default OrdersOrder;