220 lines
5.2 KiB
Vue
220 lines
5.2 KiB
Vue
<script setup>
|
||
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";
|
||
|
||
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,
|
||
},
|
||
link: headLinks,
|
||
});
|
||
|
||
// #region refs
|
||
const el = ref(null);
|
||
const httpService = useNuxtApp()["$http"];
|
||
|
||
const offset = useState("offset", () => 0);
|
||
const total = useState("total", () => 0);
|
||
const loading = useState("loading", () => false);
|
||
const hasMore = useState("hasMore", () => true);
|
||
|
||
// #endregion refs
|
||
|
||
// #region reactive
|
||
const state = reactive({
|
||
// list: new Array(5).fill(0),
|
||
pagination: {
|
||
page: 1,
|
||
pages: 1,
|
||
// offset: 0,
|
||
limit: 500,
|
||
},
|
||
});
|
||
// #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", offset.value);
|
||
url = url.replace("@limit", state.pagination.limit);
|
||
url = url.replace("@q", "none");
|
||
|
||
return await httpService.getRequest(url).then((res) => {
|
||
console.info(res);
|
||
total.value = res.hits?.total?.value ?? 0;
|
||
offset.value += state.pagination.limit;
|
||
return res;
|
||
});
|
||
};
|
||
|
||
const { data: favoriteList } = await useAsyncData(
|
||
"favorites",
|
||
() => getFavorites(),
|
||
{
|
||
transform: (data) => data.hits.hits,
|
||
}
|
||
);
|
||
|
||
// 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 updateList = (index) => {
|
||
favoriteList.value.splice(index, 1);
|
||
};
|
||
|
||
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 h-full">
|
||
<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="el"
|
||
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;
|
||
background: #f7fffd;
|
||
}
|
||
|
||
.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>
|