@@ -13,9 +13,10 @@ import {
13
13
SearchboxService ,
14
14
TranslationService ,
15
15
WindowRef ,
16
+ ProductActions ,
16
17
} from '@spartacus/core' ;
17
- import { combineLatest , Observable , of , ReplaySubject } from 'rxjs' ;
18
- import { map , switchMap , tap } from 'rxjs/operators' ;
18
+ import { combineLatest , Observable , of , ReplaySubject , Subject } from 'rxjs' ;
19
+ import { map , switchMap , tap , filter , take } from 'rxjs/operators' ;
19
20
import {
20
21
SearchBoxProductSelectedEvent ,
21
22
SearchBoxSuggestionSelectedEvent ,
@@ -30,10 +31,12 @@ const HAS_SEARCH_RESULT_CLASS = 'has-searchbox-results';
30
31
export class SearchBoxComponentService {
31
32
chosenWord = new ReplaySubject < string > ( ) ;
32
33
sharedEvent = new ReplaySubject < KeyboardEvent > ( ) ;
34
+ searchCompleted = new Subject < boolean > ( ) ;
33
35
34
36
protected enableRecentSearches : boolean = false ;
35
37
protected enableTrendingSearches : boolean = false ;
36
-
38
+ private currentQueryLength : number = 0 ;
39
+ private hasKeywordRedirect : boolean = false ;
37
40
constructor (
38
41
public searchService : SearchboxService ,
39
42
protected routingService : RoutingService ,
@@ -48,6 +51,10 @@ export class SearchBoxComponentService {
48
51
* products or suggestions.
49
52
*/
50
53
search ( query : string , config : SearchBoxConfig ) : void {
54
+ this . hasKeywordRedirect = false ;
55
+ this . currentQueryLength = query ? query . length : 0 ;
56
+ this . searchCompleted . next ( false ) ;
57
+
51
58
if (
52
59
! this . enableRecentSearches &&
53
60
! this . enableTrendingSearches &&
@@ -63,16 +70,57 @@ export class SearchBoxComponentService {
63
70
return ;
64
71
}
65
72
73
+ let productsComplete = ! config . displayProducts ;
74
+ let suggestionsComplete = ! config . displaySuggestions ;
75
+
66
76
if ( config . displayProducts ) {
67
- this . searchService . search ( query , {
68
- pageSize : config . maxProducts ,
69
- } ) ;
77
+ this . searchService
78
+ . searchWithCompletion ( query , {
79
+ pageSize : config . maxProducts ,
80
+ } )
81
+ . subscribe ( ( result : any ) => {
82
+ if (
83
+ result ?. type === ProductActions . SEARCH_PRODUCTS_SUCCESS &&
84
+ result ?. payload ?. keywordRedirectUrl
85
+ ) {
86
+ this . hasKeywordRedirect = true ;
87
+ }
88
+ productsComplete = true ;
89
+ this . checkSearchCompletion ( productsComplete , suggestionsComplete ) ;
90
+ } ) ;
70
91
}
71
92
72
93
if ( config . displaySuggestions ) {
73
- this . searchService . searchSuggestions ( query , {
74
- pageSize : config . maxSuggestions ,
75
- } ) ;
94
+ this . searchService
95
+ . searchSuggestionsWithCompletion ( query , {
96
+ pageSize : config . maxSuggestions ,
97
+ } )
98
+ . subscribe ( ( result : any ) => {
99
+ if (
100
+ result ?. type === ProductActions . GET_PRODUCT_SUGGESTIONS_SUCCESS &&
101
+ result ?. payload ?. keywordRedirectUrl
102
+ ) {
103
+ this . hasKeywordRedirect = true ;
104
+ }
105
+ suggestionsComplete = true ;
106
+ this . checkSearchCompletion ( productsComplete , suggestionsComplete ) ;
107
+ } ) ;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Check if search operations are complete based on actual completion flags
113
+ */
114
+ private checkSearchCompletion (
115
+ productsComplete : boolean ,
116
+ suggestionsComplete : boolean
117
+ ) : void {
118
+ if (
119
+ productsComplete &&
120
+ suggestionsComplete &&
121
+ this . currentQueryLength > 0
122
+ ) {
123
+ this . searchCompleted . next ( true ) ;
76
124
}
77
125
}
78
126
@@ -107,6 +155,10 @@ export class SearchBoxComponentService {
107
155
clearResults ( ) {
108
156
this . searchService . clearResults ( ) ;
109
157
this . toggleBodyClass ( HAS_SEARCH_RESULT_CLASS , false ) ;
158
+
159
+ // Reset search completion state
160
+ this . hasKeywordRedirect = false ;
161
+ this . currentQueryLength = 0 ;
110
162
}
111
163
112
164
hasBodyClass ( className : string ) : boolean {
@@ -261,12 +313,24 @@ export class SearchBoxComponentService {
261
313
262
314
/**
263
315
* Navigates to the search result page with a given query
316
+ * after waiting for all search operations to complete
264
317
*/
265
318
launchSearchPage ( query : string ) : void {
266
- this . routingService . go ( {
267
- cxRoute : 'search' ,
268
- params : { query } ,
269
- } ) ;
319
+ // Reset the completed state before starting new search
320
+ this . searchCompleted . next ( false ) ;
321
+ this . searchCompleted
322
+ . pipe (
323
+ filter ( ( complete ) => complete ) , // Only proceed when true
324
+ take ( 1 ) // Take only the first completion
325
+ )
326
+ . subscribe ( ( ) => {
327
+ if ( ! this . hasKeywordRedirect ) {
328
+ this . routingService . go ( {
329
+ cxRoute : 'search' ,
330
+ params : { query } ,
331
+ } ) ;
332
+ }
333
+ } ) ;
270
334
}
271
335
272
336
private fetchTranslation (
0 commit comments