From c38d5a64b37ceee4f22eacf643d1a12d4bbc7c8c Mon Sep 17 00:00:00 2001 From: Quique <917-quique@users.noreply.0xacab.org> Date: Fri, 16 Oct 2020 13:53:38 +0200 Subject: [PATCH] UI to change your own password --- src/App.js | 4 ++ src/Head.js | 5 ++ src/Password.js | 166 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 src/Password.js diff --git a/src/App.js b/src/App.js index a436f4b..6b2514c 100644 --- a/src/App.js +++ b/src/App.js @@ -3,6 +3,7 @@ import { BrowserRouter, Switch, Route } from "react-router-dom"; import MemberList from "./MemberList"; import ProductList from "./ProductList"; import Dashboard from "./Dashboard"; +import OwnPassword from "./Password"; import Purchase from "./purchase/Purchase"; import Topup from "./Topup"; import ShowTransaction from "./ShowTransaction"; @@ -27,6 +28,9 @@ function Panel(props) { <Route path="/transaction/:id"> <ShowTransaction /> </Route> + <Route path="/password"> + <OwnPassword /> + </Route> <Route path="/purchase"> <Purchase /> </Route> diff --git a/src/Head.js b/src/Head.js index 63d4582..740778c 100644 --- a/src/Head.js +++ b/src/Head.js @@ -35,6 +35,11 @@ function Head(props) { <Nav.Link href="/purchase">Comprar</Nav.Link> <Nav.Link href="/order/create">Abrir pedido</Nav.Link> </Nav> + + <NavDropdown title="Ajustes" id="ajustes"> + <Nav.Link href="/password">Cambiar contraseña</Nav.Link> + </NavDropdown> + {adminNav} <Form inline> <Button variant="outline-success" onClick={props.onLogout}> diff --git a/src/Password.js b/src/Password.js new file mode 100644 index 0000000..ef0a7f3 --- /dev/null +++ b/src/Password.js @@ -0,0 +1,166 @@ +import React from "react"; +import { Container, Form, Col, Row, Button, Alert } from "react-bootstrap"; +import AuthContext from "./AuthContext"; + +class OwnPassword extends React.Component { + static contextType = AuthContext; + + constructor(props) { + super(props); + this.state = { + newPassword: "", + newPassword2: "", + formErrors: "", + isNewPasswordValid: false, + isNewPassword2Valid: false, + isFormValid: false, + error: null, + passwordChanged: false, + }; + this.handleSubmit = this.handleSubmit.bind(this); + } + + /** Check whether the new password is valid, and matches with its confirmation. */ + checkNewPassword() { + let isNewPasswordValid = this.state.newPassword.length >= 6; + let isNewPassword2Valid = + this.state.newPassword === this.state.newPassword2; + + let formErrors = isNewPasswordValid + ? isNewPassword2Valid + ? "" + : "Las contraseñas no coinciden." + : "La contraseña es demasiado corta."; + + this.setState( + { + formErrors: formErrors, + isNewPasswordValid: isNewPasswordValid, + isNewPassword2Valid: isNewPassword2Valid, + }, + this.validateForm + ); + } + + /** Check all the fields are valid, so the form may be submitted. */ + validateForm() { + this.setState({ + isFormValid: + this.state.isNewPasswordValid && this.state.isNewPassword2Valid, + }); + } + + handleSubmit(event) { + event.preventDefault(); + + this.setState({ isLoading: true, error: null }); + const body = JSON.stringify({ + password: this.state.newPassword, + }); + fetch("/api/member/me", { + headers: { "x-authentication": this.context.token }, + method: "PUT", + body, + }) + .then((response) => { + if (!response.ok) { + throw new Error( + response.status.toString() + " " + response.statusText + ); + } + return response.json(); + }) + .then((json) => { + // console.log(json); + this.setState({ + isLoading: false, + passwordChanged: true, + }); + }) + .catch((error) => { + this.setState({ isLoading: false, error: error.message }); + }); + } + + render() { + let alert; + + if (this.state.formErrors) { + alert = <Alert variant="warning">{this.state.formErrors}</Alert>; + } + + if (this.state.error) { + alert = ( + <Alert variant="danger"> + Se produjo un error al intentar cambiar la contraseña:{" "} + {this.state.error} + </Alert> + ); + } + + if (this.state.passwordChanged) { + alert = ( + <Alert variant="success">La contraseña se ha cambiado con éxito.</Alert> + ); + this.state.passwordChanged = false; + } + + return ( + <Container> + <h2>Cambio de contraseña</h2> + + {alert} + + <Form onSubmit={this.handleSubmit}> + <Form.Group as={Row}> + <Form.Label as="legend" column sm={4}> + Nueva contraseña + </Form.Label> + <Col sm={8}> + <Form.Control + placeholder="Nueva contraseña" + type="password" + onChange={(e) => + this.setState({ newPassword: e.target.value }, () => { + this.checkNewPassword(); + }) + } + /> + </Col> + </Form.Group> + + <Form.Group as={Row}> + <Form.Label as="legend" column sm={4}> + Confirme la nueva contraseña + </Form.Label> + <Col sm={8}> + <Form.Control + placeholder="Repita la nueva contraseña" + type="password" + onChange={(e) => + this.setState({ newPassword2: e.target.value }, () => { + this.checkNewPassword(); + }) + } + /> + </Col> + </Form.Group> + + <Form.Group as={Row}> + <Col sm={{ offset: 4, span: 8 }}> + <Button + type="submit" + variant="primary" + disabled={!this.state.isFormValid} + > + Cambiar la contraseña + </Button> + </Col> + </Form.Group> + </Form> + </Container> + ); + } +} + +export default OwnPassword; -- GitLab