69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
import Component from "vue-class-component";
|
|
import Vue from "vue";
|
|
import { Stop, StopGroup, StopGroups } from "../model";
|
|
import { Prop, Watch } from "vue-property-decorator";
|
|
import { ensureArray, FetchingState, filter, map } from "../utils";
|
|
import { debounce } from "../decorators";
|
|
import urls from '../urls';
|
|
|
|
@Component({ template: require("../../components/picker.html") })
|
|
export class PickerComponent extends Vue {
|
|
@Prop({ default: () => [], type: Array })
|
|
protected stops?: Stop[];
|
|
|
|
private remove(stop: Stop) {
|
|
this.$emit('update:stops', this.stops.filter(s => s != stop));
|
|
}
|
|
|
|
private add(stop: Stop|Stop[]) {
|
|
this.$emit('update:stops', [...this.stops, ...ensureArray(stop)]);
|
|
}
|
|
}
|
|
|
|
@Component({ template: require('../../components/finder.html') })
|
|
export class FinderComponent extends Vue {
|
|
protected found?: StopGroups = {};
|
|
|
|
public state: FetchingState = 'ready';
|
|
public filter: string = "";
|
|
|
|
@Prop({default: [], type: Array})
|
|
public blacklist: Stop[];
|
|
|
|
get filtered(): StopGroups {
|
|
const groups = map(
|
|
this.found,
|
|
(group: StopGroup, name: string) =>
|
|
group.filter(stop => !this.blacklist.some(blacklisted => blacklisted.id == stop.id))
|
|
) as StopGroups;
|
|
|
|
return filter(groups, group => group.length > 0);
|
|
}
|
|
|
|
@Watch('filter')
|
|
@debounce(400)
|
|
async fetch() {
|
|
if (this.filter.length < 3) {
|
|
return;
|
|
}
|
|
|
|
this.state = 'fetching';
|
|
|
|
const response = await fetch(urls.prepare(urls.stops.search, { name: this.filter }));
|
|
|
|
if (response.ok) {
|
|
this.found = await response.json();
|
|
this.state = 'ready';
|
|
} else {
|
|
this.state = 'error';
|
|
}
|
|
}
|
|
|
|
private select(stop) {
|
|
this.$emit('select', stop);
|
|
}
|
|
}
|
|
|
|
Vue.component('StopPicker', PickerComponent);
|
|
Vue.component('StopFinder', FinderComponent);
|