React

by valkyris

HTML

<div id="app"></div>

CSS

body {
  background: #fff;
  padding: 20px;
  font-family: Helvetica;
}

input {
  width: 150px;
  height: 30px;
  font-size: 14px;
  padding: 5px;
  border-radius: 5px;
  border: none;
  border: 1px solid #8c8c8c;
  margin: 5px 5px 5px 0;
}

input:focus {
  outline: none;
}

.app-header {
  height: 50px;
  background-color: #002766;
  color: #fff;
  line-height: 50px;
  text-align: center;
  margin-bottom: 20px;
  box-shadow: 2px 4px 10px rgba(0, 0, 0, .2);
}

.input-button-group {
  display: flex;
  align-items: center;
}

.app-button {
  color: #fff;
  background-color: #0050b3;
  border-radius: 5px;
  border: none;
  height: 40px;
  box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
  cursor: pointer;
}

.disable-button {
  color: #000;
  background-color: #d9d9d9;
  border-radius: 5px;
  border: none;
  height: 40px;
}

.app-button:hover {
  background-color: #1890ff;
  transform: translateY(-1px);
}

.app-button:focus {
  outline: none;
}

.app-button:active {
  transform: translateY(1px);
}

.app-container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.keyword-container {
  height: 180px;
  max-height: 180px;
}

.source-input-container {
  margin: 10px 0;
}

.grid__container {
  display: flex;
  flex-direction: row;
  position: relative;
}

.grid__col {
  display: flex;
  flex-direction: column;
  border: 1px solid #20262E;
}

.grid__col:not(:first-child) {
  border-left: none;
}

.grid__col-item {
  height: 30px;
  width: 30px;
  line-height: 30px;
  text-align: center;
}

.grid__col-item.high-light {
  background-color: #69c0ff;
}

.grid__col-item.lower {
  border-top: 1px solid #20262E;
}

.keyword-alert__error {
  color: #ff4d4f;
  height: 40px;
}

.keyword-alert__success {
  color: #52c41a;
  height: 40px;
}

React

class SourceInput extends React.PureComponent {
  render() {
  	const buttonClass = !this.props.isSourceTextUIReady ? 'disable-button' : 'app-button';
  	return (
    	<div className="source-input-container">
        <div>Source Text</div>
        <div className="grid__container">
          {
            this.props.alphabet.map( (char, i) => (
              <div key={char + i} className="grid__col">
                <div className="grid__col-item">
                  <button
                    disabled={!this.props.isSourceTextUIReady}
                    onClick={() => { this.props.onSourceTextSelect(char, i) }}
                  >
                    {char}
                  </button>
                </div>
                <div className="grid__col-item lower">{this.props.encryptedAlphabet[i]}</div>
              </div>
            ))
          }
        </div>
        <div className="input-button-group">
          <input value={this.props.sourceTextValue} disabled />
          <button
            className={buttonClass}
            disabled={!this.props.isSourceTextUIReady}
            onClick={() => { this.props.onSourceTextSelect('', 0, true) }}
          >Clear</button>
        </div>
    	</div>
    )
  }
}

class KeyWord extends React.PureComponent {
  
  render() {
  	let buttonClass;
    let displayMessage;
    if (!this.props.isUpperCase || !this.props.isLengthValid) {
    	buttonClass = 'disable-button';
      displayMessage = (
      	 <div className="keyword-alert__error">
          {
          	!this.props.isUpperCase && <div>Keyword must contain upper case letters only</div>
          }
          {
            !this.props.isLengthValid && <div>Keyword must be between 3 - 8 characters long</div>
          }
        </div>
      );
    } else {
    	buttonClass = 'app-button';
      displayMessage = <div className="keyword-alert__success">Keyword OK!</div>
    }
  	return (
    	<div className="keyword-container">
        <div>Keyword</div>
       ...