update

parent e663444e
......@@ -176,5 +176,17 @@ export enum API_PATHS {
listBank = 'common/bank',
// cập nhật đặt cọc
depositUpdate = 'deposit/update'
depositUpdate = 'deposit/update',
// danh sách phạt
contractPenalties = 'contractPenalties',
// thêm phạt
contractPenaltiesAdd = 'contractPenalties/add',
// cập nhật phạt
contractPenaltiesUpdate = 'contractPenalties/update',
//Xóa phạt
contractPenaltiesDelete = 'contractPenalties/delete'
}
......@@ -532,6 +532,7 @@ export type ListBooking = {
performStatus: number;
fee: string;
bookingRandomCode: string;
expectFee: string
};
export type ListArrayArtist = {
......@@ -881,3 +882,14 @@ export type listBank = {
name: string;
status: number;
};
export type ListFinedAmount = {
createBy: string;
createTime: string;
fee: string;
id: number;
reason: string;
updateBy: string | null;
updateTime: string | null;
artistBooking: ListBooking;
};
const isEmail = (str: string) => {
const email = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const email =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return email.test(str);
};
const isMobilePhone = (str: string) => {
......@@ -11,21 +12,60 @@ const isMobilePhone = (str: string) => {
const isUserName = (str: string) => {
const userName = /^\w+$/;
return userName.test(str);
}
};
const isHasVietnamese = ( str: string) => {
const vn =
'àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ'
const strLower = str.toLowerCase()
const isHasVietnamese = (str: string) => {
const vn =
'àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ';
const strLower = str.toLowerCase();
let isOK = false
for (let i = 0; i < strLower.length; i++) {
if (vn.indexOf(strLower[i]) >= 0) {
isOK = true
break
let isOK = false;
for (let i = 0; i < strLower.length; i++) {
if (vn.indexOf(strLower[i]) >= 0) {
isOK = true;
break;
}
}
}
return isOK
}
return isOK;
};
// inject('formatMoneyv2', (payload) => {
// try {
// return payload == null || payload.amount == null
// ? ''
// : payload.amount
// .toString()
// .replace(/\D/g, '')
// .replace(/\B(?=(\d{3})+(?!\d))/g, ',')
// } catch (e) {}
// })
const formatMoney = (str: { amount: string }) => {
try {
return str == null || str.amount == null
? ''
: str.amount
.toString()
.replace(/\D/g, '')
.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
} catch (e) {}
};
const isNullOrEmpty = (str: any) => {
return (
str === null ||
str === undefined ||
str === '' ||
str === 'null' ||
str === 'undefined'
);
};
export { isEmail, isMobilePhone, isUserName, isHasVietnamese };
export {
isEmail,
isMobilePhone,
isUserName,
isHasVietnamese,
formatMoney,
isNullOrEmpty,
};
<template>
<q-dialog persistent :model-value="open">
<q-card style="min-width: 750px" bordered>
<q-form greedy @submit.prevent="confirmAdd">
<q-card-section style="padding-bottom: 10px">
<q-item style="padding-left: 10px">
<q-item-section>
<q-item-label class="text-h6 text-weight-regular"
>Thêm phạt</q-item-label
>
</q-item-section>
</q-item>
</q-card-section>
<q-card-section style="padding-top: 0px">
<div class="cols-12 q-mb-sm">
<q-input
v-model="money"
outlined
hide-bottom-space
dense
:rules="errorMoney"
label="Số tiền *"
/>
</div>
<div class="cols-12">
<q-input
outlined
hide-bottom-space
v-model="content"
:rules="errorContent"
label="Nội dung *"
type="textarea"
/>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
color="grey"
no-caps
style="width: 90px"
label="Hủy"
@click="closeDialog"
/>
<q-btn
type="submit"
color="primary"
no-caps
style="width: 90px"
label="Thêm"
/>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<script lang="ts">
import { defineComponent, PropType, Ref, ref, watch } from 'vue';
import { Dialog, Notify } from 'quasar';
import { API_PATHS, config } from 'src/assets/configurations.example';
import { AxiosResponse } from 'axios';
import { api, BaseResponseBody } from 'src/boot/axios';
import { ListBooking } from 'src/assets/type';
export default defineComponent({
props: {
open: {
type: Boolean,
required: true,
},
data: {
type: Object as PropType<ListBooking>,
required: true,
},
},
setup(props, context) {
const content: Ref<string | null> = ref(null);
const money: Ref<string | null> = ref(null);
const errorMoney = [
(val?: string) => (val && val.trim().length) || 'Vui lòng nhập số tiền',
];
const errorContent = [
(val?: string) => (val && val.trim().length) || 'Vui lòng nhập nội dung',
];
watch(
() => props.open,
(value) => {
if (value) {
content.value = null;
money.value = null;
console.log(props.data);
}
}
);
const confirmAdd = async () => {
try {
const browserResult = (await api({
url: API_PATHS.contractPenaltiesAdd,
method: 'POST',
data: {
artistBooking: {
id: props.data.id,
},
fee: money.value,
reason: content.value,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (browserResult.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: 'Thêm thành công',
actions: [{ icon: 'close', color: 'white' }],
});
void closeDialog
context.emit('success')
}
} catch (error) {}
};
const closeDialog = () => {
context.emit('toggle', );
};
return {
//
closeDialog,
confirmAdd,
//
money,
errorMoney,
errorContent,
content,
};
},
emits: ['toggle', 'success'],
});
</script>
<template>
<q-dialog persistent :model-value="open">
<q-card style="min-width: 1000px" bordered>
<q-form greedy @submit.prevent="toggle">
<q-card-section style="padding-bottom: 10px">
<q-item style="padding-left: 10px">
<q-item-section>
<q-item-label class="text-h6 text-weight-regular"
>Danh sách tiền phạt</q-item-label
>
</q-item-section>
</q-item>
</q-card-section>
<q-separator />
<q-card-section
align="right"
class="overflow-auto"
style="max-height: calc(100vh - 10rem)"
>
<div class="col-12 q-mt-sm">
<div class="q-mb-sm">
<q-btn
class="q-mr-sm"
color="primary"
no-caps
:label="$t('crudActions.add')"
@click="openAddDialog = true"
style="width: 100px"
>
</q-btn>
</div>
<q-table
:rows="listFinedAmount"
:columns="tableColumnsFinedAmount"
:no-data-label="$t('emptyData')"
row-key="name"
separator="cell"
:rows-per-page-label="$t('recordPerPage')"
:pagination="{
rowsPerPage: 0,
}"
wrap-cells
hide-pagination
class="sticky-header-table"
>
<template v-slot:body-cell-artistName="item">
<td style="text-align: center">
<div>{{ item.row.artistBooking.artistName }}</div>
</td>
</template>
<template v-slot:body-cell-customerName="item">
<td style="text-align: center">
<div>{{ item.row.artistBooking.customerName }}</div>
</td>
</template>
<template v-slot:body-cell-fee="item">
<td style="text-align: center">
<div>{{ isformatMoney(item.row.fee) }}</div>
</td>
</template>
<template v-slot:body-cell-action="item">
<q-td style="padding: 0; text-align: center">
<q-btn flat round color="primary" icon="mdi-pencil-outline">
<q-tooltip :offset="[10, 10]">Cập nhật</q-tooltip>
</q-btn>
<q-btn
@click="confirmDelete(item.row.id)"
flat
round
color="primary"
icon="mdi-delete-outline"
>
<q-tooltip :offset="[10, 10]">Xóa</q-tooltip>
</q-btn>
</q-td>
</template>
<template v-slot:body-cell-stt="item">
<q-td :item="item" style="text-align: center">
{{ 1 + item.rowIndex + 20 * (1 - 1) }}
</q-td>
</template>
</q-table>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
type="submit"
color="primary"
no-caps
style="width: 90px"
label="Đóng"
/>
</q-card-actions>
</q-form>
<add
:open="openAddDialog"
@toggle="openAddDialog = !openAddDialog"
:data="data"
@success="getList"
></add>
</q-card>
</q-dialog>
</template>
<script lang="ts">
import { defineComponent, PropType, Ref, ref, watch } from 'vue';
import { Dialog, Notify } from 'quasar';
import { API_PATHS, config } from 'src/assets/configurations.example';
import { AxiosResponse } from 'axios';
import { api, BaseResponseBody } from 'src/boot/axios';
import { formatMoney } from '../../boot/functions';
import { ListBooking, ListFinedAmount } from 'src/assets/type';
import add from '../booking/addFinedAmount.vue';
export default defineComponent({
components: {
add,
},
props: {
open: {
type: Boolean,
required: true,
},
data: {
type: Object as PropType<ListBooking>,
},
},
setup(props, context) {
const listFinedAmount: Ref<ListFinedAmount[]> = ref([]);
const totalPage = ref(1);
const openAddDialog = ref(false);
const tableColumnsFinedAmount = [
{
name: 'stt',
field: 'stt',
required: true,
label: 'STT',
headerStyle: 'text-align: center !important; width: 4%',
align: 'center',
sortable: false,
},
{
name: 'artistName',
field: 'artistName',
required: true,
label: 'Tên nghệ sĩ',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'customerName',
field: 'customerName',
required: true,
label: 'Tên khách hàng',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'fee',
field: 'fee',
required: true,
label: 'Số tiền phạt',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'reason',
field: 'reason',
required: true,
label: 'Nội dung',
headerStyle: 'text-align: center !important; width: 13%',
align: 'left',
sortable: false,
},
{
name: 'action',
field: 'action',
required: true,
label: 'Chức năng',
headerStyle: 'text-align: center !important; width: 7%',
align: 'center',
sortable: false,
},
];
watch(
() => props.open,
(value) => {
if (value) {
void getList();
}
}
);
const isformatMoney = (value: string) => {
return formatMoney({ amount: value });
};
const getList = async () => {
try {
const response = (await api({
url: API_PATHS.contractPenalties,
method: 'GET',
params: {
bookingId: props.data?.id,
},
})) as AxiosResponse<BaseResponseBody<ListFinedAmount[]>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
listFinedAmount.value = response.data.data;
// totalPage.value = response.data.data.totalPages;
}
} catch (error) {}
};
const confirmDelete = (id: number) => {
Dialog.create({
title: 'Xác nhận',
message: 'Bạn có chắc chắn muốn xóa phạt này không?',
cancel: 'Hủy',
color: 'negative',
}).onOk(() => {
void deletePost(id);
});
};
const deletePost = async (id: number) => {
try {
const deleteResult = (await api({
url: API_PATHS.contractPenaltiesDelete,
method: 'GET',
params: {
id: id,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (deleteResult.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: 'Xóa thành công',
actions: [{ icon: 'close', color: 'white' }],
});
void getList();
}
} catch (error) {}
};
const toggle = () => {
context.emit('toggle');
};
return {
//
toggle,
getList,
isformatMoney,
confirmDelete,
//
listFinedAmount,
tableColumnsFinedAmount,
totalPage,
openAddDialog,
};
},
emits: ['click:CloseBtn', 'editReCustomer', 'toggle'],
});
</script>
......@@ -58,9 +58,9 @@
<div class="col-8 fs-14">{{ detailInfoBooking.toTime }}</div>
<div class="col-4 fs-14 color">
{{ $t('listBooking.titleColumnsTable.fee') }}:
{{ $t('listBooking.titleColumnsTable.fee') }} :
</div>
<div class="col-8 fs-14">{{ detailInfoBooking.fee }}</div>
<div class="col-8 fs-14">{{ detailInfoBooking.expectFee }}</div>
<div class="col-4 fs-14 color">
{{ $t('listBooking.titleColumnsTable.favoriteScore') }}:
......
......@@ -83,7 +83,7 @@
</template>
<template v-slot:body-cell-image="item">
<q-td :item="item" align="center">
<q-td :item="item" align="center">
<q-img
:src="formatUrl(item.row.image)"
spinner-color="white"
......@@ -100,7 +100,7 @@
<template v-slot:body-cell-money="item">
<q-td :item="item" align="center">
<div>{{ item.row.amountMoney }}</div>
<div>{{ isformatMoney(item.row.amountMoney) }}</div>
</q-td>
</template>
......@@ -174,6 +174,7 @@ import { config, API_PATHS } from 'src/assets/configurations.example';
import { AxiosResponse } from 'axios';
import addNewDialog from '../../detailBooking/tableDeposit/add.vue';
import update from '../../detailBooking/tableDeposit/update.vue';
import { formatMoney } from 'boot/functions';
import { ListDeposit, FileUploadType } from 'src/assets/type';
export default defineComponent({
components: {
......@@ -192,20 +193,19 @@ export default defineComponent({
name: 'stt',
field: 'stt',
required: true,
headerStyle: 'text-align: center !important; width:20%',
headerStyle: 'text-align: center !important; width:20%',
align: 'center',
label: 'STT',
sortable: false,
},
{
name: 'userName',
field: 'userName',
required: true,
label: 'Tên chủ thẻ',
headerStyle: 'text-align: center !important; width:20%',
headerStyle: 'text-align: center !important; width:20%',
align: 'left',
sortable: false,
},
......@@ -232,7 +232,7 @@ export default defineComponent({
field: 'time',
required: true,
label: 'Thời gian ',
headerStyle: 'text-align: center !important; width:20%',
headerStyle: 'text-align: center !important; width:20%',
align: 'left',
sortable: false,
},
......@@ -242,7 +242,7 @@ export default defineComponent({
field: 'money',
required: true,
label: 'Số tiền',
headerStyle: 'text-align: center !important; width:20%',
headerStyle: 'text-align: center !important; width:20%',
align: 'left',
sortable: false,
},
......@@ -252,7 +252,7 @@ export default defineComponent({
field: 'status',
required: true,
label: 'Trạng thái',
headerStyle: 'text-align: center !important; width:20%',
headerStyle: 'text-align: center !important; width:20%',
align: 'center',
sortable: false,
},
......@@ -262,7 +262,7 @@ export default defineComponent({
field: 'action',
required: true,
label: 'Chức năng',
headerStyle: 'text-align: center !important; width:20%',
headerStyle: 'text-align: center !important; width:20%',
align: 'center',
sortable: false,
},
......@@ -319,6 +319,10 @@ export default defineComponent({
console.log(id);
};
const isformatMoney = (value: string) => {
return formatMoney({ amount: value });
};
const callApiUploadAvatar = async (file: File) => {
try {
const bodyFormData = new FormData();
......@@ -376,7 +380,7 @@ export default defineComponent({
dialogUpdate,
UpdateBirtday,
handleUpdate,
isformatMoney,
confirmBrowser,
confirmRefuse,
};
......
......@@ -994,10 +994,10 @@ export default {
address: 'Địa điểm',
fromTime: 'Thời gian bắt đầu',
toTime: 'Thời gian kết thúc',
fee: 'Giá',
fee: 'Giá dự kiến',
favoriteScore: 'Số lượt thích',
status: 'T.T Booking',
performStatus: 'T.T Thực hiện',
performStatus: 'T.T nghệ sĩ xác nhận',
action: 'Chức năng',
},
dialogLabel: {
......
......@@ -327,8 +327,8 @@ export default defineComponent({
sortable: false,
},
{
name: 'userName',
field: 'userName',
name: 'customerName',
field: 'customerName',
required: true,
label: i18n.global.t('listBooking.titleColumnsTable.userName'),
headerStyle: 'text-align: center !important; width: 9%',
......@@ -371,15 +371,15 @@ export default defineComponent({
align: 'left',
sortable: false,
},
{
name: 'fee',
field: 'fee',
required: true,
label: i18n.global.t('listBooking.titleColumnsTable.fee'),
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
// {
// name: 'fee',
// field: 'fee',
// required: true,
// label: i18n.global.t('listBooking.titleColumnsTable.fee'),
// headerStyle: 'text-align: center !important; width: 9%',
// align: 'left',
// sortable: false,
// },
// {
// name: 'favoriteScore',
// field: 'favoriteScore',
......
......@@ -269,8 +269,8 @@ export default defineComponent({
sortable: false,
},
{
name: 'userName',
field: 'userName',
name: 'customerName',
field: 'customerName',
required: true,
label: i18n.global.t('listBooking.titleColumnsTable.userName'),
headerStyle: 'text-align: center !important; width: 9%',
......@@ -313,15 +313,15 @@ export default defineComponent({
align: 'left',
sortable: false,
},
{
name: 'fee',
field: 'fee',
required: true,
label: i18n.global.t('listBooking.titleColumnsTable.fee'),
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
// {
// name: 'fee',
// field: 'fee',
// required: true,
// label: i18n.global.t('listBooking.titleColumnsTable.fee'),
// headerStyle: 'text-align: center !important; width: 9%',
// align: 'left',
// sortable: false,
// },
{
name: 'isArtistCancel',
......
......@@ -205,6 +205,43 @@
</template>
</q-td>
</template>
<template v-slot:body-cell-expectFee="item">
<q-td align="center">
<div>{{ isformatMoney(item.row.expectFee) }}</div>
</q-td>
</template>
<template v-slot:body-cell-fee="item">
<q-td align="center">
<div>{{ isformatMoney(item.row.fee) }}</div>
</q-td>
</template>
<template v-slot:body-cell-amountToDeposit="item">
<q-td align="center">
<div>{{ isformatMoney(item.row.amountToDeposit) }}</div>
</q-td>
</template>
<template v-slot:body-cell-depositAmount="item">
<q-td align="center">
<div>{{ isformatMoney(item.row.depositAmount) }}</div>
</q-td>
</template>
<template v-slot:body-cell-finedAmount="item">
<q-td style="cursor: pointer" align="center">
<div @click="openDialogfinedAmount(item.row)">
{{ isformatMoney(item.row.finedAmount) }}
</div>
</q-td>
</template>
<template v-slot:body-cell-refundAmount="item">
<q-td align="center">
<div>{{ isformatMoney(item.row.refundAmount) }}</div>
</q-td>
</template>
<template v-slot:body-cell-content="item">
<td>
......@@ -232,6 +269,12 @@
:detail-info-booking="detailInfoBooking"
@click:CloseBtn="showDialog = false"
></detailBooking>
<listFinedAmount
:open="dialogfinedAmount"
@toggle="closedialogfinedAmount"
:data="detailInfoBooking"
></listFinedAmount>
</div>
</div>
</template>
......@@ -249,13 +292,17 @@ import {
ListArrayArtist,
ListArrayCust,
} from 'src/assets/type';
import { formatMoney } from '../../boot/functions';
import detailBooking from '../../components/detailBooking/index.vue';
import moment from 'moment';
import listFinedAmount from '../../components/booking/listFinedAmount.vue';
export default defineComponent({
components: {
detailBooking,
Pagination,
listFinedAmount,
},
setup() {
const tableColumns = [
......@@ -287,8 +334,8 @@ export default defineComponent({
sortable: false,
},
{
name: 'userName',
field: 'userName',
name: 'customerName',
field: 'customerName',
required: true,
label: i18n.global.t('listBooking.titleColumnsTable.userName'),
headerStyle: 'text-align: center !important; width: 9%',
......@@ -331,24 +378,65 @@ export default defineComponent({
align: 'left',
sortable: false,
},
// {
// name: 'fee',
// field: 'fee',
// required: true,
// label: i18n.global.t('listBooking.titleColumnsTable.fee'),
// headerStyle: 'text-align: center !important; width: 9%',
// align: 'left',
// sortable: false,
// },
{
name: 'fee',
field: 'fee',
name: 'expectFee',
field: 'expectFee',
required: true,
label: i18n.global.t('listBooking.titleColumnsTable.fee'),
label: 'Giá dự kiến',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'amountToDeposit',
field: 'amountToDeposit',
required: true,
label: 'Số tiền cần cọc',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'depositAmount',
field: 'depositAmount',
required: true,
label: 'Số tiền đã cọc',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'finedAmount',
field: 'finedAmount',
required: true,
label: 'Số tiền phạt',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
{
name: 'refundAmount',
field: 'refundAmount',
required: true,
label: 'Số tiền hoàn',
headerStyle: 'text-align: center !important; width: 9%',
align: 'left',
sortable: false,
},
// {
// name: 'favoriteScore',
// field: 'favoriteScore',
// required: true,
// label: i18n.global.t('listBooking.titleColumnsTable.favoriteScore'),
// headerStyle: 'text-align: center !important; width: 7%',
// align: 'center',
// sortable: false,
// },
{
name: 'status',
field: 'status',
......@@ -362,7 +450,7 @@ export default defineComponent({
name: 'performStatus',
field: 'performStatus',
required: true,
label:'T.T Nghệ sĩ xác nhận',
label: 'T.T Nghệ sĩ xác nhận',
headerStyle: 'text-align: center !important; width: 8%',
align: 'center',
sortable: false,
......@@ -390,9 +478,12 @@ export default defineComponent({
{ id: 0, name: 'Chưa xác nhận', color: 'secondary' },
{ id: 1, name: 'Đã xác nhận', color: 'info' },
{ id: 2, name: 'Từ chối', color: 'warning' },
]);
const isformatMoney = (value: string) => {
return formatMoney({ amount: value });
};
const dialogfinedAmount = ref(false);
const showDialog = ref(false);
const detailInfoBooking: Ref<ListBooking | null> = ref(null);
const listBooking: Ref<unknown[]> = ref([]);
......@@ -429,7 +520,11 @@ export default defineComponent({
const customerOptions: Ref<ListArrayCust[]> = ref([]);
const filteredOptions: Ref<ListArrayArtist[]> = ref([]);
const customerFiltereOption: Ref<ListArrayCust[]> = ref([]);
const closedialogfinedAmount = () => {
pageIndex.value = 1;
void getListBooking();
dialogfinedAmount.value = false;
};
const getArrayArtist = async () => {
const response = (await api({
url: API_PATHS.getArrayArtist,
......@@ -480,6 +575,12 @@ export default defineComponent({
});
};
const openDialogfinedAmount = (item: ListBooking) => {
dialogfinedAmount.value = true;
detailInfoBooking.value = item;
console.log(2312312);
};
const getListBooking = async () => {
try {
const response = (await api({
......@@ -555,10 +656,12 @@ export default defineComponent({
});
return {
date,
closedialogfinedAmount,
filterFn,
changeTime,
filterFnCust,
openDialogfinedAmount,
dialogfinedAmount,
customerOptions,
customerFiltereOption,
artistOptions,
......@@ -575,6 +678,7 @@ export default defineComponent({
totalPage,
changePageSize,
getListBooking,
isformatMoney,
ListStatusBooking,
ListPerformStatus,
sreachStatus,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment