update

parent e49044de
...@@ -150,4 +150,7 @@ export enum API_PATHS { ...@@ -150,4 +150,7 @@ export enum API_PATHS {
// trang cấu hình liveStream // trang cấu hình liveStream
livestream = 'livestream/list', livestream = 'livestream/list',
updateLiveStream = 'livestream/update', updateLiveStream = 'livestream/update',
// thêm sản phẩm nổi bật
homeAddProduct = 'config/home/addProduct',
} }
...@@ -38,6 +38,10 @@ export type UserObject = { ...@@ -38,6 +38,10 @@ export type UserObject = {
updateBy: null | string; updateBy: null | string;
}; };
export type artistName = {
artistName: string;
id: number;
};
export type ArtistInfoType = { export type ArtistInfoType = {
id: number; id: number;
account: string; account: string;
......
...@@ -26,9 +26,7 @@ ...@@ -26,9 +26,7 @@
icon="mdi-magnify" icon="mdi-magnify"
/> />
<q-btn @click="openAddDialog = true" color="primary" <q-btn @click="handAddProduct" color="primary">Thêm mới</q-btn>
>Thêm mới</q-btn
>
</q-item> </q-item>
</q-card-section> </q-card-section>
<div class="col-12 q-mt-sm"> <div class="col-12 q-mt-sm">
...@@ -96,9 +94,14 @@ ...@@ -96,9 +94,14 @@
<openAdd <openAdd
v-model:imageUrl="imageUrl" v-model:imageUrl="imageUrl"
v-model:isOpened="openAddDialog" v-model:isOpened="openAddDialog"
v-model:codeProduct="codeProduct"
v-model:artistName="artistName"
v-model:nameProduct="nameProduct"
v-model:embeddedUrl="embeddedUrl"
v-model:salientStatus="salientStatus"
@SetAvatar="setAvatar($event)" @SetAvatar="setAvatar($event)"
@deleteAvatar="deleteAvatar" @deleteAvatar="deleteAvatar"
@successful="listProductNotActive" @handleSave="handleSave"
/> />
</q-dialog> </q-dialog>
</template> </template>
...@@ -111,7 +114,12 @@ import { API_PATHS, config } from 'src/assets/configurations.example'; ...@@ -111,7 +114,12 @@ import { API_PATHS, config } from 'src/assets/configurations.example';
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
import { api, BaseResponseBody } from 'src/boot/axios'; import { api, BaseResponseBody } from 'src/boot/axios';
import Pagination from 'components/pagination/index.vue'; import Pagination from 'components/pagination/index.vue';
import { listProductNotActives, PaginationResponse } from 'src/assets/type'; import {
listProductNotActives,
PaginationResponse,
FileUploadType,
artistName,
} from 'src/assets/type';
import { emit } from 'cluster'; import { emit } from 'cluster';
import openAdd from '../danh-sach-san-pham-noi-bat-chua-chon/addNewProduct.vue'; import openAdd from '../danh-sach-san-pham-noi-bat-chua-chon/addNewProduct.vue';
export default defineComponent({ export default defineComponent({
...@@ -128,6 +136,12 @@ export default defineComponent({ ...@@ -128,6 +136,12 @@ export default defineComponent({
}, },
setup(props, context) { setup(props, context) {
const avatarFile: Ref<File | null> = ref(null); const avatarFile: Ref<File | null> = ref(null);
const avatarUploaded: Ref<string> = ref('');
const artistName: Ref<artistName | null> = ref(null);
const nameProduct = ref(null);
const embeddedUrl = ref(null);
const salientStatus = ref(1);
const codeProduct = ref(null);
const setAvatar = (value: { file?: File; url?: string }) => { const setAvatar = (value: { file?: File; url?: string }) => {
avatarFile.value = value.file as File; avatarFile.value = value.file as File;
imageUrl.value = value.url as string; imageUrl.value = value.url as string;
...@@ -149,6 +163,59 @@ export default defineComponent({ ...@@ -149,6 +163,59 @@ export default defineComponent({
imageUrl.value = null; imageUrl.value = null;
}; };
const callApiUploadAvatar = async (file: File) => {
try {
const bodyFormData = new FormData();
bodyFormData.append('file', file);
const response = (await api({
headers: { 'Content-Type': 'multipart/form-data' },
// url: 'https://cms.vab.vn/file/upload/', // pro
url: config.API_IMAGE_ENDPOINT, // pro
// url: 'http://103.147.34.20:10705/file/upload/', // test
method: 'POST',
data: bodyFormData,
})) as AxiosResponse<BaseResponseBody<FileUploadType>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
return response.data.data.fileName;
} else {
return '';
}
} catch (error) {
return '';
}
};
const handleSave = async () => {
avatarUploaded.value = await callApiUploadAvatar(
avatarFile.value as File
);
try {
const browserResult = (await api({
url: API_PATHS.homeAddProduct,
method: 'POST',
data: {
code: codeProduct.value,
artistId: artistName.value?.id,
name: nameProduct.value,
embeddedUrl: embeddedUrl.value,
status: salientStatus.value,
isFeaturedOnHomepage: 0,
imageUrl: avatarUploaded.value,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (browserResult.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: 'Thêm sản phẩm thành công',
actions: [{ icon: 'close', color: 'white' }],
});
context.emit('update:isOpened', false);
}
} catch (error) {}
};
const bannerTableColumns = [ const bannerTableColumns = [
{ {
name: 'name', name: 'name',
...@@ -217,6 +284,17 @@ export default defineComponent({ ...@@ -217,6 +284,17 @@ export default defineComponent({
pageIndex.value = 1; pageIndex.value = 1;
void listProductNotActive(); void listProductNotActive();
}; };
const handAddProduct = () => {
openAddDialog.value = true;
artistName.value = null;
nameProduct.value = null;
embeddedUrl.value = null;
salientStatus.value = 1;
codeProduct.value = null;
imageUrl.value = '';
avatarUploaded.value = '';
};
const handleConfirmAdd = async () => { const handleConfirmAdd = async () => {
if ((selected.value || []).length !== 0) { if ((selected.value || []).length !== 0) {
const data = [] as any[]; const data = [] as any[];
...@@ -297,6 +375,11 @@ export default defineComponent({ ...@@ -297,6 +375,11 @@ export default defineComponent({
keyWord, keyWord,
openAddDialog, openAddDialog,
imageUrl, imageUrl,
artistName,
nameProduct,
embeddedUrl,
salientStatus,
codeProduct,
changePageSize, changePageSize,
deleteAvatar, deleteAvatar,
// hàm // hàm
...@@ -304,9 +387,11 @@ export default defineComponent({ ...@@ -304,9 +387,11 @@ export default defineComponent({
listProductNotActive, listProductNotActive,
getSelectedString, getSelectedString,
handleConfirmAdd, handleConfirmAdd,
handleSave,
handleTogle, handleTogle,
search, search,
setAvatar, setAvatar,
handAddProduct,
}; };
}, },
emits: ['update:isOpened', 'saveBannerInfo'], emits: ['update:isOpened', 'saveBannerInfo'],
......
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
@update:model-value="$emit('update:isOpened', $event)" @update:model-value="$emit('update:isOpened', $event)"
> >
<q-card class="full-width" style="max-width: 80rem" bordered> <q-card class="full-width" style="max-width: 80rem" bordered>
<q-form greedy @submit.prevent="$emit('update:isOpened', false)"> <q-form
greedy
@submit.prevent="
$emit('handleSave', {});
$emit('update:isOpened', false);
"
>
<q-card-section> <q-card-section>
<q-item> <q-item>
<q-item-section> <q-item-section>
...@@ -88,7 +94,7 @@ ...@@ -88,7 +94,7 @@
<div class="col-6"> <div class="col-6">
<q-select <q-select
v-model="artistName" :model-value="artistName"
:label="$t('listHotProduct.dialogLabel.fieldLabels.artistName')" :label="$t('listHotProduct.dialogLabel.fieldLabels.artistName')"
class="q-my-sm" class="q-my-sm"
:options="artistOptions" :options="artistOptions"
...@@ -98,18 +104,30 @@ ...@@ -98,18 +104,30 @@
outlined outlined
:rules="artistNameRules" :rules="artistNameRules"
clearable clearable
@update:model-value="$emit('update:artistName', $event)"
></q-select> ></q-select>
<q-input <q-input
v-model="nameProduct" :model-value="codeProduct"
label="Mã sản phẩm"
class="q-my-sm"
type="text"
outlined
:rules="codeProductRules"
clearable
@update:model-value="$emit('update:codeProduct', $event)"
></q-input>
<q-input
:model-value="nameProduct"
:label="$t('listHotProduct.dialogLabel.fieldLabels.name')" :label="$t('listHotProduct.dialogLabel.fieldLabels.name')"
class="q-my-sm" class="q-my-sm"
type="text" type="text"
outlined outlined
:rules="nameRules" :rules="nameRules"
clearable clearable
@update:model-value="$emit('update:nameProduct', $event)"
></q-input> ></q-input>
<q-input <q-input
v-model="embeddedUrl" :model-value="embeddedUrl"
:label=" :label="
$t('listHotProduct.dialogLabel.fieldLabels.embeddedUrl') $t('listHotProduct.dialogLabel.fieldLabels.embeddedUrl')
" "
...@@ -118,15 +136,17 @@ ...@@ -118,15 +136,17 @@
outlined outlined
:rules="embeddedUrlRules" :rules="embeddedUrlRules"
clearable clearable
@update:model-value="$emit('update:embeddedUrl', $event)"
></q-input> ></q-input>
<div class="q-pt-sm"> <div class="q-pt-sm">
<span class="text-body1">{{ <span class="text-body1">{{
$t('listHotProduct.dialogLabel.fieldLabels.salientStatus') $t('listHotProduct.dialogLabel.fieldLabels.salientStatus')
}}</span }}</span
><q-toggle ><q-toggle
v-model="salientStatus" :model-value="salientStatus"
:true-value="SystemHotProductStatus.active" :true-value="SystemHotProductStatus.active"
:false-value="SystemHotProductStatus.inactive" :false-value="SystemHotProductStatus.inactive"
@update:model-value="$emit('update:salientStatus', $event)"
/> />
</div> </div>
</div> </div>
...@@ -141,7 +161,7 @@ ...@@ -141,7 +161,7 @@
@click="$emit('update:isOpened', false)" @click="$emit('update:isOpened', false)"
/> />
<q-btn <q-btn
@click="handleSave" type="submit"
color="primary" color="primary"
no-caps no-caps
style="width: 90px" style="width: 90px"
...@@ -159,7 +179,7 @@ import { defineComponent, ref, Ref, watch } from 'vue'; ...@@ -159,7 +179,7 @@ import { defineComponent, ref, Ref, watch } from 'vue';
import { i18n } from 'src/boot/i18n'; import { i18n } from 'src/boot/i18n';
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
import { api, BaseResponseBody } from 'src/boot/axios'; import { api, BaseResponseBody } from 'src/boot/axios';
import { Dialog, Notify } from 'quasar';
import { ListArrayArtist } from 'src/assets/type'; import { ListArrayArtist } from 'src/assets/type';
import { config, API_PATHS } from 'src/assets/configurations.example'; import { config, API_PATHS } from 'src/assets/configurations.example';
export default defineComponent({ export default defineComponent({
...@@ -172,6 +192,27 @@ export default defineComponent({ ...@@ -172,6 +192,27 @@ export default defineComponent({
type: String, type: String,
required: true, required: true,
}, },
codeProduct: {
type: String,
required: true,
},
artistName: {
type: String,
required: true,
},
nameProduct: {
type: String,
required: true,
},
embeddedUrl: {
type: String,
required: true,
},
salientStatus: {
type: String,
required: true,
},
}, },
setup(_, context) { setup(_, context) {
watch( watch(
...@@ -184,11 +225,8 @@ export default defineComponent({ ...@@ -184,11 +225,8 @@ export default defineComponent({
} }
} }
); );
const salientStatus = ref(1);
const artistOptions: Ref<ListArrayArtist[]> = ref([]); const artistOptions: Ref<ListArrayArtist[]> = ref([]);
const artistName: Ref<ListArrayArtist | undefined> = ref();
const embeddedUrl: Ref<string | null> = ref(null);
const nameProduct = ref(null);
const selectedFile = (value: FileList) => { const selectedFile = (value: FileList) => {
context.emit('SetAvatar', { context.emit('SetAvatar', {
...@@ -209,9 +247,6 @@ export default defineComponent({ ...@@ -209,9 +247,6 @@ export default defineComponent({
}; };
const reset = () => { const reset = () => {
artistOptions.value = []; artistOptions.value = [];
artistName.value = undefined;
embeddedUrl.value = null;
nameProduct.value = null;
}; };
const deleteAvatar = () => { const deleteAvatar = () => {
context.emit('deleteAvatar'); context.emit('deleteAvatar');
...@@ -223,6 +258,12 @@ export default defineComponent({ ...@@ -223,6 +258,12 @@ export default defineComponent({
// eslint-disable-next-line // eslint-disable-next-line
upload.value?.click(); upload.value?.click();
}; };
const codeProductRules = [
(val?: string) =>
(val && val.trim().length) || 'Vui lòng nhập mã sản phẩm',
];
const nameRules = [ const nameRules = [
(val?: string) => (val?: string) =>
(val && val.trim().length) || (val && val.trim().length) ||
...@@ -239,35 +280,63 @@ export default defineComponent({ ...@@ -239,35 +280,63 @@ export default defineComponent({
i18n.global.t('listHotProduct.validateMessages.requireEmbeddedUrl'), i18n.global.t('listHotProduct.validateMessages.requireEmbeddedUrl'),
]; ];
const handleSave = () => { // const handleSave = () => {
context.emit('successful'); // void uploadAvatar();
context.emit('update:isOpened', false); // // try {
}; // // const browserResult = (await api({
// // url: API_PATHS.homeAddProduct,
// // method: 'POST',
// // data: {
// // code: codeProduct.value,
// // artistId: artistName.value,
// // name: nameProduct.value,
// // embeddedUrl: 'https://www.youtube.com/watch?v=psZ1g9fMfeo',
// // status: salientStatus.value,
// // isFeaturedOnHomepage: 0,
// // imageUrl: '2021/8/30/vab-image-1632988070841.jpeg',
// // },
// // })) as AxiosResponse<BaseResponseBody<unknown>>;
// // if (browserResult.data.error.code === config.API_RES_CODE.OK.code) {
// // Notify.create({
// // type: 'positive',
// // message: 'Thêm sản phẩm thành công',
// // actions: [{ icon: 'close', color: 'white' }],
// // });
// // context.emit('successful');
// // context.emit('update:isOpened', false);
// // }
// // } catch (error) {}
// };
return { return {
nameRules, nameRules,
artistNameRules, artistNameRules,
embeddedUrlRules, embeddedUrlRules,
embeddedUrl,
SystemHotProductStatus, SystemHotProductStatus,
artistOptions, artistOptions,
nameProduct,
artistName, codeProductRules,
salientStatus,
selectedFile, selectedFile,
deleteAvatar, deleteAvatar,
uploadAvatar, uploadAvatar,
upload, upload,
handleSave,
}; };
}, },
emits: [ emits: [
'update:isOpened', 'update:isOpened',
'update:imageUrl', 'update:imageUrl',
'update:codeProduct',
'update:artistName',
'update:nameProduct',
'update:embeddedUrl',
'update:salientStatus',
'SetAvatar', 'SetAvatar',
'deleteAvatar', 'deleteAvatar',
'successful',
'handleSave',
], ],
}); });
</script> </script>
...@@ -101,7 +101,7 @@ ...@@ -101,7 +101,7 @@
:rules="artistNameRules" :rules="artistNameRules"
map-options map-options
option-value="id" option-value="id"
option-label="fullName" option-label="artistName"
class="q-my-sm" class="q-my-sm"
outlined outlined
use-input use-input
......
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