Files
NSG_PORTAL_V2/components/dynamic-page/page-component/templates/sections/articles/Default.vue
T

216 lines
6.1 KiB
Vue
Raw Normal View History

2024-06-13 17:24:46 +07:00
<script setup lang="ts">
import DynamicComponent from "~/components/dynamic-page/page-component/templates/index.vue";
2024-07-05 14:51:25 +07:00
import { getInputValue } from "@/utils/parseSQL";
import { enumPageComponentTemplates } from "@/definitions/enum";
2024-06-13 17:24:46 +07:00
const router = useRouter();
const route = useRoute();
2024-06-28 15:39:26 +07:00
const store = reactive({
2024-07-05 14:51:25 +07:00
component: useDynamicPageStore(),
2024-06-28 15:39:26 +07:00
});
2024-06-13 17:24:46 +07:00
const _props = defineProps<{
2024-07-05 14:51:25 +07:00
dataResult?: any[];
2024-06-13 17:24:46 +07:00
dataQuery?: string;
component?: any;
2024-07-05 14:51:25 +07:00
label?: string;
2024-06-13 17:24:46 +07:00
}>();
const SETTING_OPTIONS = {
MAX_ELEMENT: 5,
2024-07-05 14:51:25 +07:00
TEMPLATE: "TYPE:Card",
LAYOUT: "TYPE:Card_Default",
};
const COMPONENT = {
taxonomy: enumPageComponentTemplates.ARTICLE,
2024-06-13 17:24:46 +07:00
};
2024-06-28 15:39:26 +07:00
const page = ref(1);
const limit = ref(5);
const totals = ref(2);
2024-06-13 17:24:46 +07:00
const type = "Article";
2024-06-28 15:39:26 +07:00
const listArticlePaging = ref([]);
2024-06-13 17:24:46 +07:00
const listArticleByCategory = computed(() => {
2024-06-28 15:39:26 +07:00
const data = getInputValue(_props.dataResult, "OBJECT");
if (data && Object.keys(data)?.length > 0) {
totals.value = data.Total;
return data?.Data;
}
return [];
2024-06-13 17:24:46 +07:00
});
const designObject = computed(() => {
return _props.label ? getInputValue(_props.label, "OBJECT") : {};
});
//?cpn_1=page:2&cpn_2=page:1
// Get[Article] Top[5] With[Categories:1]
2024-06-28 15:39:26 +07:00
const select = async (pageActive: number) => {
2024-06-13 17:24:46 +07:00
const componentId = _props.component?.id;
if (componentId) {
router.push({
query: {
...route.query,
2024-06-28 15:39:26 +07:00
[`cpn_${componentId}`]: `page:${pageActive}`,
2024-06-13 17:24:46 +07:00
},
});
}
2024-06-28 15:39:26 +07:00
page.value = Number(pageActive);
await loadPage(Number(pageActive));
2024-06-13 17:24:46 +07:00
};
2024-06-28 15:39:26 +07:00
const handleRouteChange = async (query: any) => {
const param = query[`cpn_${_props.component?.id}`];
if (param) {
const [_, value] = param.split(":") || [];
2024-07-05 14:51:25 +07:00
page.value = Number(value);
2024-06-28 15:39:26 +07:00
await loadPage(value);
2024-06-13 17:24:46 +07:00
}
};
onBeforeMount(() => {
if (route.query[`cpn_${_props.component?.id}`]) handleRouteChange(route.query);
});
2024-06-28 15:39:26 +07:00
const loadPage = async (page: number) => {
let newDataQuery = "";
const regex = /Page\[(.*?)\]/;
const match = _props.component?.settings?.dataQuery?.match(regex);
if (match) {
const [pageData] = match;
newDataQuery = _props.component?.settings?.dataQuery.replace(pageData, `Page[${page}]`);
} else {
newDataQuery = _props.component?.settings?.dataQuery + ` Page[${page}]`;
}
const res = await store.component.getOverviewPageComponentById(Number(_props.component?.id), newDataQuery);
const data = getInputValue(res?.settings?.dataResult, "OBJECT");
2024-07-05 14:51:25 +07:00
2024-06-28 15:39:26 +07:00
if (Object.keys(data).length > 0) {
totals.value = data.Total;
listArticlePaging.value = data?.Data || [];
}
};
const handleNextPrev = (type: "+" | "-") => {
if (listArticleByCategory.value?.length > 0) {
if (type === "+") {
page.value += 1;
} else if (type === "-") {
page.value -= 1;
}
select(page.value);
}
2024-06-13 17:24:46 +07:00
};
2024-06-28 15:39:26 +07:00
const mapActivesToItems = (index: number) => {
if (designObject.value && designObject.value.listCss) {
return designObject.value.listCss[index] || {};
2024-06-13 17:24:46 +07:00
}
2024-06-28 15:39:26 +07:00
return {};
};
2024-06-13 17:24:46 +07:00
</script>
<template>
2024-07-05 14:51:25 +07:00
<section v-if="listArticleByCategory?.length > 0">
<div class="section-container">
2024-06-28 15:39:26 +07:00
<div class="section-layout" :style="designObject['div.section']">
2024-07-05 14:51:25 +07:00
<template v-for="(component, index) in listArticlePaging?.length > 0 ? listArticlePaging : listArticleByCategory" :key="index">
<DynamicComponent
:settings="{
template: SETTING_OPTIONS.TEMPLATE,
layout: SETTING_OPTIONS.LAYOUT,
dataResult: { ...component },
label: mapActivesToItems(Number(index)),
}"
:component="COMPONENT"
/>
2024-06-28 15:39:26 +07:00
</template>
2024-06-13 17:24:46 +07:00
<div class="button-page flex">
2024-07-05 14:51:25 +07:00
<span class="btn-page prev-page" @click.stop="() => handleNextPrev('-')" v-if="page > 1">
2024-06-28 15:39:26 +07:00
<i class="el-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
2024-06-13 17:24:46 +07:00
<path
fill="currentColor"
d="M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z"
></path>
</svg>
2024-06-28 15:39:26 +07:00
</i>
2024-07-05 14:51:25 +07:00
</span>
<span :class="['btn-page', page === index + 1 && 'active']" @click.stop="() => select(index + 1)" v-for="(_, index) in Math.ceil(totals / limit)">{{ index + 1 }}</span>
<span class="btn-page next-page" @click.stop="() => handleNextPrev('+')" v-if="page < Math.ceil(totals / limit)">
2024-06-28 15:39:26 +07:00
<i class="el-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
2024-06-13 17:24:46 +07:00
<path
fill="currentColor"
d="M340.864 149.312a30.592 30.592 0 0 0 0 42.752L652.736 512 340.864 831.872a30.592 30.592 0 0 0 0 42.752 29.12 29.12 0 0 0 41.728 0L714.24 534.336a32 32 0 0 0 0-44.672L382.592 149.376a29.12 29.12 0 0 0-41.728 0z"
></path>
</svg>
2024-06-28 15:39:26 +07:00
</i>
2024-07-05 14:51:25 +07:00
</span>
2024-06-13 17:24:46 +07:00
</div>
</div>
</div>
2024-07-05 14:51:25 +07:00
<div v-html="designObject.styleClasses" style="display: none" v-if="designObject.styles"></div>
2024-06-13 17:24:46 +07:00
</section>
</template>
<style lang="scss" scoped>
.section-container {
2024-06-28 15:39:26 +07:00
.section-layout {
display: flex;
flex-direction: column;
2024-06-18 14:04:24 +07:00
/* gap: 10px; */
overflow-x: scroll;
2024-06-13 17:24:46 +07:00
&.border-custom {
border-color: #e5e5e5 !important;
}
}
.basic-article {
&.article {
margin-bottom: 10px;
display: flex;
pointer-events: none;
}
}
.flex {
display: flex;
margin-top: 10px;
justify-content: center;
overflow-x: auto;
}
.button-page {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.btn-page {
width: 40px;
height: 40px;
2024-07-05 14:51:25 +07:00
padding: 9px 16px;
2024-06-13 17:24:46 +07:00
text-align: center;
line-height: 36px;
2024-07-05 14:51:25 +07:00
border-radius: 4px;
2024-06-13 17:24:46 +07:00
margin-left: 10px;
display: flex;
justify-content: center;
align-items: center;
2024-07-05 14:51:25 +07:00
gap: 8px;
flex-shrink: 0;
background: #f2f2f2;
2024-06-28 15:39:26 +07:00
cursor: pointer;
2024-07-05 14:51:25 +07:00
color: #222222;
2024-06-28 15:39:26 +07:00
&.active {
2024-07-05 14:51:25 +07:00
background: #ed1c24;
2024-06-28 15:39:26 +07:00
color: white;
}
2024-06-13 17:24:46 +07:00
}
}
2024-06-28 15:39:26 +07:00
.el-empty {
padding: 12px 0;
}
2024-06-13 17:24:46 +07:00
</style>