102 lines
2.8 KiB
JavaScript
102 lines
2.8 KiB
JavaScript
|
import React, { Component } from 'react';
|
|||
|
import { withRouter } from 'react-router-dom';
|
|||
|
import { FormGroup, InputGroup, FormControl, Button, Glyphicon } from 'react-bootstrap';
|
|||
|
|
|||
|
/**
|
|||
|
* Class that renders a form to faciliate searching of
|
|||
|
* for a username and to redirect to that user's tweets
|
|||
|
* page.
|
|||
|
*
|
|||
|
* @extends React.Component
|
|||
|
*/
|
|||
|
class Search extends Component {
|
|||
|
|
|||
|
//#region Constructor
|
|||
|
constructor(props, context) {
|
|||
|
super(props, context);
|
|||
|
|
|||
|
// initial state
|
|||
|
this.state = {
|
|||
|
username: '',
|
|||
|
usernameHasChanged: false
|
|||
|
};
|
|||
|
}
|
|||
|
//#endregion
|
|||
|
|
|||
|
//#region Component events
|
|||
|
/**
|
|||
|
* Handles the 'Search' button click event which
|
|||
|
* sends the browser to the route to see the specified
|
|||
|
* user's tweets.
|
|||
|
*
|
|||
|
* @returns {null}
|
|||
|
*/
|
|||
|
_handleClick(e) {
|
|||
|
// if the form is in error, or the user has not typed in a username, do no nothing
|
|||
|
if (this._getValidationState() === 'error' || !this.state.usernameHasChanged) {
|
|||
|
return e.preventDefault();
|
|||
|
}
|
|||
|
|
|||
|
// redirec the user to the user's tweets page
|
|||
|
this.props.history.push('/@' + this.state.username);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* When user changes an input value, record that in the state.
|
|||
|
*
|
|||
|
* @param {SyntheticEvent} cross-browser wrapper around the browser’s native event
|
|||
|
*
|
|||
|
* @return {null}
|
|||
|
*/
|
|||
|
_handleChange(e) {
|
|||
|
let state = { usernameHasChanged: true };
|
|||
|
state[e.target.name] = e.target.value;
|
|||
|
this.setState(state);
|
|||
|
}
|
|||
|
//#endregion
|
|||
|
|
|||
|
//#region Helper methods
|
|||
|
/**
|
|||
|
* Validates the form. Return null for no state change,
|
|||
|
* 'success' if valid.
|
|||
|
*
|
|||
|
* @return {string} null for no state change, 'success'
|
|||
|
* if valid.
|
|||
|
*/
|
|||
|
_getValidationState() {
|
|||
|
|
|||
|
// ensure that the username has been changed and that a user has typed something in
|
|||
|
return (this.state.username === '' && !this.state.usernameHasChanged) || this.state.username.length > 0 ? null : 'error';
|
|||
|
}
|
|||
|
//#endregion
|
|||
|
|
|||
|
//#region React lifecycle events
|
|||
|
render() {
|
|||
|
let validationState = this._getValidationState();
|
|||
|
let isValid = validationState !== 'error';
|
|||
|
|
|||
|
return (
|
|||
|
<FormGroup validationState={validationState}>
|
|||
|
<InputGroup>
|
|||
|
<FormControl
|
|||
|
type="text"
|
|||
|
value={this.state.username}
|
|||
|
placeholder="username"
|
|||
|
name="username"
|
|||
|
onChange={ (e) => this._handleChange(e) }
|
|||
|
onKeyPress={ (e) => e.key === 'Enter' ? this._handleClick(e) : false }
|
|||
|
/>
|
|||
|
<InputGroup.Button>
|
|||
|
<Button
|
|||
|
bsStyle="primary"
|
|||
|
disabled={ !isValid }
|
|||
|
onClick={ !isValid ? null : (e) => this._handleClick(e) }><Glyphicon glyph="search" /></Button>
|
|||
|
</InputGroup.Button>
|
|||
|
</InputGroup>
|
|||
|
</FormGroup>
|
|||
|
);
|
|||
|
}
|
|||
|
//#endregion
|
|||
|
}
|
|||
|
|
|||
|
export default withRouter(Search);
|