jelhan/croodle

View on GitHub
app/components/create-options-datetime.hbs

Summary

Maintainability
Test Coverage
<div class="cr-form-wrapper box">
  {{#if this.errorMessage}}
    <BsAlert @type="warning">
      {{t this.errorMessage}}
    </BsAlert>
  {{/if}}

  <BsForm
    @onInvalid={{(scroll-first-invalid-element-into-view-port)}}
    @onSubmit={{this.submit}}
    @formLayout="horizontal"
    @model={{this.formData}}
    novalidate
    as |form|
  >
    <div class="days">
      {{#each-in this.formData.datetimes as |date timeOptions|}}
        {{!--
          @glint-ignore
          Types for value returned by `{{#each-in}}` are broken if used
          with a `Map`. https://github.com/typed-ember/glint/issues/645
        --}}
        {{#each timeOptions as |timeOption indexInTimeOptions|}}
          <div data-test-day={{date}}>
            <form.element
              @label={{format-date timeOption.jsDate dateStyle="full"}}
              {{!
                show label only for the first time of this date
              }}
              @invisibleLabel={{gt indexInTimeOptions 0}}
              @model={{timeOption}}
              @property="time"
              class="option"
              as |el|
            >
              <div class="input-group">
                <el.control
                  @placeholder="00:00"
                  @type="time"
                  @value={{el.value}}
                  {{! focus input if it's the first one }}
                  {{autofocus enabled=timeOption.isFirstTimeOnFirstDate}}
                  {{! run validation for partially filled input on focusout event }}
                  {{on "focusout" (fn this.validateInput timeOption)}}
                  {{on "change" (fn this.validateInput timeOption)}}
                  {{!
                    Validation for partially input field must be reset if input is cleared.
                    But `@onChange` is not called and `focusout` event not triggered in that
                    scenario. Need to listen to additional events to ensure that partially
                    input validation is updated as soon as user fixed a partially input.
                    The `keyup` events captures all scenarios in which the input is cleared
                    using keyboard. `focusin` event is triggered if user clicks the clears
                    button provided by native input. As a fallback validation is rerun on
                    `focusout`.
                    As the time of implementation this was only affecting Chrome cause
                    Firefox does not consider partially time input as invalid, Edge prevents
                    partially filling in first place and Desktop Safari as well as IE 11
                    do not support `<input type="time">`.
                  }}
                  {{on "focusin" (fn this.updateInputValidation timeOption)}}
                  {{on "keyup" (fn this.updateInputValidation timeOption)}}
                  id={{el.id}}
                />
                <div class="input-group-append">
                  <BsButton
                    @onClick={{fn this.formData.deleteOption timeOption}}
                    @type="link"
                    class="delete"
                    data-test-action="delete"
                  >
                    <span
                      class="oi oi-trash"
                      title={{t "create.options.button.delete.label"}}
                      aria-hidden="true"
                    ></span>
                    <span class="sr-only">
                      {{t "create.options.button.delete.label"}}
                    </span>
                  </BsButton>
                </div>
              </div>

              <BsButton
                @onClick={{fn this.formData.addOption date}}
                @type="link"
                @size="sm"
                class="add cr-option-menu__button cr-option-menu__add-button float-left"
                data-test-action="add"
              >
                <span
                  class="oi oi-plus"
                  title={{t "create.options.button.add.label"}}
                  aria-hidden="true"
                ></span>
                <span class="sr-only">{{t
                    "create.options.button.add.label"
                  }}</span>
              </BsButton>
            </form.element>
          </div>
        {{/each}}
      {{/each-in}}
    </div>

    {{#if this.formData.hasMultipleDays}}
      <form.element>
        <BsButton
          @onClick={{this.adoptTimesOfFirstDay}}
          @size="sm"
          class="adopt-times-of-first-day"
          data-test-action="adopt-times-of-first-day"
        >
          {{t "create.options-datetime.copy-first-line"}}
        </BsButton>
      </form.element>
    {{/if}}

    <div class="row cr-steps-bottom-nav">
      <div class="col-6 col-md-8 order-12">
        <NextButton />
      </div>
      <div class="col-6 col-md-4 order-1 text-right">
        <BackButton @onClick={{this.previousPage}} />
      </div>
    </div>
  </BsForm>
</div>