From e49a70c71aaa564468cbfdf3234d50bf21779a26 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Fri, 24 Jan 2020 21:52:13 +0100 Subject: [PATCH] Exctract trip to separate component --- package.json | 1 + .../components/departures/departure.html | 11 +----- resources/components/trip.html | 13 +++++++ resources/styles/_dragscroll.scss | 6 +++ resources/styles/_trip.scss | 38 ++++++++++++------- resources/styles/main.scss | 11 ++++++ resources/ts/app.ts | 2 + resources/ts/components/departures.ts | 29 +++++++++++++- resources/ts/components/index.ts | 1 + resources/ts/components/trip.ts | 11 ++++++ resources/ts/model/stop.ts | 5 ++- resources/ts/store/departures.ts | 14 +++---- resources/ts/utils.ts | 10 +++-- src/Provider/ScheduleRepository.php | 2 +- .../ZtmGdanskDepartureRepository.php | 4 +- yarn.lock | 5 +++ 16 files changed, 125 insertions(+), 38 deletions(-) create mode 100644 resources/components/trip.html create mode 100644 resources/styles/_dragscroll.scss create mode 100644 resources/ts/components/trip.ts diff --git a/package.json b/package.json index 4ecf3e5..6adb7ec 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "imagemin-webpack-plugin": "^2.3.0", "mini-css-extract-plugin": "^0.4.2", "portal-vue": "^2.1.7", + "vue-dragscroll": "^1.10.2", "vue2-leaflet": "^1.0.2", "vuex": "^3.0.1", "vuex-class": "^0.3.1", diff --git a/resources/components/departures/departure.html b/resources/components/departures/departure.html index 50c58d9..7af6a51 100644 --- a/resources/components/departures/departure.html +++ b/resources/components/departures/departure.html @@ -34,16 +34,7 @@ -
-
    -
  1. -
    -
    - -
    -
  2. -
-
+
diff --git a/resources/components/trip.html b/resources/components/trip.html new file mode 100644 index 0000000..f8a4c71 --- /dev/null +++ b/resources/components/trip.html @@ -0,0 +1,13 @@ +
+
    +
  1. +
    +
    + +
    +
    + {{ stop.departure.format('HH:mm') }} +
    +
  2. +
