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)