Fix page refresh bug in library and search
This commit is contained in:
parent
dc2d5cc460
commit
917824f098
|
@ -31,7 +31,6 @@ const goToLibraryShow = (item) => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UCard
|
<UCard
|
||||||
v-if="props.list?.length"
|
|
||||||
v-for="(item, index) in props.list"
|
v-for="(item, index) in props.list"
|
||||||
class="mx-auto"
|
class="mx-auto"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
@ -46,7 +45,6 @@ const goToLibraryShow = (item) => {
|
||||||
<!-- <template #header></template> -->
|
<!-- <template #header></template> -->
|
||||||
|
|
||||||
<ULink
|
<ULink
|
||||||
v-if="item?._source?.id"
|
|
||||||
:to="{
|
:to="{
|
||||||
name: 'hadithaLibraryShow',
|
name: 'hadithaLibraryShow',
|
||||||
params: {
|
params: {
|
||||||
|
@ -76,14 +74,6 @@ const goToLibraryShow = (item) => {
|
||||||
|
|
||||||
<!-- <template #footer> </template> -->
|
<!-- <template #footer> </template> -->
|
||||||
</UCard>
|
</UCard>
|
||||||
|
|
||||||
<no-data
|
|
||||||
class="h-full w-full flex flex-col justify-center items-center"
|
|
||||||
v-else
|
|
||||||
>
|
|
||||||
<img fit="auto" quality="80" placeholder :src="props.noDataIcon" />
|
|
||||||
<p class="no-data-text">{{ props.noDataText }}</p>
|
|
||||||
</no-data>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -7,6 +7,9 @@ const props = defineProps({
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
requestStatus: {
|
||||||
|
default: "pending",
|
||||||
|
},
|
||||||
total: {
|
total: {
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
|
@ -84,6 +87,17 @@ const removeFromFavorites = async (item = {}, index = 0) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<!-- <template v-if="props.requestStatus == 'pending'"> -->
|
||||||
|
<!-- <div class="flex items-center gap-4 mb-4" v-for="item in props?.list?.length">
|
||||||
|
<USkeleton class="h-12 w-12 rounded-full" />
|
||||||
|
|
||||||
|
<div class="grid gap-2 flex-grow-1">
|
||||||
|
<USkeleton class="h-4 " />
|
||||||
|
<USkeleton class="h-4 " />
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
<!-- </template> -->
|
||||||
|
<!-- <template v-else-if="props.requestStatus == 'success' || props.requestStatus == 'idle'"> -->
|
||||||
<div
|
<div
|
||||||
v-if="props?.list?.length"
|
v-if="props?.list?.length"
|
||||||
class="search-list-item"
|
class="search-list-item"
|
||||||
|
@ -155,6 +169,7 @@ const removeFromFavorites = async (item = {}, index = 0) => {
|
||||||
</p> -->
|
</p> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- </template> -->
|
||||||
|
|
||||||
<!-- <UModal
|
<!-- <UModal
|
||||||
v-model:open="isModalOpen"
|
v-model:open="isModalOpen"
|
||||||
|
|
|
@ -2,14 +2,22 @@
|
||||||
import hadithaApi from "@haditha/apis/hadithaApi";
|
import hadithaApi from "@haditha/apis/hadithaApi";
|
||||||
import headLinks from "@haditha/json/haditha/headLinks";
|
import headLinks from "@haditha/json/haditha/headLinks";
|
||||||
import headMetas from "@haditha/json/haditha/headMetas";
|
import headMetas from "@haditha/json/haditha/headMetas";
|
||||||
import { useInfiniteScroll } from "@vueuse/core";
|
// import { useInfiniteScroll } from "@vueuse/core";
|
||||||
|
const id_token = useCookie("id_token");
|
||||||
|
const token = id_token.value ?? "GuestAccess";
|
||||||
|
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
const baseUrl =
|
||||||
|
config.public.NUXT_PUBLIC_BASE_URL + config.public.NUXT_PUBLIC_API_NAME;
|
||||||
|
|
||||||
|
// this enable us to send cookies.
|
||||||
|
const requestFetch = useRequestFetch();
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
layout: false,
|
layout: false,
|
||||||
name: "hadithaLibrary",
|
name: "hadithaLibrary",
|
||||||
});
|
});
|
||||||
useHead({
|
useHead({
|
||||||
name: "hadithaLibrary",
|
|
||||||
title: `${import.meta.env.VITE_HADITH_PAGE_TITLE} | کتابخانه`,
|
title: `${import.meta.env.VITE_HADITH_PAGE_TITLE} | کتابخانه`,
|
||||||
meta: [
|
meta: [
|
||||||
{ name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" },
|
{ name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" },
|
||||||
|
@ -22,19 +30,21 @@ useHead({
|
||||||
});
|
});
|
||||||
|
|
||||||
// #region refs
|
// #region refs
|
||||||
const httpService = useNuxtApp()["$http"];
|
// const httpService = useNuxtApp()["$http"];
|
||||||
|
// const { $api } = useNuxtApp()
|
||||||
const offset = useState("offset", () => 0);
|
const offset = useState("offset", () => 0);
|
||||||
const total = useState("total", () => 0);
|
const total = useState("total", () => 0);
|
||||||
const loading = useState("loading", () => false);
|
// const libraryList = useState("libraryList", () => []);
|
||||||
const hasMore = useState("hasMore", () => true);
|
// const loading = useState("loading", () => false);
|
||||||
|
// const hasMore = useState("hasMore", () => true);
|
||||||
|
|
||||||
const el = ref(null);
|
// const el = ref(null);
|
||||||
// #endregion refs
|
// #endregion refs
|
||||||
|
|
||||||
// #region reactive
|
// #region reactive
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
pagination: {
|
pagination: {
|
||||||
limit: 10,
|
limit: 15,
|
||||||
page: 1,
|
page: 1,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
},
|
},
|
||||||
|
@ -42,59 +52,65 @@ const state = reactive({
|
||||||
|
|
||||||
// #region methods
|
// #region methods
|
||||||
|
|
||||||
const getLibraryList = async () => {
|
const getLibraryList = () => {
|
||||||
let url = repoUrl() + hadithaApi.library.list;
|
let url = baseUrl + repoUrl() + hadithaApi.library.list;
|
||||||
url = url.replace("@field_collapsed", "normal");
|
url = url.replace("@field_collapsed", "normal");
|
||||||
url = url.replace("@offset", offset.value);
|
url = url.replace("@offset", offset.value);
|
||||||
url = url.replace("@limit", state.pagination.limit);
|
url = url.replace("@limit", state.pagination.limit);
|
||||||
url = url.replace("@q", "none");
|
url = url.replace("@q", "none");
|
||||||
|
|
||||||
return await httpService.postRequest(url).then((res) => {
|
return requestFetch(url, {
|
||||||
total.value = res.hits?.total?.value ?? 0;
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
Authorization: token,
|
||||||
|
},
|
||||||
|
}).then((data) => {
|
||||||
|
total.value = data.hits?.total?.value ?? 0;
|
||||||
offset.value += state.pagination.limit;
|
offset.value += state.pagination.limit;
|
||||||
|
return data.hits?.hits;
|
||||||
return res;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Server-side initial load
|
// Server-side initial load
|
||||||
const { data: loadedItems } = await useAsyncData(
|
// Wrapping with useAsyncDataavoid double data fetching when
|
||||||
"libraryList",
|
// doing server-side rendering (server & client on hydration).
|
||||||
() => getLibraryList(),
|
const { data: libraryList } = await useAsyncData("libraryList", () =>
|
||||||
{
|
getLibraryList()
|
||||||
transform: (data) => data.hits.hits,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Client-side infinite scroll
|
// Client-side infinite scroll
|
||||||
useInfiniteScroll(
|
const loadMore = async () => {
|
||||||
el,
|
// const listElm = $event.target;
|
||||||
async () => {
|
|
||||||
if (!hasMore.value || loading.value) return;
|
|
||||||
|
|
||||||
loading.value = true;
|
// if (status.value == "pending") return;
|
||||||
try {
|
// // window.innerHeight + window.scrollY >= document.body.offsetHeight - 100
|
||||||
await getLibraryList().then((res) => {
|
// if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
|
||||||
const hits = res?.hits?.hits ?? [];
|
// status.value = "pending";
|
||||||
|
// mainState.pagination.offset =
|
||||||
|
// mainState.pagination.offset + mainState.pagination.limit;
|
||||||
|
|
||||||
if (hits.length > 0) {
|
// if (total.value > mainState.pagination.offset) {
|
||||||
|
// window.clearTimeout(isScrolling.value);
|
||||||
|
// isScrolling.value = setTimeout(() => {
|
||||||
|
return await getLibraryList().then((res) => {
|
||||||
|
const hits = res ?? [];
|
||||||
// Use spread operator to create new array reference
|
// Use spread operator to create new array reference
|
||||||
loadedItems.value = [...loadedItems.value, ...hits];
|
libraryList.value = [...libraryList.value, ...hits];
|
||||||
} else {
|
// status.value = "success";
|
||||||
hasMore.value = false;
|
return res;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
// }, 300);
|
||||||
hasMore.value = false;
|
// } else {
|
||||||
|
// toast.add({
|
||||||
// console.error("Error loading more items:", error);
|
// title: "کاربر محترم",
|
||||||
// Consider setting hasMore.value = false if you want to stop on error
|
// description: "دیگر رکوردی جهت بارگزاری وجود ندارد.",
|
||||||
} finally {
|
// color: "success",
|
||||||
loading.value = false;
|
// });
|
||||||
}
|
// status.value = "idle";
|
||||||
},
|
// }
|
||||||
{ distance: 100 }
|
// } else status.value = "idle";
|
||||||
);
|
};
|
||||||
|
const { isFetching } = useInfiniteScroll(loadMore, "libraryInfiniteScroll");
|
||||||
// #endregion methods
|
// #endregion methods
|
||||||
|
|
||||||
// components declaration
|
// components declaration
|
||||||
|
@ -121,15 +137,24 @@ const CardList = defineAsyncComponent(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
ref="el"
|
ref="libraryInfiniteScroll"
|
||||||
class="library-list pl-4 firefox-scrollbar grid grid-cols-2 gap-x-15 gap-y-12 md:grid-cols-3 md:gap-x-28 md:gap-y-12 lg:grid-cols-5 lg:gap-x-28 lg:gap-y-12 mx-6"
|
id="libraryInfiniteScroll"
|
||||||
|
class="library-list pl-4 firefox-scrollbar gap-x-15 gap-y-12 md:grid-cols-3 md:gap-x-28 md:gap-y-12 lg:grid-cols-5 lg:gap-x-28 lg:gap-y-12 mx-6"
|
||||||
|
:class="{ 'grid grid-cols-2': libraryList?.length }"
|
||||||
>
|
>
|
||||||
<!-- Client-side loaded content -->
|
<!-- Client-side loaded content -->
|
||||||
<card-list
|
<card-list
|
||||||
no-data-text="هنوز چیزی ذخیره نکردهاید!"
|
:list="libraryList"
|
||||||
no-data-icon="/img/haditha/no-data.png"
|
no-data-text="به زودی لیست کتاب ها بروزرسانی خواهد شد."
|
||||||
:list="loadedItems"
|
no-data-icon=""
|
||||||
></card-list>
|
></card-list>
|
||||||
|
|
||||||
|
<no-data
|
||||||
|
class="h-full w-full flex flex-col justify-center items-center"
|
||||||
|
v-if="libraryList?.length == 0"
|
||||||
|
>
|
||||||
|
<p class="no-data-text">به زودی لیست کتاب ها بروزرسانی خواهد شد.</p>
|
||||||
|
</no-data>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -169,6 +194,7 @@ const CardList = defineAsyncComponent(
|
||||||
/* padding: 1em 1.3em; */
|
/* padding: 1em 1.3em; */
|
||||||
height: calc(100dvh - 13.5em);
|
height: calc(100dvh - 13.5em);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
.no-data-text {
|
.no-data-text {
|
||||||
font-family: var(--font);
|
font-family: var(--font);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useStorage } from "@vueuse/core";
|
import { useStorage } from "@vueuse/core";
|
||||||
import { useInfiniteScroll } from "@vueuse/core";
|
// import { useInfiniteScroll } from "@vueuse/core";
|
||||||
import * as z from "zod";
|
import * as z from "zod";
|
||||||
|
|
||||||
// const myCookie = useCookie("searchPhrase");
|
// const myCookie = useCookie("searchPhrase");
|
||||||
|
@ -10,6 +10,7 @@ import headLinks from "@haditha/json/haditha/headLinks";
|
||||||
import headMetas from "@haditha/json/haditha/headMetas";
|
import headMetas from "@haditha/json/haditha/headMetas";
|
||||||
import hadithaApi from "@haditha/apis/hadithaApi";
|
import hadithaApi from "@haditha/apis/hadithaApi";
|
||||||
import type { Synonym } from "@haditha/types/hadithType";
|
import type { Synonym } from "@haditha/types/hadithType";
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
// const searchTerm = useState("searchTerm", () => ''); // Tracks the searchTerm
|
// const searchTerm = useState("searchTerm", () => ''); // Tracks the searchTerm
|
||||||
const offset = useState("offset", () => 0); // Tracks the current offset
|
const offset = useState("offset", () => 0); // Tracks the current offset
|
||||||
|
@ -34,15 +35,11 @@ useHead({
|
||||||
|
|
||||||
// #region refs
|
// #region refs
|
||||||
// وقتی از صفحه حدیث با کلیک بر روی دکمه مشابه، وارد صفحه جستجو میشویم
|
// وقتی از صفحه حدیث با کلیک بر روی دکمه مشابه، وارد صفحه جستجو میشویم
|
||||||
const showPrevSearch = ref(false);
|
// const showPrevSearch = ref(false);
|
||||||
// لیست جستجو در حالت اسکرول
|
|
||||||
// const loadedItems = ref([]);
|
|
||||||
// لودینگ
|
|
||||||
const loading = ref(false);
|
|
||||||
// هنگام اسکرول، چک میشود که ایا صفحه بعدی هم وجود دارد یا نه.
|
// هنگام اسکرول، چک میشود که ایا صفحه بعدی هم وجود دارد یا نه.
|
||||||
const hasMore = ref(true);
|
const hasMore = ref(true);
|
||||||
// عنصری که برای اسکرول استفاده میشه.
|
// عنصری که برای اسکرول استفاده میشه.
|
||||||
const el = ref(null);
|
// const el = ref(null);
|
||||||
// پلاگین ارسال درخواست
|
// پلاگین ارسال درخواست
|
||||||
const httpService = useNuxtApp()["$http"];
|
const httpService = useNuxtApp()["$http"];
|
||||||
// استفاده از روت
|
// استفاده از روت
|
||||||
|
@ -142,9 +139,10 @@ const AutoComplationState = reactive({
|
||||||
});
|
});
|
||||||
const mainState = reactive({
|
const mainState = reactive({
|
||||||
pagination: {
|
pagination: {
|
||||||
limit: 10,
|
limit: 15,
|
||||||
page: 1,
|
page: 1,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
|
offset: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -167,7 +165,7 @@ const backgroundImageStyle = computed(() => {
|
||||||
// });
|
// });
|
||||||
let optimizedImageUrl = "/img/haditha/background.webp";
|
let optimizedImageUrl = "/img/haditha/background.webp";
|
||||||
|
|
||||||
if (!showNoData.value) {
|
if (loadedItems.value) {
|
||||||
// optimizedImageUrl = img("/img/haditha/sub-header-bgi.webp", {
|
// optimizedImageUrl = img("/img/haditha/sub-header-bgi.webp", {
|
||||||
// quality: 80,
|
// quality: 80,
|
||||||
// });
|
// });
|
||||||
|
@ -205,6 +203,7 @@ const exitSimilarMode = () => {
|
||||||
};
|
};
|
||||||
// ارسال درخواست
|
// ارسال درخواست
|
||||||
const sendQuery = async (payload = {}) => {
|
const sendQuery = async (payload = {}) => {
|
||||||
|
try {
|
||||||
let url = hadithaApi.search.list;
|
let url = hadithaApi.search.list;
|
||||||
url = url.replace("@index_key", "dhparag");
|
url = url.replace("@index_key", "dhparag");
|
||||||
url = url.replace("@search_type", search_type.value); // normal, and , phrase, vector, synonym
|
url = url.replace("@search_type", search_type.value); // normal, and , phrase, vector, synonym
|
||||||
|
@ -231,7 +230,9 @@ const sendQuery = async (payload = {}) => {
|
||||||
// if (route.query.f_aik?.length) url += `&f_aik=${route.query.f_aik}`;
|
// if (route.query.f_aik?.length) url += `&f_aik=${route.query.f_aik}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await httpService.postRequest(url, payload).then((res) => {
|
return await httpService
|
||||||
|
.postRequest(url, payload)
|
||||||
|
.then((res) => {
|
||||||
total.value = res.hits.total.value ?? 0;
|
total.value = res.hits.total.value ?? 0;
|
||||||
offset.value += mainState.pagination.limit;
|
offset.value += mainState.pagination.limit;
|
||||||
|
|
||||||
|
@ -241,81 +242,111 @@ const sendQuery = async (payload = {}) => {
|
||||||
// close the history dropdown menu
|
// close the history dropdown menu
|
||||||
open.value = false;
|
open.value = false;
|
||||||
return res;
|
return res;
|
||||||
});
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("API Error:", err.message);
|
||||||
|
throw err; // Re-throw the error to be handled by useAsyncData
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Server-side initial load
|
// Server-side initial load
|
||||||
const { data: loadedItems } = await useAsyncData("search", () => sendQuery(), {
|
|
||||||
transform: (data) => data.hits.hits,
|
|
||||||
});
|
|
||||||
showNoData.value = loadedItems.value?.length == 0;
|
|
||||||
|
|
||||||
const onBeforeSendQuery = (from) => {
|
const {
|
||||||
if (loading.value) return;
|
data: loadedItems,
|
||||||
loading.value = true;
|
status,
|
||||||
|
refresh,
|
||||||
|
clear,
|
||||||
|
error,
|
||||||
|
execute,
|
||||||
|
} = await useAsyncData(
|
||||||
|
"search",
|
||||||
|
async () => {
|
||||||
|
if (searchTerm.value.length) {
|
||||||
|
return await sendQuery();
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
hits: {
|
||||||
|
hits: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transform: (data) => data.hits.hits,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const onBeforeSendQuery = () => {
|
||||||
|
if (status.value == "pending") return;
|
||||||
|
status.value = "pending";
|
||||||
|
offset.value = 0;
|
||||||
|
|
||||||
|
if (searchTerm.value?.length) {
|
||||||
|
sendQuery().then((res) => {
|
||||||
|
loadedItems.value = res?.hits?.hits ?? [];
|
||||||
|
showNoData.value = loadedItems.value?.length == 0;
|
||||||
|
status.value = "success";
|
||||||
|
|
||||||
history?.pushState(
|
history?.pushState(
|
||||||
{},
|
{},
|
||||||
document?.title,
|
document?.title,
|
||||||
route.path + `?q=${searchTerm.value}`
|
route.path + `?q=${searchTerm.value}`
|
||||||
);
|
);
|
||||||
|
route.query.q = searchTerm.value;
|
||||||
offset.value = 0;
|
|
||||||
|
|
||||||
if (searchTerm.value?.length) {
|
|
||||||
sendQuery().then((res) => {
|
|
||||||
loadedItems.value = res.hits.hits;
|
|
||||||
showNoData.value = loadedItems.value?.length == 0;
|
|
||||||
loading.value = false;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
searchTerm.value = "";
|
resetForm();
|
||||||
loading.value = false;
|
|
||||||
loadedItems.value = [];
|
// searchTerm.value = "";
|
||||||
showNoData.value = false;
|
// loading.value = false;
|
||||||
loading.value = false;
|
// loadedItems.value = [];
|
||||||
|
// showNoData.value = false;
|
||||||
|
// loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Client-side infinite scroll
|
// Client-side infinite scroll
|
||||||
useInfiniteScroll(
|
// useInfiniteScroll(
|
||||||
el,
|
// el,
|
||||||
async () => {
|
// async () => {
|
||||||
if (!hasMore.value || loading.value) return;
|
// if (!hasMore.value || loading.value) return;
|
||||||
|
|
||||||
loading.value = true;
|
// loading.value = true;
|
||||||
try {
|
// try {
|
||||||
// const nextPage = page.value + 1;
|
// // const nextPage = page.value + 1;
|
||||||
await sendQuery().then((res) => {
|
// await sendQuery().then((res) => {
|
||||||
const hits = res.hits.hits;
|
// const hits = res.hits.hits;
|
||||||
|
|
||||||
if (hits.length) {
|
// if (hits.length) {
|
||||||
loadedItems.value.push(...hits);
|
// loadedItems.value.push(...hits);
|
||||||
} else {
|
// } else {
|
||||||
hasMore.value = false;
|
// hasMore.value = false;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
} finally {
|
// } finally {
|
||||||
loading.value = false;
|
// loading.value = false;
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{ distance: 100 }
|
// { distance: 100 }
|
||||||
);
|
// );
|
||||||
// دکمه جستجو کردن
|
// دکمه جستجو کردن
|
||||||
const onSearchButtonClick = () => {
|
const onSearchButtonClick = () => {
|
||||||
if (loading.value) return;
|
if (status.value == "pending") return;
|
||||||
loading.value = true;
|
status.value = "pending";
|
||||||
|
|
||||||
sendQuery().then((res) => {
|
sendQuery().then((res) => {
|
||||||
loadedItems.value = res.hits.hits;
|
loadedItems.value = res.hits.hits;
|
||||||
showNoData.value = loadedItems.value?.length == 0;
|
showNoData.value = loadedItems.value?.length == 0;
|
||||||
loading.value = false;
|
status.value = "idle";
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
|
clear();
|
||||||
searchTerm.value = "";
|
searchTerm.value = "";
|
||||||
loadedItems.value = [];
|
route.query.q = null;
|
||||||
|
// loadedItems.value = [];
|
||||||
|
status.value = "idle";
|
||||||
showNoData.value = false;
|
showNoData.value = false;
|
||||||
loading.value = false;
|
history?.pushState({}, document?.title, route.path);
|
||||||
};
|
};
|
||||||
|
|
||||||
// وقتی کاربر کلیدی فشار میدهد
|
// وقتی کاربر کلیدی فشار میدهد
|
||||||
|
@ -333,10 +364,10 @@ const resetForm = () => {
|
||||||
// تنظیم نوع جستجو
|
// تنظیم نوع جستجو
|
||||||
const setType = (type: string) => {
|
const setType = (type: string) => {
|
||||||
search_type.value = type;
|
search_type.value = type;
|
||||||
loadedItems.value = [];
|
// loadedItems.value = [];
|
||||||
offset.value = 0;
|
offset.value = 0;
|
||||||
sendQuery().then((res) => {
|
sendQuery().then((res) => {
|
||||||
loadedItems.value = res.hits.hits;
|
loadedItems.value = res?.hits?.hits ?? [];
|
||||||
showNoData.value = loadedItems.value?.length == 0;
|
showNoData.value = loadedItems.value?.length == 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -455,6 +486,60 @@ const onAddNewTitle = (subTitles) => {
|
||||||
showNoData.value = loadedItems.value?.length == 0;
|
showNoData.value = loadedItems.value?.length == 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Using the Intersection Observer version
|
||||||
|
|
||||||
|
const loadMore = async () => {
|
||||||
|
// const listElm = $event.target;
|
||||||
|
|
||||||
|
if (!hasMore.value) return;
|
||||||
|
// // window.innerHeight + window.scrollY >= document.body.offsetHeight - 100
|
||||||
|
// if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
|
||||||
|
// status.value = "pending";
|
||||||
|
// mainState.pagination.offset =
|
||||||
|
// mainState.pagination.offset + mainState.pagination.limit;
|
||||||
|
|
||||||
|
// if (total.value > mainState.pagination.offset) {
|
||||||
|
// window.clearTimeout(isScrolling.value);
|
||||||
|
// isScrolling.value = setTimeout(() => {
|
||||||
|
return await sendQuery().then((res) => {
|
||||||
|
const hits = res?.hits?.hits ?? [];
|
||||||
|
|
||||||
|
if (hits.length == 0) hasMore.value = false;
|
||||||
|
else loadedItems.value.push(...hits);
|
||||||
|
// status.value = "success";
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
// }, 300);
|
||||||
|
// } else {
|
||||||
|
// toast.add({
|
||||||
|
// title: "کاربر محترم",
|
||||||
|
// description: "دیگر رکوردی جهت بارگزاری وجود ندارد.",
|
||||||
|
// color: "success",
|
||||||
|
// });
|
||||||
|
// status.value = "idle";
|
||||||
|
// }
|
||||||
|
// } else status.value = "idle";
|
||||||
|
};
|
||||||
|
const { isFetching } = useInfiniteScroll(loadMore, "searchInfiniteScroll");
|
||||||
|
|
||||||
|
// Add the scroll event listener when the component is mounted
|
||||||
|
// onMounted(() => {
|
||||||
|
// const targetElement = document.getElementById("search-list");
|
||||||
|
|
||||||
|
// if (targetElement) {
|
||||||
|
// targetElement.addEventListener("scroll", loadMore);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // Remove the scroll event listener when the component is unmounted
|
||||||
|
// onUnmounted(() => {
|
||||||
|
// const targetElement = document.getElementById("search-list");
|
||||||
|
// if (targetElement) {
|
||||||
|
// targetElement.removeEventListener("scroll", loadMore);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
// #endregion methods
|
// #endregion methods
|
||||||
|
|
||||||
// #region components
|
// #region components
|
||||||
|
@ -508,7 +593,7 @@ const SearchList = defineAsyncComponent(
|
||||||
|
|
||||||
<UInput
|
<UInput
|
||||||
class="w-full focus:placeholder-gray-800"
|
class="w-full focus:placeholder-gray-800"
|
||||||
v-model="searchTerm"
|
v-model.trim="searchTerm"
|
||||||
v-model:open="open"
|
v-model:open="open"
|
||||||
v-model:search-term="searchTerm"
|
v-model:search-term="searchTerm"
|
||||||
placeholder="هوشمند جستجو کنید..."
|
placeholder="هوشمند جستجو کنید..."
|
||||||
|
@ -520,7 +605,7 @@ const SearchList = defineAsyncComponent(
|
||||||
side: 'bottom',
|
side: 'bottom',
|
||||||
sideOffset: 4,
|
sideOffset: 4,
|
||||||
}"
|
}"
|
||||||
:loading="loading"
|
:loading="status == 'pending'"
|
||||||
highlight
|
highlight
|
||||||
highlightOnHover
|
highlightOnHover
|
||||||
@focus="open = true"
|
@focus="open = true"
|
||||||
|
@ -554,7 +639,7 @@ const SearchList = defineAsyncComponent(
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="search-filter flex items-center my-3 justify-between"
|
class="search-filter flex items-center my-3 justify-between"
|
||||||
v-if="!showNoData"
|
v-if="loadedItems"
|
||||||
>
|
>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<!-- #region معنایی -->
|
<!-- #region معنایی -->
|
||||||
|
@ -782,15 +867,10 @@ const SearchList = defineAsyncComponent(
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="showNoData"
|
v-if="!loadedItems"
|
||||||
class="flex justify-center flex-col items-center mt-10"
|
class="flex justify-center flex-col items-center mt-10"
|
||||||
>
|
>
|
||||||
<img
|
<img fit="auto" quality="80" src="/img/haditha/logo.webp" />
|
||||||
fit="auto"
|
|
||||||
quality="80"
|
|
||||||
placeholder
|
|
||||||
src="/img/haditha/logo.webp"
|
|
||||||
/>
|
|
||||||
<div class="title">
|
<div class="title">
|
||||||
کاوش با
|
کاوش با
|
||||||
<span class="badge-style mx-1">هوش مصنوعی</span>
|
<span class="badge-style mx-1">هوش مصنوعی</span>
|
||||||
|
@ -798,33 +878,40 @@ const SearchList = defineAsyncComponent(
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- v-show="!showNoData" -->
|
||||||
<div
|
<div
|
||||||
v-show="!showNoData"
|
|
||||||
class="search-box-container pb-0 bg-white flex justify-center"
|
class="search-box-container pb-0 bg-white flex justify-center"
|
||||||
|
:class="{ 'pt-0': loadedItems == undefined }"
|
||||||
>
|
>
|
||||||
<div class="search-list-contianer">
|
<div class="search-list-contianer">
|
||||||
<div class="total">
|
<div v-if="loadedItems" class="total">
|
||||||
<span>{{ total }}</span>
|
<span>{{ total }}</span>
|
||||||
نتیجه
|
نتیجه
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- v-show="!loading" -->
|
<!-- ref="el" -->
|
||||||
<div ref="el" class="search-list firefox-scrollbar">
|
<div
|
||||||
|
ref="searchInfiniteScroll"
|
||||||
|
id="searchInfiniteScroll"
|
||||||
|
class="search-list firefox-scrollbar"
|
||||||
|
:class="{ 'enable-scroll': loadedItems?.length }"
|
||||||
|
>
|
||||||
<search-list
|
<search-list
|
||||||
no-data-text="نتیجهای یافت نشد!"
|
no-data-text="نتیجهای یافت نشد!"
|
||||||
no-data-icon="/img/haditha/no-data.png"
|
no-data-icon="/img/haditha/no-data.png"
|
||||||
:total="total"
|
:total="total"
|
||||||
:list="loadedItems"
|
:list="loadedItems"
|
||||||
:searchTerm="searchTerm"
|
:searchTerm="searchTerm"
|
||||||
|
:requestStatus="status"
|
||||||
></search-list>
|
></search-list>
|
||||||
|
|
||||||
<!-- <no-data
|
<no-data
|
||||||
class="h-full w-full flex flex-col justify-center items-center"
|
class="h-full w-full flex flex-col justify-center items-center"
|
||||||
v-if="showNoData"
|
v-if="loadedItems?.length == 0"
|
||||||
>
|
>
|
||||||
<img fit="auto" quality="80" src="/img/haditha/no-data.png" />
|
<img fit="auto" quality="80" src="/img/haditha/no-data.png" />
|
||||||
<p class="no-data-text">"نتیجهای یافت نشد!</p>
|
<p class="no-data-text">"نتیجهای یافت نشد!</p>
|
||||||
</no-data> -->
|
</no-data>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -876,6 +963,9 @@ const SearchList = defineAsyncComponent(
|
||||||
&.pb-0 {
|
&.pb-0 {
|
||||||
padding-bottom: 0 !important;
|
padding-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
&.pt-0 {
|
||||||
|
padding-top: 0 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-list-contianer {
|
.search-list-contianer {
|
||||||
|
@ -898,9 +988,12 @@ const SearchList = defineAsyncComponent(
|
||||||
color: #b4c2cf;
|
color: #b4c2cf;
|
||||||
}
|
}
|
||||||
.search-list {
|
.search-list {
|
||||||
|
&.enable-scroll {
|
||||||
padding: 1em 1.3em;
|
padding: 1em 1.3em;
|
||||||
height: calc(100dvh - 16em);
|
height: calc(100dvh - 16em);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
&.hadithaFavorites {
|
&.hadithaFavorites {
|
||||||
height: calc(100dvh - 8em);
|
height: calc(100dvh - 8em);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user