diff --git a/src/Panel.js b/src/Panel.js index 37fa7834a688c6933d76951242e1a3c654f1d21b..4f8480071e506cda93813c9a81337024e1b1392a 100644 --- a/src/Panel.js +++ b/src/Panel.js @@ -12,6 +12,7 @@ import Topup from "./Topup"; import ShowTransaction from "./ShowTransaction"; import ShowOrder from "./order/ShowOrder"; import CreateOrder from "./order/CreateOrder"; +import EditOrder from "./order/EditOrder"; import SignIn from "./SignIn"; import ResetRequest from "./ResetRequest"; import ResetPassword from "./ResetPassword"; @@ -65,6 +66,7 @@ function LogedPanel(props) { <Route path="/order/create"> <CreateOrder /> </Route> + <Route path="/order/edit/:id" component={EditOrder} /> <Route path="/order/:id" component={ShowOrder} /> <Route path="/"> <Dashboard /> diff --git a/src/order/CreateOrder.js b/src/order/CreateOrder.js index a36b4387838566769fad26b561144f4d249ffd2f..c81c912e00a73dcf50bb2c0d3976a62f7d8f42b9 100644 --- a/src/order/CreateOrder.js +++ b/src/order/CreateOrder.js @@ -1,108 +1,25 @@ import React, { useState } from "react"; import { Redirect } from "react-router-dom"; import { Form, Row, Col, Button } from "react-bootstrap"; -import ProductPicker from "../ProductPicker"; +import OrderEditor from "./OrderEditor"; import Sender from "../Sender"; -import Fetcher from "../Fetcher"; - -function date2string(date) { - return date.toISOString().split("T")[0]; -} - -function daysAfterNow(days) { - let date = new Date(); - date.setDate(date.getDate() + days); - return date; -} function CreateOrder() { - const [picks, setPicks] = useState([]); - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - const [deadline, setDeadline] = useState(daysAfterNow(3)); + const [body, setBody] = useState(); const [order, setOrder] = useState(null); - const [prevOrders, setPrevOrders] = useState(null); if (order !== null) { return <Redirect to={"/order/" + order.ID} />; } - const body = () => { - const products = picks.map((p) => { - return { code: p.code, price: p.price }; - }); - return { name, description, deadline, products }; - }; - - const fillOrder = (name) => { - const prevOrder = prevOrders.find((o) => o.name === name); - setName(name); - setDescription(prevOrder.description); - setPicks(prevOrder.products); - }; - - const orderOptions = prevOrders - ? prevOrders.map((o) => <option key={o.name}>{o.name}</option>) - : ""; - - const disabled = picks.find((p) => isNaN(p.price)) !== undefined; + const disabled = + !body || + !body.name || + body.products.find((p) => isNaN(p.price)) !== undefined; return ( <Sender url="/api/order" body={body} onSuccess={setOrder}> - <Form.Group as={Row}> - <Form.Label as="legend" column sm={3}> - Repetir pedido - </Form.Label> - <Col sm={9}> - <Fetcher url="/api/order/picks" onFetch={setPrevOrders}> - <Form.Control - as="select" - onChange={(e) => fillOrder(e.target.value)} - > - {orderOptions} - </Form.Control> - </Fetcher> - </Col> - </Form.Group> - <hr /> - <Form.Group as={Row}> - <Form.Label as="legend" column sm={3}> - Nombre - </Form.Label> - <Col sm={9}> - <Form.Control - placeholder="nombre del pedido" - value={name} - onChange={(e) => setName(e.target.value)} - /> - </Col> - </Form.Group> - <Form.Group as={Row}> - <Form.Label as="legend" column sm={3}> - Descripción - </Form.Label> - <Col sm={9}> - <Form.Control - as="textarea" - value={description} - onChange={(e) => setDescription(e.target.value)} - /> - </Col> - </Form.Group> - <Form.Group as={Row}> - <Form.Label as="legend" column sm={3}> - Fecha límite - </Form.Label> - <Col sm={9}> - <Form.Control - type="date" - value={date2string(deadline)} - onChange={(e) => setDeadline(new Date(e.target.value))} - min={date2string(daysAfterNow(1))} - /> - </Col> - </Form.Group> - <ProductPicker picks={picks} setPicks={setPicks} price /> + <OrderEditor onChange={setBody} /> <Form.Group as={Row}> <Col> <div className="text-right"> diff --git a/src/order/EditOrder.js b/src/order/EditOrder.js new file mode 100644 index 0000000000000000000000000000000000000000..920aa402e73d29889424276800180df52d3bb4da --- /dev/null +++ b/src/order/EditOrder.js @@ -0,0 +1,59 @@ +import React, { useState } from "react"; +import { Redirect, useParams } from "react-router-dom"; +import { LinkContainer } from "react-router-bootstrap"; +import { Form, Row, Col, Button } from "react-bootstrap"; +import OrderEditor from "./OrderEditor"; +import Fetcher from "../Fetcher"; +import Sender from "../Sender"; + +function EditOrder() { + const { id } = useParams(); + const [order, setOrder] = useState(); + const [body, setBody] = useState(); + const [sent, setSent] = useState(false); + console.log(body); + + if (sent) { + return <Redirect to={"/order/" + id} />; + } + + const disabled = + !body || + !body.name || + body.products.find((p) => isNaN(p.price)) !== undefined; + + let order_editor; + if (order) { + order_editor = <OrderEditor order={order} onChange={setBody} />; + } + return ( + <Fetcher + url={"/api/order/" + id} + onFetch={(o) => setOrder(o.order)} + oneShot + > + <Sender + url={"/api/order/" + id} + method="PUT" + body={body} + onSuccess={setSent} + > + {order_editor} + <Form.Group as={Row}> + <Col> + <div className="text-right"> + <Button type="submit" disabled={disabled}> + Actualizar pedido + </Button> + <LinkContainer to={"/order/" + id}> + <Button variant="secondary">Cancelar</Button> + </LinkContainer> + </div> + </Col> + </Form.Group> + </Sender> + </Fetcher> + ); +} + +export default EditOrder; diff --git a/src/order/OrderEditor.js b/src/order/OrderEditor.js new file mode 100644 index 0000000000000000000000000000000000000000..6217c6828d2dd459f13762fe440296e0ae360a34 --- /dev/null +++ b/src/order/OrderEditor.js @@ -0,0 +1,154 @@ +import React, { useState } from "react"; +import { Form, Row, Col } from "react-bootstrap"; +import ProductPicker from "../ProductPicker"; +import Fetcher from "../Fetcher"; + +function date2string(date) { + return date.toISOString().split("T")[0]; +} + +function daysAfterNow(days) { + let date = new Date(); + date.setDate(date.getDate() + days); + return date; +} + +function order2picks(order) { + return order.products.map((p) => { + return { + code: p.code, + name: p.product.name, + price: p.price, + }; + }); +} + +function genBody(name, description, deadline, picks) { + const products = picks.map((p) => { + return { code: p.code, price: p.price }; + }); + return { name, description, deadline, products }; +} + +function OrderEditor(props) { + const [name, _setName] = useState(props.order ? props.order.name : ""); + const [description, _setDescription] = useState( + props.order ? props.order.description : "" + ); + const [deadline, _setDeadline] = useState( + props.order ? new Date(props.order.deadline) : daysAfterNow(3) + ); + const [picks, _setPicks] = useState( + props.order ? order2picks(props.order) : [] + ); + const [prevOrders, setPrevOrders] = useState(null); + + const setName = (name) => { + _setName(name); + const body = genBody(name, description, deadline, picks); + props.onChange(body); + }; + const setDescription = (description) => { + _setDescription(description); + const body = genBody(name, description, deadline, picks); + props.onChange(body); + }; + const setDeadline = (str) => { + const deadline = new Date(str); + _setDeadline(deadline); + const body = genBody(name, description, deadline, picks); + props.onChange(body); + }; + const setPicks = (picks) => { + _setPicks(picks); + const body = genBody(name, description, deadline, picks); + props.onChange(body); + }; + + const fillOrder = (name) => { + if (!name) { + return; + } + + const prevOrder = prevOrders.find((o) => o.name === name); + setName(name); + setDescription(prevOrder.description); + setPicks(order2picks(prevOrder)); + }; + + const orderOptions = prevOrders + ? [<option key=""></option>].concat( + prevOrders.map((o) => <option key={o.name}>{o.name}</option>) + ) + : ""; + + let order_picker; + if (!props.order) { + order_picker = ( + <div> + <Form.Group as={Row}> + <Form.Label as="legend" column sm={3}> + Repetir pedido + </Form.Label> + <Col sm={9}> + <Fetcher url="/api/order/picks" onFetch={setPrevOrders}> + <Form.Control + as="select" + onChange={(e) => fillOrder(e.target.value)} + > + {orderOptions} + </Form.Control> + </Fetcher> + </Col> + </Form.Group> + <hr /> + </div> + ); + } + + return ( + <div> + {order_picker} + <Form.Group as={Row}> + <Form.Label as="legend" column sm={3}> + Nombre + </Form.Label> + <Col sm={9}> + <Form.Control + placeholder="nombre del pedido" + value={name} + onChange={(e) => setName(e.target.value)} + /> + </Col> + </Form.Group> + <Form.Group as={Row}> + <Form.Label as="legend" column sm={3}> + Descripción + </Form.Label> + <Col sm={9}> + <Form.Control + as="textarea" + value={description} + onChange={(e) => setDescription(e.target.value)} + /> + </Col> + </Form.Group> + <Form.Group as={Row}> + <Form.Label as="legend" column sm={3}> + Fecha límite + </Form.Label> + <Col sm={9}> + <Form.Control + type="date" + value={date2string(deadline)} + onChange={(e) => setDeadline(e.target.value)} + min={date2string(daysAfterNow(1))} + /> + </Col> + </Form.Group> + <ProductPicker picks={picks} setPicks={setPicks} price /> + </div> + ); +} + +export default OrderEditor; diff --git a/src/order/ShowOrder.js b/src/order/ShowOrder.js index ad23d139a29bec4c3f25e2e872c4aa65ecb81d9f..ea09254018d0acea95d5a2d2d3d42971d5598802 100644 --- a/src/order/ShowOrder.js +++ b/src/order/ShowOrder.js @@ -1,7 +1,16 @@ import React from "react"; import { Redirect } from "react-router-dom"; +import { LinkContainer } from "react-router-bootstrap"; import Fetcher from "../Fetcher"; -import { Row, Col, Badge, Button, Spinner, Alert } from "react-bootstrap"; +import { + Row, + Col, + Badge, + Button, + ButtonGroup, + Spinner, + Alert, +} from "react-bootstrap"; import PurchaseOrder from "./PurchaseOrder"; import { printDate } from "../util"; import AuthContext from "../AuthContext"; @@ -148,9 +157,11 @@ class ShowOrder extends React.Component { expired = <Badge variant="info">finalizado</Badge>; } - let delbutton; + const { id } = this.props.match.params; + + let update_button; if (this.state.isLoading) { - delbutton = <Spinner animation="border" />; + update_button = <Spinner animation="border" />; } else { let deadline_week = new Date(order.deadline); deadline_week.setDate(deadline_week.getDate() + 7); @@ -159,15 +170,19 @@ class ShowOrder extends React.Component { this.context.role === "admin") && deadline_week > Date.now() ) { - delbutton = ( - <Button variant="danger" onClick={() => this.delorder()}> - Cancelar pedido - </Button> + update_button = ( + <ButtonGroup> + <LinkContainer to={"/order/edit/" + id}> + <Button variant="info">Modificar</Button> + </LinkContainer> + <Button variant="danger" onClick={() => this.delorder()}> + Cancelar + </Button> + </ButtonGroup> ); } } - const { id } = this.props.match.params; return ( <Fetcher url={"/api/order/" + id} onFetch={(data) => this.setData(data)}> {this.state.error && <Alert variant="danger">{this.state.error}</Alert>} @@ -180,7 +195,7 @@ class ShowOrder extends React.Component { Fecha limite: {printDate(this.state.order.deadline)} {expired} </p> - {delbutton} + {update_button} </Col> </Row> <p>{this.state.order.description}</p>