Skip to content

Commit 3910f93

Browse files
committed
fix: added composable (useSearch.js)
1 parent 75de3a1 commit 3910f93

File tree

5 files changed

+136
-161
lines changed

5 files changed

+136
-161
lines changed

app.vue

Lines changed: 7 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
<div class="mx-auto box-content w-[calc(100%+40px)] max-w-[935px] grow p-1">
44
<div role="tablist" class="my-4 flex max-w-full flex-col items-stretch">
55
<div class="flex flex-row flex-nowrap items-center gap-4">
6-
<HeaderLogo />
6+
<div class="flex items-center justify-center">
7+
<NuxtLink to="/">
8+
<img class="mx-auto my-0 h-10 rounded-xl" src="/logo.png" alt="logo" />
9+
</NuxtLink>
10+
</div>
711
<div class="flex flex-shrink flex-grow flex-col text-sm font-semibold text-neutral-600 dark:text-neutral-200">
812
<form
913
class="group flex h-10 flex-grow rounded-xl border border-transparent bg-neutral-800/5 dark:bg-white/10 pl-4 pr-3 transition-all focus-within:border-neutral-400 focus-within:dark:border-neutral-600 focus-within:bg-white/30 focus-within:dark:bg-neutral-800/30 hover:border-neutral-300 hover:focus-within:border-neutral-400 hover:dark:border-neutral-600">
@@ -145,120 +149,8 @@
145149
</div>
146150
</template>
147151

148-
<script setup>
149-
import getProducts from '~/gql/queries/getProducts.gql';
150-
import getCategories from '~/gql/queries/getCategories.gql';
151-
const isDropdownSortBy = ref(false);
152-
const isDropdownCategory = ref(false);
153-
const router = useRouter();
154-
const route = useRoute();
155-
const searchTerm = ref(route.query.search || '');
156-
const selectedCategory = ref(route.query.category || '');
157-
const sortByOrder = ref(route.query.orderby && route.query.orderby !== '' ? route.query.orderby : 'DESC');
158-
const sortByField = ref(route.query.fieldby && route.query.fieldby !== '' ? route.query.fieldby : 'DATE');
159-
const variables = ref({
160-
search: searchTerm,
161-
category: selectedCategory,
162-
order: sortByOrder,
163-
field: sortByField,
164-
});
165-
166-
const { result: categoriesResult } = useQuery(getCategories);
167-
const { result: productsResult, loading, fetchMore } = useQuery(getProducts, variables.value);
168-
const products = computed(() => productsResult.value?.products.nodes);
169-
const empty = computed(() => productsResult.value?.products.nodes.length);
170-
const pageInfo = computed(() => productsResult.value?.products.pageInfo);
171-
const categories = computed(() => categoriesResult.value?.productCategories.nodes.filter((categories) => categories.products.nodes.length && categories.children.nodes.length));
172-
173-
const options = reactive([{ value: 'Newest' }, { value: 'Price: High to Low' }, { value: 'Price: Low to High' }]);
174-
175-
const selectedOption = ref(sortByOrder.value === 'DESC' && sortByField.value === 'DATE' ? 'Newest' : sortByOrder.value === 'DESC' ? 'Price: High to Low' : 'Price: Low to High');
176-
177-
const loadMore = () => {
178-
fetchMore({
179-
variables: {
180-
after: pageInfo.value?.endCursor,
181-
},
182-
updateQuery(prev, { fetchMoreResult }) {
183-
const mergedData = {
184-
...prev,
185-
};
186-
mergedData.products = {
187-
...prev.products,
188-
nodes: [...prev.products.nodes, ...fetchMoreResult.products.nodes],
189-
};
190-
mergedData.products.pageInfo = fetchMoreResult.products.pageInfo;
191-
return mergedData;
192-
},
193-
});
194-
};
195-
196-
const handleScroll = () => {
197-
const scrollPosition = window.scrollY + window.innerHeight;
198-
const loadMorePosition = document.documentElement.scrollHeight - 1600;
199-
200-
if (scrollPosition >= loadMorePosition && pageInfo.value?.hasNextPage && !loading.value) {
201-
loadMore();
202-
}
203-
};
204-
205-
const handleClickOutside = (event) => {
206-
if (!event.target.closest('.dropdown')) {
207-
isDropdownSortBy.value = false;
208-
isDropdownCategory.value = false;
209-
}
210-
};
211-
212-
onMounted(() => {
213-
window.addEventListener('scroll', handleScroll);
214-
document.addEventListener('click', handleClickOutside);
215-
});
216-
217-
onUnmounted(() => {
218-
window.removeEventListener('scroll', handleScroll);
219-
document.removeEventListener('click', handleClickOutside);
220-
});
221-
222-
watch([selectedOption, searchTerm, selectedCategory], ([newSelectedOption, newSearchTerm, newCategory]) => {
223-
let updatedQuery = {
224-
...route.query,
225-
search: newSearchTerm || undefined,
226-
category: newCategory || undefined,
227-
};
228-
229-
switch (newSelectedOption) {
230-
case 'Newest':
231-
sortByOrder.value = 'DESC';
232-
sortByField.value = 'DATE';
233-
updatedQuery = {
234-
...updatedQuery,
235-
orderby: undefined,
236-
fieldby: undefined,
237-
};
238-
break;
239-
case 'Price: High to Low':
240-
sortByOrder.value = 'DESC';
241-
sortByField.value = 'PRICE';
242-
updatedQuery = {
243-
...updatedQuery,
244-
orderby: sortByOrder.value || undefined,
245-
fieldby: sortByField.value || undefined,
246-
};
247-
break;
248-
case 'Price: Low to High':
249-
sortByOrder.value = 'ASC';
250-
sortByField.value = 'PRICE';
251-
updatedQuery = {
252-
...updatedQuery,
253-
orderby: sortByOrder.value || undefined,
254-
fieldby: sortByField.value || undefined,
255-
};
256-
break;
257-
}
258-
router.push({
259-
query: updatedQuery,
260-
});
261-
});
152+
<script setup lang="ts">
153+
const { products, empty, loading, categories, options, searchTerm, selectedCategory, selectedOption, isDropdownCategory, isDropdownSortBy } = useSearch();
262154
</script>
263155

