haditha_ui/pages/haditha/favorites/index.vue
2025-05-17 07:32:27 +03:30

254 lines
6.3 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>
import hadithaApi from "@haditha/apis/hadithaApi";
import headLinks from "@haditha/json/haditha/headLinks";
import headMetas from "@haditha/json/haditha/headMetas";
// const { loggedIn, user, session, fetch, clear, openInPopup } = useUserSession()
// console.info(loggedIn, user, session, fetch, clear, openInPopup);
// 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: "hadithaFavorites",
});
useHead({
name: "hadithaFavorites",
title: `${import.meta.env.VITE_HADITH_PAGE_TITLE} | ذخیره ها`,
meta: [
{ name: "description", content: "کاوش با هوش مصنوعی در احادیث اسلامی" },
...headMetas,
],
bodyAttrs: {
class: `${import.meta.env.VITE_HADITH_SYSTEM} favorites-page`,
},
link: headLinks,
});
// #region refs
// const el = ref(null);
const httpService = useNuxtApp()["$http"];
const favOffset = useState("favOffset", () => 0);
const total = useState("total", () => 0);
// #endregion refs
// #region reactive
const state = reactive({
// list: new Array(5).fill(0),
pagination: {
page: 1,
pages: 1,
// offset: 0,
limit: 15,
},
});
// #endregion reactive
// #region methods
const getFavorites = async (dataType = "bookmark") => {
let url = repoUrl() + hadithaApi.favorite.getList;
url = url.replace("@data_type", dataType);
url = url.replace("@time_key", "all");
url = url.replace("@source", "main");
url = url.replace("@offset", favOffset.value);
url = url.replace("@limit", state.pagination.limit);
url = url.replace("@q", "none");
return await httpService.getRequest(url).then((data) => {
total.value = data.hits?.total?.value ?? 0;
favOffset.value += state.pagination.limit;
return data.hits?.hits;
});
// return await requestFetch(url, {
// headers: {
// method: "get",
// Authorization: token,
// },
// }).then((data) => {
// total.value = data.hits?.total?.value ?? 0;
// favOffset.value += state.pagination.limit;
// return data.hits?.hits;
// });
};
const { data: favoriteList } = await useAsyncData("favorites", () =>
getFavorites()
);
// Client-side infinite scroll
const loadMore = async () => {
return await getFavorites().then((res) => {
const hits = res ?? [];
favoriteList.value = [...favoriteList.value, ...hits];
return res;
});
};
// const { isFetching } = useInfiniteScroll(loadMore, "favoriteInfiniteScroll");
const { isFetching } = useInfiniteScroll(async () => {
await loadMore();
});
const updateList = (index) => {
favoriteList.value.splice(index, 1);
};
onUnmounted(() => {
favOffset.value = total.value = 0;
});
// Client-side infinite scroll
// useInfiniteScroll(
// el,
// async () => {
// if (!hasMore.value || loading.value) return;
// loading.value = true;
// try {
// await getFavorites().then((res) => {
// const hits = res?.hits?.hits ?? [];
// if (hits.length) {
// // Use spread operator to create new array reference
// favoriteList.value = [...favoriteList.value, ...hits];
// } else {
// hasMore.value = false;
// }
// });
// } catch (error) {
// hasMore.value = false;
// // console.error("Error loading more items:", error);
// // Consider setting hasMore.value = false if you want to stop on error
// } finally {
// loading.value = false;
// }
// },
// {
// distance: 100,
// }
// );
const HadithaLayout = defineAsyncComponent(() =>
import("@haditha/layouts/HadithaLayout.vue")
);
const NavigationMenu = defineAsyncComponent(() =>
import("@haditha/components/haditha/NavigationMenu.vue")
);
const SearchList = defineAsyncComponent(() =>
import("@haditha/components/haditha/search-page/SearchList.vue")
);
</script>
<template>
<HadithaLayout>
<div class="h-full flex flex-col justify-center">
<div class="bg-container">
<navigation-menu></navigation-menu>
<div class="text-logo">
<div
v-show="favoriteList?.length"
class="search-box-container pb-0 flex justify-center"
>
<div class="search-list-contianer">
<div class="total">
<span>{{ total }}</span>
نتیجه
</div>
<div
ref="favoriteInfiniteScroll"
id="favoriteInfiniteScroll"
class="search-list firefox-scrollbar hadithaFavorites"
>
<search-list
no-data-text="هنوز چیزی ذخیره نکرده‌اید!"
no-data-icon="/img/haditha/save.png"
:list="favoriteList"
@on-bookmard-removed="updateList"
></search-list>
</div>
</div>
</div>
<no-data
v-show="favoriteList?.length == 0"
class="h-full w-full flex flex-col justify-center items-center"
>
<img fit="auto" quality="80" src="/img/haditha/save.png" />
<p class="no-data-text">هنوز چیزی ذخیره نکرده‌اید!</p>
</no-data>
</div>
</div>
</div>
</HadithaLayout>
</template>
<style scoped>
.bg-container {
min-height: 100%;
/* height: 100dvh; */
background-size: cover;
background-repeat: no-repeat;
}
.text-logo {
height: 100%;
padding-top: 4.5em;
position: relative;
}
.search-box-container {
padding-top: 0.7em;
padding-bottom: 4em; /*64px */
&.pb-0 {
padding-bottom: 0 !important;
}
}
.search-list-contianer {
/*max-width: 41em; 656px*/
max-width: 75em; /*1200px*/
width: 100%;
margin: 0 1em;
.total {
padding: 0.5em 1.8em;
font-family: var(--font);
font-weight: 400;
font-size: 0.68rem; /*11px*/
line-height: 1rem;
letter-spacing: 0%;
text-align: right;
color: #b4c2cf;
}
.search-list {
padding: 1em 1.3em;
/* height: calc(100dvh - 16em); */
/* overflow-y: auto; */
&.hadithaFavorites {
/* height: calc(100dvh - 8em); */
}
&:not(:last-child) {
border-bottom: 0.3px solid #d9d9d9;
}
}
}
</style>