chore: install prettier
This commit is contained in:
@@ -4,9 +4,13 @@
|
||||
Vui lòng kiểm tra kỹ thông tin trước khi thay đổi ngày đến hạn
|
||||
</p>
|
||||
|
||||
<div v-if="loadingData" class="has-text-centered py-5">
|
||||
<div
|
||||
v-if="loadingData"
|
||||
class="has-text-centered py-5"
|
||||
>
|
||||
<SvgIcon v-bind="{ name: 'loading.svg', type: 'primary', size: 18 }" />
|
||||
<p class="mt-2">{{ isVietnamese ? 'Đang tải thông tin công nợ...' : 'Loading payment schedule information...' }}
|
||||
<p class="mt-2">
|
||||
{{ isVietnamese ? "Đang tải thông tin công nợ..." : "Loading payment schedule information..." }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -14,122 +18,166 @@
|
||||
<div class="content">
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Mã:' : 'Schedule Code:' }}</strong>
|
||||
<p>{{ paymentScheduleData.code || '-' }}</p>
|
||||
<strong>{{ isVietnamese ? "Mã:" : "Schedule Code:" }}</strong>
|
||||
<p>{{ paymentScheduleData.code || "-" }}</p>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Trạng thái:' : 'Status:' }}</strong>
|
||||
<strong>{{ isVietnamese ? "Trạng thái:" : "Status:" }}</strong>
|
||||
<p
|
||||
:class="{ 'has-text-success': paymentScheduleData.status__name === 'Đã xác nhận', 'has-text-warning': paymentScheduleData.status__name === 'Chưa xác nhận' }">
|
||||
{{ paymentScheduleData.status__name || '-' }}
|
||||
:class="{
|
||||
'has-text-success': paymentScheduleData.status__name === 'Đã xác nhận',
|
||||
'has-text-warning': paymentScheduleData.status__name === 'Chưa xác nhận',
|
||||
}"
|
||||
>
|
||||
{{ paymentScheduleData.status__name || "-" }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Loại thanh toán:' : 'Payment Type:' }}</strong>
|
||||
<p>{{ paymentScheduleData.type__name || '-' }}</p>
|
||||
<strong>{{ isVietnamese ? "Loại thanh toán:" : "Payment Type:" }}</strong>
|
||||
<p>{{ paymentScheduleData.type__name || "-" }}</p>
|
||||
</div>
|
||||
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Tiền gốc theo kỳ thanh toán:' : 'Amount:' }}</strong>
|
||||
<p class="has-text-weight-bold has-text-primary">{{ $numtoString(paymentScheduleData.amount) }}</p>
|
||||
<strong>{{ isVietnamese ? "Tiền gốc theo kỳ thanh toán:" : "Amount:" }}</strong>
|
||||
<p class="has-text-weight-bold has-text-primary">
|
||||
{{ $numtoString(paymentScheduleData.amount) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Ngày đến hạn hiện tại:' : 'Current Due Date:' }}</strong>
|
||||
<p class="has-text-weight-bold">{{ formatDate(paymentScheduleData.to_date) }}</p>
|
||||
<strong>{{ isVietnamese ? "Ngày đến hạn hiện tại:" : "Current Due Date:" }}</strong>
|
||||
<p class="has-text-weight-bold">
|
||||
{{ formatDate(paymentScheduleData.to_date) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Ngày tính lãi:' : 'Penalty Date:' }}</strong>
|
||||
<strong>{{ isVietnamese ? "Ngày tính lãi:" : "Penalty Date:" }}</strong>
|
||||
<p :class="paymentScheduleData.batch_date ? 'has-text-danger' : ''">
|
||||
{{ formatDate(paymentScheduleData.batch_date) || 'Chưa tính lãi' }}
|
||||
{{ formatDate(paymentScheduleData.batch_date) || "Chưa tính lãi" }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<p class="title is-6">{{ isVietnamese ? 'Thông tin Giao dịch liên quan' : 'Related Transaction Information' }}
|
||||
<p class="title is-6">
|
||||
{{ isVietnamese ? "Thông tin Giao dịch liên quan" : "Related Transaction Information" }}
|
||||
</p>
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Mã giao dịch:' : 'Transaction Code:' }}</strong>
|
||||
<p>{{ paymentScheduleData.txn_detail__transaction__code || '-' }}</p>
|
||||
<strong>{{ isVietnamese ? "Mã giao dịch:" : "Transaction Code:" }}</strong>
|
||||
<p>
|
||||
{{ paymentScheduleData.txn_detail__transaction__code || "-" }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Khách hàng:' : 'Customer:' }}</strong>
|
||||
<p>{{ paymentScheduleData.txn_detail__transaction__customer__fullname || '-' }}</p>
|
||||
<strong>{{ isVietnamese ? "Khách hàng:" : "Customer:" }}</strong>
|
||||
<p>
|
||||
{{ paymentScheduleData.txn_detail__transaction__customer__fullname || "-" }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<strong>{{ isVietnamese ? 'Chính sách:' : 'Policy:' }}</strong>
|
||||
<p>{{ paymentScheduleData.txn_detail__transaction__policy__code || '-' }} </p>
|
||||
<strong>{{ isVietnamese ? "Chính sách:" : "Policy:" }}</strong>
|
||||
<p>
|
||||
{{ paymentScheduleData.txn_detail__transaction__policy__code || "-" }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<div v-if="canEditDueDate">
|
||||
<Caption class="mb-4" v-bind="{ title: 'Thay đổi ngày đến hạn', size: 20 }" />
|
||||
|
||||
<Caption
|
||||
class="mb-4"
|
||||
v-bind="{ title: 'Thay đổi ngày đến hạn', size: 20 }"
|
||||
/>
|
||||
|
||||
<div class="field">
|
||||
<label class="label has-text-weight-bold">{{ isVietnamese ? 'Ngày đến hạn mới' : 'New Due Date' }}</label>
|
||||
<label class="label has-text-weight-bold">{{ isVietnamese ? "Ngày đến hạn mới" : "New Due Date" }}</label>
|
||||
<div class="control">
|
||||
<Datepicker
|
||||
:record="dateRecord"
|
||||
attr="newDueDate"
|
||||
@date="updateDueDate"
|
||||
<Datepicker
|
||||
:record="dateRecord"
|
||||
attr="newDueDate"
|
||||
@date="updateDueDate"
|
||||
position="is-bottom-left"
|
||||
:mindate="minDate"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="dateError" class="help is-danger">{{ dateError }}</p>
|
||||
<p
|
||||
v-if="dateError"
|
||||
class="help is-danger"
|
||||
>
|
||||
{{ dateError }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="field mt-5">
|
||||
<label class="label has-text-weight-bold">{{ isVietnamese ? 'Mã xác nhận' : 'Confirmation Code' }}</label>
|
||||
<label class="label has-text-weight-bold">{{ isVietnamese ? "Mã xác nhận" : "Confirmation Code" }}</label>
|
||||
<div class="control">
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input class="input" type="text"
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
:placeholder="isVietnamese ? 'Nhập mã xác nhận' : 'Enter confirmation code'"
|
||||
v-model="userInputCaptcha" @keydown.enter="handleUpdate">
|
||||
v-model="userInputCaptcha"
|
||||
@keydown.enter="handleUpdate"
|
||||
/>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-static has-text-weight-bold has-background-grey-lighter"
|
||||
style="font-family: 'Courier New', monospace; letter-spacing: 2px;">
|
||||
<a
|
||||
class="button is-static has-text-weight-bold has-background-grey-lighter"
|
||||
style="font-family: "Courier New", monospace; letter-spacing: 2px"
|
||||
>
|
||||
{{ captchaCode }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-info is-light" @click="generateCaptcha"
|
||||
:title="isVietnamese ? 'Tạo mã mới' : 'Generate new code'">
|
||||
<button
|
||||
class="button is-info is-light"
|
||||
@click="generateCaptcha"
|
||||
:title="isVietnamese ? 'Tạo mã mới' : 'Generate new code'"
|
||||
>
|
||||
<SvgIcon v-bind="{ name: 'refresh.svg', type: 'primary', size: 23 }"></SvgIcon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!isCaptchaValid && userInputCaptcha.length > 0" class="help is-danger">Mã xác nhận không đúng.</p>
|
||||
<p
|
||||
v-if="!isCaptchaValid && userInputCaptcha.length > 0"
|
||||
class="help is-danger"
|
||||
>
|
||||
Mã xác nhận không đúng.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="notification is-warning">
|
||||
<div
|
||||
v-else
|
||||
class="notification is-warning"
|
||||
>
|
||||
<p class="has-text-weight-bold">
|
||||
{{ isVietnamese ? 'Không thể thay đổi ngày đến hạn' : 'Cannot change due date' }}
|
||||
{{ isVietnamese ? "Không thể thay đổi ngày đến hạn" : "Cannot change due date" }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-grouped is-grouped-left mt-5">
|
||||
<p class="control">
|
||||
<button
|
||||
<button
|
||||
v-if="canEditDueDate"
|
||||
class="button is-success has-text-white"
|
||||
class="button is-success has-text-white"
|
||||
:class="{ 'is-loading': isLoading }"
|
||||
@click="handleUpdate"
|
||||
:disabled="!isUpdateValid || isLoading">
|
||||
<span>{{ isVietnamese ? 'Cập nhật ngày đến hạn' : 'Update Due Date' }}</span>
|
||||
@click="handleUpdate"
|
||||
:disabled="!isUpdateValid || isLoading"
|
||||
>
|
||||
<span>{{ isVietnamese ? "Cập nhật ngày đến hạn" : "Update Due Date" }}</span>
|
||||
</button>
|
||||
<button class="button" @click="emit('close')">
|
||||
<span>{{ isVietnamese ? 'Đóng' : 'Close' }}</span>
|
||||
<button
|
||||
class="button"
|
||||
@click="emit('close')"
|
||||
>
|
||||
<span>{{ isVietnamese ? "Đóng" : "Close" }}</span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
@@ -137,19 +185,19 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useNuxtApp } from '#app';
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { useNuxtApp } from "#app";
|
||||
import { useStore } from "@/stores/index";
|
||||
import dayjs from 'dayjs';
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const props = defineProps({
|
||||
scheduleItemId: {
|
||||
type: [Number, String],
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close', 'updated']);
|
||||
const emit = defineEmits(["close", "updated"]);
|
||||
|
||||
const store = useStore();
|
||||
const { $getdata, $patchapi, $snackbar } = useNuxtApp();
|
||||
@@ -158,14 +206,15 @@ const isLoading = ref(false);
|
||||
const loadingData = ref(true);
|
||||
const paymentScheduleData = ref(null);
|
||||
const dateRecord = ref({ newDueDate: null });
|
||||
const captchaCode = ref('');
|
||||
const userInputCaptcha = ref('');
|
||||
const captchaCode = ref("");
|
||||
const userInputCaptcha = ref("");
|
||||
|
||||
const isVietnamese = computed(() => store.lang === 'vi');
|
||||
const isVietnamese = computed(() => store.lang === "vi");
|
||||
|
||||
// Kiểm tra xem có thể sửa ngày đến hạn không (chưa tính lãi và chưa thanh toán)
|
||||
const canEditDueDate = computed(() => {
|
||||
const hasNoPenaltyCalculated = paymentScheduleData.value?.batch_date === null || paymentScheduleData.value?.batch_date === undefined;
|
||||
const hasNoPenaltyCalculated =
|
||||
paymentScheduleData.value?.batch_date === null || paymentScheduleData.value?.batch_date === undefined;
|
||||
const isNotPaid = paymentScheduleData.value?.status !== 2;
|
||||
return hasNoPenaltyCalculated && isNotPaid;
|
||||
});
|
||||
@@ -174,25 +223,25 @@ const canEditDueDate = computed(() => {
|
||||
const minDate = computed(() => {
|
||||
const currentDate = paymentScheduleData.value?.to_date;
|
||||
if (currentDate) {
|
||||
return dayjs(currentDate).add(1, 'day').format('YYYY-MM-DD');
|
||||
return dayjs(currentDate).add(1, "day").format("YYYY-MM-DD");
|
||||
}
|
||||
return dayjs().add(1, 'day').format('YYYY-MM-DD');
|
||||
return dayjs().add(1, "day").format("YYYY-MM-DD");
|
||||
});
|
||||
|
||||
// Kiểm tra lỗi ngày
|
||||
const dateError = computed(() => {
|
||||
if (!dateRecord.value.newDueDate) return '';
|
||||
|
||||
if (!dateRecord.value.newDueDate) return "";
|
||||
|
||||
const selectedDate = dayjs(dateRecord.value.newDueDate);
|
||||
const currentDueDate = dayjs(paymentScheduleData.value?.to_date);
|
||||
|
||||
|
||||
if (selectedDate.isBefore(currentDueDate) || selectedDate.isSame(currentDueDate)) {
|
||||
return isVietnamese.value
|
||||
? 'Ngày đến hạn mới phải lớn hơn ngày đến hạn hiện tại'
|
||||
: 'New due date must be after current due date';
|
||||
return isVietnamese.value
|
||||
? "Ngày đến hạn mới phải lớn hơn ngày đến hạn hiện tại"
|
||||
: "New due date must be after current due date";
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
return "";
|
||||
});
|
||||
|
||||
const updateDueDate = (date) => {
|
||||
@@ -201,7 +250,7 @@ const updateDueDate = (date) => {
|
||||
|
||||
const generateCaptcha = () => {
|
||||
captchaCode.value = Math.random().toString(36).substring(2, 7).toUpperCase();
|
||||
userInputCaptcha.value = '';
|
||||
userInputCaptcha.value = "";
|
||||
};
|
||||
|
||||
const isCaptchaValid = computed(() => {
|
||||
@@ -209,24 +258,26 @@ const isCaptchaValid = computed(() => {
|
||||
});
|
||||
|
||||
const isUpdateValid = computed(() => {
|
||||
return canEditDueDate.value
|
||||
&& dateRecord.value.newDueDate
|
||||
&& !dateError.value
|
||||
&& isCaptchaValid.value
|
||||
&& userInputCaptcha.value.length > 0;
|
||||
return (
|
||||
canEditDueDate.value &&
|
||||
dateRecord.value.newDueDate &&
|
||||
!dateError.value &&
|
||||
isCaptchaValid.value &&
|
||||
userInputCaptcha.value.length > 0
|
||||
);
|
||||
});
|
||||
|
||||
const formatDate = (dateString) => {
|
||||
if (!dateString) return '-';
|
||||
return dayjs(dateString).format('DD/MM/YYYY');
|
||||
if (!dateString) return "-";
|
||||
return dayjs(dateString).format("DD/MM/YYYY");
|
||||
};
|
||||
|
||||
const fetchPaymentScheduleData = async () => {
|
||||
loadingData.value = true;
|
||||
try {
|
||||
const data = await $getdata('payment_schedule', { id: props.scheduleItemId }, undefined, true);
|
||||
const data = await $getdata("payment_schedule", { id: props.scheduleItemId }, undefined, true);
|
||||
paymentScheduleData.value = data;
|
||||
|
||||
|
||||
// Set initial value for new due date
|
||||
if (data?.to_date) {
|
||||
dateRecord.value.newDueDate = data.to_date;
|
||||
@@ -234,9 +285,9 @@ const fetchPaymentScheduleData = async () => {
|
||||
} catch (e) {
|
||||
console.error("Error fetching payment schedule data:", e);
|
||||
$snackbar(
|
||||
isVietnamese.value ? 'Không thể tải thông tin công nợ.' : 'Failed to load payment schedule information.',
|
||||
'Lỗi',
|
||||
'Error'
|
||||
isVietnamese.value ? "Không thể tải thông tin công nợ." : "Failed to load payment schedule information.",
|
||||
"Lỗi",
|
||||
"Error",
|
||||
);
|
||||
} finally {
|
||||
loadingData.value = false;
|
||||
@@ -247,17 +298,17 @@ const handleUpdate = async () => {
|
||||
if (!isUpdateValid.value) {
|
||||
if (!isCaptchaValid.value) {
|
||||
$snackbar(
|
||||
isVietnamese.value ? 'Vui lòng nhập đúng mã xác nhận.' : 'Please enter the correct confirmation code.',
|
||||
'Cảnh báo',
|
||||
'Warning'
|
||||
isVietnamese.value ? "Vui lòng nhập đúng mã xác nhận." : "Please enter the correct confirmation code.",
|
||||
"Cảnh báo",
|
||||
"Warning",
|
||||
);
|
||||
} else if (dateError.value) {
|
||||
$snackbar(dateError.value, 'Cảnh báo', 'Warning');
|
||||
$snackbar(dateError.value, "Cảnh báo", "Warning");
|
||||
} else if (!canEditDueDate.value) {
|
||||
$snackbar(
|
||||
isVietnamese.value ? 'Không thể thay đổi ngày đến hạn.' : 'Cannot change due date.',
|
||||
'Cảnh báo',
|
||||
'Warning'
|
||||
isVietnamese.value ? "Không thể thay đổi ngày đến hạn." : "Cannot change due date.",
|
||||
"Cảnh báo",
|
||||
"Warning",
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -266,32 +317,32 @@ const handleUpdate = async () => {
|
||||
isLoading.value = true;
|
||||
|
||||
try {
|
||||
const response = await $patchapi('payment_schedule', {
|
||||
id: props.scheduleItemId,
|
||||
to_date: dateRecord.value.newDueDate
|
||||
const response = await $patchapi("payment_schedule", {
|
||||
id: props.scheduleItemId,
|
||||
to_date: dateRecord.value.newDueDate,
|
||||
});
|
||||
|
||||
if (response !== 'error') {
|
||||
if (response !== "error") {
|
||||
$snackbar(
|
||||
isVietnamese.value ? 'Cập nhật ngày đến hạn thành công!' : 'Due date updated successfully!',
|
||||
'Thành công',
|
||||
'Success'
|
||||
isVietnamese.value ? "Cập nhật ngày đến hạn thành công!" : "Due date updated successfully!",
|
||||
"Thành công",
|
||||
"Success",
|
||||
);
|
||||
emit('updated');
|
||||
emit('close');
|
||||
emit("updated");
|
||||
emit("close");
|
||||
} else {
|
||||
$snackbar(
|
||||
isVietnamese.value ? 'Có lỗi xảy ra khi cập nhật ngày đến hạn.' : 'An error occurred while updating due date.',
|
||||
'Lỗi',
|
||||
'Error'
|
||||
isVietnamese.value ? "Có lỗi xảy ra khi cập nhật ngày đến hạn." : "An error occurred while updating due date.",
|
||||
"Lỗi",
|
||||
"Error",
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error updating due date:", e);
|
||||
$snackbar(
|
||||
isVietnamese.value ? 'Có lỗi xảy ra khi cập nhật ngày đến hạn.' : 'An error occurred while updating due date.',
|
||||
'Lỗi',
|
||||
'Error'
|
||||
isVietnamese.value ? "Có lỗi xảy ra khi cập nhật ngày đến hạn." : "An error occurred while updating due date.",
|
||||
"Lỗi",
|
||||
"Error",
|
||||
);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
@@ -308,4 +359,4 @@ onMounted(() => {
|
||||
.notification {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user