diff --git a/components/haditha/search-page/SearchList.vue b/components/haditha/search-page/SearchList.vue index 5223b10..348a3dc 100644 --- a/components/haditha/search-page/SearchList.vue +++ b/components/haditha/search-page/SearchList.vue @@ -75,67 +75,57 @@ const removeFromFavorites = async (item = {}, index = 0) => { </script> <template> - <div class="search-list firefox-scrollbar"> - <div - v-if="props?.list?.length" - class="search-list-item" - v-for="(item, index) in props.list" - :key="index" + <div + v-if="props?.list?.length" + class="search-list-item" + v-for="(item, index) in props.list" + :key="index" + > + <div class="flex justify-between mt-4 mb-2"> + <a + :href="`/haditha/search/${item?._source?.id}/${ + item?._source?.meta?.hadith_masoum ?? + item?._source?.meta?.hadith_sanad + }`" + @click.prevent="openModal(item)" + class="from-person block" > - <div class="flex justify-between mt-4 mb-2"> - <a - :href="`/haditha/search/${item?._source?.id}/${ - item?._source?.meta?.hadith_masoum ?? - item?._source?.meta?.hadith_sanad - }`" - @click.prevent="openModal(item)" - class="from-person block" - > - {{ - item?._source?.meta?.hadith_masoum ?? - item?._source?.meta?.hadith_sanad - }} - </a> - <UButton - v-if="route.name == 'hadithaFavorites'" - @click="removeFromFavorites(item)" - variant="ghost" - color="error" - class="copy-btn" - label="حذف" - /> - </div> - - <a - @click.prevent="openModal(item)" - class="arabic-text block" - :href="`/haditha/search/${item?._source?.id}/${item?._source?.content_ar}`" - > - {{ item?._source?.content_ar }} - </a> - <a - @click.prevent="openModal(item)" - :href="`/haditha/search/${item?._source?.id}/${item?._source?.content}`" - class="persian-text block" - v-html="item?.highlight?.['content.fa'] ?? item?._source?.content" - ></a> - <div class="flex justify-end"> - <p class="reference"> - {{ item?._source?.address?.vol_title }}، صفحه - {{ item?._source?.address?.page_num }} - </p> - </div> - </div> - - <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> + {{ + item?._source?.meta?.hadith_masoum ?? + item?._source?.meta?.hadith_sanad + }} + </a> + <UButton + v-if="route.name == 'hadithaFavorites'" + @click="removeFromFavorites(item)" + variant="ghost" + color="error" + class="copy-btn" + label="حذف" + /> </div> + <a + @click.prevent="openModal(item)" + class="arabic-text block" + :href="`/haditha/search/${item?._source?.id}/${item?._source?.content_ar}`" + > + {{ item?._source?.content_ar }} + </a> + <a + @click.prevent="openModal(item)" + :href="`/haditha/search/${item?._source?.id}/${item?._source?.content}`" + class="persian-text block" + v-html="item?.highlight?.['content.fa'] ?? item?._source?.content" + ></a> + <div class="flex justify-end"> + <p class="reference"> + {{ item?._source?.address?.vol_title }}، صفحه + {{ item?._source?.address?.page_num }} + </p> + </div> + </div> + <!-- <UModal v-model:open="isModalOpen" :dismissible="false" @@ -189,77 +179,11 @@ const removeFromFavorites = async (item = {}, index = 0) => { color: var(--ui-color-two); margin-bottom: 0.5em; - .search-list-item { - .from-person { - font-family: IRANSansX; - font-weight: 300; - font-size: 0.75rem; /*12px*/ - line-height: 1.125rem; /*18px*/ - letter-spacing: 0%; - text-align: right; - color: #00a762; /* #4be8ae 7.38% */ - margin-bottom: 0.5em; - - &:hover, - &:focus, - &:active { - cursor: pointer; - background-color: #fafafa; - } - } - .arabic-text { - font-family: Takrim; - font-weight: 400; - font-size: 1.125rem; /*18px*/ - line-height: 2rem; /*23px*/ - letter-spacing: 0%; - text-align: right; - color: var(--ui-color-two); - margin-bottom: 0.5em; - - &:hover, - &:focus, - &:active { - cursor: pointer; - background-color: #fafafa; - } - } - .persian-text { - font-family: Takrim; - font-weight: 400; - font-size: 1rem; /*16px*/ - line-height: 1.375rem; /*22px*/ - letter-spacing: 0%; - text-align: right; - color: #626b84; - margin-bottom: 0.5em; - } - .reference { - height: 24px; - gap: 4px; - padding-top: 0.25em; /*4px*/ - padding-right: 0.5em; /*8px*/ - padding-bottom: 0.25em; /*4px*/ - padding-left: 0.5em; /*8px*/ - border-radius: 6px; /*18px*/ - border-width: 0.5px; - border: 0.5px solid #d9d9d9; - - font-family: IRANSansX; - font-weight: 300; - font-size: 0.625rem; /*10px*/ - line-height: 0.9rem; /*15px*/ - letter-spacing: 0%; - text-align: right; - color: #8a92a8; - - &:hover, - &:focus, - &:active { - cursor: pointer; - background-color: #fafafa; - } - } + &:hover, + &:focus, + &:active { + cursor: pointer; + background-color: #fafafa; } } .persian-text { @@ -285,8 +209,8 @@ const removeFromFavorites = async (item = {}, index = 0) => { font-family: IRANSansX; font-weight: 300; - font-size: 1rem; - line-height: 1.5rem; /*24px*/ + font-size: 0.625rem; /*10px*/ + line-height: 0.9rem; /*15px*/ letter-spacing: 0%; text-align: right; color: #8a92a8; @@ -300,103 +224,3 @@ const removeFromFavorites = async (item = {}, index = 0) => { } } </style> -<!-- -<style> - -.text__orange { - color: orange; -} - -.modal-content { - border: 0.3px solid #e0e0e0; - box-shadow: 0px 8px 20px 0px #0000001a; - background: #ffffff; - width: 100%; - max-width: 720px; /*18px*/ - border-radius: 16px; /*18px*/ - gap: 8px; - border-width: 0.3px; - .modal-body { - border-radius: 16px; /*18px*/ - - height: 800px; /*18px*/ - position: relative; - - .top-left-bgi { - position: absolute; - top: 0; - left: 0; - background-image: url("../../../assets/haditha/images/modal-top-bgi.png"); - backdrop-filter: blur(54px); - width: 447px; - height: 447px; - top: 0; - left: 0; - - background-repeat: no-repeat; - background-size: auto; - z-index: -1; - } - - &::before { - content: ""; - position: absolute; - right: 0; - bottom: 0; - background-image: url("../../../assets/haditha/images/modal-bttom-right-bgi.png"); - backdrop-filter: blur(54px); - width: 438px; - height: 238px; - mix-blend-mode: Multiply; - background-repeat: no-repeat; - background-size: cover; - z-index: -1; - } - - &::after { - content: ""; - - position: absolute; - bottom: 0; - left: 0; - - width: 458px; - height: 239px; - mix-blend-mode: Multiply; - background-image: url("../../../assets/haditha/images/modal-bottom-left-bgi.png"); - background-repeat: no-repeat; - background-size: cover; - backdrop-filter: blur(54px); - z-index: -1; - } - } -} - -.modal-overlay { - background: #00000033; -} -.copy-btn { - padding: 0.2em 1em; - - /* width: 44px; */ - /* height: 24px; */ - gap: 4px; - border-radius: 6px; - border-width: 0.5px; - padding-top: 4px; - padding-right: 12px; - padding-bottom: 4px; - padding-left: 12px; - /* background: #ffffff; */ - /* border: 0.5px solid #d9d9d9; */ - - font-family: IRANSansX; - font-weight: 300; - font-size: 12px; - line-height: 18px; - letter-spacing: 0%; - text-align: right; - - /* color: #a71111; */ -} -</style> diff --git a/pages/haditha/library/[id]/[slug]/index.vue b/pages/haditha/library/[id]/[slug]/index.vue index e92e5c2..46c2a29 100644 --- a/pages/haditha/library/[id]/[slug]/index.vue +++ b/pages/haditha/library/[id]/[slug]/index.vue @@ -199,7 +199,7 @@ const onClose = () => { const handlePagination = ( prevNextIndicator: number, - pageNumber: number | undefined = undefined + userEnteredPage: number | undefined = undefined ) => { if (loading.value) return; loading.value = true; @@ -215,10 +215,14 @@ const handlePagination = ( let url = repoUrl() + hadithaApi.library.prevNextHadith; url = url.replace("@index_key", "dhparag"); url = url.replace("@vol_id", volId); - url = url.replace("@page_num", (pageNumber ?? page_num.value).toString()); + url = url.replace( + "@page_num", + (userEnteredPage ?? page_num.value).toString() + ); url = url.replace("@step", prevNextIndicator.toString()); - page_num.value += prevNextIndicator; + // اگر کاربر شماره صفحه ای را وارد نکرده باشد.. + if (!userEnteredPage) page_num.value = +page_num.value + prevNextIndicator; httpService .getRequest(url) @@ -248,11 +252,13 @@ const getDataTree = () => { const prepareTreeData = (data) => { return data.map((item) => { - return { + const res = { ...item, ...item._source, title: item._source.content, }; + delete res._source; + return res; }); }; @@ -320,7 +326,7 @@ const UTree = defineAsyncComponent( </div> <div class="separator"></div> - <div class="page-content py-14 p-2"> + <div class="page-content firefox-scrollbar py-14 p-2"> <!-- <h2></h2> --> <p v-if="state.selectedItem?.length" diff --git a/pages/haditha/search/[id]/[slug]/index.vue b/pages/haditha/search/[id]/[slug]/index.vue index fe3611d..0f9eec9 100644 --- a/pages/haditha/search/[id]/[slug]/index.vue +++ b/pages/haditha/search/[id]/[slug]/index.vue @@ -12,6 +12,8 @@ import hadithaApi from "@haditha/apis/hadithaApi"; import type { HadithResponseModel } from "@haditha/types/hadithType"; import type { HadithResponseShowModel } from "~/systems/hadith_ui/types/hadithType"; +import headLinks from "@haditha/json/haditha/headLinks"; +import headMetas from "@haditha/json/haditha/headMetas"; // #endregion imports // #region meta @@ -24,94 +26,12 @@ useHead({ title: `${import.meta.env.VITE_HADITH_PAGE_TITLE}`, meta: [ { name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" }, - { - name: "msapplication-TileImage", - content: "/img/haditha/fav-icons/ms-icon-144x144.png", - }, - { name: "theme-color", content: "#ffffff" }, + ...headMetas, ], bodyAttrs: { class: import.meta.env.VITE_HADITH_SYSTEM, }, - link: [ - { - rel: "icon", - type: "image/x-icon", - href: "/img/haditha/fav-icons/favicon.ico", - }, - { rel: "manifest", href: "/img/haditha/fav-icons/manifest.json" }, - // rel: icon - { - rel: "icon", - type: "image/png", - sizes: "16x16", - href: "/img/haditha/fav-icons/favicon-16x16.png", - }, - { - rel: "icon", - type: "image/png", - sizes: "32x32", - href: "/img/haditha/fav-icons/favicon-32x32.png", - }, - { - rel: "icon", - type: "image/png", - sizes: "96x96", - href: "/img/haditha/fav-icons/favicon-96x96.png", - }, - { - rel: "icon", - sizes: "192x192", - type: "image/png", - href: "/img/haditha/fav-icons/android-icon-192x192.png", - }, - // rel: apple - { - rel: "apple-touch-icon", - sizes: "57x57", - href: "/img/haditha/fav-icons/apple-icon-57x57.png", - }, - { - rel: "apple-touch-icon", - sizes: "60x60", - href: "/img/haditha/fav-icons/android-icon-60x60.png", - }, - { - rel: "apple-touch-icon", - sizes: "72x72", - href: "/img/haditha/fav-icons/android-icon-72x72.png", - }, - { - rel: "apple-touch-icon", - sizes: "76x76", - href: "/img/haditha/fav-icons/android-icon-76x76.png", - }, - { - rel: "apple-touch-icon", - sizes: "114x114", - href: "/img/haditha/fav-icons/android-icon-114x114.png", - }, - { - rel: "apple-touch-icon", - sizes: "120x120", - href: "/img/haditha/fav-icons/android-icon-120x120.png", - }, - { - rel: "apple-touch-icon", - sizes: "144x144", - href: "/img/haditha/fav-icons/android-icon-144x144.png", - }, - { - rel: "apple-touch-icon", - sizes: "152x152", - href: "/img/haditha/fav-icons/android-icon-152x152.png", - }, - { - rel: "apple-touch-icon", - sizes: "180x180", - href: "/img/haditha/fav-icons/android-icon-180x180.png", - }, - ], + link: headLinks, }); // #endregion imports @@ -335,7 +255,7 @@ const handlePagination = (prevNextIndicator: string) => { </div> </div> - <div class="content"> + <div class="content firefox-scrollbar"> <div class="search-item"> <div class="text-arabic-section"> <div class="section-header"> @@ -513,11 +433,10 @@ const handlePagination = (prevNextIndicator: string) => { <!-- because of the buttons, using without scoped. --> <style> -.page-inner-container{ +.page-inner-container { height: 100%; } .search-show-page { - .body-header { .modal-title { padding: 0 0.5em 1.5em; @@ -846,7 +765,7 @@ const handlePagination = (prevNextIndicator: string) => { .body-content { .content { height: calc(100dvh - 15em); - overflow-y: auto; + overflow-y: auto; } } } diff --git a/pages/haditha/search/index.vue b/pages/haditha/search/index.vue index 3dd52da..91755f0 100644 --- a/pages/haditha/search/index.vue +++ b/pages/haditha/search/index.vue @@ -13,6 +13,7 @@ import type { Synonym } from "@haditha/types/hadithType"; // const searchTerm = useState("searchTerm", () => ''); // Tracks the searchTerm const offset = useState("offset", () => 0); // Tracks the current offset +const total = useState("total", () => 0); // Tracks the total definePageMeta({ layout: false, @@ -48,15 +49,13 @@ const httpService = useNuxtApp()["$http"]; const route = useRoute(); const router = useRouter(); // تعداد کل نتایج -const total = ref(0); // رکوردهای جتسجو شده توسط کاربر const userSearchHistory = useStorage( "userSearchHistory", new Set() // Initial value ); // کلمه ی جستجو شده توسط کاربر -const searchTerm = ref(route.query.q ?? ""); - +const searchTerm = ref<string>(<string>route.query.q ?? ""); // وقتی کاربر از صفحه اصلی وارد جستجو میشود. // if (route.query.q) { // searchTerm.value = route.query.q ?? ""; @@ -220,10 +219,15 @@ const sendQuery = async (payload = {}) => { : "q=none" ); - // fetch search list from backend(ssr) return await httpService.postRequest(url, payload).then((res) => { total.value = res.hits.total.value ?? 0; offset.value += mainState.pagination.limit; + + // check if search term is not empty + if (searchTerm.value) userSearchHistory.value.add(searchTerm.value); // Add the value to the Set + + // close the history dropdown menu + open.value = false; return res; }); }; @@ -236,14 +240,15 @@ const { data: loadedItems } = await useAsyncData("search", () => sendQuery(), { }, }); -const onBeforeSendQuery = () => { - route.query.q = searchTerm.value; +const onBeforeSendQuery = (from) => { history?.pushState( {}, document?.title, route.path + `?q=${searchTerm.value}` ); + offset.value = 0; + sendQuery().then((res) => { loadedItems.value = res.hits.hits; }); @@ -261,14 +266,7 @@ useInfiniteScroll( const hits = res.hits.hits; if (hits.length) { - // if (initialItems.value.length) { - // loadedItems.value.push(...initialItems.value); - // loadedItems.value.push(...hits); - // initialItems.value = []; - // } else loadedItems.value.push(...hits); - loadedItems.value.push(...hits); - offset.value += mainState.pagination.limit; } else { hasMore.value = false; } @@ -491,8 +489,8 @@ const SearchList = defineAsyncComponent( highlightOnHover @focus="open = true" @blur="open = false" - @change="onBeforeSendQuery" - @keydown.enter="onBeforeSendQuery" + @change="onBeforeSendQuery('change')" + @keydown.enter="onBeforeSendQuery('enter')" > <!-- @keydown="onKeyDown" --> <!-- @update:modelValue="onUpdateModel" --> @@ -739,7 +737,7 @@ const SearchList = defineAsyncComponent( </div> </div> <div - v-if="searchTerm?.length == 0" + v-if="searchTerm?.length == 0 && loadedItems?.length == 0" class="flex justify-center flex-col items-center mt-10" > <img @@ -756,7 +754,7 @@ const SearchList = defineAsyncComponent( </div> <div - v-if="loadedItems.length" + v-else-if="searchTerm?.length && loadedItems?.length" class="search-box-container pb-0 bg-white flex justify-center" > <div class="search-list-contianer">