changes
This commit is contained in:
@@ -20,7 +20,8 @@ const body = ref({
|
||||
});
|
||||
|
||||
function selected(field, data) {
|
||||
body.value[field] = data.id;
|
||||
if (data === null) body.value[field] = data;
|
||||
else body.value[field] = data.id;
|
||||
}
|
||||
|
||||
async function createProduct() {
|
||||
@@ -31,309 +32,319 @@ async function createProduct() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="subtitle is-4">AddProductForm</h1>
|
||||
<form class="fixed-grid has-12-cols">
|
||||
<div class="grid">
|
||||
<div class="cell is-col-span-8">
|
||||
<div class="field">
|
||||
<label class="label">Tên sản phẩm</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
v-model.trim="body.name"
|
||||
type="text"
|
||||
placeholder="Tên"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">OS</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'OS',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'OS',
|
||||
addon: {
|
||||
component: 'imports/addons/AddOS',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm hệ điều hành',
|
||||
},
|
||||
}"
|
||||
@option="selected('os', $event)"
|
||||
<form class="fixed-grid has-12-cols">
|
||||
<div class="grid">
|
||||
<div class="cell is-col-span-8">
|
||||
<div class="field">
|
||||
<label class="label">Tên sản phẩm</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
v-model.trim="body.name"
|
||||
type="text"
|
||||
placeholder="Tên"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Hãng</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Manufacturer',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'Hãng',
|
||||
addon: {
|
||||
component: 'imports/addons/AddManufacturer',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm hãng',
|
||||
},
|
||||
}"
|
||||
@option="selected('manufacturer', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Pin</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Battery',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
placeholder: 'Pin',
|
||||
addon: {
|
||||
component: 'imports/addons/AddBattery',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm pin',
|
||||
},
|
||||
}"
|
||||
@option="selected('battery', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Màn hình</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Screen',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
placeholder: 'Màn hình',
|
||||
addon: {
|
||||
component: 'imports/addons/AddScreen',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm màn hình',
|
||||
},
|
||||
}"
|
||||
@option="selected('screen', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">CPU</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'CPU',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'CPU',
|
||||
addon: {
|
||||
component: 'imports/addons/AddCPU',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm CPU',
|
||||
},
|
||||
}"
|
||||
@option="selected('cpu', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">GPU</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'GPU',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'GPU',
|
||||
addon: {
|
||||
component: 'imports/addons/AddGPU',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm GPU',
|
||||
},
|
||||
}"
|
||||
@option="selected('gpu', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Camera</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Camera_System',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
placeholder: 'Camera',
|
||||
addon: {
|
||||
component: 'imports/addons/AddCamera',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm camera',
|
||||
},
|
||||
}"
|
||||
@option="selected('camera_system', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">SIM</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'SIM',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
placeholder: 'SIM',
|
||||
addon: {
|
||||
component: 'imports/addons/AddSIM',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm SIM',
|
||||
},
|
||||
}"
|
||||
@option="selected('sim', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Kết nối</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Network_Technology',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'Kết nối',
|
||||
addon: {
|
||||
component: 'imports/addons/AddNetworkTechnology',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm kết nối',
|
||||
},
|
||||
}"
|
||||
@option="selected('network_technology', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Công nghệ sạc</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Charging_Technology',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
placeholder: 'Công nghệ sạc',
|
||||
addon: {
|
||||
component: 'imports/addons/AddChargingTechnology',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm công nghệ sạc',
|
||||
},
|
||||
}"
|
||||
@option="selected('charging_technology', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Bộ nhớ ngoài</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'External_Storage',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
placeholder: 'Bộ nhớ ngoài',
|
||||
addon: {
|
||||
component: 'imports/addons/AddExternalStorage',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm bộ nhớ ngoài',
|
||||
},
|
||||
}"
|
||||
@option="selected('external_storage', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Chỉ số IP</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'IP_Rating',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'Chỉ số IP',
|
||||
addon: {
|
||||
component: 'imports/addons/AddIPRating',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm chỉ số IP',
|
||||
},
|
||||
}"
|
||||
@option="selected('ip_rating', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Chất liệu</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Design',
|
||||
field: 'label',
|
||||
column: ['frame_material', 'back_material'],
|
||||
first: true,
|
||||
placeholder: 'Chất liệu',
|
||||
addon: {
|
||||
component: 'imports/addons/AddDesign',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm chất liệu',
|
||||
},
|
||||
}"
|
||||
@option="selected('design', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-12">
|
||||
<button
|
||||
:class="['button is-primary', { 'is-loading': isPending }]"
|
||||
:disabled="Object.values(body).every((v) => v === null)"
|
||||
@click.prevent="createProduct"
|
||||
>
|
||||
<span class="icon">
|
||||
<Icon name="material-symbols:add-2-rounded" />
|
||||
</span>
|
||||
<span>Tạo sản phẩm</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">OS</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'OS',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'OS',
|
||||
addon: {
|
||||
component: 'imports/addons/AddOS',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm hệ điều hành',
|
||||
},
|
||||
}"
|
||||
@option="selected('os', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Hãng</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Manufacturer',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Hãng',
|
||||
addon: {
|
||||
component: 'imports/addons/AddManufacturer',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm hãng',
|
||||
},
|
||||
}"
|
||||
@option="selected('manufacturer', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Pin</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Battery',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Pin',
|
||||
addon: {
|
||||
component: 'imports/addons/AddBattery',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm pin',
|
||||
},
|
||||
}"
|
||||
@option="selected('battery', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Màn hình</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Screen',
|
||||
field: 'label',
|
||||
column: ['resolution', 'standard', 'technology'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Màn hình',
|
||||
addon: {
|
||||
component: 'imports/addons/AddScreen',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm màn hình',
|
||||
},
|
||||
}"
|
||||
@option="selected('screen', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">CPU</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'CPU',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'CPU',
|
||||
addon: {
|
||||
component: 'imports/addons/AddCPU',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm CPU',
|
||||
},
|
||||
}"
|
||||
@option="selected('cpu', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">GPU</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'GPU',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'GPU',
|
||||
addon: {
|
||||
component: 'imports/addons/AddGPU',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm GPU',
|
||||
},
|
||||
}"
|
||||
@option="selected('gpu', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Camera</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Camera_System',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Camera',
|
||||
addon: {
|
||||
component: 'imports/addons/AddCamera',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm camera',
|
||||
},
|
||||
}"
|
||||
@option="selected('camera_system', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">SIM</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'SIM',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'SIM',
|
||||
addon: {
|
||||
component: 'imports/addons/AddSIM',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm SIM',
|
||||
},
|
||||
}"
|
||||
@option="selected('sim', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Kết nối</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Network_Technology',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Kết nối',
|
||||
addon: {
|
||||
component: 'imports/addons/AddNetworkTechnology',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm kết nối',
|
||||
},
|
||||
}"
|
||||
@option="selected('network_technology', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Công nghệ sạc</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Charging_Technology',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Công nghệ sạc',
|
||||
addon: {
|
||||
component: 'imports/addons/AddChargingTechnology',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm công nghệ sạc',
|
||||
},
|
||||
}"
|
||||
@option="selected('charging_technology', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Bộ nhớ ngoài</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'External_Storage',
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Bộ nhớ ngoài',
|
||||
addon: {
|
||||
component: 'imports/addons/AddExternalStorage',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm bộ nhớ ngoài',
|
||||
},
|
||||
}"
|
||||
@option="selected('external_storage', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Chỉ số IP</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'IP_Rating',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Chỉ số IP',
|
||||
addon: {
|
||||
component: 'imports/addons/AddIPRating',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm chỉ số IP',
|
||||
},
|
||||
}"
|
||||
@option="selected('ip_rating', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="field">
|
||||
<label class="label">Chất liệu</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Design',
|
||||
field: 'label',
|
||||
column: ['frame_material', 'back_material'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Chất liệu',
|
||||
addon: {
|
||||
component: 'imports/addons/AddDesign',
|
||||
width: '70%',
|
||||
height: 'auto',
|
||||
title: 'Thêm chất liệu',
|
||||
},
|
||||
}"
|
||||
@option="selected('design', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-12">
|
||||
<button
|
||||
:class="['button is-primary', { 'is-loading': isPending }]"
|
||||
:disabled="Object.values(body).every((v) => v === null)"
|
||||
@click.prevent="createProduct"
|
||||
>
|
||||
<span class="icon">
|
||||
<Icon name="material-symbols:add-rounded" />
|
||||
</span>
|
||||
<span>Tạo sản phẩm</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
61
app/components/imports/AddProductVariant.vue
Normal file
61
app/components/imports/AddProductVariant.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<script setup>
|
||||
import DataView from "@/components/datatable/DataView.vue";
|
||||
import AddProductVariantForm from "@/components/imports/AddProductVariantForm.vue";
|
||||
const product = ref();
|
||||
const key = ref(0);
|
||||
watch(product, () => {
|
||||
key.value++;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="fixed-grid has-12-cols">
|
||||
<div class="grid">
|
||||
<div class="cell is-col-span-6 is-col-start-4">
|
||||
<div class="field">
|
||||
<label class="label">Sản phẩm</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'product',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Tìm sản phẩm',
|
||||
addon: {
|
||||
component: 'imports/AddProductForm',
|
||||
width: '90%',
|
||||
height: 'auto',
|
||||
title: 'Thêm sản phẩm',
|
||||
},
|
||||
}"
|
||||
@option="product = $event"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="product"
|
||||
class="cell is-col-span-12"
|
||||
>
|
||||
<DataView
|
||||
:key="key"
|
||||
v-bind="{
|
||||
api: 'Product_Variant',
|
||||
setting: 'product-variants',
|
||||
pagename: 'product-variants',
|
||||
params: {
|
||||
values:
|
||||
'id,code,product,product__name,color,color__code,color__name,color__hex_code,ram,ram__code,ram__capacity,internal_storage,internal_storage__code,internal_storage__capacity,image,price,note,create_time,update_time',
|
||||
filter: { product: product.id },
|
||||
},
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AddProductVariantForm
|
||||
v-if="product"
|
||||
:productId="product.id"
|
||||
@created="key++"
|
||||
/>
|
||||
</template>
|
||||
@@ -1,20 +1,33 @@
|
||||
<script setup>
|
||||
import InputNumber from "@/components/common/InputNumber.vue";
|
||||
import { omitBy } from "es-toolkit";
|
||||
|
||||
const { $insertapi } = useNuxtApp();
|
||||
const props = defineProps({
|
||||
productId: Number,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["created"]);
|
||||
|
||||
const { $empty, $insertapi } = useNuxtApp();
|
||||
const isPending = ref(false);
|
||||
const body = ref({
|
||||
product: null,
|
||||
product: props.productId,
|
||||
price: null,
|
||||
internal_storage: null,
|
||||
ram: null,
|
||||
color: null,
|
||||
note: null,
|
||||
note: "",
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.productId,
|
||||
(newVal) => {
|
||||
body.value.product = props.productId;
|
||||
},
|
||||
);
|
||||
|
||||
function selected(field, data) {
|
||||
if (field === "price") {
|
||||
if (data === null || field === "price") {
|
||||
body.value[field] = data;
|
||||
} else {
|
||||
body.value[field] = data.id;
|
||||
@@ -23,38 +36,21 @@ function selected(field, data) {
|
||||
|
||||
async function createProductVariant() {
|
||||
isPending.value = true;
|
||||
const res = await $insertapi("Product_Variant", body.value);
|
||||
const trimmedBody = omitBy(body.value, $empty);
|
||||
const res = await $insertapi("Product_Variant", trimmedBody);
|
||||
isPending.value = false;
|
||||
if (res !== "error") {
|
||||
emit("created");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="subtitle is-4">AddProductVariantForm</h1>
|
||||
<h1 class="subtitle">Thêm phiên bản</h1>
|
||||
<form class="fixed-grid has-12-cols">
|
||||
<div class="grid">
|
||||
<div class="cell is-col-span-8">
|
||||
<div class="field">
|
||||
<label class="label">Sản phẩm</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'product',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
placeholder: 'Sản phẩm',
|
||||
addon: {
|
||||
component: 'imports/AddProductForm',
|
||||
width: '90%',
|
||||
height: 'auto',
|
||||
title: 'Thêm sản phẩm',
|
||||
},
|
||||
}"
|
||||
@option="selected('product', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="cell is-col-span-3">
|
||||
<div class="field">
|
||||
<label class="label">Đơn giá</label>
|
||||
<div class="control">
|
||||
@@ -70,15 +66,16 @@ async function createProductVariant() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="cell is-col-span-3">
|
||||
<div class="field">
|
||||
<label class="label">Màu sắc</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'color',
|
||||
api: 'Color',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Màu sắc',
|
||||
addon: {
|
||||
component: 'imports/addons/AddColor',
|
||||
@@ -91,7 +88,7 @@ async function createProductVariant() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="cell is-col-span-3">
|
||||
<div class="field">
|
||||
<label class="label">RAM</label>
|
||||
<SearchBox
|
||||
@@ -100,6 +97,7 @@ async function createProductVariant() {
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'RAM',
|
||||
addon: {
|
||||
component: 'imports/addons/AddRAM',
|
||||
@@ -112,7 +110,7 @@ async function createProductVariant() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell is-col-span-4">
|
||||
<div class="cell is-col-span-3">
|
||||
<div class="field">
|
||||
<label class="label">Bộ nhớ trong</label>
|
||||
<SearchBox
|
||||
@@ -121,6 +119,7 @@ async function createProductVariant() {
|
||||
field: 'code',
|
||||
column: ['code'],
|
||||
first: true,
|
||||
clearable: true,
|
||||
placeholder: 'Bộ nhớ trong',
|
||||
addon: {
|
||||
component: 'imports/addons/AddInternalStorage',
|
||||
@@ -148,11 +147,14 @@ async function createProductVariant() {
|
||||
<div class="cell is-col-span-12">
|
||||
<button
|
||||
:class="['button is-primary', { 'is-loading': isPending }]"
|
||||
:disabled="Object.values(body).every((v) => v === null)"
|
||||
:disabled="Object.values(body).every($empty)"
|
||||
@click.prevent="createProductVariant"
|
||||
>
|
||||
<span class="icon">
|
||||
<Icon name="material-symbols:add-2-rounded" />
|
||||
<Icon
|
||||
name="material-symbols:add-rounded"
|
||||
:size="18"
|
||||
/>
|
||||
</span>
|
||||
<span>Thêm phiên bản</span>
|
||||
</button>
|
||||
|
||||
12
app/components/imports/Color.vue
Normal file
12
app/components/imports/Color.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
color: String,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="w-20 h-4"
|
||||
:style="{ backgroundColor: color, outline: '1px solid var(--bulma-grey-85)' }"
|
||||
></div>
|
||||
</template>
|
||||
@@ -1,22 +1,43 @@
|
||||
<script setup>
|
||||
import AddProductForm from "@/components/imports/AddProductForm.vue";
|
||||
import AddProductVariantForm from "@/components/imports/AddProductVariantForm.vue";
|
||||
import FileUpload from "@/components/media/FileUpload.vue";
|
||||
import AddProductVariant from "@/components/imports/AddProductVariant.vue";
|
||||
const menus = [
|
||||
{
|
||||
id: "add-product",
|
||||
name: "Tạo sản phẩm",
|
||||
},
|
||||
{
|
||||
id: "add-product-variant",
|
||||
name: "Thêm phiên bản",
|
||||
},
|
||||
];
|
||||
const activeMenu = ref(menus[1]);
|
||||
</script>
|
||||
<template>
|
||||
<FileUpload
|
||||
:type="['file']"
|
||||
class="mb-2"
|
||||
@files="onFiles"
|
||||
>
|
||||
<template #icon>
|
||||
<Icon
|
||||
name="material-symbols:upload-rounded"
|
||||
:size="20"
|
||||
/>
|
||||
</template>
|
||||
<span class="font-medium">Import</span>
|
||||
</FileUpload>
|
||||
<AddProductForm />
|
||||
<AddProductVariantForm />
|
||||
<div class="fixed-grid has-12-cols">
|
||||
<div class="grid is-gap-4">
|
||||
<div class="cell is-col-span-2">
|
||||
<aside class="menu">
|
||||
<ul class="menu-list">
|
||||
<li
|
||||
v-for="menu in menus"
|
||||
:key="menu.id"
|
||||
>
|
||||
<a
|
||||
@click="activeMenu = menu"
|
||||
:class="{
|
||||
'is-active': activeMenu.id === menu.id,
|
||||
}"
|
||||
>{{ menu.name }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
<div class="cell is-col-span-10">
|
||||
<AddProductForm v-if="activeMenu.id === 'add-product'" />
|
||||
<AddProductVariant v-if="activeMenu.id === 'add-product-variant'" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user