Skip to content

Commit

Permalink
it works? just like that?
Browse files Browse the repository at this point in the history
  • Loading branch information
HerrLevin committed Jan 15, 2025
1 parent f8cc403 commit 1f61f1a
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 27 deletions.
44 changes: 23 additions & 21 deletions resources/vue/components/Checkin/AutocompleteListEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,35 @@ import {defineComponent} from 'vue'
import {ShortStation} from "../../../types/Station";
export default defineComponent({
name: "AutocompleteListEntry",
props: {
station: {
type: Object () as ShortStation,
required: false
},
text: {
type: String,
required: false
},
prefix: {
type: String,
required: false
}
name: "AutocompleteListEntry",
props: {
station: {
type: Object() as ShortStation,
required: false
},
text: {
type: String,
required: false
},
prefix: {
type: String,
required: false
}
},
})
</script>

<template>
<li class="list-group-item autocomplete-item">
<a href="#" class="text-trwl">
<i v-show="prefix" :class="prefix"></i>
{{ station?.name || text }} <span v-if="station?.rilIdentifier">({{ station.rilIdentifier }})</span>
</a>
</li>
<li class="list-group-item autocomplete-item">
<a href="#" class="text-trwl">
<i v-show="prefix" :class="prefix"></i>
{{ station?.name || text }} <span v-if="station?.rilIdentifier">({{ station.rilIdentifier }})</span>
</a>
</li>
</template>

<style scoped lang="scss">
.autocomplete-item {
background-color: var(--mdb-modal-bg) !important;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,6 @@ export default {
</template>

<style lang="scss" scoped>
.autocomplete-item {
background-color: var(--mdb-modal-bg) !important;
}
.slide-fade-leave-active,
.slide-fade-enter-active {
transition: all 0.3s ease-out;
Expand Down
221 changes: 221 additions & 0 deletions resources/vue/components/TripCreation/StationInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
<script>
import FullScreenModal from "../FullScreenModal.vue";
import _ from "lodash";
import {trans} from "laravel-vue-i18n";
import AutocompleteListEntry from "../Checkin/AutocompleteListEntry.vue";
import {DateTime} from "luxon";
export default {
name: "StationInput",
components: {AutocompleteListEntry, FullScreenModal},
props: {
placeholder: {
type: String,
},
arrival: {
type: Boolean,
default: true
},
departure: {
type: Boolean,
default: true
}
},
emits: ['update:station', 'update:timeFieldA', 'update:timeFieldB', 'delete'],
data() {
return {
timeFieldA: "--:--",
timeFieldB: "--:--",
station: null,
stationInput: "",
loading: false,
autocompleteList: [],
recent: [],
id: "",
pauseAutoComplete: false
};
},
computed: {
timeFieldALabel() {
if (this.arrival && this.departure) {
return trans("trip_creation.form.arrival");
}
return this.arrival ? trans("trip_creation.form.arrival") : trans("trip_creation.form.departure");
},
timeFieldBLabel() {
if (this.arrival && this.departure) {
return trans("trip_creation.form.departure");
}
return this.arrival ? trans("trip_creation.form.arrival") : trans("trip_creation.form.departure");
},
timeFieldAId() {
return "timeFieldA" + this.id;
},
timeFieldBId() {
return "timeFieldB" + this.id;
},
},
methods: {
formatTime(time) {
let object = DateTime.fromISO(time);
if (object.isValid) {
return object.toFormat("HH:mm");
}
return "--:--";
},
showModal() {
this.$refs.modal.show();
// delay focus to make sure the modal is shown
setTimeout(() => {
this.$refs.stationInputField.focus();
}, 100);
},
setStation(item) {
this.stationInput = item.name;
this.$emit('update:station', item);
this.autocompleteList = [];
this.pauseAutoComplete = true;
//this.$refs.modal.hide();
},
timeFieldAChanged(event) {
this.$emit('update:timeFieldA', event.target.value)
this.timeFieldA = this.formatTime(event.target.value);
},
timeFieldBChanged(event) {
this.$emit('update:timeFieldB', event.target.value)
this.timeFieldB = this.formatTime(event.target.value);
},
getRecent() {
fetch(`/api/v1/trains/station/history`).then((response) => {
response.json().then((result) => {
this.recent = result.data;
});
});
},
autocomplete() {
if (this.pauseAutoComplete) {
this.pauseAutoComplete = false;
return;
}
this.loading = true;
if (!this.stationInput || this.stationInput.length < 3) {
this.autocompleteList = [];
this.loading = false;
return;
}
let query = this.stationInput.replace(/%2F/, ' ').replace(/\//, ' ');
fetch(`/api/v1/stations/?query=${query}`).then((response) => {
response.json().then((result) => {
this.autocompleteList = result.data;
this.loading = false;
});
});
}
},
mounted() {
// I hate it, it's extremely ugly, but it works
// see https://github.com/vuejs/vue/issues/5886
// There is a plugin for this, but it's not worth it with only one component
this.id = Math.random().toString().substring(2);
this.getRecent();
},
watch: {
stationInput: _.debounce(function () {
this.autocomplete();
}, 500),
},
};
</script>

<template>
<FullScreenModal ref="modal">
<template #header>
<h5>{{ placeholder }}</h5>
</template>
<template #body>
<input v-model="stationInput"
:placeholder="placeholder"
class="form-control mobile-input-fs-16"
name="station"
type="text"
ref="stationInputField"
/>
<ul class="list-group list-group-light list-group-small mb-2">
<AutocompleteListEntry
v-for="item in recent"
v-show="stationInput.length <= 0"
:station="item"
@click="setStation(item)"
/>
<AutocompleteListEntry
v-for="item in autocompleteList"
:station="item"
@click="setStation(item)"
/>
</ul>


<!-- Time Fields -->
<div class="row g-3 align-items-center justify-content-between mt-2" v-if="departure && arrival">
<div class="col-auto">
<label :for="timeFieldAId" class="col-form-label">{{ timeFieldALabel }}</label>
</div>
<div class="col-auto">
<input
:id="timeFieldAId"
:aria-label="timeFieldALabel"
:placeholder="timeFieldALabel"
class="form-control mobile-input-fs-16"
type="datetime-local"
@input="timeFieldAChanged"
>
</div>
</div>

<div class="row g-3 align-items-center justify-content-between mt-2">
<div class="col-auto">
<label :for="timeFieldBId" class="form-label">{{ timeFieldBLabel }}</label>
</div>
<div class="col-auto">
<input
:id="timeFieldBId"
:aria-label="timeFieldBLabel"
:placeholder="timeFieldBLabel"
class="form-control mobile-input-fs-16"
type="datetime-local"
@input="timeFieldBChanged"
>
</div>
</div>
</template>
</FullScreenModal>

<!-- Station Input -->
<div class="input-group">
<input type="text" class="form-control mb-2" :placeholder="placeholder"
:aria-label="placeholder" aria-describedby="basic-addon1"
v-model="stationInput" @focusin="showModal"
>
<span class="input-group-text font-monospace">
{{ this.timeFieldB }}
</span>
<span class="input-group-text font-monospace" v-if="departure && arrival">
{{ this.timeFieldA }}
</span>
<button class="btn btn-sm btn-outline-danger input-group-button py-1" type="button" @click="$emit('delete')">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</template>

<style>
.autocomplete-item {
background-color: var(--mdb-modal-bg) !important;
}
.input-group-button {
height: calc(2.08rem + 2px);
}
</style>
50 changes: 48 additions & 2 deletions resources/vue/components/TripCreation/TripCreationPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import StationRow from "./StationRow.vue";
import {DateTime} from "luxon";
import {trans} from "laravel-vue-i18n";
import StationInput from "./StationInput.vue";
export default {
name: "TripCreationForm",
components: {StationRow},
components: {StationInput, StationRow},
mounted() {
this.initForm();
this.loadOperators();
Expand Down Expand Up @@ -213,7 +214,7 @@ export default {
</script>

<template>
<div class="row full-height mt-n4">
<div class="row full-height mt-n4 mx-0">
<div class="col col-md-5 col-lg-4 col-xl-3 p-0 h-100">
<div class="accordion accordion-flush border-bottom" id="TripCreationMetaDataAccordion">
<div class="accordion-item">
Expand Down Expand Up @@ -314,6 +315,51 @@ export default {
</div>
</div>
</div>

<form @submit.prevent="sendForm" class="px-4 mt-4">
<StationInput
:placeholder="trans('trip_creation.form.origin')"
:arrival="false"
v-on:update:station="setOrigin"
v-on:update:timeFieldB="setDeparture"
></StationInput>

<div class="row g-3 mt-1" v-for="(stopover, key) in stopovers" :key="key">
<div class="d-flex align-items-center w-100">
<div class="flex-grow-1 d-flex">
<StationInput
:placeholder="trans('trip_creation.form.stopover')"
v-on:update:station="setStopoverStation($event, key)"
v-on:update:timeFieldB="setStopoverDeparture($event, key)"
v-on:update:timeFieldA="setStopoverArrival($event, key)"
v-on:delete="removeStopover(key)"
></StationInput>
</div>
</div>
</div>

<div class="mb-2 px-3">
<a href="#" @click="addStopover">{{ trans("trip_creation.form.add_stopover") }}
<i class="fa fa-plus" aria-hidden="true"></i>
</a>
</div>

<StationInput
:placeholder="trans('trip_creation.form.destination')"
:arrival="true"
:departure="false"
v-on:update:station="setDestination"
v-on:update:timeFieldB="setArrival"
></StationInput>

<div class="mt-4 border-top pt-4 d-flex justify-content-end">
<button type="submit" class="btn btn-primary">
{{ trans("trip_creation.form.save") }}
</button>
</div>

</form>

</div>
<div class="col d-none d-md-block bg-warning">
col 2
Expand Down

0 comments on commit 1f61f1a

Please sign in to comment.