Skip to content

Flight Booker

Live islandRuns locally in this page

Page shell

<flight-booker></flight-booker>

<script src="./build/cami.cdn.js"></script>
<!-- CDN version below -->
<!-- <script src="https://unpkg.com/cami@0.4/build/cami.cdn.js"></script> -->
<script type="module" src="./island.js"></script>

Island source

const { html, ReactiveElement } = cami
class FlightBookerElement extends ReactiveElement {
    flightType = 'one-way flight';
    startDate = new Date().toISOString().split('T')[0];
    endDate = new Date().toISOString().split('T')[0];
    isButtonDisabled = false;
    updateFlightType(event) {
        this.flightType = event.currentTarget.value;
        this.checkButtonState();
    }
    updateStartDate(event) {
        this.startDate = event.currentTarget.value;
        this.checkButtonState();
    }
    updateEndDate(event) {
        this.endDate = event.currentTarget.value;
        this.checkButtonState();
    }
    checkButtonState() {
        this.isButtonDisabled = this.flightType === 'return flight'
            && new Date(this.startDate) > new Date(this.endDate);
    }
    bookFlight() {
        let message = `You have booked a ${this.flightType} on ${this.startDate}.`;
        if (this.flightType === 'return flight') {
            message += ` Return on ${this.endDate}.`;
        }
        alert(message);
    }
    template() {
        return html `
      <select .value=${this.flightType} @change=${(event) => this.updateFlightType(event)}>
        <option>one-way flight</option>
        <option>return flight</option>
      </select>
      <input type="date" .value=${this.startDate} @input=${(event) => this.updateStartDate(event)}>
      <input type="date" .value=${this.endDate} @input=${(event) => this.updateEndDate(event)} ?disabled=${this.flightType === 'one-way flight'}>
      <button @click=${() => this.bookFlight()} ?disabled=${this.isButtonDisabled}>Book</button>
    `;
    }
}
customElements.define('flight-booker', FlightBookerElement);
import { html, ReactiveElement } from 'cami'

type FlightType = 'one-way flight' | 'return flight'

class FlightBookerElement extends ReactiveElement {
  flightType: FlightType = 'one-way flight'
  startDate: string = new Date().toISOString().split('T')[0]
  endDate: string = new Date().toISOString().split('T')[0]
  isButtonDisabled: boolean = false

  updateFlightType(event: Event): void {
    this.flightType = (event.currentTarget as HTMLSelectElement).value as FlightType
    this.checkButtonState()
  }

  updateStartDate(event: InputEvent): void {
    this.startDate = (event.currentTarget as HTMLInputElement).value
    this.checkButtonState()
  }

  updateEndDate(event: InputEvent): void {
    this.endDate = (event.currentTarget as HTMLInputElement).value
    this.checkButtonState()
  }

  checkButtonState(): void {
    this.isButtonDisabled = this.flightType === 'return flight'
      && new Date(this.startDate) > new Date(this.endDate)
  }

  bookFlight(): void {
    let message = `You have booked a ${this.flightType} on ${this.startDate}.`
    if (this.flightType === 'return flight') {
      message += ` Return on ${this.endDate}.`
    }
    alert(message)
  }

  template(): ReturnType<typeof html> {
    return html`
      <select .value=${this.flightType} @change=${(event: Event) => this.updateFlightType(event)}>
        <option>one-way flight</option>
        <option>return flight</option>
      </select>
      <input type="date" .value=${this.startDate} @input=${(event: InputEvent) => this.updateStartDate(event)}>
      <input type="date" .value=${this.endDate} @input=${(event: InputEvent) => this.updateEndDate(event)} ?disabled=${this.flightType === 'one-way flight'}>
      <button @click=${() => this.bookFlight()} ?disabled=${this.isButtonDisabled}>Book</button>
    `
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'flight-booker': FlightBookerElement
  }
}

customElements.define('flight-booker', FlightBookerElement)