264156
<style lang="postcss">

components/header/Date.vue

Lines changed: 0 additions & 32 deletions
This file was deleted.

components/header/Logo.vue

Lines changed: 0 additions & 7 deletions
This file was deleted.

components/header/index.vue

Lines changed: 0 additions & 7 deletions
This file was deleted.

composables/useSearch.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import getProducts from '~/gql/queries/getProducts.gql';
2+
import getCategories from '~/gql/queries/getCategories.gql';
3+
4+
export default function useSearch() {
5+
const isDropdownSortBy = ref(false);
6+
const isDropdownCategory = ref(false);
7+
const router = useRouter();
8+
const route = useRoute();
9+
const searchTerm = ref(route.query.search || '');
10+
const selectedCategory = ref(route.query.category || '');
11+
const sortByOrder = ref(route.query.orderby && route.query.orderby !== '' ? route.query.orderby : 'DESC');
12+
const sortByField = ref(route.query.fieldby && route.query.fieldby !== '' ? route.query.fieldby : 'DATE');
13+
const variables = ref({
14+
search: searchTerm,
15+
category: selectedCategory,
16+
order: sortByOrder,
17+
field: sortByField,
18+
});
19+
20+
const { result: categoriesResult } = useQuery(getCategories);
21+
const { result: productsResult, loading, fetchMore } = useQuery(getProducts, variables.value);
22+
const products = computed(() => productsResult.value?.products.nodes);
23+
const empty = computed(() => productsResult.value?.products.nodes.length);
24+
const pageInfo = computed(() => productsResult.value?.products.pageInfo);
25+
const categories = computed(() => categoriesResult.value?.productCategories.nodes.filter((categories) => categories.products.nodes.length && categories.children.nodes.length));
26+
27+
const options = reactive([{ value: 'Newest' }, { value: 'Price: High to Low' }, { value: 'Price: Low to High' }]);
28+
29+
const selectedOption = ref(sortByOrder.value === 'DESC' && sortByField.value === 'DATE' ? 'Newest' : sortByOrder.value === 'DESC' ? 'Price: High to Low' : 'Price: Low to High');
30+
31+
const loadMore = () => {
32+
fetchMore({
33+
variables: {
34+
after: pageInfo.value?.endCursor,
35+
},
36+
updateQuery(prev, { fetchMoreResult }) {
37+
const mergedData = {
38+
...prev,
39+
};
40+
mergedData.products = {
41+
...prev.products,
42+
nodes: [...prev.products.nodes, ...fetchMoreResult.products.nodes],
43+
};
44+
mergedData.products.pageInfo = fetchMoreResult.products.pageInfo;
45+
return mergedData;
46+
},
47+
});
48+
};
49+
50+
const handleScroll = () => {
51+
const scrollPosition = window.scrollY + window.innerHeight;
52+
const loadMorePosition = document.documentElement.scrollHeight - 1600;
53+
54+
if (scrollPosition >= loadMorePosition && pageInfo.value?.hasNextPage && !loading.value) {
55+
loadMore();
56+
}
57+
};
58+
59+
const handleClickOutside = (event) => {
60+
if (!event.target.closest('.dropdown')) {
61+
isDropdownSortBy.value = false;
62+
isDropdownCategory.value = false;
63+
}
64+
};
65+
66+
onMounted(() => {
67+
window.addEventListener('scroll', handleScroll);
68+
document.addEventListener('click', handleClickOutside);
69+
});
70+
71+
onUnmounted(() => {
72+
window.removeEventListener('scroll', handleScroll);
73+
document.removeEventListener('click', handleClickOutside);
74+
});
75+
76+
watch([selectedOption, searchTerm, selectedCategory], ([newSelectedOption, newSearchTerm, newCategory]) => {
77+
let updatedQuery = {
78+
...route.query,
79+
search: newSearchTerm || undefined,
80+
category: newCategory || undefined,
81+
};
82+
83+
switch (newSelectedOption) {
84+
case 'Newest':
85+
sortByOrder.value = 'DESC';
86+
sortByField.value = 'DATE';
87+
updatedQuery = {
88+
...updatedQuery,
89+
orderby: undefined,
90+
fieldby: undefined,
91+
};
92+
break;
93+
case 'Price: High to Low':
94+
sortByOrder.value = 'DESC';
95+
sortByField.value = 'PRICE';
96+
updatedQuery = {
97+
...updatedQuery,
98+
orderby: sortByOrder.value || undefined,
99+
fieldby: sortByField.value || undefined,
100+
};
101+
break;
102+
case 'Price: Low to High':
103+
sortByOrder.value = 'ASC';
104+
sortByField.value = 'PRICE';
105+
updatedQuery = {
106+
...updatedQuery,
107+
orderby: sortByOrder.value || undefined,
108+
fieldby: sortByField.value || undefined,
109+
};
110+
break;
111+
}
112+
router.push({
113+
query: updatedQuery,
114+
});
115+
});
116+
117+
return {
118+
products,
119+
empty,
120+
loading,
121+
categories,
122+
options,
123+
searchTerm,
124+
selectedCategory,
125+
selectedOption,
126+
isDropdownSortBy,
127+
isDropdownCategory,
128+
};
129+
}

0 commit comments

Comments
 (0)