From 3800df1b4005255a315df026e1c7ea9d7f9a71c2 Mon Sep 17 00:00:00 2001 From: mustafa-rezae Date: Tue, 18 Mar 2025 16:02:10 +0330 Subject: [PATCH] Connecting search apis --- apis/hadithaApi.js | 6 +- assets/haditha/font-icons/close-bg-circle.svg | 5 + assets/haditha/font-icons/edit-bg-circle.svg | 17 + components/haditha/AutoComplation.vue | 636 +++++++++++++----- components/haditha/search-page/SearchList.vue | 54 +- .../haditha/search-page/[id]/[slug]/index.vue | 0 pages/haditha/search/[id]/[slug]/index.vue | 334 +++++---- pages/haditha/search/index.vue | 10 +- types/hadithType.ts | 327 ++++----- 9 files changed, 912 insertions(+), 477 deletions(-) create mode 100644 assets/haditha/font-icons/close-bg-circle.svg create mode 100644 assets/haditha/font-icons/edit-bg-circle.svg delete mode 100644 components/haditha/search-page/[id]/[slug]/index.vue diff --git a/apis/hadithaApi.js b/apis/hadithaApi.js index a6df26e..1e66d06 100644 --- a/apis/hadithaApi.js +++ b/apis/hadithaApi.js @@ -1,4 +1,6 @@ export default { - search: - "repo/monir/search/@index_key/@search_type/@type_key/@listkey/@field_collapsed/@offset/@limit/@q=none", + search: { + list: "repo/monir/search/@index_key/@search_type/@type_key/@listkey/@field_collapsed/@offset/@limit/@q=none", + show: "repo/public/get/byid/@index_key/@id", + }, }; diff --git a/assets/haditha/font-icons/close-bg-circle.svg b/assets/haditha/font-icons/close-bg-circle.svg new file mode 100644 index 0000000..4cb2aa3 --- /dev/null +++ b/assets/haditha/font-icons/close-bg-circle.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/haditha/font-icons/edit-bg-circle.svg b/assets/haditha/font-icons/edit-bg-circle.svg new file mode 100644 index 0000000..c25c914 --- /dev/null +++ b/assets/haditha/font-icons/edit-bg-circle.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/components/haditha/AutoComplation.vue b/components/haditha/AutoComplation.vue index c814e77..412f26a 100644 --- a/components/haditha/AutoComplation.vue +++ b/components/haditha/AutoComplation.vue @@ -3,7 +3,8 @@ import type { InputMenuItem } from "@nuxt/ui"; import hadithaApi from "../../apis/hadithaApi"; import type { HadithResponseModel } from "../../types/hadithType"; import { useStorage } from "@vueuse/core"; -import type { MaybeArrayOfArray } from "@nuxt/ui/runtime/types/utils.js"; +import * as z from "zod"; +import type { FormSubmitEvent } from "@nuxt/ui"; // #region props const props = defineProps({ @@ -25,10 +26,15 @@ const userSearchHistory = useStorage( "userSearchHistory", new Set() // Initial value ); - -const searchTerm = ref(""); +const searchTerm = useStorage("searchPhrase", ""); const open = ref(false); const loading = ref(false); +const httpService = useNuxtApp()["$http"]; + +const search_type = ref("normal"); +const type_key = ref("hadith"); + +const synonymOne = ref(false); // If you want to share state across multiple components, // you can use the same key in useState. Nuxt will ensure @@ -42,82 +48,97 @@ const doneTypingInterval = ref(1000); // #region reactive const state = reactive({ list: [], - filters: [ - { - label: "معنایی", - items: [], - }, - { - label: "ترجمه", - items: [], - }, - { - label: "مترادف", - items: [ - { - label: "جستجو در همه", + vector: { + label: "معنایی", + value: "vector", + icon: "i-haditha-robot-indicator", + }, + type: { + icon: "", + value: "normal", + label: "نوع", + items: [ + { + label: "جستجو در همه", + onSelect(e: Event) { + console.info(e); + search_type.value = "normal"; }, - { - label: "فقط در متن عربی حدیث", + }, + { + label: "فقط در متن عربی حدیث", + onSelect(e: Event) { + search_type.value = "arabic"; }, - { - label: "فقط در ترجمه ها", + }, + { + label: "فقط در ترجمه ها", + onSelect(e: Event) { + search_type.value = "translations"; }, - { - label: "فقط در شروح", + }, + { + label: "فقط در شروح", + onSelect(e: Event) { + search_type.value = "descriptions"; }, - ], - }, - { - label: "نوع", - items: [ - { - label: "جستجو در همه", - }, - { - label: "فقط در متن عربی حدیث", - }, - { - label: "فقط در ترجمه ها", - }, - { - label: "فقط در شروح", - }, - ], - }, - { - label: "عین عبارت", - items: [ - { - label: "جستجو در همه", - }, - { - label: "فقط در متن عربی حدیث", - }, - { - label: "فقط در ترجمه ها", - }, - { - label: "فقط در شروح", - }, - ], - }, - ], + }, + ], + }, + synonym: { + value: "synonym", + label: "مترادف", + icon: "i-haditha-chevron-down", + items: [ + { + label: "جستجو در همه", + slot: "arabic", + }, + { + label: "فقط در متن عربی حدیث", + slot: "arabic", + }, + { + label: "فقط در ترجمه ها", + slot: "arabic", + }, + { + label: "فقط در شروح", + slot: "arabic", + }, + ], + }, + type_key: { + label: "ترجمه", + value: "hadith", + }, + phrase: { + label: "عین عبارت", + value: "normal", + }, }); // #endregion reactive +// #region watch +// watch( +// () => route, +// (newRoute, oldRoute) => { +// console.info(newRoute.query); +// if (newRoute.query) searchTerm.value = newRoute.query.q; +// }, +// { immediate: true } +// ); +// #endregion emits + +onMounted(() => { + if (searchTerm.value.length) sendQuery(); +}); // #region methods const clearSimilar = () => { console.info("clearSimilar"); }; -const onBlur = () => { - console.info("onBlur"); -}; -const onChange = () => { - console.info("onChange"); - sendQuery(); -}; + const onUpdateModel = (newVal: boolean | InputMenuItem | any) => { console.info("onUpdateModel", newVal); }; @@ -132,15 +153,24 @@ const onKeyUp = () => { }, doneTypingInterval.value); }; +const setType = (type: string) => { + search_type.value = type; + sendQuery(); +}; +const setKey = (type: string) => { + type_key.value = type; + sendQuery(); +}; + const sendQuery = async () => { if (loading.value) return; loading.value = true; - let url = hadithaApi.search; + let url = hadithaApi.search.list; url = url.replace("@index_key", "dhparag"); - url = url.replace("@search_type", "normal"); - url = url.replace("@type_key", "hadith"); + url = url.replace("@search_type", search_type.value); // normal, and , phrase, vector, synonym + url = url.replace("@type_key", type_key.value); // hadith, hadith_fa, hadith_ar, hadith_shr url = url.replace("@offset", "0"); url = url.replace("@limit", "10"); url = url.replace("@listkey", "normal"); @@ -150,34 +180,69 @@ const sendQuery = async () => { searchTerm.value.length ? `q=${searchTerm.value}` : "q=none" ); + // const baseURL = + // config.public.NUXT_PUBLIC_BASE_URL + config.public.NUXT_PUBLIC_API_NAME; + // fetch search list from backend(ssr) - const { data, status, error, refresh, clear } = - await useHadithaSearchComposable(url, { - method: "post", + return await httpService + .postRequest(url) + .then((res) => { + // pass res and search query to the parent. + emit("response-ready", { + res: res, + searchQuery: searchTerm.value, + }); + + loading.value = false; + // 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; + + // store search phrase + useStorage("searchPhrase", searchTerm.value); + }) + .finally(() => { + loading.value = false; }); - - if (status.value == "success") { - loading.value = false; - } - - // pass res and search query to the parent. - emit("response-ready", { - res: data.value, - searchQuery: searchTerm.value, - }); - - // 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; }; +// ------------------- form ------------------- +type Schema = z.output; +const toast = useToast(); +const schema = z.object({ + name: z.string(), +}); +const showForm = ref(false); +const isSynonymPopupOpen = ref(false); +const Formstate = reactive({ + name: "", +}); +async function onSubmit(event: FormSubmitEvent) { + toast.add({ + title: "Success", + description: "The form has been submitted.", + color: "success", + }); + console.log(event.data); +} + +// get synonyms +async function openSynonymPopup(type: string) { + search_type.value = type; + console.info("openSynonymPopup"); + sendQuery().then(() => { + isSynonymPopupOpen.value = true; + }); +} + // #endregion methods @@ -339,50 +589,6 @@ const sendQuery = async () => { .search-input { position: relative; } - .search-filter { - .filter-item { - /* width: 81px; */ - height: 40px; - border-radius: 12px; - border-width: 0.3px; - padding-top: 8px; - padding-right: 12px; - padding-bottom: 8px; - padding-left: 12px; - gap: 4px; - background-color: #fff; - border: 0.3px solid #e0e0e0; - box-shadow: 0px 1px 4px 0px #0000000d; - color: #8a92a8; - font-family: IRANSansX; - font-weight: 400; - font-size: 13px; - line-height: 20px; - letter-spacing: 0%; - text-align: right; - - &.active { - color: linear-gradient(102.02deg, #4be8ae 7.38%, #00a762 91.78%); - - * { - color: #fff; - } - } - } - } - - &.search-page { - &::before { - content: none; - } - .my-trailing-button { - /* width: 32px; */ - /* height: 32px; */ - } - .haditha-search-input { - height: 56px; - } - } } } @@ -429,7 +635,7 @@ const sendQuery = async () => { height: 72px; justify-content: space-between; padding-top: 12px; - padding-right: 12px; + /* padding-right: 12px; */ padding-bottom: 12px; padding-left: 12px; border-radius: 12px; @@ -447,5 +653,129 @@ const sendQuery = async () => { text-align: right; color: #a7acbe; } + .search-filter { + .filter-item { + /* width: 81px; */ + height: 40px; + border-radius: 12px; + border-width: 0.3px; + padding-top: 8px; + padding-right: 12px; + padding-bottom: 8px; + padding-left: 12px; + gap: 4px; + background-color: #fff; + border: 0.3px solid #e0e0e0; + box-shadow: 0px 1px 4px 0px #0000000d; + color: #8a92a8; + font-family: IRANSansX; + font-weight: 400; + font-size: 13px; + line-height: 20px; + letter-spacing: 0%; + text-align: right; + + &.active { + background-image: linear-gradient( + 102.02deg, + #4be8ae 7.38%, + #00a762 91.78% + ); + + border-color: #4be8ae; + color: #fff; + box-shadow: none; + } + } + } + + &.search-page { + .haditha-search-root { + &::before { + content: none; + } + .my-trailing-button { + width: 40px; + height: 40px; + + span.iconify { + width: 25px; + height: 25px; + } + } + .haditha-search-input { + height: 56px; + } + } + } +} +.popover-root-content { + width: 20.5em; + height: 17.75em; + /* gap: 8px; */ + /* border-radius: 16px; */ + border-width: 0.3px; + /* padding-top: 16px; */ + /* padding-right: 8px; */ + /* padding-bottom: 16px; */ + /* padding-left: 8px; */ + background: #ffffff; + border: 0.3px solid #e0e0e0; + box-shadow: 0px 8px 20px 0px #0000001a; + + .synonymItem { + .title { + font-family: IRANSansX; + font-weight: 400; + font-size: 14px; + line-height: 100%; + letter-spacing: 0%; + text-align: center; + vertical-align: middle; + color: #8a92a8; + } + /* border-bottom: 1px solid #d9d9d9; */ + + .promotion-item { + width: 52.599998474121094; + height: 36; + gap: 4px; + border-radius: 8px; + border-width: 0.3px; + padding-top: 11px; + padding-right: 12px; + padding-bottom: 11px; + padding-left: 12px; + border: 0.3px solid #d9d9d9; + background: #f0f1f4; + + font-family: IRANSansX; + font-weight: 400; + font-size: 12px; + line-height: 100%; + letter-spacing: 0%; + text-align: right; + color: #626b84; + + &.active { + background: linear-gradient(320.71deg, #b9fde0 6.56%, #e4f9f0 69.69%); + border: 0.3px solid #29d985; + color: #626b84; + } + } + .add-button { + width: 48; + height: 36; + gap: 4px; + border-radius: 8px; + border-width: 1px; + padding-right: 11px; + padding-left: 11px; + background: #ffffff; + border: 1px solid #f0f1f4; + + color: #8a92a8; + } + } } diff --git a/components/haditha/search-page/SearchList.vue b/components/haditha/search-page/SearchList.vue index 10ebc39..a7a68c7 100644 --- a/components/haditha/search-page/SearchList.vue +++ b/components/haditha/search-page/SearchList.vue @@ -15,29 +15,36 @@ const props = defineProps({ default: "/img/haditha/no-data.png", }, }); -const route = useRoute(); +const router = useRouter(); -const modal = useModal(); -const isModalOpen = ref(false); +// const modal = useModal(); +// const isModalOpen = ref(false); -function openModal() { +function openModal(selectedItem) { // modal.open(SearchShow, { title: "Welcome" }); - isModalOpen.value = true; -} -async function closeModal() { - await modal.close(); -} -function resetModal() { - modal.reset(); -} -function updateModalTitle() { - modal.patch({ title: "Updated Title" }); + // isModalOpen.value = true; + router.push({ + name: "hadithaSearchShow", + params: { + id: selectedItem._id, + slug: "no-slug", + }, + }); } +// async function closeModal() { +// await modal.close(); +// } +// function resetModal() { +// modal.reset(); +// } +// function updateModalTitle() { +// modal.patch({ title: "Updated Title" }); +// } // components declaration -const SearchShow = defineAsyncComponent(() => - import("@haditha/components/haditha/search-page/SearchShow.vue") -); +// const SearchShow = defineAsyncComponent(() => +// import("@haditha/components/haditha/search-page/SearchShow.vue") +// ); diff --git a/components/haditha/search-page/[id]/[slug]/index.vue b/components/haditha/search-page/[id]/[slug]/index.vue deleted file mode 100644 index e69de29..0000000 diff --git a/pages/haditha/search/[id]/[slug]/index.vue b/pages/haditha/search/[id]/[slug]/index.vue index 282e8cc..242aaf1 100644 --- a/pages/haditha/search/[id]/[slug]/index.vue +++ b/pages/haditha/search/[id]/[slug]/index.vue @@ -1,13 +1,27 @@ -