chore: install prettier
This commit is contained in:
@@ -7,17 +7,8 @@ const props = defineProps({
|
||||
row: Object,
|
||||
});
|
||||
|
||||
const {
|
||||
$buildFileUrl,
|
||||
$id,
|
||||
$formatFileSize,
|
||||
$getdata,
|
||||
$getpath,
|
||||
$getapi,
|
||||
$findapi,
|
||||
$snackbar,
|
||||
$exportpdf,
|
||||
} = useNuxtApp();
|
||||
const { $buildFileUrl, $id, $formatFileSize, $getdata, $getpath, $getapi, $findapi, $snackbar, $exportpdf } =
|
||||
useNuxtApp();
|
||||
const store = useStore();
|
||||
const product = props.row || {};
|
||||
const tab = ref("info");
|
||||
@@ -37,19 +28,7 @@ const documents = ref([]);
|
||||
const projectDocuments = ref([]);
|
||||
const viewingImage = ref(null);
|
||||
const imageExtensions = ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"];
|
||||
const documentExtensions = [
|
||||
"pdf",
|
||||
"doc",
|
||||
"docx",
|
||||
"xls",
|
||||
"xlsx",
|
||||
"ppt",
|
||||
"pptx",
|
||||
"txt",
|
||||
"csv",
|
||||
"zip",
|
||||
"rar",
|
||||
];
|
||||
const documentExtensions = ["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "csv", "zip", "rar"];
|
||||
|
||||
const policies = ref([]);
|
||||
const selectedPolicy = ref(null);
|
||||
@@ -79,9 +58,7 @@ async function loadAllPolicyData() {
|
||||
const plansData = await $getdata("paymentplan", {}, undefined, false);
|
||||
|
||||
policies.value = policiesData || [];
|
||||
allPaymentPlans.value = plansData
|
||||
? plansData.sort((a, b) => a.cycle - b.cycle)
|
||||
: [];
|
||||
allPaymentPlans.value = plansData ? plansData.sort((a, b) => a.cycle - b.cycle) : [];
|
||||
|
||||
if (policies.value.length > 0) {
|
||||
loadPlansForPolicy(policies.value[0].id);
|
||||
@@ -102,27 +79,18 @@ function loadPlansForPolicy(id) {
|
||||
if (!policy) return;
|
||||
|
||||
selectedPolicy.value = policy;
|
||||
paymentPlans.value = allPaymentPlans.value.filter(
|
||||
(plan) => plan.policy === id
|
||||
);
|
||||
paymentPlans.value = allPaymentPlans.value.filter((plan) => plan.policy === id);
|
||||
activeTab.value = id;
|
||||
}
|
||||
|
||||
function printContent() {
|
||||
if (!record.value || !selectedPolicy.value) {
|
||||
$snackbar(
|
||||
isVietnamese.value
|
||||
? "Vui lòng chọn chính sách"
|
||||
: "Please select a policy",
|
||||
{ type: "is-warning" }
|
||||
);
|
||||
$snackbar(isVietnamese.value ? "Vui lòng chọn chính sách" : "Please select a policy", { type: "is-warning" });
|
||||
return;
|
||||
}
|
||||
|
||||
const docId = 'print-area';
|
||||
const fileName = `${selectedPolicy.value?.name || "Payment Schedule"} - ${
|
||||
record.value?.code
|
||||
}`;
|
||||
const docId = "print-area";
|
||||
const fileName = `${selectedPolicy.value?.name || "Payment Schedule"} - ${record.value?.code}`;
|
||||
|
||||
if (typeof $exportpdf === "function") {
|
||||
$exportpdf(docId, fileName);
|
||||
@@ -184,12 +152,7 @@ async function loadProductFiles() {
|
||||
|
||||
const files = await Promise.all(
|
||||
links.map(async (link) => {
|
||||
const fileData = await $getdata(
|
||||
"file",
|
||||
{ id: link.file },
|
||||
undefined,
|
||||
true
|
||||
).catch((error) => {
|
||||
const fileData = await $getdata("file", { id: link.file }, undefined, true).catch((error) => {
|
||||
console.error(`Error loading file ${link.file}:`, error);
|
||||
return null;
|
||||
});
|
||||
@@ -203,7 +166,7 @@ async function loadProductFiles() {
|
||||
caption: fileData?.caption || "",
|
||||
create_time: link.create_time,
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
const imageList = [];
|
||||
@@ -256,12 +219,7 @@ async function loadProjectFiles() {
|
||||
|
||||
const files = await Promise.all(
|
||||
links.map(async (link) => {
|
||||
const fileData = await $getdata(
|
||||
"file",
|
||||
{ id: link.file },
|
||||
undefined,
|
||||
true
|
||||
).catch((error) => {
|
||||
const fileData = await $getdata("file", { id: link.file }, undefined, true).catch((error) => {
|
||||
console.error(`Error loading project file ${link.file}:`, error);
|
||||
return null;
|
||||
});
|
||||
@@ -269,7 +227,7 @@ async function loadProjectFiles() {
|
||||
link,
|
||||
fileData,
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
const validFiles = files.filter((entry) => entry.fileData);
|
||||
@@ -286,9 +244,7 @@ async function loadProjectFiles() {
|
||||
caption: entry.fileData.caption || "",
|
||||
url: $buildFileUrl(entry.fileData.file),
|
||||
file: entry.fileData.file,
|
||||
size: entry.fileData.size
|
||||
? $formatFileSize(Number(entry.fileData.size))
|
||||
: "",
|
||||
size: entry.fileData.size ? $formatFileSize(Number(entry.fileData.size)) : "",
|
||||
uploaded_by: entry.fileData.creator__fullname || "Admin",
|
||||
uploaded_at: entry.fileData.create_time || entry.link.create_time || "",
|
||||
};
|
||||
@@ -333,48 +289,44 @@ async function loadLookupNames() {
|
||||
|
||||
if (record.value.status && !record.value.status__name) {
|
||||
promises.push(
|
||||
$getdata("productstatus", { id: record.value.status }, undefined, true)
|
||||
.then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.status__name = data.name;
|
||||
}
|
||||
})
|
||||
$getdata("productstatus", { id: record.value.status }, undefined, true).then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.status__name = data.name;
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (record.value.type && !record.value.type__name) {
|
||||
promises.push(
|
||||
$getdata("producttype", { id: record.value.type }, undefined, true)
|
||||
.then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.type__name = data.name;
|
||||
record.value.type__en = data.name_en || data.en || data.name;
|
||||
}
|
||||
})
|
||||
$getdata("producttype", { id: record.value.type }, undefined, true).then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.type__name = data.name;
|
||||
record.value.type__en = data.name_en || data.en || data.name;
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (record.value.direction && !record.value.direction__name) {
|
||||
promises.push(
|
||||
$getdata("direction", { id: record.value.direction }, undefined, true)
|
||||
.then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.direction__name = data.name;
|
||||
record.value.direction__en = data.name_en || data.en || data.name;
|
||||
}
|
||||
})
|
||||
$getdata("direction", { id: record.value.direction }, undefined, true).then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.direction__name = data.name;
|
||||
record.value.direction__en = data.name_en || data.en || data.name;
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (record.value.zone_type && !record.value.zone_type__name) {
|
||||
promises.push(
|
||||
$getdata("zonetype", { id: record.value.zone_type }, undefined, true)
|
||||
.then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.zone_type__name = data.name;
|
||||
record.value.zone_type__en = data.name_en || data.en || data.name;
|
||||
}
|
||||
})
|
||||
$getdata("zonetype", { id: record.value.zone_type }, undefined, true).then((data) => {
|
||||
if (data && data.name) {
|
||||
record.value.zone_type__name = data.name;
|
||||
record.value.zone_type__en = data.name_en || data.en || data.name;
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -391,21 +343,16 @@ async function loadLookupNames() {
|
||||
const rs = await $getapi([projectApi]);
|
||||
const data = rs[0]?.data;
|
||||
if (data) {
|
||||
const projectName =
|
||||
data.name || data.fullname || data.code || data.title;
|
||||
const projectName = data.name || data.fullname || data.code || data.title;
|
||||
if (projectName) {
|
||||
record.value.project__name = projectName;
|
||||
record.value.project__fullname =
|
||||
data.fullname || data.name || projectName;
|
||||
record.value.project__fullname = data.fullname || data.name || projectName;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Failed to load project for id ${record.value.project}:`,
|
||||
err
|
||||
);
|
||||
console.error(`Failed to load project for id ${record.value.project}:`, err);
|
||||
}
|
||||
})()
|
||||
})(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -418,20 +365,13 @@ async function loadLookupNames() {
|
||||
async function loadFullData() {
|
||||
if (!props.row?.id) return;
|
||||
try {
|
||||
const fullData = await $getdata(
|
||||
"product",
|
||||
{ id: props.row.id },
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
const fullData = await $getdata("product", { id: props.row.id }, undefined, true);
|
||||
record.value = fullData;
|
||||
|
||||
await loadLookupNames();
|
||||
await loadProductFiles();
|
||||
await loadProjectFiles();
|
||||
await loadAllPolicyData();
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error loading full product data:", error);
|
||||
record.value = props.row ? { ...props.row } : null;
|
||||
@@ -450,7 +390,7 @@ watch(
|
||||
await loadFullData();
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
{ immediate: false },
|
||||
);
|
||||
|
||||
watch(
|
||||
@@ -463,7 +403,7 @@ watch(
|
||||
projectDocuments.value = [];
|
||||
}
|
||||
},
|
||||
{ immediate: false }
|
||||
{ immediate: false },
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -472,7 +412,10 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="record" class="px-5">
|
||||
<div
|
||||
v-if="record"
|
||||
class="px-5"
|
||||
>
|
||||
<div class="tabs is-toggle is-fullwidth mb-4">
|
||||
<ul>
|
||||
<li :class="{ 'is-active': tab === 'info' }">
|
||||
@@ -502,14 +445,17 @@ onMounted(async () => {
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<div v-if="tab === 'info' && record" :id="docid">
|
||||
<div
|
||||
v-if="tab === 'info' && record"
|
||||
:id="docid"
|
||||
>
|
||||
<TransactionView
|
||||
pagename="ProductView"
|
||||
:transactionId="product.txnprd"
|
||||
:productId="product.id"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Tab Hình ảnh -->
|
||||
<div v-if="tab === 'image' && record">
|
||||
<div class="columns is-gapless">
|
||||
@@ -565,9 +511,7 @@ onMounted(async () => {
|
||||
</div>
|
||||
<div class="card-content p-2">
|
||||
<div class="image-meta">
|
||||
<p
|
||||
class="has-text-weight-semibold is-size-7 is-clipped"
|
||||
>
|
||||
<p class="has-text-weight-semibold is-size-7 is-clipped">
|
||||
{{ image.name }}
|
||||
</p>
|
||||
<p class="is-size-7 is-clipped">
|
||||
@@ -578,7 +522,10 @@ onMounted(async () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="has-text-centered py-4">
|
||||
<div
|
||||
v-else
|
||||
class="has-text-centered py-4"
|
||||
>
|
||||
<p class="">Chưa có hình ảnh nào được tải lên.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -609,9 +556,7 @@ onMounted(async () => {
|
||||
</div>
|
||||
<div class="card-content p-2">
|
||||
<div class="image-meta">
|
||||
<p
|
||||
class="has-text-weight-semibold is-size-7 is-clipped"
|
||||
>
|
||||
<p class="has-text-weight-semibold is-size-7 is-clipped">
|
||||
{{ image.name }}
|
||||
</p>
|
||||
<p class="is-size-7 is-clipped">
|
||||
@@ -622,7 +567,10 @@ onMounted(async () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="has-text-centered py-4">
|
||||
<div
|
||||
v-else
|
||||
class="has-text-centered py-4"
|
||||
>
|
||||
<p class="">Chưa có hình ảnh dự án nào được tải lên.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -636,16 +584,13 @@ onMounted(async () => {
|
||||
@click.self="closeViewImage"
|
||||
>
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-content" style="width: 90vw; height: 90vh">
|
||||
<div
|
||||
class="modal-content"
|
||||
style="width: 90vw; height: 90vh"
|
||||
>
|
||||
<figure
|
||||
class="image"
|
||||
style="
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
"
|
||||
style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center"
|
||||
>
|
||||
<img
|
||||
:src="viewingImage.url"
|
||||
@@ -704,7 +649,10 @@ onMounted(async () => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="doc in documents" :key="doc.id">
|
||||
<tr
|
||||
v-for="doc in documents"
|
||||
:key="doc.id"
|
||||
>
|
||||
<td>
|
||||
<div class="is-flex is-align-items-center">
|
||||
<span class="icon is-medium has-text-info mr-2">
|
||||
@@ -735,13 +683,7 @@ onMounted(async () => {
|
||||
{{ doc.uploaded_by }}
|
||||
</p>
|
||||
<p class="is-size-7 has-text-grey">
|
||||
{{
|
||||
doc.uploaded_at
|
||||
? new Date(doc.uploaded_at).toLocaleString(
|
||||
"vi-VN"
|
||||
)
|
||||
: "-"
|
||||
}}
|
||||
{{ doc.uploaded_at ? new Date(doc.uploaded_at).toLocaleString("vi-VN") : "-" }}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
@@ -767,10 +709,11 @@ onMounted(async () => {
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="documents.length === 0">
|
||||
<td colspan="4" class="has-text-centered py-4">
|
||||
<p class="has-text-grey">
|
||||
Chưa có tài liệu nào được đính kèm.
|
||||
</p>
|
||||
<td
|
||||
colspan="4"
|
||||
class="has-text-centered py-4"
|
||||
>
|
||||
<p class="has-text-grey">Chưa có tài liệu nào được đính kèm.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -791,7 +734,10 @@ onMounted(async () => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="doc in projectDocuments" :key="doc.id">
|
||||
<tr
|
||||
v-for="doc in projectDocuments"
|
||||
:key="doc.id"
|
||||
>
|
||||
<td>
|
||||
<div class="is-flex is-align-items-center">
|
||||
<span class="icon is-medium has-text-info mr-2">
|
||||
@@ -822,13 +768,7 @@ onMounted(async () => {
|
||||
{{ doc.uploaded_by }}
|
||||
</p>
|
||||
<p class="is-size-7 has-text-grey">
|
||||
{{
|
||||
doc.uploaded_at
|
||||
? new Date(doc.uploaded_at).toLocaleString(
|
||||
"vi-VN"
|
||||
)
|
||||
: "-"
|
||||
}}
|
||||
{{ doc.uploaded_at ? new Date(doc.uploaded_at).toLocaleString("vi-VN") : "-" }}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
@@ -854,10 +794,11 @@ onMounted(async () => {
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="projectDocuments.length === 0">
|
||||
<td colspan="4" class="has-text-centered py-4">
|
||||
<p class="has-text-grey">
|
||||
Chưa có tài liệu dự án nào được đính kèm.
|
||||
</p>
|
||||
<td
|
||||
colspan="4"
|
||||
class="has-text-centered py-4"
|
||||
>
|
||||
<p class="has-text-grey">Chưa có tài liệu dự án nào được đính kèm.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -869,11 +810,18 @@ onMounted(async () => {
|
||||
</div>
|
||||
|
||||
<!-- Tab Chính sách tài chính -->
|
||||
<div v-if="tab === 'financial-policy' && record" class="py-3">
|
||||
<div v-if="isLoadingPolicies" class="has-text-centered">
|
||||
<div
|
||||
v-if="tab === 'financial-policy' && record"
|
||||
class="py-3"
|
||||
>
|
||||
<div
|
||||
v-if="isLoadingPolicies"
|
||||
class="has-text-centered"
|
||||
>
|
||||
<p class="has-text-info is-italic">Đang tải chính sách...</p>
|
||||
</div>
|
||||
<PaymentSchedule v-else
|
||||
<PaymentSchedule
|
||||
v-else
|
||||
:productData="record"
|
||||
:policies="policies"
|
||||
:activeTab="activeTab"
|
||||
@@ -1052,4 +1000,4 @@ li a:hover .icon :deep(img) {
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user