...
This commit is contained in:
@@ -1,21 +1,98 @@
|
||||
<script setup>
|
||||
import { Listbox, InputText } from 'primevue';
|
||||
import { onBeforeMount, ref } from 'vue';
|
||||
import { onBeforeMount, ref, watch } from 'vue';
|
||||
import { CategoryService } from '@/service/CategoryService';
|
||||
import ImageUploader from '@/views/uikit/ImageUploader.vue';
|
||||
import ImageGallery from '@/views/uikit/ImageGallery.vue';
|
||||
import KiwiChips from '@/views/uikit/KiwiChips.vue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import { BelongingService } from '@/service/BelongingService';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import MapComponent from '@/views/uikit/MapComponent.vue';
|
||||
|
||||
const toast = useToast();
|
||||
const categories = ref([]);
|
||||
const selectedCategory = ref();
|
||||
const belongingName = ref('');
|
||||
const description = ref('');
|
||||
const imageNames = ref([]);
|
||||
const features = ref([]);
|
||||
const featuresValues = ref({});
|
||||
const documentNames = ref([]);
|
||||
const documentData = ref([]);
|
||||
const mainImageName = ref([]);
|
||||
const tags = ref('');
|
||||
const signedImageUrls = ref([{ url: 'https://upload.hitromall.com/product-images/0ff87b0cc333539a361e007d20aa9685-co3.jpg' }]);
|
||||
const belonging = ref({
|
||||
location: {
|
||||
type: 'Point',
|
||||
coordinates: [0, 0]
|
||||
}
|
||||
});
|
||||
const tags = ref([]);
|
||||
const signedImageUrls = ref([]);
|
||||
const signedDocumentsUrls = ref([]);
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const mapKey = 'web.79abbab4970e401781f434da3e41cfa6';
|
||||
const serviceKey = 'service.11d860f52c434bd29e5f84d0a0a41108';
|
||||
const mapRef = ref();
|
||||
|
||||
onBeforeMount(async () => {
|
||||
categories.value = await CategoryService.getAllCategories();
|
||||
console.log(route.name);
|
||||
if (route.name === 'edit-belonging') {
|
||||
belonging.value = await BelongingService.getBelonging(route.params.belongingId);
|
||||
}
|
||||
});
|
||||
const handleSelectCategory = ($event) => {
|
||||
if ($event.value) {
|
||||
belonging.value.category = $event.value;
|
||||
selectedCategory.value = categories.value.find((x) => x._id === $event.value);
|
||||
features.value = selectedCategory.value.features;
|
||||
} else {
|
||||
belonging.value = {
|
||||
location: {
|
||||
type: 'Point',
|
||||
coordinates: [0, 0]
|
||||
}
|
||||
};
|
||||
selectedCategory.value = {};
|
||||
}
|
||||
};
|
||||
|
||||
const saveBelonging = async () => {
|
||||
let status = 'failed';
|
||||
console.log(belonging);
|
||||
if (belonging?.value._id?.trim()) {
|
||||
status = await BelongingService.updateBelonging(belonging.value._id, belonging.value);
|
||||
} else {
|
||||
status = await BelongingService.createBelonging(belonging.value);
|
||||
}
|
||||
|
||||
if (status === 'success') {
|
||||
toast.add({ severity: 'success', summary: 'موفق', detail: 'ویژگی جدید ساخته شد.', life: 3000 });
|
||||
} else {
|
||||
toast.add({ severity: 'error', summary: 'ناموفق', detail: status, life: 3000 });
|
||||
}
|
||||
|
||||
await router.push('/belonging/list-belongings');
|
||||
};
|
||||
|
||||
watch(
|
||||
() => mapRef.value?.state.map,
|
||||
(nv, ol) => {
|
||||
if (ol) return;
|
||||
setTimeout(() => {
|
||||
mapRef.value?.state.map?.setMapType('standard-night');
|
||||
if (mapRef.value?.state.mapType) mapRef.value.state.mapType = 'standard-night';
|
||||
}, 2000);
|
||||
setTimeout(() => {
|
||||
mapRef.value?.search({
|
||||
term: 'ولی عصر',
|
||||
coords: [51.36281969540723, 35.69672648316882]
|
||||
});
|
||||
}, 3000);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<div className="card">
|
||||
@@ -26,38 +103,63 @@ onBeforeMount(async () => {
|
||||
<div class="w-3/4 ml-3">
|
||||
<div class="">
|
||||
<label> نام دارایی </label>
|
||||
<InputText v-model="belongingName" class="w-full my-2" placeholder="مثلا: 100 عدد کولر گازی" />
|
||||
<InputText v-model="belonging.name" class="w-full my-2" placeholder="مثلا: 100 عدد کولر گازی" />
|
||||
</div>
|
||||
<div class="my-6">
|
||||
<label> توضیحات </label>
|
||||
<Textarea v-model="description" class="w-full my-2" placeholder="مثلا: در تاریخ 1403/09/11 خریداری شد." rows="6" />
|
||||
<Textarea v-model="belonging.description" class="w-full my-2" placeholder="مثلا: در تاریخ 1403/09/11 خریداری شد." rows="6" />
|
||||
</div>
|
||||
<div class="my-6" v-if="signedImageUrls.length">
|
||||
<label> تصاویر </label>
|
||||
<ImageGallery v-model="signedImageUrls" gallery-id="images" />
|
||||
<div class="my-6">
|
||||
<label> تصاویر، فایل ها و مدارک </label>
|
||||
<ImageUploader v-model="belonging.documentNames" :max-files="50" mode="private" delete-endpoint="/api/files/bucket/delete/belonging-documents" upload-endpoint="/api/files/bucket/upload-multi-filepond/belonging-documents" />
|
||||
<div v-if="signedImageUrls.length > 0">
|
||||
<ImageGallery v-model="documentData" gallery-id="images" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-6" v-if="signedImageUrls.length">
|
||||
<div class="my-6" v-if="signedDocumentsUrls.length > 0">
|
||||
<label> فایل ها و مدارک </label>
|
||||
</div>
|
||||
<div class="my-6 max-h-96 overflow-y-auto" v-if="features.length > 0">
|
||||
<label> اطلاعات دارایی </label>
|
||||
<div class="my-6 mr-10" v-for="feature of features">
|
||||
<label>{{ feature.nativeName }}</label>
|
||||
<InputText v-model="featuresValues[feature._id]" class="w-1/3 my-2 block" placeholder="" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-10">
|
||||
<label> موقعیت دارایی </label>
|
||||
<MapComponent v-model="belonging.location.coordinates" />
|
||||
<!-- <MapIrComponent />-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/4">
|
||||
<div>
|
||||
<label> دسته بندی </label>
|
||||
<Listbox v-model="selectedCategory" :options="categories" optionLabel="nativeName" optionValue="_id" checkmark :highlightOnSelect="false" class="w-full my-2" />
|
||||
<Listbox @change="handleSelectCategory($event)" :options="categories" optionLabel="nativeName" optionValue="_id" checkmark :highlightOnSelect="false" class="w-full my-2" />
|
||||
</div>
|
||||
<div class="my-6">
|
||||
<label> تصویر اصلی </label>
|
||||
<ImageUploader v-model="mainImageName" :max-files="1" mode="private" delete-endpoint="/api/files/bucket/delete/belonging-images" upload-endpoint="/api/files/bucket/upload-multi-filepond/belonging-images" />
|
||||
<ImageUploader
|
||||
v-model="belonging.mainImageName"
|
||||
accepted-files="image/*"
|
||||
:max-files="1"
|
||||
mode="private"
|
||||
delete-endpoint="/api/files/bucket/delete/belonging-images"
|
||||
upload-endpoint="/api/files/bucket/upload-multi-filepond/belonging-images"
|
||||
/>
|
||||
</div>
|
||||
<div class="my-8">
|
||||
<label> برچسب ها </label>
|
||||
<Chips v-model="tags" separator="," class="w-full" placeholder="مثلا: زمین، ملک، کیانپارس..." />
|
||||
<KiwiChips v-model="belonging.tags" class="w-full" placeholder="مثلا: زمین، ملک، کیانپارس..." />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center">
|
||||
<Button>ذخیره</Button>
|
||||
<Button @click="saveBelonging">ذخیره</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
@import url('leaflet/dist/leaflet.css');
|
||||
</style>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { FilterMatchMode } from '@primevue/core/api';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { BelongingService } from '@/service/BelongingService';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
onMounted(() => {
|
||||
BelongingService.getAllBelongings().then((data) => (belongings.value = data));
|
||||
@@ -15,22 +16,12 @@ const belongings = ref();
|
||||
const productDialog = ref(false);
|
||||
const deleteProductDialog = ref(false);
|
||||
const deleteProductsDialog = ref(false);
|
||||
const product = ref({});
|
||||
const belonging = ref({});
|
||||
const selectedBelongings = ref();
|
||||
const filters = ref({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS }
|
||||
});
|
||||
const submitted = ref(false);
|
||||
const statuses = ref([
|
||||
{ label: 'INSTOCK', value: 'instock' },
|
||||
{ label: 'LOWSTOCK', value: 'lowstock' },
|
||||
{ label: 'OUTOFSTOCK', value: 'outofstock' }
|
||||
]);
|
||||
|
||||
function formatCurrency(value) {
|
||||
if (value) return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
|
||||
return;
|
||||
}
|
||||
|
||||
function openNew() {
|
||||
product.value = {};
|
||||
@@ -65,9 +56,10 @@ function saveProduct() {
|
||||
}
|
||||
}
|
||||
|
||||
function editProduct(prod) {
|
||||
product.value = { ...prod };
|
||||
productDialog.value = true;
|
||||
const router = useRouter();
|
||||
|
||||
function editBelonging(belongingId) {
|
||||
router.push('/belonging/edit-belonging/' + belongingId);
|
||||
}
|
||||
|
||||
function confirmDeleteProduct(prod) {
|
||||
@@ -112,7 +104,7 @@ function confirmDeleteSelected() {
|
||||
}
|
||||
|
||||
function deleteSelectedBelongings() {
|
||||
products.value = products.value.filter((val) => !selectedBelongings.value.includes(val));
|
||||
belonging.value = belonging.value.filter((val) => !selectedBelongings.value.includes(val));
|
||||
deleteProductsDialog.value = false;
|
||||
selectedBelongings.value = null;
|
||||
toast.add({ severity: 'success', summary: 'Successful', detail: 'Products Deleted', life: 3000 });
|
||||
@@ -144,8 +136,7 @@ function getStatusLabel(status) {
|
||||
<Button label="حذف دارایی" icon="pi pi-trash" severity="secondary" @click="confirmDeleteSelected" :disabled="!selectedBelongings || !selectedBelongings.length" />
|
||||
</template>
|
||||
|
||||
<template #end>
|
||||
</template>
|
||||
<template #end> </template>
|
||||
</Toolbar>
|
||||
|
||||
<DataTable
|
||||
@@ -175,20 +166,20 @@ function getStatusLabel(status) {
|
||||
<Column selectionMode="multiple" style="width: 3rem" :exportable="false"></Column>
|
||||
<Column header="تصویر">
|
||||
<template #body="slotProps">
|
||||
<img :src="`https://primefaces.org/cdn/primevue/images/product/${slotProps.data.image}`" :alt="slotProps.data.image" class="rounded" style="width: 64px" />
|
||||
<img :src="`${slotProps.data.mainImageUrl}`" :alt="slotProps.data.name" class="rounded" style="width: 64px" />
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="belongingCode" header="کد" style="min-width: 12rem"></Column>
|
||||
<Column field="name" header="نام" sortable style="min-width: 16rem"></Column>
|
||||
<Column field="category" header="دسته بندی" sortable style="min-width: 10rem">
|
||||
<template #body="slotProps">
|
||||
{{ slotProps.data.nativeName }}
|
||||
{{ slotProps.data.category.nativeName }}
|
||||
</template>
|
||||
</Column>
|
||||
<Column :exportable="false" style="min-width: 12rem">
|
||||
<template #body="slotProps">
|
||||
<Button icon="pi pi-pencil" outlined rounded class="mr-2" @click="editProduct(slotProps.data)" />
|
||||
<Button icon="pi pi-trash" outlined rounded severity="danger" @click="confirmDeleteProduct(slotProps.data)" />
|
||||
<Button icon="pi pi-pencil" outlined rounded class="mr-2 mx-3" @click="editBelonging(slotProps.data._id)" />
|
||||
<Button icon="pi pi-trash" outlined rounded severity="danger" class="mx-3" @click="confirmDeleteProduct(slotProps.data)" />
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
@@ -196,7 +187,7 @@ function getStatusLabel(status) {
|
||||
|
||||
<Dialog v-model:visible="productDialog" :style="{ width: '450px' }" header="Product Details" :modal="true">
|
||||
<div class="flex flex-col gap-6">
|
||||
<img v-if="product.image" :src="`https://primefaces.org/cdn/primevue/images/product/${product.image}`" :alt="product.image" class="block m-auto pb-4" />
|
||||
<img v-if="belonging.image" :src="`https://primefaces.org/cdn/primevue/images/product/${product.image}`" :alt="product.image" class="block m-auto pb-4" />
|
||||
<div>
|
||||
<label for="name" class="block font-bold mb-3">Name</label>
|
||||
<InputText id="name" v-model.trim="product.name" required="true" autofocus :invalid="submitted && !product.name" fluid />
|
||||
@@ -255,13 +246,13 @@ function getStatusLabel(status) {
|
||||
<div class="flex items-center gap-4">
|
||||
<i class="pi pi-exclamation-triangle !text-3xl" />
|
||||
<span v-if="product"
|
||||
>Are you sure you want to delete <b>{{ product.name }}</b
|
||||
>?</span
|
||||
>Are you sure you want to delete <b>{{ product.name }}</b
|
||||
>?</span
|
||||
>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="No" icon="pi pi-times" text @click="deleteProductDialog = false" />
|
||||
<Button label="Yes" icon="pi pi-check" @click="deleteProduct" />
|
||||
<Button label="خیر" icon="pi pi-times" text @click="deleteProductDialog = false" />
|
||||
<Button label="بله" icon="pi pi-check" @click="deleteProduct" />
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ function deleteSelectedCategories() {
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex flex-wrap gap-2 items-center justify-between">
|
||||
<h4 class="m-0">مدیریت اموال</h4>
|
||||
<h4 class="m-0">مدیریت دسته بندی ها</h4>
|
||||
<IconField>
|
||||
<InputIcon>
|
||||
<i class="pi pi-search" />
|
||||
|
||||
@@ -93,15 +93,6 @@ function findIndexById(id) {
|
||||
return index;
|
||||
}
|
||||
|
||||
function createId() {
|
||||
let id = '';
|
||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for (var i = 0; i < 5; i++) {
|
||||
id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
function exportCSV() {
|
||||
dt.value.exportCSV();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Tabs, TabList, Tab } from 'primevue';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import axios from 'axios';
|
||||
import { FeatureService } from '@/service/FeatureService';
|
||||
|
||||
const toast = useToast();
|
||||
const selectedTab = ref('');
|
||||
const selectedFeature = ref();
|
||||
|
||||
Reference in New Issue
Block a user