@@ -20,7 +20,7 @@ const {
2020const { t : $t } = useTranslation ()
2121
2222const emit = defineEmits <{
23- (e : ' search' ): void ,
23+ (e : ' search' , input : string ): void ,
2424}>()
2525
2626const searchParams = defineModel <BlockchainSearchParams >({
@@ -50,8 +50,9 @@ const chips: { label: string, value: BlockchainSearchParams['types'][number] }[]
5050 },
5151]
5252
53- const handleSearch = () => {
54- emit (' search' )
53+ const handleSearch = (input : string ) => {
54+ isHistoryVisible .value = false
55+ emit (' search' , input )
5556}
5657
5758const handleTypeFilterChange = () => {
@@ -61,29 +62,80 @@ const handleTypeFilterChange = () => {
6162 searchParams .value .types = typeFilters
6263 }
6364
64- handleSearch ()
65+ handleSearch (searchParams . value . input )
6566}
67+ const history = useLocalStorage <string []>(' bc-search-history-product-landing' , [])
68+ // using localHistory instead of history directly to avoid
69+ // that the search history in the UI is updated before navigating away
70+ const localHistory = ref <InternalPostSearchResponseWithChainId [' data' ]>(history .value .map (item => JSON .parse (item )))
71+ const hasHistory = computed (() => !! localHistory .value .length )
72+ const hasResults = computed (() => results !== undefined )
73+
74+ const isHistoryVisible = ref <boolean >(! hasResults .value && hasHistory .value )
75+ const resultsOrHistory = computed (() => {
76+ if ((! hasResults .value && hasHistory .value ) || isHistoryVisible .value ) {
77+ return localHistory .value
78+ }
79+ return results
80+ })
81+ const showHistory = () => {
82+ isHistoryVisible .value = ! isHistoryVisible .value
83+ localHistory .value = history .value .map (item => JSON .parse (item ))
84+ }
85+ const handleClick = (searchResult : InternalPostSearchResponseWithChainId [' data' ][number ]) => {
86+ const currentEntry = JSON .stringify (searchResult )
87+ if (history .value .length >= 10 ) {
88+ history .value .pop ()
89+ }
90+ history .value = history .value .filter (entry => entry !== currentEntry )
91+ history .value .unshift (currentEntry )
92+ }
93+ watch (hasResults , () => {
94+ if (! hasHistory .value ) return
95+ if (hasResults .value ) return
96+ isHistoryVisible .value = true
97+ })
6698 </script >
6799
68100<template >
69101 <BaseSearchInput
70102 v-model =" searchParams.input"
71- :is-loading
72- :has-error
103+ :is-loading = " isHistoryVisible ? false : isLoading "
104+ :has-error = " isHistoryVisible ? false : hasError "
73105 :label =" $t('products.landing_page.search.input_label')"
74106 :placeholder =" $t('products.landing_page.search.input_placeholder')"
75107 :group-by =" 'type'"
76- :results
108+ :results = " resultsOrHistory "
77109 @search =" handleSearch"
78110 >
79- <template #dropdown-fixed-header >
80- <BaseChipGroup
81- v-model =" searchParams.types"
82- :items =" chips"
83- class =" overflow-x-auto overscroll-contain min-h-fit"
84- :aria-label =" $t('products.landing_page.search.filter_aria_label')"
85- @update:model-value =" handleTypeFilterChange"
86- />
111+ <template #dropdown-fixed-header =" { idSearchInput } " >
112+ <div
113+ class =" min-h-fit overflow-x-auto overscroll-contain flex gap-md items-center px-2xl py-lg"
114+ @keydown.enter.stop
115+ >
116+ <BaseButtonIcon
117+ v-if =" hasHistory"
118+ :aria-controls =" idSearchInput"
119+ :is-disabled =" !hasResults"
120+ role =" switch"
121+ screenreader-text =" products.landing_page.search.history.action.toggle_history"
122+ name =" history"
123+ :aria-checked =" `${isHistoryVisible}`"
124+ variant =" secondary"
125+ @click =" showHistory"
126+ />
127+ <BaseChipGroup
128+ v-if =" !isHistoryVisible"
129+ v-model =" searchParams.types"
130+ :aria-controls =" idSearchInput"
131+ :items =" chips"
132+ :aria-label =" $t('products.landing_page.search.filter_aria_label')"
133+ @update:model-value =" handleTypeFilterChange"
134+ />
135+ <span v-else >
136+ {{ $t('products.landing_page.search.history.recent') }}
137+ </span >
138+ </div >
87139 <hr class =" mx-2xl text-gray-600" >
88140 </template >
89141
@@ -107,7 +159,10 @@ const handleTypeFilterChange = () => {
107159 </template >
108160
109161 <template #result-item =" { result } " >
110- <BlockchainSearchResultItem :result />
162+ <BlockchainSearchResultItem
163+ :result
164+ @click =" handleClick(result)"
165+ />
111166 </template >
112167
113168 <template #loading-content >
0 commit comments