Compare commits

...

3 Commits

Author SHA1 Message Date
mustafa-rezae
363d1269f2 Work on login 2025-03-29 14:52:24 +03:30
mustafa-rezae
3800df1b40 Connecting search apis 2025-03-18 16:02:10 +03:30
mustafa-rezae
832f5dbf52 Connecting search apis 2025-03-15 13:41:29 +03:30
11 changed files with 1596 additions and 562 deletions

View File

@ -1,73 +0,0 @@
export default {
items: {
get: "monir/search/get/byid/",
},
Farhanghestan: {
search_normal: "monir/search/0/10",
search_And: "monir/search/and/0/10",
search_Phrase: "monir/search/phrase/0/10",
search_Code: "monir/search/code/all/0/10",
},
subject: {
add: "sanad/subject/add",
// edit: "sanad/subject/edit",
delete: "sanad/subject/delete",
order: "monir/sanad/subject/order",
},
index: {
Index_one: "safheh212/one",
index_multi: "safheh212/multi",
},
nesha: {
search_normal: "monir/search/nesha/0/10",
},
wordSWeight: {
list: "ngrams/elastic/{{index_key}}/1to3",
},
rezome: {
add: "rezumeh",
get: "rezumeh/get",
},
navigation: {
list: "navigate/list/@entity",
report:
"navigate/report/{{index_key}}/{{offset}}/{{limit}}/{{aggs}}/{{filter}}",
reportItem: "navigate/report/items",
reportSubjectItem: "navigate/report/subject={{subject_title}}/items",
},
bnavigation: {
list: "repo/navigate/list",
report: "repo/navigate/report",
reportItem: "repo/navigate/report/items",
reportSubjectItem: "repo/navigate/report/subject={{subject_title}}/items",
},
schema: {
list: "schema",
},
search: {
autoComplate:
"{{appname}}/complation/{{index_key}}/{{filter}}",
logAutoComplate:
"searchlog/complation/{{filter}}",
default:
"{{appname}}/data/{{index_key}}/{{sortKey}}/{{offset}}/{{limit}}/{{filter}}",
queryNormal:
"{{appname}}/search/{{index_key}}/{{search_type}}/{{sortKey}}/{{field_collapse}}/{{offset}}/{{limit}}/{{filter}}",
textSearch:
"{{appname}}/search/text/{{index_key}}/{{field}}/{{offset}}/{{limit}}/{{filter}}",
},
chart: {
timeline: "{{appname}}/data/timeline/{{index_key}}",
xy: "{{appname}}/data/xy/{{index_key}}/{{field_key}}",
items:
"navigate/report/items/search/{{index_key}}/{{offset}}/{{limit}}/{{filter}}",
chartTreeMap: "list/project/treemap/{{chart_key}}/{{filter}}",
treeItems:"navigate/report/items/search/{{index_key}}/{{offset}}/{{limit}}/{{filter}}",
tree: "list/subject/list",
graph:"repo/majles/{{to_key}}/relation"
},
synonym:{
getSynonyms:"synonym/get/words",
synonymSearch:"search/qasection/synonym/@listkey/@offset/@limit/@q",
}
};

6
apis/hadithaApi.js Normal file
View File

@ -0,0 +1,6 @@
export default {
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",
},
};

View File

@ -0,0 +1,5 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12.7158" r="10" fill="white"/>
<path d="M9 15.7158L15 9.71582" stroke="#8A92A8" stroke-linecap="round"/>
<path d="M9 9.71582L15 15.7158" stroke="#8A92A8" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 302 B

View File

