22 <v-scroll-x-reverse-transition >
33 <v-card class =" polar-routing-menu" >
44 <v-card-title >{{ $t('common:plugins.routing.title') }} </v-card-title >
5- <v-text-field
6- v-model =" startpointInput"
7- :label =" $t('common:plugins.routing.startLabel')"
8- :hint =" $t('common:plugins.routing.inputHint')"
9- persistent-hint
10- @input =" sendSearchRequest"
11- >
12- </v-text-field >
13- <v-text-field
14- v-model =" endpointInput"
15- :label =" $t('common:plugins.routing.endLabel')"
16- >
17- </v-text-field >
18- <v-btn @click =" resetCoordinates"
19- >{{ $t('common:plugins.routing.resetButton') }}
5+
6+ <!-- Start Point Input with Dropdown -->
7+ <div style =" position : relative " >
8+ <v-text-field
9+ v-model =" startpointInput"
10+ :label =" $t('common:plugins.routing.startLabel')"
11+ @input =" handleAddressSearch('start')"
12+ ></v-text-field >
13+ <v-list
14+ v-if =" startSearchResults.length && startDropdownOpen"
15+ class =" dropdown"
16+ >
17+ <v-list-item
18+ v-for =" (result, index) in startSearchResults"
19+ :key =" index"
20+ @click =" selectStart(result)"
21+ >
22+ <span >
23+ {{ result.strassenname }}
24+ <template v-if =" result .hausnummer " >
25+ {{ result.hausnummer }}</template
26+ >
27+ </span >
28+ </v-list-item >
29+ </v-list >
30+ </div >
31+
32+ <div style =" position : relative " >
33+ <v-text-field
34+ v-model =" endpointInput"
35+ :label =" $t('common:plugins.routing.endLabel')"
36+ @input =" handleAddressSearch('end')"
37+ ></v-text-field >
38+ <v-list
39+ v-if =" endSearchResults.length && endDropdownOpen"
40+ class =" dropdown"
41+ >
42+ <v-list-item
43+ v-for =" (result, index) in endSearchResults"
44+ :key =" index"
45+ @click =" selectEnd(result)"
46+ >
47+ <span >
48+ {{ result.strassenname }}
49+ <template v-if =" result .hausnummer " >
50+ {{ result.hausnummer }}</template
51+ >
52+ </span >
53+ </v-list-item >
54+ </v-list >
55+ </div >
56+
57+ <v-btn @click =" resetCoordinates" >
58+ {{ $t('common:plugins.routing.resetButton') }}
2059 </v-btn >
60+
2161 <v-select
2262 v-model =" selectedTravelModeItem"
2363 clearable
3474 item-value =" key"
3575 item-text =" translatedKey"
3676 ></v-select >
77+
3778 <div >
3879 {{ $t('common:plugins.routing.avoidRoutesTitle') }}
3980 <v-layout row wrap >
4889 </v-flex >
4990 </v-layout >
5091 </div >
92+
5193 <v-btn @click =" sendRequest" >Send Request</v-btn >
5294 <v-btn @click =" showSteps = !showSteps" >
5395 {{ $t('common:plugins.routing.routeDetails') }}
5496 </v-btn >
97+
5598 <div v-if =" showSteps" >
5699 <v-list v-for =" (step, i) in searchResponseSegments" :key =" i" >
57100 {{ step }}
64107<script lang="ts">
65108import Vue from ' vue'
66109import { mapGetters , mapActions , mapMutations } from ' vuex'
110+ import debounce from ' lodash.debounce'
67111
68112export default Vue .extend ({
69113 name: ' RoutingPlugin' ,
70114 data : () => ({
71- isOpen: false ,
72- // TODO: wieder rausnhemen, wenn es nicht funktioniert
73- inline: null ,
74115 showSteps: false ,
116+ startDropdownOpen: false ,
117+ endDropdownOpen: false ,
75118 }),
76119 computed: {
77- ... mapGetters ([' hasSmallDisplay' ]),
78120 ... mapGetters (' plugin/routing' , [
79- ' renderType' ,
80- ' travelModeOptionsFromMapConfig' ,
81- ' preferenceOptionsFromMapConfig' ,
82121 ' selectableTravelModes' ,
83122 ' selectablePreferences' ,
84123 ' selectableRouteTypesToAvoid' ,
85124 ' selectedRouteTypesToAvoid' ,
86- ' searchResponseData ' ,
125+ ' searchResults ' ,
87126 ' start' ,
88127 ' end' ,
128+ ' startAddress' ,
129+ ' endAddress' ,
130+ ' waitMs' ,
89131 ]),
90132 startpointInput: {
91- get(): Coordinate {
92- return this .start
133+ get() {
134+ return this .startAddress ? this . startAddress : this . start
93135 },
94- set(value : Coordinate ): void {
95- this .start (value )
136+ set(value ) {
137+ console .error (' Setting startpointInput to:' , value )
138+ this .setStart (value )
96139 },
97140 },
98141 endpointInput: {
99- get(): Coordinate {
100- return this .end
142+ get() {
143+ return this .endAddress ? this . endAddress : this . end
101144 },
102- set(value : Coordinate ) : void {
103- this .end (value )
145+ set(value ) {
146+ this .setEnd (value )
104147 },
105148 },
149+ startSearchResults() {
150+ return this .searchResults
151+ .flatMap ((result ) => {
152+ const baseName = result .strassenname
153+ if (result .hausnummern && result .hausnummern .length > 0 ) {
154+ return result .hausnummern .map ((hausnummer ) => ({
155+ displayName: ` ${baseName } ${hausnummer } ` ,
156+ ... result ,
157+ hausnummer ,
158+ }))
159+ }
160+ return [{ displayName: baseName , ... result }]
161+ })
162+ .slice (0 , 20 )
163+ },
164+ endSearchResults() {
165+ return this .searchResults
166+ .flatMap ((result ) => {
167+ const baseName = result .strassenname
168+ if (result .hausnummern && result .hausnummern .length > 0 ) {
169+ return result .hausnummern .map ((hausnummer ) => ({
170+ displayName: ` ${baseName } ${hausnummer } ` ,
171+ ... result ,
172+ hausnummer ,
173+ }))
174+ }
175+ return [{ displayName: baseName , ... result }]
176+ })
177+ .slice (0 , 20 )
178+ },
179+
106180 selectedTravelModeItem: {
107- get(): string {
181+ get() {
108182 return this .selectedTravelMode
109183 },
110- set(value : string ) : void {
184+ set(value ) {
111185 this .setSelectedTravelMode (value )
112186 },
113187 },
114188 selectedPreferenceItem: {
115- get(): string {
189+ get() {
116190 return this .selectedPreference
117191 },
118- set(value : string ) : void {
192+ set(value ) {
119193 this .setSelectedPreference (value )
120194 },
121195 },
@@ -132,47 +206,98 @@ export default Vue.extend({
132206 }))
133207 },
134208 selectedRouteTypesToAvoidItem: {
135- get(): string {
209+ get() {
136210 return this .selectedRouteTypesToAvoid
137211 },
138- set(value : string ) : void {
212+ set(value ) {
139213 this .setSelectedRouteTypesToAvoid (value )
140214 },
141215 },
142- searchResponseSegments: {
143- get(): object {
144- return this .searchResponseData ?.features [0 ].properties .segments [0 ].steps
145- },
146- },
147- },
148- watch: {
149- search : function () {
150- // TODO: prüfen, ob die Koordinaten im richtigen Format sind
151- // TODO: Koordinaten an den Routingdienst übermitteln mit sendRequest() - zu vermeidende Routentypen mitsenden
152- this .sendRequest ()
216+ searchResponseSegments() {
217+ return this .searchResponseData ?.features [0 ].properties .segments [0 ].steps
153218 },
154219 },
155220 mounted() {
156221 this .initializeTool ()
157222 },
158223 methods: {
159224 ... mapActions (' plugin/routing' , [
225+ ' sendSearchRequest' ,
160226 ' initializeTool' ,
161- ' resetCoordinates' ,
162227 ' sendRequest' ,
163- ' sendSearchRequest' ,
164228 ]),
165229 ... mapMutations (' plugin/routing' , [
230+ ' setStart' ,
231+ ' setEnd' ,
166232 ' setSelectedTravelMode' ,
167233 ' setSelectedPreference' ,
168234 ' setSelectedRouteTypesToAvoid' ,
169- ' setSearchResponseData' ,
235+ ' setStartAddress' ,
236+ ' setEndAddress' ,
170237 ]),
171- translatedRouteTypeToAvoid(myKey ) {
172- const localKey = this .selectableRouteTypesToAvoid .find (
173- (element ) => element .key === myKey
174- ).localKey
175- return localKey
238+ debouncedSendSearchRequest: debounce (function (payload ) {
239+ this .sendSearchRequest (payload )
240+ }, 300 ),
241+ handleAddressSearch(type ) {
242+ const input = type === ' start' ? this .startpointInput : this .endpointInput
243+
244+ if (type === ' start' ) {
245+ this .startDropdownOpen = true
246+ this .endDropdownOpen = false
247+ } else if (type === ' end' ) {
248+ this .startDropdownOpen = false
249+ this .endDropdownOpen = true
250+ }
251+
252+ this .debouncedSendSearchRequest ({ input , type })
253+ },
254+ toggleDropdown(type ) {
255+ if (type === ' start' ) {
256+ this .startDropdownOpen = true
257+ this .endDropdownOpen = false
258+ } else if (type === ' end' ) {
259+ this .startDropdownOpen = false
260+ this .endDropdownOpen = true
261+ }
262+ },
263+ resetCoordinates() {
264+ this .setStart (null )
265+ this .setEnd (null )
266+ this .setStartAddress (null )
267+ this .setEndAddress (null )
268+ },
269+ selectStart(result ) {
270+ if (result .strassenname ) {
271+ this .startpointInput = result .displayName
272+ this .setStart (result .position )
273+ this .setStartAddress (result .displayName )
274+ this .startDropdownOpen = false
275+ this .$nextTick (() => {
276+ this .$store .commit (' plugin/routing/setSearchResults' , [])
277+ })
278+ } else {
279+ console .error (' No street name available for selected result:' , result )
280+ }
281+ },
282+ selectEnd(result ) {
283+ if (result .strassenname ) {
284+ this .endpointInput = result .displayName
285+ this .setEnd (result .position )
286+ this .setEndAddress (result .displayName )
287+ this .endDropdownOpen = false
288+ this .$nextTick (() => {
289+ this .$store .commit (' plugin/routing/setSearchResults' , [])
290+ })
291+ } else {
292+ console .error (' No street name available for selected result:' , result )
293+ }
294+ },
295+
296+ translatedRouteTypeToAvoid(key ) {
297+ const routeType = this .selectableRouteTypesToAvoid .find (
298+ (type ) => type .key === key
299+ )
300+ return routeType ? this .$t (routeType .localKey ) : key
176301 },
177302 },
178303})
@@ -188,4 +313,11 @@ export default Vue.extend({
188313 padding-left : 20px ;
189314 padding-right : 20px ;
190315}
316+
317+ .dropdown {
318+ max-height : 300px ; /* Passt die Höhe an */
319+ overflow-y : auto ; /* Ermöglicht Scrollen */
320+ border : 1px solid #ccc ;
321+ background-color : #fff ;
322+ }
191323 </style >
0 commit comments