Files
web/app/components/application/Contract.vue
2026-05-05 11:06:49 +07:00

287 lines
7.3 KiB
Vue

<template>
<div :id="docid">
<!-- Loading state -->
<div
v-if="isLoading"
class="has-text-centered mt-5 mb-5"
style="min-height: 500px"
>
<button class="button is-primary is-loading is-large"></button>
<p class="mt-4 has-text-primary has-text-weight-semibold">
{{ isVietnamese ? "Đang tải hợp đồng..." : "Loading contracts..." }}
</p>
</div>
<!-- No contract state -->
<div
v-else-if="!hasContracts"
class="has-text-centered mt-5 mb-5"
style="min-height: 500px"
>
<article class="message is-primary">
<div
class="message-body"
style="font-size: 17px; text-align: left; color: black"
>
{{
isVietnamese
? "Chưa có hợp đồng. Vui lòng tạo giao dịch và hợp đồng trước."
: "No contract available. Please create transaction and contract first."
}}
</div>
</article>
</div>
<!-- Contracts list -->
<template v-else>
<!-- Tabs khi nhiều hợp đồng -->
<div
class="tabs border-bottom"
id="ignore"
v-if="contractsList.length > 1"
>
<ul class="tabs-list">
<li
class="tabs-item"
style="border: none"
v-for="(contract, index) in contractsList"
:key="index"
:class="{
'bg-primary has-text-white': activeContractIndex === index,
}"
@click="switchContract(index)"
>
<a class="tabs-link">
<span>{{ contract.document[0]?.name || contract.document[0]?.en || `Contract ${index + 1}` }}</span>
</a>
</li>
</ul>
</div>
<!-- Contract content -->
<div v-if="currentContract && pdfFileUrl && hasValidDocument">
<div class="contract-content mt-2">
<iframe
:src="`https://mozilla.github.io/pdf.js/web/viewer.html?file=${pdfFileUrl}`"
width="100%"
height="90vh"
scrolling="no"
style="border: none; height: 75vh; top: 0; left: 0; right: 0; bottom: 0"
>
</iframe>
</div>
</div>
<!-- Download buttons -->
<div
class="mt-4"
id="ignore"
>
<button
v-if="hasValidDocument"
class="button is-primary has-text-white mr-4"
@click="downloadDocx"
>
{{ isVietnamese ? "Tải file docx" : "Download contract as docx" }}
</button>
<button
v-if="hasValidDocument"
class="button is-primary has-text-white mr-4"
@click="downloadPdf"
>
{{ isVietnamese ? "Tải file pdf" : "Download contract as pdf" }}
</button>
<p
v-if="contractError"
class="has-text-danger mt-2"
>
{{ contractError }}
</p>
</div>
</template>
</div>
</template>
<script>
import { useStore } from "@/stores/index";
export default {
setup() {
const store = useStore();
return { store };
},
props: {
contractId: {
type: [Number, String],
default: null,
},
row: {
type: Object,
default: null,
},
directDocument: {
type: Object,
default: null,
},
},
emits: ["contractCreated", "update", "close", "dataevent"],
data() {
return {
docid: this.$id(),
contractsList: [],
activeContractIndex: 0,
isLoading: false,
contractError: null,
lang: this.store.lang,
isVietnamese: this.store.lang === "vi",
link: this.$getpath().indexOf("dev") >= 0 ? "dev.utopia.y99.vn" : "utopia.y99.vn",
pdfFileUrl: undefined,
};
},
computed: {
hasContracts() {
return this.contractsList && this.contractsList.length > 0;
},
currentContract() {
return this.hasContracts ? this.contractsList[this.activeContractIndex] : null;
},
hasValidDocument() {
if (!this.currentContract) return false;
return (
this.currentContract.document &&
this.currentContract.document.length > 0 &&
this.currentContract.document[0]?.pdf
);
},
},
async created() {
try {
this.isLoading = true;
this.contractError = null;
if (this.directDocument) {
this.contractsList = [{ document: [this.directDocument] }];
this.updatePdfUrl(0);
return;
}
let contracts = [];
let fetchParams = null;
if (this.contractId) {
fetchParams = { id: this.contractId };
} else if (this.row?.id) {
fetchParams = { transaction: this.row.id };
}
if (!fetchParams) {
throw new Error(
this.isVietnamese
? "Không có ID hợp đồng hoặc transaction để tải."
: "No contract ID or transaction provided to load.",
);
}
contracts = await this.$getdata("contract", fetchParams, undefined);
if (!contracts || contracts.length === 0) {
throw new Error(this.isVietnamese ? "Không tìm thấy hợp đồng." : "Contract not found.");
}
this.contractsList = contracts;
console.log(this.contractsList);
if (this.hasContracts) {
this.updatePdfUrl(this.activeContractIndex);
}
} catch (error) {
console.error("Error loading contracts:", error);
this.contractError =
error.message || (this.isVietnamese ? "Lỗi khi tải danh sách hợp đồng." : "Error loading contracts list.");
this.contractsList = [];
} finally {
this.isLoading = false;
}
},
methods: {
updatePdfUrl(index) {
const contract = this.contractsList[index];
if (contract?.document && contract.document[0]?.pdf) {
this.pdfFileUrl = `${this.$getpath()}download-contract/${contract.document[0].pdf}`;
} else {
this.pdfFileUrl = undefined;
}
},
switchContract(index) {
this.activeContractIndex = index;
this.updatePdfUrl(index);
},
downloadDocx() {
if (!this.hasValidDocument) {
this.$snackbar(this.isVietnamese ? "Không có file để tải" : "No file to download", { type: "is-warning" });
return;
}
const filename = this.currentContract.document[0].file;
const url = `${this.$getpath()}download/?name=${filename}&type=contract`;
this.$download(url, filename);
},
downloadPdf() {
if (!this.hasValidDocument) {
this.$snackbar(this.isVietnamese ? "Không có file để tải" : "No file to download", { type: "is-warning" });
return;
}
const filename = this.currentContract.document[0].pdf;
const url = `${this.$getpath()}download/?name=${filename}&type=contract`;
this.$download(url, filename);
},
},
};
</script>
<style scoped>
.contract-content {
max-width: 95%;
margin: 0 auto;
font-size: 18px;
line-height: 1.5;
font-family: "Times New Roman", serif;
page-break-inside: avoid;
break-inside: avoid;
}
.tabs {
width: auto;
margin-bottom: 0;
}
.tabs-list {
border: none;
transition: all 0.3s ease;
}
.tabs-item {
transition: background-color 0.3s ease;
}
.tabs-item.bg-primary:hover a {
color: white !important;
}
.tabs-link {
padding: 6px 12px;
}
@media print {
.contract-content {
max-width: 100%;
}
}
</style>