czydojade/resources/ts/components/picker.ts
2018-09-17 22:46:02 +02:00

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);