Files
NSG_PORTAL_V2/components/dynamic-page/page-component/templates/articles/layouts/Card.vue
T

190 lines
4.9 KiB
Vue
Raw Normal View History

<script lang="ts" setup>
2024-06-13 17:24:46 +07:00
import { enumPageComponentTemplates } from "@/definitions/enum";
import { DEFAULT_QUERY_DROP } from "@/utils/parseSQL";
import { getInputValue } from "@/utils/parseSQL";
const props = defineProps<{
dataResult?: any;
dataType?: any;
dataQuery?: any;
layout?: string;
2024-06-13 17:24:46 +07:00
label?: string;
}>();
2024-06-13 17:24:46 +07:00
const LAYOUT_PARSE = computed(() => {
const parseLayout =
props.layout?.split("-")?.map((_layout: any) => {
const parseItem = _layout.split(":");
return {
[parseItem[0]]: parseItem[0] === "HIDE" ? parseItem[1].split(",") : parseItem[1],
};
}) || [];
const designObject = props.label ? getInputValue(props.label, "OBJECT") : {};
return Object.assign({}, ...parseLayout, designObject);
});
const emit = defineEmits(["selectComponent", "dropData"]);
const selectComponent = () => {
emit("selectComponent");
};
const parseData = computed(() => {
if (!props.dataResult) return;
const result = getInputValue(props.dataResult, "OBJECT");
return result;
});
const drop = (e: any) => {
if (e.dataTransfer.getData(`${enumPageComponentTemplates.ARTICLE}`)) {
const data = e.dataTransfer.getData(`${enumPageComponentTemplates.ARTICLE}`);
const { dataType, dataResult } = JSON.parse(data);
const dataQuery = DEFAULT_QUERY_DROP(dataType, dataResult.id);
emit("dropData", {
dataType,
dataResult,
dataQuery: dataQuery,
});
}
};
</script>
<template>
2024-06-13 17:24:46 +07:00
<article
class="basic-article border-custom"
@click="selectComponent"
@dragover.prevent
@drop.stop.prevent="drop"
:class="[LAYOUT_PARSE['LAYOUT'] || 'horizontal', !parseData && 'no-data', LAYOUT_PARSE['REVERSE'] ? 'reverse' : '', ...(LAYOUT_PARSE['border']?.length > 0 ? LAYOUT_PARSE['border'] : [])]"
:style="[LAYOUT_PARSE['background'] && `background: ${LAYOUT_PARSE['background']}`]"
>
<div v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('thumbnail')" class="basic-article_thumbnail" :style="[LAYOUT_PARSE['LAYOUT'] === 'horizontal' && LAYOUT_PARSE['WidthImg'] && `width: ${LAYOUT_PARSE['WidthImg']}%`]">
<template v-if="parseData">
<nuxt-link :to="`bai-viet/${parseData?.slug}`">
<img class="object-fit-cover" :src="parseData.thumbnail ? parseData.thumbnail : '/images/default-thumbnail.jpg'" :alt="parseData.title?.replace(/<[^>]+>/g, '')" />
</nuxt-link>
</template>
<span v-else class="empty-block" style="width: 100%; height: 100%; min-height: 50px"></span>
</div>
<div class="basic-article_content !py-0" :class="[!parseData && 'no-data']">
<div>
<nuxt-link :to="`bai-viet/${parseData?.slug}`" v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('title')" class="mb-1 text-truncate-two-lines font-bold line-clamp-2 hover:text-primary-600">
<template v-if="parseData">
{{ parseData.title?.replace(/<[^>]+>/g, "") }}
</template>
<span v-else class="empty-block" style="height: 8px"></span>
</nuxt-link>
<p v-if="!LAYOUT_PARSE['HIDE'] || !LAYOUT_PARSE['HIDE'].includes('paragraph')" class="mb-0 line-clamp-3">
<template v-if="parseData">
{{ parseData.intro ? parseData.intro?.replace(/<[^>]+>/g, "") : parseData.detail?.replace(/<[^>]+>/g, "") }}
</template>
<span v-else class="empty-block" style="height: 5px"></span>
</p>
</div>
</div>
</article>
</template>
<style lang="scss" scoped>
.basic-article {
2024-06-13 17:24:46 +07:00
display: flex;
2024-06-17 11:48:00 +07:00
gap: 12px;
height: 100%;
&.no-data {
gap: 5px !important;
}
&.vertical {
2024-06-13 17:24:46 +07:00
flex-direction: column;
.basic-article_thumbnail {
width: 100%;
}
&.reverse {
flex-direction: column-reverse;
height: 100%;
2024-06-17 11:48:00 +07:00
@media (max-width: 640px) {
flex-direction:column;
}
2024-06-13 17:24:46 +07:00
}
}
&.border-custom {
border-color: #e5e5e5 !important;
}
&.borderLeft {
2024-06-13 17:24:46 +07:00
border-left: 1px solid;
2024-06-17 11:48:00 +07:00
padding-left: 16px;
}
&.borderRight {
2024-06-13 17:24:46 +07:00
border-right: 1px solid;
2024-06-17 11:48:00 +07:00
padding-right: 16px;
}
&.borderTop {
2024-06-13 17:24:46 +07:00
border-top: 1px solid;
2024-06-17 11:48:00 +07:00
padding-top: 16px;
}
&.borderBottom {
2024-06-13 17:24:46 +07:00
border-bottom: 1px solid;
2024-06-17 11:48:00 +07:00
padding-bottom: 16px;
}
2024-06-17 11:48:00 +07:00
&.borderRight ,
&.borderLeft,
&.borderTop,
&.borderBottom {
@media (max-width: 640px) {
border: 0;
padding: 0;
}
}
&.horizontal {
2024-06-17 11:48:00 +07:00
@apply sm:flex-row flex-col;
2024-06-13 17:24:46 +07:00
.basic-article_thumbnail {
width: 40%;
2024-06-17 11:48:00 +07:00
@media (max-width: 640px) {
width: 100% !important;
}
2024-06-13 17:24:46 +07:00
}
&.reverse {
2024-06-13 17:24:46 +07:00
flex-direction: row-reverse;
}
}
&_thumbnail {
img {
width: 100%;
border-radius: 6px;
aspect-ratio: 16/10;
}
}
&_content {
padding: 10px 0px;
2024-06-13 17:24:46 +07:00
flex: 1;
&.no-data {
padding: 0px;
}
h3 {
font-size: 15px;
}
p {
font-size: 12px;
margin-top: 10px;
}
}
2024-06-13 17:24:46 +07:00
// .empty-block {
// background-color: #409eff;
// height: 100px;
// display: block;
// }
}
</style>