@ -0,0 +1,17 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12.7158" r="10" fill="white"/>
<path d="M12.2796 9.32295L8.52883 13.0737C8.3805 13.222 8.24277 13.4975 8.21099 13.6988L8.00968 15.1291C7.93551 15.6482 8.29576 16.0085 8.81492 15.9343L10.2452 15.733C10.4465 15.7012 10.7326 15.5635 10.8704 15.4152L14.6211 11.6645C15.2674 11.0182 15.5746 10.2659 14.6211 9.31235C13.6781 8.36938 12.9259 8.67665 12.2796 9.32295Z" stroke="url(#paint0_linear_67_4557)" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.7395 9.86206C12.0574 11.0063 12.9473 11.8963 14.0916 12.2142" stroke="url(#paint1_linear_67_4557)" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.2796 9.32295L8.52883 13.0737C8.3805 13.222 8.24277 13.4975 8.21099 13.6988L8.00968 15.1291C7.93551 15.6482 8.29576 16.0085 8.81492 15.9343L10.2452 15.733C10.4465 15.7012 10.7326 15.5635 10.8704 15.4152L14.6211 11.6645C15.2674 11.0182 15.5746 10.2659 14.6211 9.31235C13.6781 8.36938 12.9259 8.67665 12.2796 9.32295Z" stroke="#8A92A8" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.7395 9.86206C12.0574 11.0063 12.9473 11.8963 14.0916 12.2142" stroke="#8A92A8" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<defs>
<linearGradient id="paint0_linear_67_4557" x1="15.274" y1="8.71582" x2="7.53191" y2="8.85851" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
<linearGradient id="paint1_linear_67_4557" x1="14.1071" y1="9.86206" x2="11.5871" y2="9.90852" gradientUnits="userSpaceOnUse">
<stop stop-color="#D284FF"/>
<stop offset="1" stop-color="#4D00FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,4 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import type { InputMenuItem } from "@nuxt/ui";
import hadithaApi from "../../apis/hadithaApi";
import { useStorage } from "@vueuse/core";
import * as z from "zod";
import type { FormSubmitEvent } from "@nuxt/ui";
// #region props
const props = defineProps({ const props = defineProps({
showFilter: { showFilter: {
default: false, default: false,
@ -7,163 +14,238 @@ const props = defineProps({
default: false, default: false,
}, },
}); });
// #endregion props
// #region emits
const emit = defineEmits(["response-ready"]); const emit = defineEmits(["response-ready"]);
const router = useRouter(); // #endregion emits
export type Sample = { // #region refs
fromPerson: string; const userSearchHistory = useStorage(
arabicText: string; "userSearchHistory",
persianText: string; new Set() // Initial value
reference: string; );
}; const searchTerm = useStorage<string>("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);
const synonymTwo = ref(false);
// If you want to share state across multiple components,
// you can use the same key in useState. Nuxt will ensure
// that the state is shared and reactive across your application.
// const typingTimer = useState<number>("typingTimer", () => 0);
// const doneTypingInterval = useState<number>("doneTypingInterval", () => 1000);
const typingTimer = ref<number | any>(0);
const doneTypingInterval = ref<number>(1000);
// #endregion refs
// #region reactive
const state = reactive({ const state = reactive({
list: [ list: [],
{ vector: {
fromPerson: "امام علی علیه‌السلام",
arabicText:
" وَمَا يَذۡكُرُونَ إِلَّآ أَن يَشَآءَ ٱللَّهُ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ",
persianText:
" خداوند متعال ما (اهل بیت) را آفرید و ما را خازنان علم خود در آسمان و زمین قرار داد. و نماز در مسیحیت برای ما قرار که پیش",
reference: "الکافی، جلد ۱، صفحه ۱۰۳",
},
{
fromPerson: "امام علی علیه‌السلام",
arabicText:
" وَمَا يَذۡكُرُونَ إِلَّآ أَن يَشَآءَ ٱللَّهُ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ",
persianText:
" خداوند متعال ما (اهل بیت) را آفرید و ما را خازنان علم خود در آسمان و زمین قرار داد. و نماز در مسیحیت برای ما قرار که پیش",
reference: "الکافی، جلد ۱، صفحه ۱۰۳",
},
{
fromPerson: "امام علی علیه‌السلام",
arabicText:
" وَمَا يَذۡكُرُونَ إِلَّآ أَن يَشَآءَ ٱللَّهُ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ",
persianText:
" خداوند متعال ما (اهل بیت) را آفرید و ما را خازنان علم خود در آسمان و زمین قرار داد. و نماز در مسیحیت برای ما قرار که پیش",
reference: "الکافی، جلد ۱، صفحه ۱۰۳",
},
],
filters: [
{
label: "معنایی", label: "معنایی",
items: [], value: "vector",
icon: "i-haditha-robot-indicator",
}, },
{ type: {
label: "ترجمه", icon: "",
items: [], value: "normal",
},
{
label: "مترادف",
items: [
{
label: "جستجو در همه",
},
{
label: "فقط در متن عربی حدیث",
},
{
label: "فقط در ترجمه ها",
},
{
label: "فقط در شروح",
},
],
},
{
label: "نوع", label: "نوع",
items: [ items: [
{ {
label: "جستجو در همه", 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";
},
}, },
], ],
}, },
{ synonym: {
label: "عین عبارت", value: "synonym",
label: "مترادف",
icon: "i-haditha-chevron-down",
items: [ items: [
{ {
label: "جستجو در همه", label: "جستجو در همه",
slot: "arabic",
}, },
{ {
label: "فقط در متن عربی حدیث", label: "فقط در متن عربی حدیث",
slot: "arabic",
}, },
{ {
label: "فقط در ترجمه ها", label: "فقط در ترجمه ها",
slot: "arabic",
}, },
{ {
label: "فقط در شروح", label: "فقط در شروح",
slot: "arabic",
}, },
], ],
}, },
], type_key: {
label: "ترجمه",
value: "hadith",
},
phrase: {
label: "عین عبارت",
value: "normal",
},
}); });
const searchTerm = ref<string>(""); // #endregion reactive
const open = ref(false);
const loading = ref(false);
// fetch history list from backend(ssr) // #region watch
// const { data: users, status } = await useFetch( // watch(
// "https://jsonplaceholder.typicode.com/users", // () => route,
// { // (newRoute, oldRoute) => {
// transform: (data: { id: number; name: string }[]) => { // console.info(newRoute.query);
// return ( // if (newRoute.query) searchTerm.value = <string>newRoute.query.q;
// data?.map((user) => ({
// label: user.name,
// value: String(user.id),
// avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` },
// })) || []
// );
// }, // },
// lazy: true, // { immediate: true }
// }
// ); // );
// #endregion emits
onMounted(() => {
if (searchTerm.value.length) sendQuery();
});
// #region methods
const clearSimilar = () => { const clearSimilar = () => {
console.info("clearSimilar"); console.info("clearSimilar");
}; };
const onBlur = () => {
// console.info("onBlue"); const onUpdateModel = (newVal: boolean | InputMenuItem | any) => {
};
const onChange = () => {
// console.info("onChange");
};
const onUpdateModel = (newVal: string) => {
console.info("onUpdateModel", newVal); console.info("onUpdateModel", newVal);
}; };
const onSearch = () => {
console.info("onSearch");
router.push({
name: "hadithaSearch",
});
};
const onKeyDown = () => { const onKeyDown = () => {
// console.info("onKeyDown"); clearTimeout(typingTimer.value);
}; };
const onKeyUp = () => { const onKeyUp = () => {
// console.info("onKeyUp"); clearTimeout(typingTimer.value);
typingTimer.value = setTimeout(() => {
sendQuery();
}, doneTypingInterval.value);
}; };
const onSend = () => {
console.info("onSend");
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.list;
url = url.replace("@index_key", "dhparag");
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");
url = url.replace("@field_collapsed", "normal");
url = url.replace(
"@q=none",
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)
return await httpService
.postRequest(url)
.then((res) => {
// pass res and search query to the parent.
emit("response-ready", { emit("response-ready", {
searchList: state.list, res: res,
searchQuery: searchTerm.value, 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);
})
.catch((err) => {
console.info(err);
})
.finally(() => {
loading.value = false;
});
}; };
// ------------------- form -------------------
type Schema = z.output<typeof schema>;
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<Schema>) {
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
</script> </script>
<template> <template>
<div class="haditha-search-root-wrapper"> <div class="haditha-search-root-wrapper">
<div class="haditha-search-root"> <div class="haditha-search-root" :class="{ 'no-backdrop': showPrevSearch }">
<!-- وقتی کاربر در صفحه نمایش بر روی مشابه کلیک میکند و به صفحه جستجو وارد میشود. -->
<div v-if="showPrevSearch" class="prev-search-item flex items-center"> <div v-if="showPrevSearch" class="prev-search-item flex items-center">
<span class="total">۴۷ مشابه </span> <span class="total">۴۷ مشابه </span>
<span class="text me-auto"> <span class="text me-auto">
@ -177,16 +259,18 @@ const onSend = () => {
@click="clearSimilar" @click="clearSimilar"
/> />
</div> </div>
<!-- <client-only> -->
<div class="search-input"> <div class="search-input">
<UInputMenu <UInputMenu
class="w-full focus:placeholder-gray-800" class="w-full focus:placeholder-gray-800"
:items="[]" :items="<any>Array.from(userSearchHistory)"
v-model="searchTerm" v-model="searchTerm"
v-model:open="open" v-model:open="open"
v-model:search-term="searchTerm" v-model:search-term="searchTerm"
placeholder="هوشمند جستجو کنید..." placeholder="هوشمند جستجو کنید..."
:ui="{ :ui="{
base: ['haditha-search-input'], base: 'haditha-search-input',
}" }"
:content="{ :content="{
align: 'start', align: 'start',
@ -198,23 +282,212 @@ const onSend = () => {
highlightOnHover highlightOnHover
@focus="open = true" @focus="open = true"
@blur="open = false" @blur="open = false"
@change="onChange" @change="sendQuery"
@update:modelValue="onUpdateModel" @update:modelValue="onUpdateModel"
@update:searchTerm="onUpdateModel" @update:searchTerm="onUpdateModel"
@keydown="onKeyDown" @keydown="onKeyDown"
@keyup="onKeyUp" @keyup="onKeyUp"
@keydown.enter="onSend" @keydown.enter="sendQuery"
> >
</UInputMenu> </UInputMenu>
</div> </div>
<UButton class="my-trailing-button" @click.prevent="onSearch" icon="i-haditha-search"> <UButton
class="my-trailing-button"
@click.prevent="sendQuery"
icon="i-haditha-search"
>
<!-- <UIcon name="i-lucide-search" /> --> <!-- <UIcon name="i-lucide-search" /> -->
</UButton> </UButton>
<!-- </client-only> -->
</div> </div>
<div class="search-filter my-3 space-x-2" v-if="props.showFilter"> <div
class="search-filter flex items-center my-3 justify-between"
v-if="props.showFilter && searchTerm.length"
>
<div class="flex items-center space-x-2">
<!-- معنایی -->
<!-- @click.self="search_type = 'vector'" -->
<UButton
@click.self="setType('vector')"
:class="{ active: search_type == 'vector' }"
type="button"
class="filter-item"
:icon="state.vector.icon"
>
{{ state.vector.label }}
<UIcon
v-if="search_type == 'vector'"
@click.self="search_type = 'normal'"
name="i-haditha-close-bg-circle"
size="20px"
>
</UIcon>
</UButton>
<!-- مترادف -->
<UPopover
:content="{
align: 'start',
side: 'bottom',
sideOffset: 8,
}"
:ui="{
content: 'popover-root-content',
}"
v-model:open="isSynonymPopupOpen"
>
<UButton
@click="openSynonymPopup('synonym')"
class="filter-item"
:label="state.synonym.label"
trailingIcon="i-haditha-dropdown-chevron-down"
/>
<template #content>
<!-- synonym item -->
<div class="synonymItem px-2 py-4">
<div class="flex justify-between items-center p-3 mb-2">
<span class="title"> نماز </span>
<USwitch dir="ltr" v-model="synonymOne" />
</div>
<div class="flex items-center px-2">
<UButton
type="button"
@click="true"
class="me-2.5 mb-3.5 promotion-item"
:class="{ active: false }"
>
صلات
<!-- <UIcon name="i-haditha-close-bg-circle" size="12px"> </UIcon> -->
</UButton>
<UButton
type="button"
@click="true"
class="me-2.5 mb-3.5 promotion-item"
:class="{ active: false }"
>
عبادت
<!-- <UIcon name="i-haditha-close-bg-circle" size="12px"> </UIcon> -->
</UButton>
<UButton
v-if="!showForm"
type="button"
@click="showForm = true"
class="me-2.5 mb-3.5 add-button"
:class="{ active: false }"
icon="i-haditha-add"
>
</UButton>
<UForm
v-else
:schema="schema"
:state="state"
class="w-25 me-2.5 mb-3.5"
>
<UFormField name="name" required size="md">
<UInput
v-model="Formstate.name"
placeholder="بنویسید ..."
/>
</UFormField>
</UForm>
</div>
</div>
<USeparator class="px-2" color="neutral" type="solid" size="xs" />
<!-- synonym item -->
<div class="synonymItem px-2 py-4">
<div class="flex justify-between items-center p-3 mb-2">
<span class="title"> نماز </span>
<USwitch dir="ltr" v-model="synonymTwo" />
</div>
<div class="flex items-center px-2">
<UButton
type="button"
@click="true"
class="me-2.5 mb-3.5 promotion-item"
:class="{ active: false }"
>
صلات
<!-- <UIcon name="i-haditha-close-bg-circle" size="12px"> </UIcon> -->
</UButton>
<UButton
type="button"
@click="true"
class="me-2.5 mb-3.5 promotion-item"
:class="{ active: false }"
>
عبادت
<!-- <UIcon name="i-haditha-close-bg-circle" size="12px"> </UIcon> -->
</UButton>
<UButton
v-if="!showForm"
type="button"
@click="showForm = true"
class="me-2.5 mb-3.5 add-button"
:class="{ active: false }"
icon="i-haditha-add"
>
</UButton>
<UForm
v-else
:schema="schema"
:state="state"
class="w-25 me-2.5 mb-3.5"
>
<UFormField name="name" required size="md">
<UInput
v-model="Formstate.name"
placeholder="بنویسید ..."
/>
</UFormField>
</UForm>
</div>
</div>
<USeparator class="px-2" color="neutral" type="solid" size="xs" />
</template>
</UPopover>
<!-- ترجمه -->
<UButton
@click.self="setKey('hadith_fa')"
:class="{ active: type_key == 'hadith_fa' }"
type="button"
class="filter-item"
>
{{ state.type_key.label }}
<UIcon
v-if="type_key == 'hadith_fa'"
@click.self="setKey('hadith')"
name="i-haditha-close-bg-circle"
size="20px"
>
</UIcon>
</UButton>
<!-- عین عبارت -->
<UButton
@click.self="setType('phrase')"
:class="{ active: search_type == 'phrase' }"
class="filter-item"
>
{{ state.phrase.label }}
<UIcon
v-if="search_type == 'phrase'"
@click.self="search_type = 'normal'"
name="i-haditha-close-bg-circle"
size="20px"
>
</UIcon>
</UButton>
</div>
<!-- نوع -->
<div>
<UDropdownMenu <UDropdownMenu
v-for="(filter, index) in state.filters" :items="state.type.items"
:items="filter.items"
:content="{ :content="{
align: 'start', align: 'start',
side: 'bottom', side: 'bottom',
@ -223,15 +496,30 @@ const onSend = () => {
:ui="{ :ui="{
content: 'w-48', content: 'w-48',
}" }"
:class="{ active: state.type.value == 'hadith' }"
> >
<UButton <UButton
class="filter-item" class="filter-item"
:label="filter.label" :label="state.type.label"
:trailingIcon="filter.items?.length ? 'i-haditha-chevron-down' : ''" trailingIcon="i-haditha-dropdown-chevron-down"
/> >
{{ state.type.label }}
<UIcon
v-if="state.type.value != 'normal'"
@click.self="state.type.value = 'normal'"
name="i-haditha-close-bg-circle"
size="20px"
>
</UIcon>
</UButton>
<!-- <template #item> item </template> -->
<!-- <template #item-label> item label </template> -->
</UDropdownMenu> </UDropdownMenu>
</div> </div>
</div> </div>
</div>
</template> </template>
<style scoped> <style scoped>
@ -321,50 +609,6 @@ const onSend = () => {
.search-input { .search-input {
position: relative; 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;
}
}
} }
} }
</style> </style>
@ -411,7 +655,7 @@ const onSend = () => {
height: 72px; height: 72px;
justify-content: space-between; justify-content: space-between;
padding-top: 12px; padding-top: 12px;
padding-right: 12px; /* padding-right: 12px; */
padding-bottom: 12px; padding-bottom: 12px;
padding-left: 12px; padding-left: 12px;
border-radius: 12px; border-radius: 12px;
@ -429,5 +673,129 @@ const onSend = () => {
text-align: right; text-align: right;
color: #a7acbe; 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;
}
}
} }
</style> </style>

View File

@ -5,6 +5,9 @@ const props = defineProps({
return []; return [];
}, },
}, },
total: {
default: 0,
},
noDataText: { noDataText: {
default: "نتیجه‌ای یافت نشد!", default: "نتیجه‌ای یافت نشد!",
}, },
@ -12,56 +15,65 @@ const props = defineProps({
default: "/img/haditha/no-data.png", default: "/img/haditha/no-data.png",
}, },
}); });
const route = useRoute(); const router = useRouter();
const modal = useModal(); // const modal = useModal();
const isModalOpen = ref(false); // const isModalOpen = ref(false);
function openModal() { function openModal(selectedItem) {
// modal.open(SearchShow, { title: "Welcome" }); // modal.open(SearchShow, { title: "Welcome" });
isModalOpen.value = true; // isModalOpen.value = true;
} router.push({
async function closeModal() { name: "hadithaSearchShow",
await modal.close(); params: {
} id: selectedItem._id,
function resetModal() { slug: "no-slug",
modal.reset(); },
} });
function updateModalTitle() {
modal.patch({ title: "Updated Title" });
} }
// async function closeModal() {
// await modal.close();
// }
// function resetModal() {
// modal.reset();
// }
// function updateModalTitle() {
// modal.patch({ title: "Updated Title" });
// }
// components declaration // components declaration
const SearchShow = defineAsyncComponent(() => // const SearchShow = defineAsyncComponent(() =>
import("@haditha/components/haditha/search-page/SearchShow.vue") // import("@haditha/components/haditha/search-page/SearchShow.vue")
); // );
</script> </script>
<template> <template>
<div class="search-list-contianer"> <div class="search-list-contianer">
<div class="total"> <div class="total">
<span>48</span> <span>{{ total }}</span>
نتیجه نتیجه
</div> </div>
<div class="search-list firefox-scrollbar" :class="route.name"> <div class="search-list firefox-scrollbar">
<div <div
v-if="props.list.length" v-if="props.list.length"
class="search-list-item" class="search-list-item"
v-for="(item, index) in props.list" v-for="(item, index) in props.list"
:key="index" :key="index"
> >
<p @click="openModal(item)" class="from-person">امام علی علیهالسلام</p> <p @click="openModal(item)" class="from-person">
<p @click="openModal(item)" class="arabic-text"> {{ item._source.meta.hadith_masoum ?? "بدون عنوان" }}
وَمَا يَذۡكُرُونَ إِلَّآ أَن يَشَآءَ ٱللَّهُ هُوَ أَهلُ ٱلتَّقوَىٰ
وَأَهلُ ٱلمَغفِرَةِ هُوَ أَهلُ ٱلتَّقوَىٰ وَأَهلُ ٱلمَغفِرَةِ
</p>
<p class="persian-text">
خداوند متعال ما (اهل بیت) را آفرید و ما را خازنان علم خود در آسمان و
زمین قرار داد. و نماز در مسیحیت برای ما قرار که پیش
</p> </p>
<p @click="openModal(item)" class="arabic-text">بدون متن عربی</p>
<p
class="persian-text"
v-html="item.highlight['content.fa'] ?? item._source.content"
></p>
<div class="flex justify-end"> <div class="flex justify-end">
<p class="reference">الکافی، جلد ۱، صفحه ۱۰۳</p> <p class="reference">
{{ item._source.address.vol_title }}، صفحه
{{ item._source.address.page_num }}
</p>
</div> </div>
</div> </div>
@ -74,7 +86,7 @@ const SearchShow = defineAsyncComponent(() =>
</no-data> </no-data>
</div> </div>
<UModal <!-- <UModal
v-model:open="isModalOpen" v-model:open="isModalOpen"
:dismissible="false" :dismissible="false"
:ui="{ :ui="{
@ -89,13 +101,13 @@ const SearchShow = defineAsyncComponent(() =>
close: 'modal-close', close: 'modal-close',
}" }"
> >
<!-- <template #header><div class="hidden"></div></template> --> <template #header><div class="hidden"></div></template>
<!-- <template #content></template> --> <template #content></template>
<template #body> <template #body>
<search-show @close="isModalOpen = !isModalOpen"></search-show> <search-show @close="isModalOpen = !isModalOpen"></search-show>
</template> </template>
<!-- <template #footer></template> --> <<template #footer></template>
</UModal> </UModal> -->
</div> </div>
</template> </template>
@ -118,7 +130,7 @@ const SearchShow = defineAsyncComponent(() =>
} }
.search-list { .search-list {
padding: 1em 1.3em; padding: 1em 1.3em;
height: calc(100dvh - 15.2em); height: calc(100dvh - 16em);
overflow-y: auto; overflow-y: auto;
&.hadithaFavorites { &.hadithaFavorites {
@ -214,6 +226,10 @@ const SearchShow = defineAsyncComponent(() =>
</style> </style>
<style> <style>
.text__orange {
color: orange;
}
.modal-content { .modal-content {
border: 0.3px solid #e0e0e0; border: 0.3px solid #e0e0e0;
box-shadow: 0px 8px 20px 0px #0000001a; box-shadow: 0px 8px 20px 0px #0000001a;

View File

@ -18,3 +18,9 @@ onUnmounted(() => {
<slot></slot> <slot></slot>
</main> </main>
</template> </template>
<style>
#__nuxt.isolate {
height: 100%;
}
</style>

View File

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import * as z from "zod"; import * as z from "zod";
import type { FormSubmitEvent } from "@nuxt/ui"; import type { FormSubmitEvent } from "@nuxt/ui";
import hadithaApi from "../../apis/hadithaApi";
import { useAuthStore } from "~/stores/authStore";
definePageMeta({ definePageMeta({
layout: false, layout: false,
@ -16,18 +18,22 @@ useHead({
}, },
}); });
const localizedErrors = { const router = useRouter();
required: "Invalid email address", const authStore = useAuthStore();
// Add more error codes and translations as needed // const localizedErrors = {
}; // required: "Invalid email address",
// // Add more error codes and translations as needed
// };
const schema = z.object({ const schema = z.object({
mobile: z mobile: z
.string() .string()
.min(1, "این فیلد ضروری است.(exmaple : 09--*******)") .min(1, "این فیلد ضروری است.(exmaple : 09--*******)")
.max(11, "موبایل حداکثر 11 عدد می باشد.(exmaple : 09--*******)") .max(11, "موبایل حداکثر 11 عدد می باشد.(exmaple : 09--*******)"),
}); });
const loading = ref(false);
type Schema = z.output<typeof schema>; type Schema = z.output<typeof schema>;
const state = reactive<Partial<Schema>>({ const state = reactive<Partial<Schema>>({
@ -36,12 +42,35 @@ const state = reactive<Partial<Schema>>({
const toast = useToast(); const toast = useToast();
async function onSubmit(event: FormSubmitEvent<Schema>) { async function onSubmit(event: FormSubmitEvent<Schema>) {
console.log(event.data);
const payoload = {
username: "dev",
password: "dev123",
};
authStore
.login(payoload)
.then((res) => {
loading.value = false;
// check if search term is not empty
toast.add({ toast.add({
title: "Success", title: "Success",
description: "The form has been submitted.", description: res.data.message,
color: "success", color: "success",
}); });
console.log(event.data);
navigateTo({
name: "haditha",
});
})
.catch((err) => {
console.info(err);
})
.finally(() => {
loading.value = false;
});
} }
// components declaration // components declaration

View File

@ -0,0 +1,561 @@
<script setup lang="ts">
// 1. Imports
// 2. Metas
// 3. Props
// 2. Reactive State
// 3. Computed Properties
// 4. Functions / Methods
// 5. Lifecycle Hooks
// 6. Watchers
// #region imports
import hadithaApi from "@haditha/apis/hadithaApi";
import type { HadithResponseModel } from "@haditha/types/hadithType";
import type { HadithResponseShowModel } from "~/systems/hadith_ui/types/hadithType";
// #endregion imports
// #region meta
definePageMeta({
layout: false,
name: "hadithaSearchShow",
});
useHead({
title: `${import.meta.env.VITE_HADITH_PAGE_TITLE}`,
meta: [
{ name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" },
],
bodyAttrs: {
class: import.meta.env.VITE_HADITH_SYSTEM,
},
});
// #endregion imports
// #region props
// const props = defineProps({
// selectedItem: {
// type: Object,
// default() {
// return {};
// },
// },
// });
// #endregion imports
// #region refs and reactives
const emit = defineEmits(["close"]);
const route = useRoute();
const router = useRouter();
const loading = ref(false);
const state = reactive({
selectedItem: {} as HadithResponseShowModel,
});
// #endregion refs and reactives
// #region methods
const fetchData = async () => {
if (loading.value) return;
loading.value = true;
let url = hadithaApi.search.show;
url = url.replace("@index_key", "dhparag");
url = url.replace("@id", route.params.id);
// fetch search list from backend(ssr)
const { data, status, error, refresh, clear } =
await useHadithaSearchComposable<HadithResponseShowModel>(url, {
method: "get",
});
if (status.value == "success") {
loading.value = false;
state.selectedItem = <HadithResponseShowModel>data.value;
}
};
const goToTheSearch = (type: string) => {
router.push({
name: "hadithaSearch",
});
};
const goToTheChatbot = () => {
router.push({
name: "hadithaChatbot",
});
};
// #endregion methods
fetchData();
</script>
<template>
<UContainer
ui="{
base: 'sm:px-6 lg:px-4',
}"
class="page-inner-container sm:px-6 lg:px-4 py-8"
>
<div class="search-show-page">
<div class="body-header">
<span class="top-left-bgi z-0"></span>
<div class="modal-title flex justify-between">
<NuxtImg
fit="auto"
quality="80"
placeholder
src="/img/haditha/haditha-title.svg"
/>
<UButton
icon="i-haditha-close"
color="neutral"
variant="ghost"
class="close-btn"
@click="goToTheSearch('normal')"
/>
</div>
</div>
<div class="body-content">
<div class="h-full flex flex-col justify-center z-2">
<div class="bg-container h-full">
<div class="header flex">
<UButton
variant="ghost"
class="bookmark-btn"
icon="i-haditha-tag"
>
</UButton>
<div class="referene">
<span> نشانی: </span>
{{ state.selectedItem?._source?.address?.vol_title }}، صفحه
{{ state.selectedItem?._source?.address?.page_num }}
</div>
</div>
<div class="content">
<div class="search-item">
<div class="text-arabic-section">
<div class="section-header">
<span class="section-title">
{{
state.selectedItem?._source?.meta?.hadith_masoum ??
"بدون عنوان"
}}
</span>
<UButton variant="ghost" class="copy-btn" label="کپی" />
</div>
<div class="arabic-text">
<p>بدون متن عربی</p>
</div>
</div>
<div class="separator"></div>
<div class="text-persian-section">
<div class="section-header">
<span class="section-title"> ترجمه </span>
<UButton variant="ghost" class="copy-btn" label="کپی" />
</div>
<p class="from">
{{
state.selectedItem?._source?.meta?.hadith_masoum ??
"بدون عنوان"
}}:
</p>
<p
class="persian-text"
v-html="state.selectedItem?._source?.content"
></p>
</div>
<div class="separator"></div>
<div class="text-description-section">
<div class="section-header">
<span class="section-title"> شرح </span>
<UButton variant="ghost" class="copy-btn" label="کپی" />
</div>
<p
class="description-item"
v-html="state.selectedItem?._source?.content"
></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="body-footer">
<div class="mt-5 z-2">
<div class="flex justify-between actions">
<UButton
class="similar-btn"
icon="i-haditha-search-3"
label="مشابه"
color="neutral"
variant="outline"
@click.prevent="goToTheSearch('similar')"
/>
<UButton
class="explore-btn"
trailing-icon="i-haditha-explore"
label="کاوش"
variant="solid"
@click.prevent="goToTheChatbot"
/>
</div>
<div class="flex justify-between pagination">
<UButton
class="prev-haditha"
label="حدیث قبل"
color=""
variant="soft"
icon="i-haditha-chevron-right"
/>
<UButton
class="next-haditha"
label="حدیث بعد"
color=""
variant="soft"
trailing-icon="i-haditha-chevron-left"
/>
</div>
</div>
</div>
</div>
</UContainer>
</template>
<!-- because of the buttons, using without scoped. -->
<style>
.search-show-page {
.body-header {
.modal-title {
padding: 0 0.5em 1.5em;
margin-bottom: 2.5em;
.close-btn {
color: var(--ui-color-two);
/* width: 24px; */
/* height: 24px; */
padding: 0.2em;
background-color: transparent;
}
}
}
.body-content {
.header {
.bookmark-btn {
width: 49px;
height: 32px;
gap: 4px;
border-radius: 6px;
border-width: 0.5px;
padding-top: 4px;
padding-right: 12px;
padding-bottom: 4px;
padding-left: 12px;
border: 0.5px solid #d9d9d9;
background: #ffffff;
display: flex;
justify-content: center;
align-items: center;
/* span { */
/* width: 19; */
/* height: 21; */
/* background: #29d985; */
/* } */
}
.referene {
margin-right: 0.5em;
width: 182;
height: 32;
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: #8a92a8;
display: flex;
align-items: center;
span {
margin-left: 0.1em;
font-family: IRANSansX;
font-weight: 300;
font-size: 12px;
line-height: 18px;
letter-spacing: 0%;
text-align: right;
color: #4d00ff;
}
}
}
.content {
/* height: calc(100dvh - 29em); */
/* overflow-y: auto; */
.search-item {
padding: 1em 0 1em 0.1em;
.section-header {
display: flex;
justify-content: space-between;
text-align: right;
margin-bottom: 0.5em;
.section-title {
font-family: IRANSansX;
font-weight: 400;
font-size: 14px;
line-height: 21px;
letter-spacing: 0%;
text-align: right;
/* Fallback color */
color: #4be8ae;
/* Gradient background */
background-image: linear-gradient(
102.02deg,
#4be8ae 7.38%,
#00a762 91.78%
);
/* Clip the background to the text */
background-clip: text;
-webkit-background-clip: text; /* For Safari */
/* Make the text transparent */
color: transparent;
-webkit-text-fill-color: transparent; /* For Safari */
}
.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: #8a92a8;
}
}
.text-arabic-section {
padding: 2em 0;
.arabic-text {
font-family: Takrim;
font-weight: 400;
font-size: 18px;
line-height: 32px;
letter-spacing: 0%;
text-align: right;
color: var(--ui-color-two);
margin-bottom: 0.5em;
}
}
.text-persian-section {
padding: 2em 0;
.section-header {
}
.from,
.persian-text {
font-family: Takrim;
font-weight: 400;
font-size: 18px;
line-height: 30px;
letter-spacing: 0%;
text-align: right;
color: var(--ui-color-two);
}
/* .persian-text {
font-family: Takrim;
font-weight: 400;
font-size: 16px;
line-height: 22px;
letter-spacing: 0%;
text-align: right;
color: #626b84;
margin-bottom: 0.5em;
} */
}
.text-description-section {
padding: 2em 0;
.description-item {
font-family: Takrim;
font-weight: 400;
font-size: 18px;
line-height: 30px;
letter-spacing: 0%;
text-align: right;
color: var(--ui-color-two);
/*
height: 24px;
gap: 4px;
padding-top: 4px;
padding-right: 8px;
padding-bottom: 4px;
padding-left: 8px;
border-radius: 6px;
border-width: 0.5px;
border: 0.5px solid #d9d9d9;
font-family: IRANSansX;
font-weight: 300;
font-size: 10px;
line-height: 15px;
letter-spacing: 0%;
text-align: right;
color: #8a92a8; */
}
}
.separator {
/* border: 0.5px solid #eee; */
height: 1px;
background-position: center center;
background-size: contain;
background-image: linear-gradient(
90deg,
#ffffff 0%,
#a0f5ff 30.4%,
#3fc9fa 71.47%,
#a7ffe7 100%
);
}
}
}
}
.body-footer {
.actions {
margin-bottom: 1em;
.similar-btn {
width: 114;
height: 56;
gap: 8px;
border-radius: 12px;
border-width: 0.5px;
padding-top: 8px;
padding-right: 20px;
padding-bottom: 8px;
padding-left: 24px;
background: #ffffff;
border: 0.5px solid;
border-image-source: linear-gradient(
102.02deg,
#4be8ae 7.38%,
#00a762 91.78%
);
box-shadow: 0px 8px 20px 0px #0000001a;
font-family: IRANSansX;
font-weight: 400;
font-size: 15px;
line-height: 22.5px;
letter-spacing: 0%;
text-align: right;
color: var(--ui-color-two);
}
.explore-btn {
width: 118;
height: 56;
gap: 4px;
border-radius: 12px;
padding-top: 8px;
padding-right: 24px;
padding-bottom: 8px;
padding-left: 20px;
background: linear-gradient(268.94deg, #d284ff -0.65%, #4d00ff 104.59%);
box-shadow: 0px 8px 20px 0px #0000001a;
font-family: IRANSansX;
font-weight: 400;
font-size: 16px;
line-height: 24px;
letter-spacing: 0%;
text-align: right;
color: #fff;
}
}
.pagination {
padding: 0.7em 0px;
/* width: 672; */
/* height: 56; */
justify-content: space-between;
border-radius: 16px;
border-width: 0.3px;
padding-right: 32px;
padding-left: 32px;
background: #ffffff;
border: 0.3px solid #e0e0e0;
box-shadow: 0px 8px 20px 0px #0000001a;
.prev-haditha {
font-family: IRANSansX;
font-weight: 300;
font-size: 12px;
line-height: 20px;
letter-spacing: 0%;
text-align: right;
color: var(--ui-color-two);
}
.next-haditha {
font-family: IRANSansX;
font-weight: 300;
font-size: 12px;
line-height: 20px;
letter-spacing: 0%;
text-align: right;
color: var(--ui-color-two);
}
}
}
}
</style>

View File

@ -15,8 +15,8 @@ useHead({
}); });
const img = useImage(); const img = useImage();
const searchQuery = ref(""); const searchQuery = ref("");
const total = ref(0);
const state = reactive({ const state = reactive({
searchList: [], searchList: [],
}); });
@ -45,8 +45,9 @@ const backgroundImageStyle = computed(() => {
const renderContent = (payload) => { const renderContent = (payload) => {
console.info(payload); console.info(payload);
state.searchList = payload.searchList; total.value = payload.res?.hits.total.value ?? 0;
searchQuery.value = payload.searchQuery; state.searchList = payload.res?.hits.hits ?? [];
searchQuery.value = payload.searchQuery ?? "";
}; };
// components declaration // components declaration
@ -85,7 +86,12 @@ const SearchList = defineAsyncComponent(() =>
v-if="searchQuery?.length == 0" v-if="searchQuery?.length == 0"
class="flex justify-center flex-col items-center" class="flex justify-center flex-col items-center"
> >
<NuxtImg fit="auto" quality="80" placeholder src="/img/haditha/logo.png" /> <NuxtImg
fit="auto"
quality="80"
placeholder
src="/img/haditha/logo.png"
/>
<div class="title"> <div class="title">
کاوش با کاوش با
<span class="badge-style"> هوش مصنوعی </span> <span class="badge-style"> هوش مصنوعی </span>
@ -112,6 +118,7 @@ const SearchList = defineAsyncComponent(() =>
<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"
:list="state.searchList" :list="state.searchList"
></search-list> ></search-list>
</div> </div>

View File

@ -1,260 +1,352 @@
export type SummaryOption = { key: string; label: string; type: string }; export interface HadithResponseModel {
export type Filter = { status: number;
title: string; message: string;
filter_key: string; postion: number;
source_key: string; meta: any;
by_more: number; took: number;
}; timed_out: boolean;
export type Summary = { _shards: Shards;
title: string; hits: Hits;
key: string; aggregations: Aggregations;
options: SummaryOption[]; params: Params;
}; }
export type Tag = { export interface HadithResponseShowModel {
قانون: string; status: number
عنوان: string; message: string
متن: string; postion: number
ماده: string; meta: any
نوع: string; _index: string
سال: string; _id: string
دسته: string; _version: number
مصوب: string; _seq_no: number
تاریخ: string; _primary_term: number
}; found: boolean
export type Domain = { _source: Source
label: string; }
tag: string;
key: string;
field_collapse: string;
table_actions: TableActions[];
table_columns: TableColumns;
};
export type DomainItem = { export interface Shards {
label: string; total: number;
tag: string; successful: number;
key: string; skipped: number;
field_collapse: string; failed: number;
table_actions: TableActions[]; }
table_columns: TableColumns[];
};
export type baseTableAction = { export interface Hits {
title: string; total: Total;
key: string; max_score: number;
"v-can": string; hits: Hit[];
icon: string; }
type: string;
link_route?: { export interface Total {
value: number;
relation: string;
}
export interface Hit {
_index: string;
_id: string;
_score: number;
_source: Source;
highlight?: Highlight;
}
export interface Source {
id: string; id: string;
name: string; address: Address;
key: string; content: string;
}; meta: Meta;
toggle_icons?: { icon1: string; icon2: string }; parag_order: number;
}; style_tag: string;
export type TableActions = [ heading_level: number;
baseTableAction & { sub_ayehs: any[];
api_items: { sub_hadithes: any[];
data_type: string; type_key: string;
ref_key: string; type_title: string;
id: string; lang: string;
title: string; tocs: string[];
}; xml: string;
} ai_embeddings: number[];
]; ai_classes: AiClass[];
export type TableColumnItem = { }
key: string;
title: string;
width: string;
textAlign?: string;
isLink?: true;
link_route?: { id: string; name: string; key: string };
trancate_word?: number;
colors?: {
منسوخه: string;
معتبر: string;
موقت: string;
"بااجرامنتفي مي شود": string;
تمديد: string;
آزمايشي: string;
تنفيذ: string;
};
};
export type TableColumns = TableColumnItem[]; export interface Address {
book_title: string;
page_end: number;
page_num: number;
vol_id: string;
vol_num: string;
vol_title: string;
}
export type Advance = { export interface Meta {
key: string; hadith_description: string;
hadith_sanad: string;
hadith_references: any[];
}
export interface AiClass {
score: number;
label: string; label: string;
tag: string; }
type: string;
placeholder: string;
labelClass: string;
inputClass: string;
multi_select: string;
options?: [{ value: string; title: string }];
};
export type SearchType = {
key: string;
description?: string;
label: string;
item?: {
label: string;
type: string;
component: string;
};
};
export type SearchContentActions = {
icon?: "";
title: string;
key: string;
type: string;
"v-can": string;
api_items?: { export interface Highlight {
data_type: string; "content.fa": string[];
ref_key: string; xml: string[];
id: string; "ai_classes.label"?: string[];
title: string; "content.ph": string[];
}; content: string[];
toggle_icons?: { icon1: string; icon2: string }; type_key: string[];
}; }
export type Item = { export interface Aggregations {
key: string; book_title: BookTitle;
source_key: string; ai_classes: AiClasses;
label: string; ai_keywords: AiKeywords;
style: string; vol_title: VolTitle;
process?: string; type_title: TypeTitle;
lang: Lang;
}
link_route?: { export interface BookTitle {
id: string; doc_count_error_upper_bound: number;
name: string; sum_other_doc_count: number;
key: string; buckets: Bucket[];
}; }
};
export type Items = {
key: string;
items: Item[];
array_key: string;
};
export type SearchContentCollapseItems = { export interface Bucket {
key: string; key: string;
items: Items[]; doc_count: number;
}; }
export type ListItem = {
title: string;
list_key: string;
filter_key: string;
icon: string;
};
export type List = ListItem[];
// search
export type searchActiveTab = {
key: string;
label: string;
key_navbar:string;
description: string;
routeName: string;
searchContent: string;
showTableList: number;
summary: Summary;
filter: Filter[];
domain: {
tags: Tag;
domain: Domain[] | [];
}|{};
advance: Advance[];
searchType: SearchType[];
search_content: {
actions: SearchContentActions[];
collapse_items: SearchContentCollapseItems;
};
lists: List;
colors_qanon_etebar: {
منسوخه: "red";
معتبر: "green";
موقت: "blue";
"بااجرامنتفي مي شود": "blue";
تمديد: "coral";
آزمايشي: "blue";
تنفيذ: "coral";
};
}| undefined;
export type searchSchema = searchActiveTab[];
export type searchActiveSchema = [];
// search list export interface AiClasses {
export type searchChartSchemaItem = { doc_count_error_upper_bound: number;
key: string; sum_other_doc_count: number;
label: string; buckets: Bucket2[];
description: string; }
routeName: string;
searchContent: string;
showTableList: number;
summary: Summary;
filter: Filter[];
search_content: {
actions: SearchContentActions[];
collapse_items: SearchContentCollapseItems;
};
info: {
title: string;
index_name: string;
meta: string;
table_columns: string;
table_columns_subject: string;
entity_view: string;
lists: [];
items: [{ name: string; title: string }];
};
actions: TableActions;
items: searchListActiveTab[];
};
export type searchListActiveTabItem = { export interface Bucket2 {
key: string; key: string;
id: number; doc_count: number;
url_GET_item: string; }
key_filter: string;
label: string;
};
export type searchListActiveTab = {
key: string;
label: string;
field_collapsed: string;
items: searchListActiveTabItem[];
};
export type searchListSchema = searchChartSchemaItem[]; export interface AiKeywords {
export type activeSearchListSchema = searchChartSchemaItem; doc_count_error_upper_bound: number;
sum_other_doc_count: number;
buckets: Bucket3[];
}
// search chart export interface Bucket3 {
export type searchChartActiveTab = {
key: string; key: string;
componentName: string; doc_count: number;
label: string; }
chartBase: {
key: string;
label: string;
items: [{ key: string; label: string }];
};
};
export type searchChartSchema = activeSearchChartSchema[];
export type activeSearchChartSchema = searchActiveTab & {
items: searchChartSchemaItem[];
};
export type searchSynonymTitle = {}; export interface VolTitle {
export type searchSynonymForm = []; doc_count_error_upper_bound: number;
export type selectionFilterItems = []; sum_other_doc_count: number;
buckets: Bucket4[];
}
export type helpSchema = helpActiveSchema[]; export interface Bucket4 {
export type helpActiveSchema = {
key: string; key: string;
label: string; doc_count: number;
title: string; }
comment: string;
}; export interface TypeTitle {
export type DomainActive = Domain; doc_count_error_upper_bound: number;
sum_other_doc_count: number;
buckets: Bucket5[];
}
export interface Bucket5 {
key: string;
doc_count: number;
}
export interface Lang {
doc_count_error_upper_bound: number;
sum_other_doc_count: number;
buckets: Bucket6[];
}
export interface Bucket6 {
key: string;
doc_count: number;
}
export interface Params {
index: string;
body: Body;
}
export interface Body {
query: Query;
from: string;
size: string;
aggs: Aggs;
highlight: Highlight2;
}
export interface Query {
bool: Bool;
}
export interface Bool {
must: Must[];
}
export interface Must {
bool: Bool2;
}
export interface Bool2 {
should?: Should[];
filter?: Filter;
}
export interface Should {
match_phrase?: MatchPhrase;
match?: Match;
bool?: Bool3;
}
export interface MatchPhrase {
"content.ph": ContentPh;
}
export interface ContentPh {
query: string;
boost: number;
}
export interface Match {
"content.fa"?: ContentFa;
content?: Content;
"content.ar"?: ContentAr;
}
export interface ContentFa {
query: string;
boost: number;
}
export interface Content {
query: string;
boost: number;
}
export interface ContentAr {
query: string;
boost: number;
}
export interface Bool3 {
must: Must2[];
}
export interface Must2 {
match: Match2;
}
export interface Match2 {
book_title: BookTitle2;
}
export interface BookTitle2 {
query: string;
boost: number;
}
export interface Filter {
bool: Bool4;
}
export interface Bool4 {
must: Must3[];
}
export interface Must3 {
term: Term;
}
export interface Term {
type_key: string;
}
export interface Aggs {
book_title: BookTitle3;
ai_classes: AiClasses2;
ai_keywords: AiKeywords2;
vol_title: VolTitle2;
type_title: TypeTitle2;
lang: Lang2;
}
export interface BookTitle3 {
terms: Terms;
}
export interface Terms {
field: string;
size: number;
}
export interface AiClasses2 {
terms: Terms2;
}
export interface Terms2 {
field: string;
size: number;
}
export interface AiKeywords2 {
terms: Terms3;
}
export interface Terms3 {
field: string;
size: number;
}
export interface VolTitle2 {
terms: Terms4;
}
export interface Terms4 {
field: string;
size: number;
}
export interface TypeTitle2 {
terms: Terms5;
}
export interface Terms5 {
field: string;
size: number;
}
export interface Lang2 {
terms: Terms6;
}
export interface Terms6 {
field: string;
size: number;
}
export interface Highlight2 {
pre_tags: string[];
post_tags: string[];
fields: Fields;
require_field_match: boolean;
fragment_size: number;
number_of_fragments: number;
boundary_scanner: string;
}
export interface Fields {
"*": GeneratedType;
}
export interface GeneratedType {}