+
diff --git a/resources/styles/_dragscroll.scss b/resources/styles/_dragscroll.scss new file mode 100644 index 0000000..a3acc93 --- /dev/null +++ b/resources/styles/_dragscroll.scss @@ -0,0 +1,6 @@ +.drag-scroll { + cursor : grab; + &:active { + cursor : grabbing; + } +} diff --git a/resources/styles/_trip.scss b/resources/styles/_trip.scss index 10729ff..505d725 100644 --- a/resources/styles/_trip.scss +++ b/resources/styles/_trip.scss @@ -4,7 +4,8 @@ $description-rotation: 60deg; $description-width: 250px; $trip-stop-marker-size: .9rem; -$trip-stop-line-width: .2rem; +$trip-stop-marker-spacing: .75rem; +$trip-line-width: .2rem; .trip { display: flex; @@ -18,45 +19,49 @@ $trip-stop-line-width: .2rem; display: flex; list-style: none; overflow-x: auto; + + @include no-scrollbars; + @extend .drag-scroll; } -.trip-stop { +.trip__stop { width: 2.5rem; position: relative; flex-shrink: 0; display: flex; align-items: center; justify-content: center; + flex-direction: column; } -.trip-stop:first-child { - .trip-stop__marker::before { +.trip__stop:first-child { + .trip__marker::before { content: none; } } -.trip-stop:last-child { - .trip-stop__marker::after { +.trip__stop:last-child { + .trip__marker::after { content: none; } } -.trip-stop__marker { +.trip__marker { width: $trip-stop-marker-size; height: $trip-stop-marker-size; - border: $dark $trip-stop-line-width solid; + border: $dark $trip-line-width solid; border-radius: 100%; background: white; - margin: .75rem 0; + margin: $trip-stop-marker-spacing 0; &::before, &::after { content: ""; display: block; - height: $trip-stop-line-width; + height: $trip-line-width; background: $dark; width: 50%; position: absolute; - top: 50%; + top: $trip-stop-marker-spacing + ($trip-stop-marker-size) / 2; transform: translateY(-50%); z-index: -1; } @@ -72,7 +77,7 @@ $trip-stop-line-width: .2rem; @each $type, $color in $line-types { .trip--#{$type} { - .trip-stop__marker { + .trip__marker { border-color: $color; &::before, &::after { @@ -82,7 +87,7 @@ $trip-stop-line-width: .2rem; } } -.trip-stop__description { +.trip__description { display: flex; transform: rotate(-$description-rotation) translateX(.75rem); transform-origin: 0 50%; @@ -95,3 +100,10 @@ $trip-stop-line-width: .2rem; width: max-content; } } + + +.trip__departure { + font-size: $small-font-size; + font-weight: bold; + margin-bottom: .5rem; +} diff --git a/resources/styles/main.scss b/resources/styles/main.scss index 956b9b8..9d185cd 100644 --- a/resources/styles/main.scss +++ b/resources/styles/main.scss @@ -42,6 +42,16 @@ $grid-gutter-width: $spacer * 2; } } +@mixin no-scrollbars { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* Internet Explorer 10+ */ + + &::-webkit-scrollbar { /* WebKit */ + width: 0; + height: 0; + } +} + @import "common"; @import "stop"; @import "departure"; @@ -52,6 +62,7 @@ $grid-gutter-width: $spacer * 2; @import "form"; @import "fabourites"; @import "trip"; +@import "dragscroll"; body { min-height: 100vh; diff --git a/resources/ts/app.ts b/resources/ts/app.ts index bb4087c..d845656 100644 --- a/resources/ts/app.ts +++ b/resources/ts/app.ts @@ -14,10 +14,12 @@ window['Popper'] = Popper; import Vue from "vue"; import Vuex from 'vuex'; import PortalVue from 'portal-vue'; +import VueDragscroll from 'vue-dragscroll'; import { Workbox } from "workbox-window"; Vue.use(Vuex); Vue.use(PortalVue); +Vue.use(VueDragscroll); // async dependencies (async function () { diff --git a/resources/ts/components/departures.ts b/resources/ts/components/departures.ts index 6b43d76..7668877 100644 --- a/resources/ts/components/departures.ts +++ b/resources/ts/components/departures.ts @@ -5,6 +5,8 @@ import { namespace } from 'vuex-class'; import store from '../store' import { Trip } from "../model/trip"; import urls from "../urls"; +import { Jsonified } from "../utils"; +import * as moment from "moment"; const { State } = namespace('departures'); @@ -19,9 +21,20 @@ export class DeparturesComponent extends Vue { @Component({ template: require("../../components/departures/departure.html") }) export class DepartureComponent extends Vue { @Prop(Object) departure: Departure; + scheduledTrip: Trip = null; showTrip: boolean = false; - trip: Trip = null; + + processTrip(trip: Jsonified): Trip { + return { + ...trip, + schedule: trip.schedule.map(s => ({ + ...s, + arrival: moment.parseZone(s.arrival), + departure: moment.parseZone(s.departure), + })) + }; + }; get timeDiffers() { const departure = this.departure; @@ -42,9 +55,21 @@ export class DepartureComponent extends Vue { const response = await fetch(urls.prepare(urls.trip, { id: this.departure.trip.id })); if (response.ok) { - this.trip = await response.json(); + this.scheduledTrip = this.processTrip(await response.json()); } } + + get trip() { + const trip = this.scheduledTrip; + return trip && { + ...trip, + schedule: trip.schedule.map(stop => ({ + ...stop, + arrival: stop.arrival.clone().add(this.departure.delay, 'seconds'), + departure: stop.departure.clone().add(this.departure.delay, 'seconds'), + })) + }; + } } Vue.component('Departures', DeparturesComponent); diff --git a/resources/ts/components/index.ts b/resources/ts/components/index.ts index c7258d3..cc580e7 100644 --- a/resources/ts/components/index.ts +++ b/resources/ts/components/index.ts @@ -7,3 +7,4 @@ export * from './messages' export * from './map' export * from './app' export * from './favourites' +export * from './trip' diff --git a/resources/ts/components/trip.ts b/resources/ts/components/trip.ts new file mode 100644 index 0000000..3575d9e --- /dev/null +++ b/resources/ts/components/trip.ts @@ -0,0 +1,11 @@ +import Vue from "vue"; +import Component from "vue-class-component"; +import { Prop } from "vue-property-decorator"; +import { ScheduledStop } from "../model/trip"; + +@Component({ template: require("../../components/trip.html") }) +export class TripComponent extends Vue { + @Prop(Array) public schedule: ScheduledStop[]; +} + +Vue.component('Trip', TripComponent); diff --git a/resources/ts/model/stop.ts b/resources/ts/model/stop.ts index 415acd3..ebb3bfb 100644 --- a/resources/ts/model/stop.ts +++ b/resources/ts/model/stop.ts @@ -2,7 +2,10 @@ export interface Stop { id: any; name: string; description?: string; - location?: [ number, number ]; + location?: { + lat: number, + lng: number, + }; onDemand?: boolean; variant?: string; } diff --git a/resources/ts/store/departures.ts b/resources/ts/store/departures.ts index 8878c10..220ac06 100644 --- a/resources/ts/store/departures.ts +++ b/resources/ts/store/departures.ts @@ -1,6 +1,6 @@ import { Module } from "vuex"; import { RootState } from "./root"; -import { Departure, Stop } from "../model"; +import { Departure, Line, Stop } from "../model"; import * as moment from 'moment' import common, { CommonState } from './common' import urls from "../urls"; @@ -43,12 +43,12 @@ export const departures: Module = { } const departures = await response.json() as Jsonified[]; - commit('update', departures.map(departure => { - departure.scheduled = moment.parseZone(departure.scheduled); - departure.estimated = departure.estimated && moment.parseZone(departure.estimated); - - return departure as Departure; - })); + commit('update', departures.map((departure): Departure => ({ + ...departure, + line: departure.line as Line, + scheduled: moment.parseZone(departure.scheduled), + estimated: departure.estimated && moment.parseZone(departure.estimated), + }))); } } }; diff --git a/resources/ts/utils.ts b/resources/ts/utils.ts index 010c6d7..0fcbb68 100644 --- a/resources/ts/utils.ts +++ b/resources/ts/utils.ts @@ -1,9 +1,13 @@ -type Simplify = string | +import { Moment } from "moment"; + +type Simplify = string | T extends string ? string : T extends number ? number : T extends boolean ? boolean : - T extends Array ? Array : - T extends Object ? Object : any; + T extends Moment ? string : + T extends Array ? Array> : + T extends (infer K)[] ? Simplify[] : + T extends Object ? Jsonified : any; export type Jsonified = { [K in keyof T]: Simplify } export type Optionalify = { [K in keyof T]?: T[K] } diff --git a/src/Provider/ScheduleRepository.php b/src/Provider/ScheduleRepository.php index 554d9e5..951a20f 100644 --- a/src/Provider/ScheduleRepository.php +++ b/src/Provider/ScheduleRepository.php @@ -8,7 +8,7 @@ use Tightenco\Collect\Support\Collection; interface ScheduleRepository { - const DEFAULT_DEPARTURES_COUNT = 8; + const DEFAULT_DEPARTURES_COUNT = 16; public function getDeparturesForStop( Stop $stop, diff --git a/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php b/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php index ba01778..0e956bd 100644 --- a/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php +++ b/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php @@ -46,7 +46,9 @@ class ZtmGdanskDepartureRepository implements DepartureRepository $first = $real->map(t\getter('scheduled'))->min() ?? $now; $scheduled = $this->getScheduledDepartures($stop, $first); - return $this->pair($scheduled, $real); + return $this->pair($scheduled, $real)->filter(function (Departure $departure) use ($now) { + return $departure->getDeparture() > $now; + }); } private function getRealDepartures(Stop $stop) diff --git a/yarn.lock b/yarn.lock index 5d6839c..50bab86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6197,6 +6197,11 @@ vue-class-component@^6.2.0: resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-6.3.2.tgz#e6037e84d1df2af3bde4f455e50ca1b9eec02be6" integrity sha512-cH208IoM+jgZyEf/g7mnFyofwPDJTM/QvBNhYMjqGB8fCsRyTf68rH2ISw/G20tJv+5mIThQ3upKwoL4jLTr1A== +vue-dragscroll@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/vue-dragscroll/-/vue-dragscroll-1.10.2.tgz#34ace3c6aa7a39edc157cac5e9ea1d5b31b1119c" + integrity sha512-fGVw8KP3ggbp49csa1Tbj2my0YuNmZ1zxYYge4QWIypGNHVwd9hResy/v6QF5HxY0a+qd2EBteeBpxtJxFMp5A== + vue-property-decorator@^7.0.0: version "7.3.0" resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-7.3.0.tgz#d50d67f0b0f1c814f9f2fba36d6eeccbcc62dbb6"