<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import CardPreview from './CardPreview'
import { generateCAHCard } from '../utils'
import styles from '../styles/components/CardAdd.styl'

class CardAdd extends React.Component {
  static propTypes = {
    deckId: PropTypes.string.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    history: PropTypes.shape({ goBack: PropTypes.func.isRequired }).isRequired
  }

  static defaultProps = {}

  constructor(props) {
    super(props)

    this.handleCancel = this.handleCancel.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)

    // Default values for the edit fields
    this.state = {
      title: '',
      description: ''
    }

    this.focusInput = null
  }

  componentDidMount() {
    // This happens a little too fast. If you get to this view via keyboard
    // shortcut, the focus event fires before the keyup and writes the value
    // into the field. Adding a 100ms delay prevents this from happening.
    setTimeout(() => {
      this.focusInput.focus()
    }, 100)
  }

  handleSubmit(e, deckId) {
    e.preventDefault()
    if (!this.state.title || this.state.title.trim() === '') {
      return
    }

    const card = {
      title: this.state.title,
      answer: this.state.answer || ''
    }
    this.props.handleSubmit(deckId, card)
  }

  handleCancel() {
    this.props.history.goBack()
  }

  handleChange(event, key) {
    const state = { ...this.state }
    state[key] = event.target.value
    this.setState(state)
  }

  render() {
    const { deckId } = this.props
    const { title, answer } = generateCAHCard()

    return (
      <figure className={`grid-figure ${styles['grid-figure']}`}>
        <form
          className="edit-form"
          onSubmit={e => this.handleSubmit(e, deckId)}
        >
          <label htmlFor="title">
            <span>Card Title</span>
            <input
              type="text"
              className="large-input"
              name="title"
              tabIndex={0}
              placeholder={title}
              ref={input => (this.focusInput = input)}
              onChange={e => this.handleChange(e, 'title')}
            />
          </label>

          <label htmlFor="answer">
            <span>
              Card Answer&nbsp;&nbsp;(
              <a
                href="//guides.github.com/features/mastering-markdown/"
                target="_blank"
                rel="noreferrer noopener"
              >
                Markdown
              </a>)
            </span>
            <textarea
              type="text"
              className="mono"
              name="answer"
              tabIndex={-1}
              placeholder={answer}
              rows="4"
              onChange={e => this.handleChange(e, 'answer')}
            />
          </label>

          <CardPreview title={this.state.title} answer={this.state.answer} />

          <div className={`${styles['control-buttons']}`}>
            <button type="submit" className="button outline">
              Save
            </button>
            <button
              type="button"
              className="button"
              onClick={this.handleCancel}
            >
              Cancel
            </button>
          </div>
        </form>
      </figure>
    )
  }
}

export default CardAdd
<commit_msg>feat: adding check for dirty fields before navigating out of the CardAdd view; also, fixed issue where the cancel button will work correctly after repeated clicks of add cards<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import CardPreview from './CardPreview'
import { generateCAHCard } from '../utils'
import styles from '../styles/components/CardAdd.styl'

class CardAdd extends React.Component {
  static propTypes = {
    deckId: PropTypes.string.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    // history: PropTypes.shape({ goBack: PropTypes.func.isRequired }).isRequired,
    push: PropTypes.func.isRequired
  }

  static defaultProps = {}

  constructor(props) {
    super(props)

    this.handleCancel = this.handleCancel.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)

    // Default values for the edit fields
    this.state = {
      title: '',
      answer: ''
    }

    this.focusInput = null
  }

  componentDidMount() {
    // This happens a little too fast. If you get to this view via keyboard
    // shortcut, the focus event fires before the keyup and writes the value
    // into the field. Adding a 100ms delay prevents this from happening.
    setTimeout(() => {
      this.focusInput.focus()
    }, 100)
  }

  handleSubmit(e, deckId) {
    e.preventDefault()
    if (!this.state.title || this.state.title.trim() === '') {
      return
    }

    const card = {
      title: this.state.title,
      answer: this.state.answer || ''
    }
    this.props.handleSubmit(deckId, card)
  }

  checkIfDirty = () => this.state.title !== '' || this.state.answer !== ''

  handleCancel() {
    if (this.checkIfDirty()) {
      if (
        confirm(
          'Are you sure you want to cancel? You have unsaved changes that will be lost.'
        )
      ) {
        this.props.push(`/view/${this.props.deckId}`)
      }
    } else {
      this.props.push(`/view/${this.props.deckId}`)
    }
    // We can't simply do the below because users get confused.
    // this.props.history.goBack()
  }

  handleChange(event, key) {
    const state = { ...this.state }
    state[key] = event.target.value
    this.setState(state)
  }

  render() {
    const { deckId } = this.props
    const { title, answer } = generateCAHCard()

    return (
      <figure className={`grid-figure ${styles['grid-figure']}`}>
        <form
          className="edit-form"
          onSubmit={e => this.handleSubmit(e, deckId)}
        >
          <label htmlFor="title">
            <span>Card Title</span>
            <input
              type="text"
              className="large-input"
              name="title"
              tabIndex={0}
              placeholder={title}
              ref={input => (this.focusInput = input)}
              onChange={e => this.handleChange(e, 'title')}
            />
          </label>

          <label htmlFor="answer">
            <span>
              Card Answer&nbsp;&nbsp;(
              <a
                href="//guides.github.com/features/mastering-markdown/"
                target="_blank"
                rel="noreferrer noopener"
              >
                Markdown
              </a>)
            </span>
            <textarea
              type="text"
              className="mono"
              name="answer"
              tabIndex={-1}
              placeholder={answer}
              rows="4"
              onChange={e => this.handleChange(e, 'answer')}
            />
          </label>

          <CardPreview title={this.state.title} answer={this.state.answer} />

          <div className={`${styles['control-buttons']}`}>
            <button type="submit" className="button outline">
              Save
            </button>
            <button
              type="button"
              className="button"
              onClick={this.handleCancel}
            >
              Cancel
            </button>
          </div>
        </form>
      </figure>
    )
  }
}

export default CardAdd

{'fraction_non_alphanumeric': 0.12623728813559323, 'fraction_numerical': 0.0024406779661016948, 'mean_word_length': 1.7876039304610734, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '894050', 'n_tokens_mistral': 2060, 'n_tokens_neox': 2022, 'n_words': 467}