haditha_ui/pages/haditha/library/index.vue
2025-05-19 16:29:48 +03:30

237 lines
6.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import hadithaApi from "@haditha/apis/hadithaApi";
import headLinks from "@haditha/json/haditha/headLinks";
import headMetas from "@haditha/json/haditha/headMetas";
// import { useInfiniteScroll } from "@vueuse/core";
// const id_token = useCookie("id_token");
// const token = id_token.value ?? "GuestAccess";
// const config = useRuntimeConfig();
// const baseUrl =
// config.public.NUXT_PUBLIC_BASE_URL + config.public.NUXT_PUBLIC_API_NAME;
// this enable us to send cookies.
// const requestFetch = useRequestFetch();
definePageMeta({
layout: false,
name: "hadithaLibrary",
});
useHead({
title: `${import.meta.env.VITE_HADITH_PAGE_TITLE} | کتابخانه`,
meta: [
{ name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" },
...headMetas,
],
bodyAttrs: {
class: `${import.meta.env.VITE_HADITH_SYSTEM} library-page`,
},
link: headLinks,
});
// #region refs
const httpService = useNuxtApp()["$http"];
// const { $api } = useNuxtApp()
const offset = useState("offset", () => 0);
const total = useState("total", () => 0);
// const libraryList = useState("libraryList", () => []);
// const loading = useState("loading", () => false);
// const hasMore = useState("hasMore", () => true);
// const el = ref(null);
// #endregion refs
// #region reactive
const state = reactive({
pagination: {
limit: 15,
page: 1,
pages: 1,
},
});
// #region methods
const getLibraryList = async () => {
// let url = baseUrl + repoUrl() + hadithaApi.library.list;
let url = repoUrl() + hadithaApi.library.list;
url = url.replace("@field_collapsed", "normal");
url = url.replace("@offset", offset.value);
url = url.replace("@limit", state.pagination.limit);
url = url.replace("@q", "none");
// return requestFetch(url, {
// method: "POST",
// headers: {
// Authorization: token,
// },
// })
return httpService.postRequest(url).then((data) => {
total.value = data.hits?.total?.value ?? 0;
offset.value += state.pagination.limit;
return data.hits?.hits;
});
};
// Server-side initial load
// Wrapping with useAsyncDataavoid double data fetching when
// doing server-side rendering (server & client on hydration).
const { data: libraryList } = await useAsyncData("libraryList", () =>
getLibraryList()
);
// Client-side infinite scroll
const loadMore = async () => {
// const listElm = $event.target;
// if (status.value == "pending") return;
// // window.innerHeight + window.scrollY >= document.body.offsetHeight - 100
// if (listElm.scrollTop + listElm.clientHeight >= listElm.scrollHeight) {
// status.value = "pending";
// mainState.pagination.offset =
// mainState.pagination.offset + mainState.pagination.limit;
// if (total.value > mainState.pagination.offset) {
// window.clearTimeout(isScrolling.value);
// isScrolling.value = setTimeout(() => {
return await getLibraryList().then((res) => {
const hits = res ?? [];
// Use spread operator to create new array reference
libraryList.value = [...libraryList.value, ...hits];
// status.value = "success";
return res;
});
// }, 300);
// } else {
// toast.add({
// title: "کاربر محترم",
// description: "دیگر رکوردی جهت بارگزاری وجود ندارد.",
// color: "success",
// });
// status.value = "idle";
// }
// } else status.value = "idle";
};
// const { isFetching } = useInfiniteScroll(loadMore, "libraryInfiniteScroll");
const { isFetching } = useCustomInfiniteScroll(async () => {
await loadMore();
});
// #endregion methods
// #region hooks
onUnmounted(() => {
offset.value = total.value = 0;
});
// #endregion hooks
// components declaration
const HadithaLayout = defineAsyncComponent(
() => import("@haditha/layouts/HadithaLayout.vue")
);
const NavigationMenu = defineAsyncComponent(
() => import("@haditha/components/haditha/NavigationMenu.vue")
);
const CardList = defineAsyncComponent(
() => import("@haditha/components/haditha/CardList.vue")
);
</script>
<template>
<HadithaLayout>
<div class="search-box-container h-fullsd flex flex-col justify-center">
<navigation-menu></navigation-menu>
<div class="library-list-contianer">
<div class="page-header flex items-center">
<span class="title">کتابخانه</span>
<img fit="auto" quality="80" src="/img/haditha/haditha-title.svg" />
</div>
<div
ref="libraryInfiniteScroll"
id="libraryInfiniteScroll"
class="library-list pl-4 firefox-scrollbar gap-x-15 gap-y-12 md:grid-cols-3 md:gap-x-28 md:gap-y-12 lg:grid-cols-5 lg:gap-x-28 lg:gap-y-12 mx-6"
:class="{ 'grid grid-cols-2': libraryList?.length }"
>
<!-- Client-side loaded content -->
<card-list
:list="libraryList"
no-data-text="به زودی لیست کتاب ها بروزرسانی خواهد شد."
no-data-icon=""
></card-list>
<no-data
class="h-full w-full flex flex-col justify-center items-center"
v-if="libraryList?.length == 0"
>
<p class="no-data-text">به زودی لیست کتاب ها بروزرسانی خواهد شد.</p>
</no-data>
</div>
</div>
</div>
</HadithaLayout>
</template>
<style scoped>
.search-box-container {
padding-top: 8.3em;
.library-list-contianer {
height: 100%;
margin-top: 10em;
max-width: 1200px;
width: 100%;
margin: 0 1em;
margin-right: auto;
margin-left: auto;
.page-header {
margin-bottom: 2em;
.title {
margin-left: 0.4em;
font-family: var(--font);
font-weight: 300;
font-size: 24px;
line-height: 36px;
letter-spacing: 0%;
text-align: center;
color: var(--ui-color-two);
}
}
.library-list {
/* padding: 1em 1.3em; */
/* height: calc(100dvh - 13.5em); */
/* overflow-y: auto; */
/* scroll-behavior: smooth; */
}
.no-data-text {
font-family: var(--font);
font-weight: 300;
font-size: 16px;
line-height: 24px;
letter-spacing: 0%;
text-align: center;
}
}
}
@media screen and (max-width: 991.99px) {
.search-box-container {
padding-top: 0em;
}
.library-list {
height: calc(100dvh - 13em);
}
.page-header {
margin-top: 4em;
margin-right: 2em;
margin-bottom: 1em;
}
}
</style>