App

Bundles

Stats
BundleMinifiedGzipBrotli
index.js53.9 kB21.1 kB19.2 kB

Source

<template>
	<div class="form-group" v-bind:class="{ 'has-error': errorMsg }">
		<label class="form-label" v-bind:for="label + '-date'">{{ label }}</label
		><input
			v-bind:id="label + '-date'"
			class="form-input"
			type="text"
			v-bind:value="date"
			v-on:input="e => onSetDate(e.target.value)"
			v-bind:disabled="disabled || false"
		/>
		<p v-if="errorMsg" class="form-input-hint">{{ errorMsg }}</p>
	</div>
</template>

<script>
export default {
	props: ["errorMsg", "label", "date", "disabled", "onSetDate"]
};
</script>
<template>
	<TripType v-on:setTripType="newTripType => (tripType = newTripType)" />

	<DateEntry
		label="Departing"
		v-bind:date="departing"
		v-bind:errorMsg="departingError"
		v-on:setDate="newDate => (departing = newDate)"
	/>

	<DateEntry
		label="Returning"
		v-bind:date="returning"
		v-bind:errorMsg="returningError"
		v-on:setDate="newDate => (returning = newDate)"
		v-bind:disabled="tripType == oneWayFlight"
	/>

	<div class="form-group">
		<button
			class="btn btn-primary"
			v-on:click="bookFlight"
			v-bind:disabled="isBookDisabled"
		>
			book
		</button>
	</div>
</template>

<script>
import { today, validateDate } from "../../../../lib/date";
import TripType from "./TripType.vue";
import DateEntry from "./DateEntry.vue";

const oneWayFlight = "one-way";
const returnFlight = "return";

function getErrorMessage(date) {
	try {
		validateDate(date);
		return null;
	} catch (error) {
		return error.message;
	}
}

export default {
	components: { TripType, DateEntry },
	data() {
		let currentDate = today();

		return {
			oneWayFlight,
			returnFlight,
			tripType: oneWayFlight,
			departing: currentDate,
			returning: currentDate
		};
	},
	methods: {
		bookFlight() {
			const type = this.tripType == returnFlight ? "return" : "one-way";

			let message = `You have booked a ${type} flight, leaving ${this.departing}`;
			if (type === "return") {
				message += ` and returning ${this.returning}`;
			}

			alert(message);
		}
	},
	computed: {
		departingError() {
			return getErrorMessage(this.departing);
		},
		returningError() {
			let returningError = getErrorMessage(this.returning);
			if (
				this.departingError == null &&
				returningError == null &&
				this.tripType == returnFlight &&
				this.returning < this.departing
			) {
				returningError = "Returning date must be on or after departing date.";
			}

			return returningError;
		},
		isBookDisabled() {
			return this.departingError || this.returningError;
		}
	}
};
</script>
<template>
	<div class="form-group">
		<label class="form-label" for="trip-type">Trip type</label
		><select
			id="trip-type"
			class="form-select"
			v-on:input="e => onSetTripType(e.target.value)"
		>
			<option value="one-way">one-way flight</option>
			<option value="return">return flight</option>
		</select>
	</div>
</template>

<script>
export default {
	props: ["onSetTripType"]
};
</script>
import { createApp } from "vue";
import FlightBooker from "./FlightBooker.vue";

createApp(FlightBooker).mount("#app");