590 lines
15 KiB
Vue
590 lines
15 KiB
Vue
<script setup lang="ts">
|
|
// 1. Imports
|
|
// 2. Metas
|
|
// 3. Props
|
|
// 2. Reactive State
|
|
// 3. Computed Properties
|
|
// 4. Functions / Methods
|
|
// 5. Lifecycle Hooks
|
|
// 6. Watchers
|
|
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
|
|
// #region imports
|
|
import hadithaApi from "@haditha/apis/hadithaApi";
|
|
import type { HadithResponseModel, Hits } from "@haditha/types/hadithType";
|
|
// #endregion imports
|
|
|
|
// #region meta
|
|
|
|
definePageMeta({
|
|
layout: false,
|
|
name: "hadithaLibraryShow",
|
|
});
|
|
|
|
useHead({
|
|
title: `${import.meta.env.VITE_HADITH_PAGE_TITLE} | ${route.params.slug}`,
|
|
meta: [
|
|
{ name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" },
|
|
],
|
|
bodyAttrs: {
|
|
class: import.meta.env.VITE_HADITH_SYSTEM,
|
|
},
|
|
});
|
|
// #endregion imports
|
|
// #region props
|
|
|
|
const props = defineProps({
|
|
list: {
|
|
default() {
|
|
return [];
|
|
},
|
|
},
|
|
noDataText: {
|
|
default: "نتیجهای یافت نشد!",
|
|
},
|
|
noDataIcon: {
|
|
default: "/img/haditha/no-data.png",
|
|
},
|
|
});
|
|
// #endregion props
|
|
|
|
// #region refs and reactives
|
|
|
|
const prevIsDisabled = computed(() => {
|
|
console.info("prevIsDisabled");
|
|
let isDisabled = true;
|
|
if (state.selectedItem[0]._source.address.page_num)
|
|
return !(state.selectedItem[0]._source.address.page_num - 1 > 1);
|
|
return isDisabled;
|
|
});
|
|
const nextIsDisabled = computed(() => {
|
|
console.info("prevIsDisabled");
|
|
|
|
let isDisabled = true;
|
|
if (state.selectedItem[0]._source.address.page_num)
|
|
return !(
|
|
state.selectedItem[0]._source.address.page_num + 1 <
|
|
+route.query.page_count
|
|
);
|
|
return isDisabled;
|
|
});
|
|
|
|
// const page_num = computed({
|
|
// // getter
|
|
// get() {
|
|
// return state.selectedItem?.[0]._source.address.page_num - 1 >= 1
|
|
// ? state.selectedItem?.[0]._source.address.page_num - 1
|
|
// : 1;
|
|
// },
|
|
// // setter
|
|
// set(newValue) {
|
|
// console.info(newValue);
|
|
|
|
// // handlePagination(1, newValue);
|
|
// },
|
|
// });
|
|
|
|
const treeItems = [
|
|
{
|
|
title: "فصل اول",
|
|
icon: "lucide:plus",
|
|
children: [
|
|
{ title: "useAuth.ts", icon: "vscode-icons:file-type-typescript" },
|
|
{ title: "useUser.ts", icon: "vscode-icons:file-type-typescript" },
|
|
],
|
|
},
|
|
{
|
|
title: "فصل دوم",
|
|
icon: "lucide:plus",
|
|
children: [
|
|
{ title: "useAuth.ts", icon: "vscode-icons:file-type-typescript" },
|
|
{ title: "useUser.ts", icon: "vscode-icons:file-type-typescript" },
|
|
],
|
|
},
|
|
{
|
|
title: "فصل سوم",
|
|
icon: "lucide:plus",
|
|
children: [
|
|
{
|
|
title: "بخش اول",
|
|
icon: "lucide:plus",
|
|
children: [
|
|
{ title: "بخش اول-یک", icon: "vscode-icons:file-type-vue" },
|
|
{
|
|
title: "بخش اول-دو",
|
|
icon: "vscode-icons:file-type-vue",
|
|
children: [
|
|
{ title: "بخش اول-یک-یک", icon: "vscode-icons:file-type-vue" },
|
|
{ title: "بخش اول-یک-دو", icon: "vscode-icons:file-type-vue" },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
title: "بخش دوم",
|
|
icon: "lucide:plus",
|
|
children: [
|
|
{ title: "Card.vue", icon: "vscode-icons:file-type-vue" },
|
|
{
|
|
title: "Button.vue",
|
|
icon: "vscode-icons:file-type-vue",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{ title: "فصل چهارم", icon: "vscode-icons:file-type-vue" },
|
|
{ title: "فصل پنجم", icon: "vscode-icons:file-type-nuxt" },
|
|
];
|
|
const isModalOpen = ref(false);
|
|
const loading = ref(false);
|
|
const httpService = useNuxtApp()["$http"];
|
|
|
|
const state = reactive({
|
|
selectedItem: {} as Hits,
|
|
});
|
|
|
|
const page_num = ref(1);
|
|
// #endregion refs and reactives
|
|
|
|
// #region methods
|
|
const fetchData = async () => {
|
|
if (loading.value) return;
|
|
loading.value = true;
|
|
|
|
let url = repoUrl() + hadithaApi.library.show;
|
|
url = url.replace("@appname", "monir");
|
|
url = url.replace("@page_start", route.query.page_first);
|
|
url = url.replace("@page_end", +route.query.page_first + 1);
|
|
url = url.replace("@vol_id", route.params.id.toString());
|
|
|
|
// fetch search list from backend(ssr)
|
|
const { data, status, error, refresh, clear } =
|
|
await useHadithaSearchComposable<HadithResponseModel>(url, {
|
|
method: "get",
|
|
});
|
|
|
|
if (status.value == "success") {
|
|
state.selectedItem = <Hits>data.value.hits.hits;
|
|
}
|
|
|
|
loading.value = false;
|
|
};
|
|
|
|
fetchData();
|
|
|
|
const goToTheLibrary = (type: string) => {
|
|
router.push({
|
|
name: "hadithaLibrary",
|
|
});
|
|
};
|
|
const onOpenList = () => {
|
|
console.info("onOpenList");
|
|
isModalOpen.value = true;
|
|
};
|
|
const onSearch = () => {
|
|
// console.info("onSearch");
|
|
router.push({
|
|
name:'hadithaSearch'
|
|
})
|
|
};
|
|
const onClose = () => {
|
|
console.info("onClose");
|
|
router.push({
|
|
name: "hadithLibrary",
|
|
});
|
|
};
|
|
|
|
const handlePagination = (
|
|
prevNextIndicator: number | string,
|
|
pageNumber: number | string | undefined = undefined
|
|
) => {
|
|
if (loading.value) return;
|
|
loading.value = true;
|
|
|
|
if (
|
|
!(
|
|
state.selectedItem[0]._source.address.page_num + prevNextIndicator > 1 &&
|
|
state.selectedItem[0]._source.address.page_num + prevNextIndicator <
|
|
+route.query.page_count
|
|
)
|
|
)
|
|
return;
|
|
|
|
let url = repoUrl() + hadithaApi.library.prevNextHadith;
|
|
url = url.replace("@index_key", "dhparag");
|
|
url = url.replace("@vol_id", state.selectedItem[0]._source.address.vol_id);
|
|
url = url.replace(
|
|
"@page_num",
|
|
pageNumber ?? state.selectedItem[0]._source.address.page_num
|
|
);
|
|
url = url.replace("@step", <string>prevNextIndicator);
|
|
|
|
httpService
|
|
.getRequest(url)
|
|
.then((res: HadithResponseModel) => {
|
|
state.selectedItem = res.hits.hits;
|
|
})
|
|
.finally(() => (loading.value = false));
|
|
};
|
|
const handlePageChange = () => {
|
|
handlePagination(1, page_num.value);
|
|
};
|
|
|
|
// #endregion methods
|
|
|
|
// components declaration
|
|
const HadithaLayout = defineAsyncComponent(
|
|
() => import("@haditha/layouts/HadithaLayout.vue")
|
|
);
|
|
const UTree = defineAsyncComponent(
|
|
() => import("@haditha/components/haditha/library-show/UTree.vue")
|
|
);
|
|
// const AccordionMenu = defineAsyncComponent(
|
|
// () => import("@haditha/components/haditha/library-show/AccordionMenu..vue")
|
|
// );
|
|
</script>
|
|
|
|
<template>
|
|
<HadithaLayout>
|
|
<div class="page-container h-full">
|
|
<UContainer
|
|
ui="{
|
|
base: 'sm:px-6 lg:px-4',
|
|
}"
|
|
class="page-inner-container sm:px-6 lg:px-4"
|
|
>
|
|
<div class="page-header py-4 flex justify-between items-center">
|
|
<div class="flex items-center">
|
|
<UButton
|
|
class="menu p-1 me-8"
|
|
@click="onOpenList"
|
|
icon="i-lucide-menu"
|
|
variant=""
|
|
/>
|
|
|
|
<h1 class="m-0 title">
|
|
{{ route.params.slug }}
|
|
</h1>
|
|
</div>
|
|
|
|
<div class="flex items-center">
|
|
<UButton
|
|
@click="onSearch"
|
|
class="my-trailing-button search p-0"
|
|
icon="i-lucide-search"
|
|
variant=""
|
|
size="xl"
|
|
>
|
|
</UButton>
|
|
|
|
<UButton
|
|
@click="goToTheLibrary"
|
|
class="my-trailing-button close p-0 ms-8"
|
|
icon="i-lucide:x"
|
|
variant=""
|
|
size="xl"
|
|
>
|
|
</UButton>
|
|
</div>
|
|
</div>
|
|
<div class="separator"></div>
|
|
|
|
<div class="page-content py-14 p-2">
|
|
<!-- <h2></h2> -->
|
|
<p
|
|
v-for="(parag, index) in state.selectedItem"
|
|
:key="index"
|
|
v-html="parag?._source?.content"
|
|
></p>
|
|
</div>
|
|
|
|
<div class="body-footer">
|
|
<div class="mt-5 z-2">
|
|
<div class="flex justify-between pagination">
|
|
<UButton
|
|
@click="handlePagination(-1)"
|
|
class="prev-haditha"
|
|
label="حدیث قبل"
|
|
color=""
|
|
variant="soft"
|
|
icon="i-haditha-chevron-right"
|
|
:disabled="prevIsDisabled"
|
|
/>
|
|
<div class="flex items-center">
|
|
<span class="total-pages">{{ route.query.page_count }}</span>
|
|
<span class="mx-2">/</span>
|
|
<UInput
|
|
:disabled="loading"
|
|
color="neutral"
|
|
variant="outline"
|
|
v-model="page_num"
|
|
@change="handlePageChange"
|
|
:ui="{
|
|
root: 'root ',
|
|
base: 'base page-number-input',
|
|
leading: 'leading',
|
|
leadingIcon: 'leadingIcon',
|
|
leadingAvatar: 'leadingAvatar',
|
|
leadingAvatarSize: 'leadingAvatarSize',
|
|
trailing: 'trailing',
|
|
trailingIcon: 'trailingIcon',
|
|
}"
|
|
/>
|
|
</div>
|
|
<UButton
|
|
@click="handlePagination(1)"
|
|
class="next-haditha"
|
|
label="حدیث بعد"
|
|
color=""
|
|
variant="soft"
|
|
trailing-icon="i-haditha-chevron-left"
|
|
:disabled="nextIsDisabled"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</UContainer>
|
|
</div>
|
|
|
|
<UModal
|
|
v-model:open="isModalOpen"
|
|
:dismissible="false"
|
|
:ui="{
|
|
footer: 'modal-footer',
|
|
overlay: 'modal-overlay',
|
|
content: 'modal-content accordion-menu h-10',
|
|
header: 'modal-header',
|
|
wrapper: 'modal-wrapper',
|
|
body: 'modal-body',
|
|
title: 'modal-title',
|
|
description: 'modal-description',
|
|
close: 'modal-close ring-[white]',
|
|
}"
|
|
title="فهرست"
|
|
:close="{
|
|
color: 'primary',
|
|
variant: 'outline',
|
|
class: 'rounded-full',
|
|
}"
|
|
>
|
|
<!-- <template #header></template> -->
|
|
<!-- <template #content></template> -->
|
|
<template #body>
|
|
<UTree :items="treeItems" />
|
|
<!-- <accordion-menu @close="isModalOpen = !isModalOpen"></accordion-menu> -->
|
|
</template>
|
|
<!-- <template #footer></template> -->
|
|
</UModal>
|
|
</HadithaLayout>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.page-container {
|
|
background: #f7fffd;
|
|
|
|
.page-inner-container {
|
|
/* position: relative; */
|
|
/* padding-bottom: 4em; */
|
|
/* width: 100%; */
|
|
/* max-width: 1200px; */
|
|
/* margin-right: auto; */
|
|
/* margin-left: auto; */
|
|
.page-header {
|
|
color: var(--ui-color-two);
|
|
|
|
.menu {
|
|
width: 24;
|
|
height: 24;
|
|
|
|
margin-left: 2.2em;
|
|
}
|
|
.title {
|
|
font-family: IRANSansX;
|
|
font-weight: 400;
|
|
font-size: 16px;
|
|
line-height: 20px;
|
|
letter-spacing: 0%;
|
|
text-align: right;
|
|
|
|
/* Fallback color */
|
|
color: #4d00ff;
|
|
|
|
/* Gradient background */
|
|
background: linear-gradient(268.94deg, #d284ff -0.65%, #4d00ff 104.59%);
|
|
|
|
/* 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 */
|
|
}
|
|
}
|
|
.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%
|
|
);
|
|
}
|
|
.page-content {
|
|
/* margin: 1.5em; */
|
|
|
|
font-family: Takrim;
|
|
font-weight: 400;
|
|
font-size: 20px;
|
|
line-height: 40px;
|
|
letter-spacing: 0%;
|
|
text-align: right;
|
|
|
|
color: var(--ui-color-two);
|
|
|
|
height: calc(100dvh - 8em);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.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;
|
|
|
|
.total-pages {
|
|
font-family: IRANSansX;
|
|
font-weight: 400;
|
|
font-size: 12px;
|
|
line-height: 100%;
|
|
letter-spacing: 0%;
|
|
text-align: right;
|
|
color: #8a92a8;
|
|
}
|
|
.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>
|
|
|
|
<style>
|
|
.page-container {
|
|
.page-inner-container {
|
|
.body-footer {
|
|
.pagination {
|
|
.page-number-input {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 3em /*36px*/;
|
|
height: 3em /*36px*/;
|
|
gap: 4px;
|
|
border-radius: 12px;
|
|
border-width: 0.5px;
|
|
border: 0.3px solid #e0e0e0;
|
|
box-shadow: 0px 8px 20px 0px #0000001a;
|
|
font-family: IRANSansX;
|
|
font-weight: 400;
|
|
font-size: 0.75rem;
|
|
line-height: 100%;
|
|
letter-spacing: 0%;
|
|
text-align: center;
|
|
color: #8a92a8;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|