Work on library show page.

This commit is contained in:
mustafa-rezae 2025-04-12 14:42:52 +03:30
parent 4745294ffc
commit 358ced7603
11 changed files with 336 additions and 115 deletions

View File

@ -17,10 +17,11 @@ export default {
setCategories: "favorite/tags/@data_type/set",
getCounts: "favorite/tags/@data_type/counts",
getList: "favorite/list/@data_type/@offset/@limit/@filter",
getList: "favorite/list/@data_type/@offset/@limit",
},
library: {
list: "monir/book/volume/@field_collapsed/@offset/@limit/@q",
show: "@appname/book/page/@page_start/@page_end/@vol_id",
prevNextHadith: "monir/nextpage/@index_key/@vol_id/@page_num/@step",
},
};

View File

@ -82,7 +82,6 @@ const state = reactive({
value: "normal",
class: "",
onSelect(e: Event) {
console.info(e);
search_type.value = "normal";
state.type.label = e.explicitOriginalTarget?.innerText;
sendQuery();
@ -98,7 +97,6 @@ const state = reactive({
onSelect(e: Event) {
search_type.value = "arabic";
state.type.label = e.explicitOriginalTarget?.innerText;
console.info(e);
state.type.items[0].class = "active";
sendQuery();
@ -112,7 +110,6 @@ const state = reactive({
onSelect(e: Event) {
search_type.value = "translations";
state.type.label = e.explicitOriginalTarget?.innerText;
console.info(e);
state.type.items[0].class = "active";
sendQuery();
@ -127,8 +124,6 @@ const state = reactive({
search_type.value = "descriptions";
state.type.label = e.explicitOriginalTarget?.innerText;
state.type.items[0].class = "active";
console.info(e);
sendQuery();
},
},
@ -155,7 +150,6 @@ const state = reactive({
// watch(
// () => route,
// (newRoute, oldRoute) => {
// console.info(newRoute.query);
// if (newRoute.query) searchTerm.value = <string>newRoute.query.q;
// },
// { immediate: true }
@ -282,15 +276,12 @@ const onClearSynonymClear = () => {
async function openSynonymPopup(type: string) {
search_type.value = type;
console.info("openSynonymPopup");
getSynonyms().then(() => {
isSynonymPopupOpen.value = true;
});
}
const onTypeSelectChanged = (value: string) => {
console.info(value);
if (value == "translations") typeModelValueFa.value = "ترجمه";
else if (value == "arabic") typeModelValueFa.value = "عربی";
else if (value == "descriptions") typeModelValueFa.value = "شروح";
@ -332,11 +323,7 @@ const prepareSynonym = () => {
const enabledSwitches = state.synonym.items.filter((i) => i.enable);
const res = {};
console.info(enabledSwitches);
enabledSwitches.forEach((item) => {
console.info(item);
if (item.subTitles.length)
res[item.title] = item.subTitles
.filter((i) => i.active)
@ -344,8 +331,6 @@ const prepareSynonym = () => {
.join(",");
});
console.info(res);
return {
synonym: res,
};

View File

@ -12,6 +12,21 @@ const props = defineProps({
default: "/img/haditha/no-data.png",
},
});
const router = useRouter();
const goToLibraryShow = (item) => {
router.push({
name: "hadithaLibraryShow",
params: {
id: item?._source?.id,
slug: item?._source?.title,
},
query: {
firstPage: item._source.page_first,
},
});
};
</script>
<template>
@ -41,34 +56,37 @@ const props = defineProps({
>
<!-- <template #header></template> -->
<client-only>
<ULink
:to="{
name: 'hadithaLibraryShow',
params: {
id: 1,
slug: item?._source?.title,
},
}"
color="neutral"
variant="outline"
:ui="{
leadingIcon: 'text-(--ui-primary)',
}"
@click=""
>
<img
fit="auto"
quality="80"
placeholder
src="/img/haditha/sample-bgi.svg"
/>
<p class="title">{{ item?._source?.title }}</p>
<p class="version">
{{ item?._source?.vol_title + item?._source?.vol_num }}
</p>
</ULink>
</client-only>
<ULink
v-if="item?._source?.id"
:to="{
name: 'hadithaLibraryShow',
params: {
id: item?._source?.id,
slug: item?._source?.title,
},
query: {
page_first: item._source.page_first,
page_last: item._source.page_last,
page_count: item._source.page_count,
},
}"
color="neutral"
variant="outline"
:ui="{
leadingIcon: 'text-(--ui-primary)',
}"
>
<img
fit="auto"
quality="80"
placeholder
src="/img/haditha/sample-bgi.svg"
/>
<p class="title">{{ item?._source?.title }}</p>
<p class="version">
{{ item?._source?.vol_title + item?._source?.vol_num }}
</p>
</ULink>
<!-- <template #footer> </template> -->
</UCard>

View File

@ -43,29 +43,30 @@ const state = reactive<Partial<Schema>>({
const toast = useToast();
async function onSubmit(event: FormSubmitEvent<Schema>) {
// const payoload = {
// username: "dev",
// password: "dev123",
// // captcha: "",
// };
const payoload = {
username: "m.rezae",
password: "123456",
captcha: undefined,
};
authStore
.loginAsGuest()
.login(payoload)
.then((res) => {
loading.value = false;
// check if search term is not empty
toast.add({
title: "Success",
description: res.data.message,
title: "درخواست با موفقیت انجام شد.",
description: "خوش آمدید.",
color: "success",
});
if (!res.data.isNew) emits("next-step");
else
navigateTo({
name: "haditha",
});
// todo: when sms activated, uncomment this.
// if (res.data.isNew) emits("next-step");
// else
navigateTo({
name: "haditha",
});
})
.catch((err) => {
console.info(err);

View File

@ -45,7 +45,6 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
// captcha: "",
};
console.info("verify code");
// .loginAsGuest()
authStore
.login(payoload)
@ -71,7 +70,6 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
});
}
onMounted(() => {
// console.info(pinInputRef.value);
// if (pinInputRef.value) {
// pinInputRef.value.focus(); // Or whatever focus method your PinInput component provides
// }

View File

@ -39,15 +39,15 @@ const getCategories = async (dataType = "bookmark") => {
loading.value = true;
let url = repoUrl() + hadithaApi.favorite.getList;
url = url.replace("@field_collapsed", "book_title");
url = url.replace("@data_type", dataType);
url = url.replace("@offset", 0);
url = url.replace("@limit", 20);
url = url.replace("@q", "none");
// url = url.replace("@filter", "get");
return await httpService
.getRequest(url)
.then((res) => {
state.list = res.data;
state.list = res.hits.hits;
getCounts();
})
.catch((err) => {

View File

@ -13,8 +13,7 @@ const router = useRouter();
// #region imports
import hadithaApi from "@haditha/apis/hadithaApi";
// import type { HadithResponseModel } from "@haditha/types/hadithType";
import type { HadithResponseModel } from "~/systems/hadith_ui/types/hadithType";
import type { HadithResponseModel, Hits } from "@haditha/types/hadithType";
// #endregion imports
// #region meta
@ -53,6 +52,40 @@ const props = defineProps({
// #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: "فصل اول",
@ -110,8 +143,10 @@ const loading = ref(false);
const httpService = useNuxtApp()["$http"];
const state = reactive({
selectedItem: {} as HadithResponseModel,
selectedItem: {} as Hits,
});
const page_num = ref(1);
// #endregion refs and reactives
// #region methods
@ -119,12 +154,10 @@ const fetchData = async () => {
if (loading.value) return;
loading.value = true;
console.info(route.params.id);
let url = repoUrl() + hadithaApi.library.show;
url = url.replace("@appname", "monir");
url = url.replace("@page_start", "0");
url = url.replace("@page_end", "10");
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)
@ -133,13 +166,8 @@ const fetchData = async () => {
method: "get",
});
// console.info(data.value);
console.info(status.value);
if (status.value == "success") {
console.info(data.value);
console.info(data.value.hits.hits);
state.selectedItem = <HadithResponseModel>data.value.hits.hits;
state.selectedItem = <Hits>data.value.hits.hits;
}
loading.value = false;
@ -158,6 +186,9 @@ const onOpenList = () => {
};
const onSearch = () => {
// console.info("onSearch");
router.push({
name:'hadithaSearch'
})
};
const onClose = () => {
console.info("onClose");
@ -165,6 +196,43 @@ const onClose = () => {
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
@ -225,32 +293,58 @@ const UTree = defineAsyncComponent(
<div class="separator"></div>
<div class="page-content py-14 p-2">
<h2>
عَنِ الْحَسَنِ بْنِ عَلِيِّ بْنِ يُوسُفَ، عَنْ جَدِّهِ، قَالَ: قَالَ
أَبُو عَبْدِ اللَّهِ (عَلَيْهِ السَّلَامُ):
</h2>
<p>
إِنَّمَا يَدْرُسُ الْإِنسَانُ لِيَعْلَمَ، وَإِنَّمَا يَعْلَمُ
لِيَعْمَلَ، وَإِنَّمَا يَعْمَلُ لِيُعْرَفَ بِهِ، وَإِنَّمَا يُعْرَفُ
بِهِ لِيُقْبَلَ بِهِ، وَإِنَّمَا يُقْبَلُ بِهِ لِيُؤْمَنَ عَلَيْهِ،
وَإِنَّمَا يُؤْمَنُ عَلَيْهِ لِيُدْخَلَ الْجَنَّة امام جعفر صادق
علیهالسلام:عَنِ الْحَسَنِ بْنِ عَلِيِّ بْنِ يُوسُفَ، عَنْ جَدِّهِ،
قَالَ: قَالَ أَبُو عَبْدِ اللَّهِ إِنَّمَا يَدْرُسُ الْإِنسَانُ
لِيَعْلَمَ، وَإِنَّمَا يَعْلَمُ لِيَعْمَلَ، وَإِنَّمَا يَعْمَلُ
لِيُعْرَفَ بِهِ، وَإِنَّمَا يُعْرَفُ بِهِ لِيُقْبَلَ بِهِ،
وَإِنَّمَا يُقْبَلُ بِهِ لِيُؤْمَنَ عَلَيْهِ، وَإِنَّمَا يُؤْمَنُ
عَلَيْهِ لِيُدْخَلَ الْجَنَّةَ
</p>
<!-- <h2></h2> -->
<p
v-for="(parag, index) in state.selectedItem"
:key="index"
v-html="parag?._source?.content"
></p>
</div>
<h2>امام جعفر صادق علیهالسلام:</h2>
<p>
عَنِ الْحَسَنِ بْنِ عَلِيِّ بْنِ يُوسُفَ، عَنْ جَدِّهِ، قَالَ: قَالَ
أَبُو عَبْدِ اللَّهِ (عَلَيْهِ السَّلَامُ): إِنَّمَا يَدْرُسُ
الْإِنسَانُ لِيَعْلَمَ، وَإِنَّمَا يَعْلَمُ لِيَعْمَلَ، وَإِنَّمَا
يَعْمَلُ لِيُعْرَفَ بِهِ، وَإِنَّمَا يُعْرَفُ بِهِ لِيُقْبَلَ بِهِ،
وَإِنَّمَا يُقْبَلُ بِهِ لِيُؤْمَنَ عَلَيْهِ، وَإِنَّمَا يُؤْمَنُ
عَلَيْهِ لِيُدْخَلَ الْجَنَّةَ
</p>
<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>
@ -292,6 +386,8 @@ const UTree = defineAsyncComponent(
background: #f7fffd;
.page-inner-container {
/* position: relative; */
/* padding-bottom: 4em; */
/* width: 100%; */
/* max-width: 1200px; */
/* margin-right: auto; */
@ -353,6 +449,140 @@ const UTree = defineAsyncComponent(
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;
}
}
}
}
}

View File

@ -39,7 +39,7 @@ const getLibraryList = async (dataType = "bookmark") => {
loading.value = true;
let url = repoUrl() + hadithaApi.library.list;
url = url.replace("@field_collapsed", "book_title");
url = url.replace("@field_collapsed", "normal");
url = url.replace("@offset", 0);
url = url.replace("@limit", 20);
url = url.replace("@q", "none");

View File

@ -35,7 +35,6 @@ const Rules = defineAsyncComponent(() =>
);
onMounted(() => {
console.info(route.path);
// if (route.path == "/haditha/about-us") componentName.value = "AboutUs";
// if (route.path == "/haditha/contact-us") componentName.value = "ContactUs";
// if (route.path == "/haditha/rules") componentName.value = "Rules";

View File

@ -59,8 +59,6 @@ const fetchData = async () => {
if (loading.value) return;
loading.value = true;
console.info(route.params.id);
let url = hadithaApi.search.show;
url = url.replace("@index_key", "dhparag");
url = url.replace("@id", route.params.id);
@ -71,8 +69,6 @@ const fetchData = async () => {
method: "get",
});
console.info(data);
if (status.value == "success") {
state.selectedItem = <HadithResponseShowModel>data.value;
}
@ -94,8 +90,6 @@ const goToTheChatbot = () => {
};
const handleFavorite = async (item = {}) => {
console.info("addToFavorites");
addToFavorites();
// // add
@ -109,8 +103,6 @@ const handleFavorite = async (item = {}) => {
};
const addToFavorites = async (item = {}) => {
console.info("addToFavorites");
let url = repoUrl() + hadithaApi.favorite.add;
url = url.replace("{{data_type}}", "bookmark");
url = url.replace("{{ref_key}}", "dhparag");
@ -141,7 +133,6 @@ const removeFromFavorites = async (item = {}, index = 0) => {
};
const handlePagination = (prevNextIndicator: string) => {
console.info("fsdfsdfsdf");
if (loading.value) return;
loading.value = true;
@ -347,8 +338,8 @@ const localCopyTextToClipboard = (text: string) => {
label="مشابه"
color="neutral"
variant="outline"
/>
<!-- @click.prevent="goToTheSearch('similar')" -->
/>
<!-- @click.prevent="goToTheSearch('similar')" -->
<UButton
class="explore-btn"
trailing-icon="i-haditha-explore"

View File

@ -43,8 +43,6 @@ const backgroundImageStyle = computed(() => {
});
const renderContent = (payload) => {
console.info(payload);
total.value = payload.res?.hits.total.value ?? 0;
state.searchList = payload.res?.hits.hits ?? [];
searchQuery.value = payload.searchQuery ?? "";