11import { ref } from "vue" ;
2- import {
3- fetchStopAreaDetails ,
4- fetchStops ,
5- type FullyDescribedStopArea ,
6- type StopArea ,
7- type StopPoint ,
8- } from "./TBM" ;
2+ import { fetchStopAreaDetails , type StopAreaDetails , type StopArea , type StopPoint } from "./TBM" ;
93import router from "@/router" ;
104import { type LocationQuery , type RouteLocationNormalized } from "vue-router" ;
115import { unique } from "." ;
126
13- const selectedStops = ref < FullyDescribedStopArea [ ] > ( [ ] ) ;
7+ const selectedStopAreas = ref < StopAreaDetails [ ] > ( [ ] ) ;
148const excludedStopPoints = ref < [ StopArea [ "id" ] , StopPoint [ "id" ] ] [ ] > ( [ ] ) ;
159
16- const stops = ref < StopArea [ ] > ( [ ] ) ;
10+ const stopAreas = ref < StopArea [ ] > ( [ ] ) ;
1711
1812let query : LocationQuery = { } ;
1913let queryInternallyUpdated = false ;
@@ -22,38 +16,41 @@ function provideQuery(q: LocationQuery) {
2216 query = { ...q } ;
2317}
2418
19+ // In ascending order
20+ function getStopAreaKeysFromQuery ( q : LocationQuery ) {
21+ return Object . keys ( q )
22+ . filter ( ( k ) => ! isNaN ( parseInt ( k ) ) )
23+ . sort ( ( a , b ) => parseInt ( a ) - parseInt ( b ) ) ;
24+ }
25+
2526async function queryUpdated ( to : RouteLocationNormalized ) {
2627 if ( queryInternallyUpdated ) {
2728 queryInternallyUpdated = false ;
2829 return ;
2930 }
3031 query = { ...to . query } ;
3132
32- for ( const k of Object . keys ( to . query )
33- . filter ( ( k ) => ! isNaN ( parseInt ( k ) ) )
34- . sort ( ( a , b ) => parseInt ( a ) - parseInt ( b ) ) ) {
35- const providenStop = to . query [ k ] as string ;
33+ const stopAreaKeys = getStopAreaKeysFromQuery ( to . query ) ;
34+ for ( const k of stopAreaKeys ) {
35+ const providedStopAreaId = to . query [ k ] as string ;
3636
37- if ( selectedStops . value . find ( ( s ) => s . name === providenStop ) ) continue ;
38- const found = ( await fetchStops ( providenStop ) ) . find ( ( s ) => s . name === providenStop ) ;
39- if ( ! found ) {
40- delete query [ k ] ;
41- queryInternallyUpdated = true ;
42- router . push ( { query } ) ;
43- continue ;
44- }
45- const fullyDescribedStopArea = await fetchStopAreaDetails ( found ) ;
46- if ( ! fullyDescribedStopArea ) {
37+ const deserializedStopAreaId = deserializeStopAreaId ( providedStopAreaId ) ;
38+ if ( selectedStopAreas . value . find ( ( sa ) => sa . id === deserializedStopAreaId ) ) continue ;
39+
40+ const StopAreaDetails = await fetchStopAreaDetails ( { id : deserializedStopAreaId } ) ;
41+ if ( ! StopAreaDetails ) {
4742 delete query [ k ] ;
4843 queryInternallyUpdated = true ;
4944 router . push ( { query } ) ;
5045 continue ;
5146 }
52- selectedStops . value = [ ...selectedStops . value , fullyDescribedStopArea ] ;
47+ selectedStopAreas . value = [ ...selectedStopAreas . value , StopAreaDetails ] ;
5348 }
5449
55- const providenStops = Object . keys ( query ) . map ( ( k ) => query [ k ] ) ;
56- selectedStops . value = selectedStops . value . filter ( ( s ) => providenStops . includes ( s . name ) ) ;
50+ selectedStopAreas . value = selectedStopAreas . value . filter ( ( sa ) => {
51+ const serializedStopAreaId = serializeStopAreaId ( sa . id ) ;
52+ return stopAreaKeys . find ( ( k ) => query [ k ] === serializedStopAreaId ) ;
53+ } ) ;
5754
5855 excludedStopPoints . value = deserializeExcludedStopPoints (
5956 typeof query [ "eSP" ] === "string" ? query [ "eSP" ] : "" ,
@@ -73,16 +70,16 @@ function deserializeExcludedStopPoints(serializedExcludedStopPoints: string) {
7370 const stopAreaName = query [ stopAreaNumber ] ;
7471 if ( ! stopAreaName ) continue ;
7572
76- const stopArea = selectedStops . value . find ( ( s ) => s . name === stopAreaName ) ;
77- if ( ! stopArea ) continue ;
73+ const StopAreaDetails = selectedStopAreas . value . find ( ( s ) => s . name === stopAreaName ) ;
74+ if ( ! StopAreaDetails ) continue ;
7875
7976 const stopPoints = stopAreaString . split ( "-" ) ;
8077
8178 for ( let i = 1 ; i < stopPoints . length ; i ++ ) {
82- const stopPoint = stopArea . details . stopPoints . find ( ( s ) => s . id . endsWith ( stopPoints [ i ] ) ) ;
79+ const stopPoint = StopAreaDetails . stopPoints . find ( ( s ) => s . id . endsWith ( stopPoints [ i ] ) ) ;
8380 if ( ! stopPoint ) continue ;
8481
85- excludedStopPoints . push ( [ stopArea . id , stopPoint . id ] ) ;
82+ excludedStopPoints . push ( [ StopAreaDetails . id , stopPoint . id ] ) ;
8683 }
8784 }
8885
@@ -93,7 +90,7 @@ function serializeExcludedStopPoints(excludedStopPoints: [StopArea["id"], StopPo
9390 const partialExcludedStopPoints = [ ] as string [ ] ;
9491
9592 for ( const stopAreaId of excludedStopPoints . map ( ( [ stopArea ] ) => stopArea ) . filter ( unique ) ) {
96- const stopArea = selectedStops . value . find ( ( s ) => s . id === stopAreaId ) ;
93+ const stopArea = selectedStopAreas . value . find ( ( s ) => s . id === stopAreaId ) ;
9794 if ( ! stopArea ) continue ;
9895
9996 const stopAreaNumber = Object . keys ( query ) . find ( ( k ) => query [ k ] === stopArea . name ) ;
@@ -110,11 +107,19 @@ function serializeExcludedStopPoints(excludedStopPoints: [StopArea["id"], StopPo
110107 return partialExcludedStopPoints . join ( "," ) ;
111108}
112109
113- async function addStopArea ( stop : string ) {
114- const alreadySelected = selectedStops . value . find ( ( s ) => s . name === stop ) ;
110+ function serializeStopAreaId ( stopAreaId : StopArea [ "id" ] ) {
111+ return stopAreaId . substring ( "stop_area:" . length ) ;
112+ }
113+
114+ function deserializeStopAreaId ( stopAreaId : string ) : StopArea [ "id" ] {
115+ return `stop_area:${ stopAreaId } ` ;
116+ }
117+
118+ async function addStopArea ( stopArea : StopArea ) {
119+ const alreadySelected = selectedStopAreas . value . find ( ( s ) => s . id === stopArea . id ) ;
115120 if ( alreadySelected ) {
116121 if ( excludedStopPoints . value . find ( ( [ sa ] ) => sa === alreadySelected . id ) ) {
117- excludedStopPoints . value = excludedStopPoints . value . filter ( ( [ sp ] ) => sp != alreadySelected . id ) ;
122+ excludedStopPoints . value = excludedStopPoints . value . filter ( ( [ sa ] ) => sa != alreadySelected . id ) ;
118123 query [ "eSP" ] = serializeExcludedStopPoints ( excludedStopPoints . value ) ;
119124 if ( ! query [ "eSP" ] . length ) delete query [ "eSP" ] ;
120125 queryInternallyUpdated = true ;
@@ -123,22 +128,69 @@ async function addStopArea(stop: string) {
123128 } else return - 1 ; //display error
124129 }
125130
126- const found = stops . value . find ( ( s ) => s . name === stop ) ;
127- if ( ! found ) return - 2 ; // display error
131+ const StopAreaDetails = await fetchStopAreaDetails ( stopArea ) ;
132+ if ( ! StopAreaDetails ) return - 2 ; // display error
128133
129- const fullyDescribedStopArea = await fetchStopAreaDetails ( found ) ;
130- if ( ! fullyDescribedStopArea ) return - 3 ; // display error
131-
132- query [ Object . keys ( query ) . length + 1 ] = fullyDescribedStopArea . name ;
134+ query [ getStopAreaKeysFromQuery ( query ) . length + 1 ] = serializeStopAreaId ( StopAreaDetails . id ) ;
133135 queryInternallyUpdated = true ;
134136 router . push ( { query } ) ;
135137
136- selectedStops . value . push ( fullyDescribedStopArea ) ;
138+ selectedStopAreas . value . push ( StopAreaDetails ) ;
137139
138140 return 0 ;
139141}
140142
141- async function addStopPoint ( stopArea : StopArea , stopPointId : StopPoint [ "id" ] ) {
143+ function removeStopArea ( stopArea : StopAreaDetails ) {
144+ selectedStopAreas . value = selectedStopAreas . value . filter ( ( s ) => s . id != stopArea . id ) ;
145+
146+ let queryNeedUpdate = false ;
147+
148+ if ( excludedStopPoints . value . find ( ( [ stopAreaId ] ) => stopAreaId === stopArea . id ) ) {
149+ queryNeedUpdate = true ;
150+ excludedStopPoints . value = excludedStopPoints . value . filter ( ( [ stopAreaId ] ) => stopAreaId !== stopArea . id ) ;
151+ query [ "eSP" ] = serializeExcludedStopPoints ( excludedStopPoints . value ) ;
152+ if ( ! query [ "eSP" ] . length ) delete query [ "eSP" ] ;
153+ }
154+
155+ const serializedStopAreaId = serializeStopAreaId ( stopArea . id ) ;
156+ Object . keys ( query ) . forEach ( ( k ) => {
157+ if ( query [ k ] === serializedStopAreaId ) {
158+ queryNeedUpdate = true ;
159+ delete query [ k ] ;
160+ }
161+ } ) ;
162+
163+ let gap = 0 ;
164+ getStopAreaKeysFromQuery ( query ) . forEach ( ( k , i , arr ) => {
165+ const intK = parseInt ( k ) ;
166+
167+ // Init, full rename case
168+ if ( i === 0 ) gap = intK - 1 ;
169+
170+ if ( gap ) {
171+ query [ ( intK - gap ) . toString ( ) ] = query [ k ] ;
172+ delete query [ k ] ;
173+ }
174+
175+ // End of array, do not compute next gap
176+ if ( i === arr . length - 1 ) return ;
177+ const intK2 = parseInt ( arr [ i + 1 ] ) ;
178+
179+ // Next gap
180+ gap += intK2 - intK - 1 ;
181+ } ) ;
182+ if ( gap ) queryNeedUpdate = true ;
183+
184+ if ( queryNeedUpdate ) {
185+ queryInternallyUpdated = true ;
186+ router . push ( { query } ) ;
187+ }
188+ }
189+
190+ async function addStopPoint (
191+ stopArea : Parameters < typeof fetchStopAreaDetails > [ 0 ] ,
192+ stopPointId : StopPoint [ "id" ] ,
193+ ) {
142194 if ( excludedStopPoints . value . find ( ( [ _ , sp ] ) => sp === stopPointId ) ) {
143195 excludedStopPoints . value = excludedStopPoints . value . filter ( ( [ _ , sp ] ) => sp != stopPointId ) ;
144196 query [ "eSP" ] = serializeExcludedStopPoints ( excludedStopPoints . value ) ;
@@ -148,18 +200,19 @@ async function addStopPoint(stopArea: StopArea, stopPointId: StopPoint["id"]) {
148200 return 1 ;
149201 }
150202
151- const fullyDescribedStopArea = await fetchStopAreaDetails ( stopArea ) ;
152- if ( ! fullyDescribedStopArea ) return - 3 ; // display error
203+ // Add stop area, exclude all stop points except stopPointId
204+ const StopAreaDetails = await fetchStopAreaDetails ( stopArea ) ;
205+ if ( ! StopAreaDetails ) return - 3 ; // display error
153206
154- for ( const stopPoint of fullyDescribedStopArea . details . stopPoints )
207+ for ( const stopPoint of StopAreaDetails . stopPoints )
155208 excludedStopPoints . value . push ( [ stopArea . id , stopPoint . id ] ) ;
156209
157- selectedStops . value . push ( fullyDescribedStopArea ) ;
210+ selectedStopAreas . value . push ( StopAreaDetails ) ;
158211
159212 return 0 ;
160213}
161214
162- function removeStopPoint ( stopArea : FullyDescribedStopArea , stopPoint : StopPoint ) {
215+ function removeStopPoint ( stopArea : StopAreaDetails , stopPoint : StopPoint ) {
163216 if (
164217 excludedStopPoints . value . find (
165218 ( [ stopAreaId , stopPointId ] ) => stopArea . id === stopAreaId && stopPoint . id === stopPointId ,
@@ -174,40 +227,15 @@ function removeStopPoint(stopArea: FullyDescribedStopArea, stopPoint: StopPoint)
174227 queryInternallyUpdated = true ;
175228 router . push ( { query } ) ;
176229
177- if ( stopArea . details . stopPoints . every ( ( s ) => excludedStopPoints . value . find ( ( esp ) => s . id === esp [ 1 ] ) ) )
230+ if ( stopArea . stopPoints . every ( ( s ) => excludedStopPoints . value . find ( ( esp ) => s . id === esp [ 1 ] ) ) )
178231 removeStopArea ( stopArea ) ;
179232}
180233
181- function removeStopArea ( stopArea : FullyDescribedStopArea ) {
182- selectedStops . value = selectedStops . value . filter ( ( s ) => s . id != stopArea . id ) ;
183-
184- let queryNeedUpdate = false ;
185-
186- if ( excludedStopPoints . value . find ( ( [ stopAreaId ] ) => stopAreaId === stopArea . id ) ) {
187- queryNeedUpdate = true ;
188- excludedStopPoints . value = excludedStopPoints . value . filter ( ( [ stopAreaId ] ) => stopAreaId !== stopArea . id ) ;
189- query [ "eSP" ] = serializeExcludedStopPoints ( excludedStopPoints . value ) ;
190- if ( ! query [ "eSP" ] . length ) delete query [ "eSP" ] ;
191- }
192-
193- Object . keys ( query ) . forEach ( ( k ) => {
194- if ( query [ k ] === stopArea . name ) {
195- queryNeedUpdate = true ;
196- delete query [ k ] ;
197- }
198- } ) ;
199-
200- if ( queryNeedUpdate ) {
201- queryInternallyUpdated = true ;
202- router . push ( { query } ) ;
203- }
204- }
205-
206- function getWantedStops ( stops : typeof selectedStops . value ) {
207- return stops . reduce (
208- ( acc , stopArea : FullyDescribedStopArea ) => [
234+ function getWantedStops ( stopAreas : typeof selectedStopAreas . value ) {
235+ return stopAreas . reduce (
236+ ( acc , stopArea : StopAreaDetails ) => [
209237 ...acc ,
210- ...stopArea . details . stopPoints
238+ ...stopArea . stopPoints
211239 . filter (
212240 ( sp ) =>
213241 ! excludedStopPoints . value . find (
@@ -223,9 +251,9 @@ function getWantedStops(stops: typeof selectedStops.value) {
223251}
224252
225253export {
226- selectedStops ,
254+ selectedStopAreas ,
227255 excludedStopPoints ,
228- stops ,
256+ stopAreas ,
229257 addStopArea ,
230258 addStopPoint ,
231259 removeStopPoint ,
0 commit comments