| @@ -1,4 +1,4 @@ | |||||
| { | { | ||||
| "title": "NovinPlast", | |||||
| "description": "NovinPlast" | |||||
| } | |||||
| "title": "TruckShop", | |||||
| "description": "TruckShop" | |||||
| } | |||||
| @@ -1 +0,0 @@ | |||||
| .quill-editor[data-v-a2cbff30]{height:300px;border:1px solid #ccc;border-radius:5px}.quill-editor .ql-container[data-v-a2cbff30]{font-family:Vazir,Arial,sans-serif;font-size:14px}.quill-editor .ql-editor[data-v-a2cbff30]{padding:10px;text-align:right}.ql-editor[data-v-a2cbff30]{direction:rtl;text-align:right}.ql-editor[data-v-a2cbff30]:before{content:attr(placeholder);direction:rtl!important;text-align:right}.Image-Preview[data-v-a2cbff30]{min-width:200px;max-height:200px;max-width:200px;-o-object-fit:cover;object-fit:cover;border-radius:8px;border:1px solid #ddd}.delete-btn[data-v-a2cbff30]{display:flex;align-items:center;padding:3px;font-size:10px;background-color:#e74c3c;color:#fff;border:none;border-radius:5px;cursor:pointer;transition:background-color .3s ease,transform .2s ease;gap:8px;margin-right:100px}.delete-btn[data-v-a2cbff30]:hover{background-color:#c0392b;transform:scale(1.05)}.delete-btn[data-v-a2cbff30]:active{background-color:#a93226}.delete-btn[data-v-a2cbff30]:focus{outline:none} | |||||
| @@ -1 +0,0 @@ | |||||
| .quill-editor[data-v-099ca948]{height:300px;border:1px solid #ccc;border-radius:5px}.quill-editor .ql-container[data-v-099ca948]{font-family:Vazir,Arial,sans-serif;font-size:14px}.quill-editor .ql-editor[data-v-099ca948]{padding:10px;text-align:right}.ql-editor[data-v-099ca948]{direction:rtl;text-align:right}.ql-editor[data-v-099ca948]:before{content:attr(placeholder);direction:rtl!important;text-align:right}.Image-Preview[data-v-099ca948]{min-width:200px;max-height:200px;max-width:200px;-o-object-fit:cover;object-fit:cover;border-radius:8px;border:1px solid #ddd}.delete-btn[data-v-099ca948]{display:flex;align-items:center;padding:3px;font-size:10px;background-color:#e74c3c;color:#fff;border:none;border-radius:5px;cursor:pointer;transition:background-color .3s ease,transform .2s ease;gap:8px;margin-right:200px}.delete-btn[data-v-099ca948]:hover{background-color:#c0392b;transform:scale(1.05)}.delete-btn[data-v-099ca948]:active{background-color:#a93226}.delete-btn[data-v-099ca948]:focus{outline:none} | |||||
| @@ -1,4 +1,4 @@ | |||||
| <!doctype html><html lang=""><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="icon" id="favicon" href="/panel/favicon.svg"/><link rel="stylesheet" href="/panel/fonts/vazir.css"/><title>TruckShop</title><script defer="defer" src="/panel/js/chunk-vendors.f38378b4.js"></script><script defer="defer" src="/panel/js/app.67eaa993.js"></script><link href="/panel/css/chunk-vendors.8ada15f4.css" rel="stylesheet"><link href="/panel/css/app.4211482e.css" rel="stylesheet"></head><body lang><noscript><strong>We're sorry but TruckShop doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>document.addEventListener("DOMContentLoaded", function () { | |||||
| <!doctype html><html lang=""><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="icon" id="favicon" href="/panel/favicon.svg"/><link rel="stylesheet" href="/panel/fonts/vazir.css"/><title>TruckShop</title><script defer="defer" src="/panel/js/chunk-vendors.f38378b4.js"></script><script defer="defer" src="/panel/js/app.472e38d2.js"></script><link href="/panel/css/chunk-vendors.8ada15f4.css" rel="stylesheet"><link href="/panel/css/app.4211482e.css" rel="stylesheet"></head><body lang><noscript><strong>We're sorry but TruckShop doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>document.addEventListener("DOMContentLoaded", function () { | |||||
| const faviconUrl = localStorage.getItem("logo"); | const faviconUrl = localStorage.getItem("logo"); | ||||
| if (faviconUrl) { | if (faviconUrl) { | ||||
| const faviconLink = document.getElementById("favicon"); | const faviconLink = document.getElementById("favicon"); | ||||
| @@ -1,11 +1,11 @@ | |||||
| { | { | ||||
| "name": "NovinPlast", | |||||
| "name": "TruckShop", | |||||
| "version": "0.1.0", | "version": "0.1.0", | ||||
| "lockfileVersion": 3, | "lockfileVersion": 3, | ||||
| "requires": true, | "requires": true, | ||||
| "packages": { | "packages": { | ||||
| "": { | "": { | ||||
| "name": "NovinPlast", | |||||
| "name": "TruckShop", | |||||
| "version": "0.1.0", | "version": "0.1.0", | ||||
| "dependencies": { | "dependencies": { | ||||
| "@amcharts/amcharts4": "^4.10.38", | "@amcharts/amcharts4": "^4.10.38", | ||||
| @@ -1,5 +1,5 @@ | |||||
| { | { | ||||
| "name": "NovinPlast", | |||||
| "name": "TruckShop", | |||||
| "version": "0.1.0", | "version": "0.1.0", | ||||
| "private": true, | "private": true, | ||||
| "scripts": { | "scripts": { | ||||
| @@ -6,7 +6,6 @@ | |||||
| <meta name="viewport" content="width=device-width,initial-scale=1.0" /> | <meta name="viewport" content="width=device-width,initial-scale=1.0" /> | ||||
| <link rel="icon" id="favicon" href="<%= BASE_URL %>favicon.svg" /> | <link rel="icon" id="favicon" href="<%= BASE_URL %>favicon.svg" /> | ||||
| <link rel="stylesheet" href="<%= BASE_URL %>fonts/vazir.css" /> | <link rel="stylesheet" href="<%= BASE_URL %>fonts/vazir.css" /> | ||||
| <script defer src="https://bazarce.liara.run/script.js" data-website-id="7baabdd5-3224-41c1-9267-d2a1abd29d01"></script> | |||||
| <title><%= htmlWebpackPlugin.options.title %></title> | <title><%= htmlWebpackPlugin.options.title %></title> | ||||
| </head> | </head> | ||||
| @@ -135,18 +135,18 @@ | |||||
| } | } | ||||
| } | } | ||||
| const handlerChangeCheckbox = async (e, attr) => { | |||||
| if (!e.target.checked) { | |||||
| try { | |||||
| const { data: { success, message } } = await ApiService.delete(`admin/products/${props.productId}/attributes/${attr.id}`) | |||||
| if (success) { | |||||
| toast.success(message) | |||||
| } | |||||
| } catch (e) { | |||||
| toast.error(e.response?.data?.message) | |||||
| } | |||||
| } | |||||
| const handlerChangeCheckbox = async () => { | |||||
| // if (!e.target.checked) { | |||||
| // try { | |||||
| // const { data: { success, message } } = await ApiService.delete(`admin/products/${props.productId}/attributes/${attr.id}`) | |||||
| // | |||||
| // if (success) { | |||||
| // toast.success(message) | |||||
| // } | |||||
| // } catch (e) { | |||||
| // toast.error(e.response?.data?.message) | |||||
| // } | |||||
| // } | |||||
| } | } | ||||
| getAttributes() | getAttributes() | ||||
| @@ -1,8 +1,9 @@ | |||||
| <script setup> | <script setup> | ||||
| import {ref, reactive, defineProps, defineExpose, defineEmits } from "vue" | |||||
| import {ref, reactive, defineProps, defineExpose, defineEmits, computed} from "vue" | |||||
| import ApiService from "@/services/ApiService"; | import ApiService from "@/services/ApiService"; | ||||
| import { toast } from "vue3-toastify"; | import { toast } from "vue3-toastify"; | ||||
| import {BRow} from "bootstrap-vue-next"; | import {BRow} from "bootstrap-vue-next"; | ||||
| import ApiServiece from "@/services/ApiService"; | |||||
| const defaultFormState = { | const defaultFormState = { | ||||
| title: null, | title: null, | ||||
| @@ -16,10 +17,14 @@ | |||||
| productId: { | productId: { | ||||
| type: Number, | type: Number, | ||||
| required: true, | required: true, | ||||
| } | |||||
| }, | |||||
| product: { | |||||
| type: Object, | |||||
| required: true, | |||||
| }, | |||||
| }) | }) | ||||
| const emit = defineEmits(["changeLng", "data"]); | |||||
| const emit = defineEmits(["changeLng", "data", "update:productRow"]); | |||||
| const form = reactive({ ...defaultFormState }); | const form = reactive({ ...defaultFormState }); | ||||
| @@ -27,6 +32,34 @@ | |||||
| const loading = ref(false) | const loading = ref(false) | ||||
| const loadingDelete = ref(false) | |||||
| const productRowModel = computed({ | |||||
| get: () => props.product, | |||||
| set: (newValue) => emit('update:productRow', newValue) | |||||
| }); | |||||
| const findLocaleTranslation = computed(() => { | |||||
| const foundTranslation = props.product?.translations?.find( | |||||
| item => item?.locale === form.locale | |||||
| ); | |||||
| if (foundTranslation) { | |||||
| switch (foundTranslation?.locale) { | |||||
| case "en": | |||||
| return "انگلیسی"; | |||||
| case "fa": | |||||
| return "فارسی"; | |||||
| case "ar": | |||||
| return "عربی"; | |||||
| default: | |||||
| return null; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| }); | |||||
| const clearError = (field) => { | const clearError = (field) => { | ||||
| errors.value[field] = ""; | errors.value[field] = ""; | ||||
| }; | }; | ||||
| @@ -53,11 +86,50 @@ | |||||
| } | } | ||||
| } | } | ||||
| const handlerRemoveTranslation = async () => { | |||||
| const findLocale = props.product?.translations?.find(item => item?.locale === form.locale); | |||||
| if (findLocale) { | |||||
| try { | |||||
| loadingDelete.value = true; | |||||
| const { data: { success, message, data } } = await ApiServiece.delete( | |||||
| `admin/products/${props.product?.id}/translations/${findLocale?.id}` | |||||
| ) | |||||
| if (success) { | |||||
| const updatedCategory = props.product | |||||
| updatedCategory.translations = data?.translations | |||||
| productRowModel.value = updatedCategory | |||||
| Object.assign(form, defaultFormState) | |||||
| toast.success(message) | |||||
| } | |||||
| } catch (e) { | |||||
| toast.error(e?.response?.data?.message) | |||||
| }finally { | |||||
| loadingDelete.value = false | |||||
| } | |||||
| } | |||||
| } | |||||
| defineExpose({ form }) | defineExpose({ form }) | ||||
| </script> | </script> | ||||
| <template> | <template> | ||||
| <div class="p-2"> | <div class="p-2"> | ||||
| <BButton | |||||
| :disabled="!findLocaleTranslation" | |||||
| :loading="loadingDelete" | |||||
| @click="handlerRemoveTranslation" | |||||
| class="btn btn-sm rounded btn-danger d-block mt-2" | |||||
| style="margin-right: auto" | |||||
| > | |||||
| حذف ترجمه {{ findLocaleTranslation }} | |||||
| </BButton> | |||||
| <BRow class="g-3"> | <BRow class="g-3"> | ||||
| <BCol md="6"> | <BCol md="6"> | ||||
| <div class="form-group"> | <div class="form-group"> | ||||
| @@ -44,7 +44,7 @@ export default { | |||||
| if (result.isConfirmed) { | if (result.isConfirmed) { | ||||
| await store.dispatch("user/logout"); | await store.dispatch("user/logout"); | ||||
| router.push({ name: "otpLogin" }); | |||||
| router.push({ name: "login-v2" }); | |||||
| console.log("User logged out successfully."); | console.log("User logged out successfully."); | ||||
| } | } | ||||
| } catch (error) { | } catch (error) { | ||||
| @@ -18,6 +18,7 @@ | |||||
| class="btn-close" | class="btn-close" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| aria-label="Close" | aria-label="Close" | ||||
| @click="step = 1" | |||||
| ></button> | ></button> | ||||
| </div> | </div> | ||||
| <div class="modal-body"> | <div class="modal-body"> | ||||
| @@ -163,6 +164,7 @@ | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @click="step = 1" | |||||
| > | > | ||||
| بستن | بستن | ||||
| </button> | </button> | ||||
| @@ -296,7 +298,6 @@ export default { | |||||
| }, 500); | }, 500); | ||||
| }) | }) | ||||
| .catch((error) => { | .catch((error) => { | ||||
| console.error(error); | |||||
| toast.error(`${error.response.data.message}`, { | toast.error(`${error.response.data.message}`, { | ||||
| position: "top-right", | position: "top-right", | ||||
| autoClose: 1000, | autoClose: 1000, | ||||
| @@ -338,14 +338,19 @@ export default { | |||||
| ); | ); | ||||
| if (data?.success) { | if (data?.success) { | ||||
| const updatedBrands = brandRowModel.value ? {...brandRowModel.value} : null; | |||||
| if (updatedBrands) { | |||||
| updatedBrands.translations = [...(updatedBrands.translations || []), data?.data]; | |||||
| brandRowModel.value = updatedBrands; | |||||
| const updatedCategory = brandRowModel.value; | |||||
| if (existingTranslation) { | |||||
| updatedCategory.translations = data?.data?.translations || []; | |||||
| } else { | |||||
| updatedCategory.translations = [ | |||||
| ...(updatedCategory.translations || []), | |||||
| ...(data?.data?.translations || []) | |||||
| ]; | |||||
| } | } | ||||
| brandRowModel.value = updatedCategory; | |||||
| toast.success(data?.message) | toast.success(data?.message) | ||||
| setTimeout(() => { | setTimeout(() => { | ||||
| @@ -405,14 +410,19 @@ export default { | |||||
| ) | ) | ||||
| if (success) { | if (success) { | ||||
| const updatedBrands = brandRowModel.value ? {...brandRowModel.value} : null; | |||||
| if (updatedBrands) { | |||||
| updatedBrands.translations = [...(updatedBrands.translations || []), data]; | |||||
| brandRowModel.value = updatedBrands; | |||||
| const updatedBrand = brandRowModel.value; | |||||
| if (findLocale) { | |||||
| updatedBrand.translations = data?.translations || []; | |||||
| } else { | |||||
| updatedBrand.translations = [ | |||||
| ...(updatedBrand.translations || []), | |||||
| ...(data?.translations || []) | |||||
| ]; | |||||
| } | } | ||||
| brandRowModel.value = updatedBrand; | |||||
| localTitle.value = null | localTitle.value = null | ||||
| localDesc.value = null | localDesc.value = null | ||||
| @@ -123,6 +123,7 @@ getAttributes() | |||||
| class="btn-close" | class="btn-close" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| aria-label="Close" | aria-label="Close" | ||||
| @click="step = 1" | |||||
| ></button> | ></button> | ||||
| </div> | </div> | ||||
| @@ -195,6 +196,7 @@ getAttributes() | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @click="step = 1" | |||||
| > | > | ||||
| بستن | بستن | ||||
| </button> | </button> | ||||
| @@ -269,20 +271,21 @@ getAttributes() | |||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | <button | ||||
| type="button" | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | |||||
| @click="step = 1" | |||||
| > | > | ||||
| بستن | بستن | ||||
| </button> | </button> | ||||
| <button type="submit" class="btn btn-primary" :disabled="loadingAttr"> | <button type="submit" class="btn btn-primary" :disabled="loadingAttr"> | ||||
| <span | |||||
| v-if="loadingAttr" | |||||
| class="spinner-border spinner-border-sm" | |||||
| role="status" | |||||
| aria-hidden="true" | |||||
| /> | |||||
| <span | |||||
| v-if="loadingAttr" | |||||
| class="spinner-border spinner-border-sm" | |||||
| role="status" | |||||
| aria-hidden="true" | |||||
| /> | |||||
| ذخیره | ذخیره | ||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| @@ -159,11 +159,11 @@ const handlerRemoveTranslation = async () => { | |||||
| const updatedCategory = props.attrRow; | const updatedCategory = props.attrRow; | ||||
| if (findLocale) { | if (findLocale) { | ||||
| updatedCategory.translations = data?.data?.translations || []; | |||||
| updatedCategory.translations = data?.translations || []; | |||||
| } else { | } else { | ||||
| updatedCategory.translations = [ | updatedCategory.translations = [ | ||||
| ...(updatedCategory.translations || []), | |||||
| ...(data?.data?.translations || []) | |||||
| ...(updatedCategory?.translations || []), | |||||
| ...(data?.translations || []) | |||||
| ]; | ]; | ||||
| } | } | ||||
| @@ -184,25 +184,6 @@ const handlerRemoveTranslation = async () => { | |||||
| const clearError = (field) => { | const clearError = (field) => { | ||||
| errors.value[field] = ""; | errors.value[field] = ""; | ||||
| } | } | ||||
| // const handlerSubmitColor = async () => { | |||||
| // try { | |||||
| // loading.value = true | |||||
| // | |||||
| // const { data: { message, success } } = await ApiService.put( | |||||
| // `admin/attribute-values/${attrRowModel.value?.id}`, { | |||||
| // code: colorCode.value, | |||||
| // }) | |||||
| // | |||||
| // if (success) { | |||||
| // toast.success(message) | |||||
| // } | |||||
| // } catch (e) { | |||||
| // toast.error(e?.response?.data?.message) | |||||
| // } finally { | |||||
| // loading.value = false | |||||
| // } | |||||
| // } | |||||
| </script> | </script> | ||||
| <template> | <template> | ||||
| @@ -298,6 +279,7 @@ const clearError = (field) => { | |||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | <button | ||||
| type="button" | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @@ -60,6 +60,7 @@ | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @click="step = 1" | |||||
| > | > | ||||
| بستن | بستن | ||||
| </button> | </button> | ||||
| @@ -134,20 +135,22 @@ | |||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | <button | ||||
| type="button" | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @click="step = 1" | |||||
| > | > | ||||
| بستن | بستن | ||||
| </button> | </button> | ||||
| <button type="submit" class="btn btn-primary" :disabled="loadingAttr"> | <button type="submit" class="btn btn-primary" :disabled="loadingAttr"> | ||||
| <span | |||||
| v-if="loadingAttr" | |||||
| class="spinner-border spinner-border-sm" | |||||
| role="status" | |||||
| aria-hidden="true" | |||||
| /> | |||||
| <span | |||||
| v-if="loadingAttr" | |||||
| class="spinner-border spinner-border-sm" | |||||
| role="status" | |||||
| aria-hidden="true" | |||||
| /> | |||||
| ذخیره | ذخیره | ||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| @@ -255,6 +258,9 @@ export default { | |||||
| if (success) { | if (success) { | ||||
| toast.success(message) | toast.success(message) | ||||
| //document.getElementById("close").click(); | //document.getElementById("close").click(); | ||||
| attrName.value = undefined; | |||||
| emit("attribute-updated"); | emit("attribute-updated"); | ||||
| } | } | ||||
| } catch (e) { | } catch (e) { | ||||
| @@ -276,6 +282,7 @@ export default { | |||||
| } | } | ||||
| } | } | ||||
| getAttributes() | getAttributes() | ||||
| return { | return { | ||||
| @@ -10,7 +10,7 @@ | |||||
| <div class="modal-dialog modal-sm" role="document"> | <div class="modal-dialog modal-sm" role="document"> | ||||
| <div class="modal-content"> | <div class="modal-content"> | ||||
| <div class="modal-header"> | <div class="modal-header"> | ||||
| <h5 class="modal-title" id="exampleModalLabel">ویرایش رنگ</h5> | |||||
| <h5 class="modal-title" id="exampleModalLabel">ویرایش ویژگی</h5> | |||||
| <button | <button | ||||
| type="button" | type="button" | ||||
| class="btn-close" | class="btn-close" | ||||
| @@ -44,6 +44,7 @@ | |||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | <button | ||||
| type="button" | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @@ -51,9 +52,9 @@ | |||||
| بستن | بستن | ||||
| </button> | </button> | ||||
| <button @click="handlerSubmitCategory" class="btn btn-primary" :disabled="loading"> | |||||
| <button @click="handlerSubmitAttribute" class="btn btn-primary" :disabled="loadingAttr"> | |||||
| <span | <span | ||||
| v-if="loading" | |||||
| v-if="loadingAttr" | |||||
| class="spinner-border spinner-border-sm" | class="spinner-border spinner-border-sm" | ||||
| role="status" | role="status" | ||||
| aria-hidden="true" | aria-hidden="true" | ||||
| @@ -133,6 +134,7 @@ | |||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | <button | ||||
| type="button" | |||||
| class="btn btn-secondary" | class="btn btn-secondary" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| id="close" | id="close" | ||||
| @@ -141,12 +143,12 @@ | |||||
| </button> | </button> | ||||
| <button type="submit" class="btn btn-primary" :disabled="loading"> | <button type="submit" class="btn btn-primary" :disabled="loading"> | ||||
| <span | |||||
| v-if="loading" | |||||
| class="spinner-border spinner-border-sm" | |||||
| role="status" | |||||
| aria-hidden="true" | |||||
| /> | |||||
| <span | |||||
| v-if="loading" | |||||
| class="spinner-border spinner-border-sm" | |||||
| role="status" | |||||
| aria-hidden="true" | |||||
| /> | |||||
| ذخیره | ذخیره | ||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| @@ -200,6 +202,7 @@ export default { | |||||
| const categories = ref([]); | const categories = ref([]); | ||||
| const locale = ref('fa'); | const locale = ref('fa'); | ||||
| const loadingDelete = ref(false); | const loadingDelete = ref(false); | ||||
| const loadingAttr = ref(false); | |||||
| const attrRowModel = computed({ | const attrRowModel = computed({ | ||||
| get: () => props.attrRow, | get: () => props.attrRow, | ||||
| @@ -304,11 +307,9 @@ export default { | |||||
| attrRowModel.value = updatedCategory; | attrRowModel.value = updatedCategory; | ||||
| console.log(attrRowModel.value,'attrRowModel.value') | |||||
| toast.success(data?.message) | toast.success(data?.message) | ||||
| emit("cat-updated"); | |||||
| emit("attribute-updated"); | |||||
| } | } | ||||
| } catch (error) { | } catch (error) { | ||||
| @@ -337,11 +338,11 @@ export default { | |||||
| const updatedCategory = props.attrRow; | const updatedCategory = props.attrRow; | ||||
| if (findLocale) { | if (findLocale) { | ||||
| updatedCategory.translations = data?.data?.translations || []; | |||||
| updatedCategory.translations = data?.translations || []; | |||||
| } else { | } else { | ||||
| updatedCategory.translations = [ | updatedCategory.translations = [ | ||||
| ...(updatedCategory.translations || []), | ...(updatedCategory.translations || []), | ||||
| ...(data?.data?.translations || []) | |||||
| ...(data?.translations || []) | |||||
| ]; | ]; | ||||
| } | } | ||||
| @@ -381,6 +382,28 @@ export default { | |||||
| } | } | ||||
| } | } | ||||
| const handlerSubmitAttribute = async () => { | |||||
| try { | |||||
| loadingAttr.value = true; | |||||
| const params = { | |||||
| category_id: categoryId.value, | |||||
| } | |||||
| const { data: { success, message } } = await ApiServiece.put(`admin/attributes/${props.attrRow?.id}`, params) | |||||
| if (success) { | |||||
| toast.success(message) | |||||
| emit("attribute-updated"); | |||||
| } | |||||
| } catch (e) { | |||||
| toast.error(e?.response?.data?.message) | |||||
| } finally { | |||||
| loadingAttr.value = false; | |||||
| } | |||||
| } | |||||
| getAttributes() | getAttributes() | ||||
| return { | return { | ||||
| @@ -399,6 +422,8 @@ export default { | |||||
| findLocaleTranslation, | findLocaleTranslation, | ||||
| handlerRemoveTranslation, | handlerRemoveTranslation, | ||||
| loadingDelete, | loadingDelete, | ||||
| handlerSubmitAttribute, | |||||
| loadingAttr, | |||||
| }; | }; | ||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -4,8 +4,10 @@ | |||||
| id="addBlogCat" | id="addBlogCat" | ||||
| tabindex="-1" | tabindex="-1" | ||||
| role="dialog" | role="dialog" | ||||
| aria-labelledby="exampleModalLabel" | |||||
| aria-hidden="true" | aria-hidden="true" | ||||
| data-bs-backdrop="static" | |||||
| aria-labelledby="staticBackdropLabel" | |||||
| data-bs-keyboard="false" | |||||
| > | > | ||||
| <div class="modal-dialog modal-sm" role="document"> | <div class="modal-dialog modal-sm" role="document"> | ||||
| <div class="modal-content"> | <div class="modal-content"> | ||||
| @@ -18,6 +20,7 @@ | |||||
| class="btn-close" | class="btn-close" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| aria-label="Close" | aria-label="Close" | ||||
| @click="step = 1" | |||||
| ></button> | ></button> | ||||
| </div> | </div> | ||||
| <div class="modal-body"> | <div class="modal-body"> | ||||
| @@ -209,13 +209,18 @@ export default { | |||||
| } | } | ||||
| ); | ); | ||||
| console.log(data,'data data data') | |||||
| if (data?.success) { | |||||
| const updatedCategory = props.catRow | |||||
| toast.success("!دسته با موفقیت ویرایش شد", { | |||||
| position: "top-right", | |||||
| autoClose: 1000, | |||||
| }); | |||||
| updatedCategory.translations = data?.data?.translations | |||||
| categoryRowModel.value = updatedCategory | |||||
| toast.success(data?.message, { | |||||
| position: "top-right", | |||||
| autoClose: 1000, | |||||
| }); | |||||
| } | |||||
| } catch (e) { | } catch (e) { | ||||
| toast.error(`${e?.response?.data?.message}`, { | toast.error(`${e?.response?.data?.message}`, { | ||||
| position: "top-right", | position: "top-right", | ||||
| @@ -273,10 +278,10 @@ export default { | |||||
| updatedCategory.translations = data?.translations | updatedCategory.translations = data?.translations | ||||
| titleCat.value = null | |||||
| categoryRowModel.value = updatedCategory | categoryRowModel.value = updatedCategory | ||||
| titleCat.value = null | |||||
| toast.success(message) | toast.success(message) | ||||
| } | } | ||||
| } catch (e) { | } catch (e) { | ||||
| @@ -298,6 +303,7 @@ export default { | |||||
| handlerChangeLocale, | handlerChangeLocale, | ||||
| findLocaleTranslation, | findLocaleTranslation, | ||||
| handlerRemoveTranslation, | handlerRemoveTranslation, | ||||
| loadingDelete, | |||||
| }; | }; | ||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -4,10 +4,12 @@ | |||||
| id="addCat" | id="addCat" | ||||
| tabindex="-1" | tabindex="-1" | ||||
| role="dialog" | role="dialog" | ||||
| aria-labelledby="exampleModalLabel" | |||||
| aria-hidden="true" | aria-hidden="true" | ||||
| data-bs-backdrop="static" | |||||
| aria-labelledby="staticBackdropLabel" | |||||
| data-bs-keyboard="false" | |||||
| > | > | ||||
| <div class="modal-dialog modal-sm" role="document"> | |||||
| <div class="modal-dialog modal-sm" role="document" > | |||||
| <div class="modal-content"> | <div class="modal-content"> | ||||
| <div class="modal-header"> | <div class="modal-header"> | ||||
| <h5 class="modal-title" id="exampleModalLabel"> | <h5 class="modal-title" id="exampleModalLabel"> | ||||
| @@ -18,6 +20,7 @@ | |||||
| class="btn-close" | class="btn-close" | ||||
| data-bs-dismiss="modal" | data-bs-dismiss="modal" | ||||
| aria-label="Close" | aria-label="Close" | ||||
| @click="step = 1" | |||||
| ></button> | ></button> | ||||
| </div> | </div> | ||||
| <div class="modal-body"> | <div class="modal-body"> | ||||
| @@ -153,13 +156,6 @@ | |||||
| class="d-flex justify-content-between gap-2" | class="d-flex justify-content-between gap-2" | ||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | |||||
| class="btn btn-secondary" | |||||
| @click="step--" | |||||
| > | |||||
| قبلی | |||||
| </button> | |||||
| <button type="submit" class="btn btn-primary" :disabled="loading"> | <button type="submit" class="btn btn-primary" :disabled="loading"> | ||||
| <span | <span | ||||
| v-if="loading" | v-if="loading" | ||||
| @@ -287,6 +283,9 @@ export default { | |||||
| try { | try { | ||||
| loadingStep.value = true; | loadingStep.value = true; | ||||
| if (selectedPaernt.value.trim() === '') | |||||
| selectedPaernt.value = undefined | |||||
| const { data: { success, data, message } } = await ApiServiece.post(`admin/categories`, { | const { data: { success, data, message } } = await ApiServiece.post(`admin/categories`, { | ||||
| parent_id: selectedPaernt.value | parent_id: selectedPaernt.value | ||||
| }, { | }, { | ||||
| @@ -63,7 +63,6 @@ | |||||
| </BTab> | </BTab> | ||||
| <BTab title="ترجمه ها"> | <BTab title="ترجمه ها"> | ||||
| <form @submit.prevent="editCat" class="mt-4"> | <form @submit.prevent="editCat" class="mt-4"> | ||||
| <BButton | <BButton | ||||
| :disabled="!findLocaleTranslation" | :disabled="!findLocaleTranslation" | ||||
| :loading="loadingDelete" | :loading="loadingDelete" | ||||
| @@ -385,6 +384,10 @@ export default { | |||||
| categoryRowModel.value = updatedCategory | categoryRowModel.value = updatedCategory | ||||
| title.value = "" | |||||
| description.value = "" | |||||
| toast.success(message) | toast.success(message) | ||||
| } | } | ||||
| } catch (e) { | } catch (e) { | ||||
| @@ -4,7 +4,7 @@ import appConfig from "../../app.config"; | |||||
| //import store from "../state/store"; | //import store from "../state/store"; | ||||
| const router = createRouter({ | const router = createRouter({ | ||||
| history: createWebHistory("/"), | |||||
| history: createWebHistory("/panel"), | |||||
| routes, | routes, | ||||
| }); | }); | ||||
| @@ -1,7 +1,7 @@ | |||||
| import axios from "axios"; | import axios from "axios"; | ||||
| import router from "@/router/index"; | import router from "@/router/index"; | ||||
| const url = process.env.VUE_APP_ROOT_URL; | |||||
| const url = process.env.VUE_APP_ROOT_URL; | |||||
| const ApiServiece = axios.create({ | const ApiServiece = axios.create({ | ||||
| baseURL: url, | baseURL: url, | ||||
| @@ -30,7 +30,7 @@ ApiServiece.interceptors.response.use( | |||||
| }, | }, | ||||
| (error) => { | (error) => { | ||||
| if (error?.status === 401) { | if (error?.status === 401) { | ||||
| router.push({ name: "otpLogin" }); | |||||
| router.push({ name: "login-v2" }); | |||||
| } | } | ||||
| return Promise.reject(error); | return Promise.reject(error); | ||||
| } | } | ||||
| @@ -130,11 +130,11 @@ export default { | |||||
| const deleteAttribute = (id, title) => { | const deleteAttribute = (id, title) => { | ||||
| Swal.fire({ | Swal.fire({ | ||||
| text: `می خواهید رنگ ${title ?? ''} را حذف کنید ؟`, | |||||
| text: `می خواهید ${title ?? ''} را حذف کنید ؟`, | |||||
| icon: "warning", | icon: "warning", | ||||
| showCancelButton: true, | showCancelButton: true, | ||||
| confirmButtonColor: "#3085d6", | |||||
| cancelButtonColor: "#d33", | |||||
| confirmButtonColor: "#d33", | |||||
| cancelButtonColor: "red", | |||||
| confirmButtonText: "بله!", | confirmButtonText: "بله!", | ||||
| cancelButtonText: "خیر", | cancelButtonText: "خیر", | ||||
| }).then((result) => { | }).then((result) => { | ||||
| @@ -8,14 +8,6 @@ | |||||
| <div class="text-center mb-4"> | <div class="text-center mb-4"> | ||||
| <img :src="logo" alt="Logo" class="styled-logo" /> | <img :src="logo" alt="Logo" class="styled-logo" /> | ||||
| </div> | </div> | ||||
| <h4 class="f-w-500 mb-1">ورود با شماره موبایل</h4> | |||||
| <p class="mb-3"> | |||||
| یا | |||||
| <router-link to="/otpLogin" class="link-primary"> | |||||
| ورود با کد یکبار مصرف | |||||
| </router-link> | |||||
| </p> | |||||
| <div class="mb-3"> | <div class="mb-3"> | ||||
| <input | <input | ||||
| @input="clearError('mobile')" | @input="clearError('mobile')" | ||||
| @@ -491,11 +491,11 @@ export default { | |||||
| const locale = ref('fa') | const locale = ref('fa') | ||||
| const handleSearch = async (searchTerm) => { | const handleSearch = async (searchTerm) => { | ||||
| if (searchTerm.length < 3) return; | |||||
| if (searchTerm?.length < 3) return; | |||||
| categorySelectorLoader.value = true; | categorySelectorLoader.value = true; | ||||
| try { | try { | ||||
| const response = await ApiServiece.get( | const response = await ApiServiece.get( | ||||
| `admin/categories?title=${searchTerm}` | |||||
| `admin/categories?title=${searchTerm ?? ''}` | |||||
| ); | ); | ||||
| cats.value = response.data.data; | cats.value = response.data.data; | ||||
| categorySelectorLoader.value = false; | categorySelectorLoader.value = false; | ||||
| @@ -516,19 +516,19 @@ export default { | |||||
| const formattedProducts = computed(() => | const formattedProducts = computed(() => | ||||
| Array.isArray(products.value) | Array.isArray(products.value) | ||||
| ? products.value.map((product) => ({ | |||||
| value: product.id, | |||||
| label: product.title, | |||||
| ? products.value?.map((product) => ({ | |||||
| value: product?.id, | |||||
| label: product?.translation?.title || 'بدون عنوان', | |||||
| })) | })) | ||||
| : [] | : [] | ||||
| ); | ); | ||||
| const handleProductSearch = async (searchTerm) => { | const handleProductSearch = async (searchTerm) => { | ||||
| if (searchTerm.length < 3) return; | |||||
| if (searchTerm?.length < 3) return; | |||||
| productSelectorLoader.value = true; | productSelectorLoader.value = true; | ||||
| try { | try { | ||||
| const response = await ApiServiece.get( | const response = await ApiServiece.get( | ||||
| `admin/products?title=${searchTerm}` | |||||
| `admin/products?title=${searchTerm ?? ''}` | |||||
| ); | ); | ||||
| products.value = response.data.data; | products.value = response.data.data; | ||||
| productSelectorLoader.value = false; | productSelectorLoader.value = false; | ||||
| @@ -572,11 +572,11 @@ export default { | |||||
| ); | ); | ||||
| const handleBrandSearch = async (searchTerm) => { | const handleBrandSearch = async (searchTerm) => { | ||||
| if (searchTerm.length < 3) return; | |||||
| if (searchTerm?.length < 3) return; | |||||
| brandSelectorLoader.value = true; | brandSelectorLoader.value = true; | ||||
| try { | try { | ||||
| const response = await ApiServiece.get( | const response = await ApiServiece.get( | ||||
| `admin/brands?title=${searchTerm}` | |||||
| `admin/brands?title=${searchTerm ?? ''}` | |||||
| ); | ); | ||||
| brands.value = response.data.data; | brands.value = response.data.data; | ||||
| brandSelectorLoader.value = false; | brandSelectorLoader.value = false; | ||||
| @@ -682,6 +682,12 @@ export default { | |||||
| onMounted(() => { | onMounted(() => { | ||||
| getBanner(); | getBanner(); | ||||
| handleProductSearch() | |||||
| handleSearch() | |||||
| handleBrandSearch() | |||||
| }); | }); | ||||
| const submitForm = () => { | const submitForm = () => { | ||||
| @@ -124,7 +124,7 @@ export default { | |||||
| }; | }; | ||||
| const deleteCat = (id, title) => { | const deleteCat = (id, title) => { | ||||
| Swal.fire({ | Swal.fire({ | ||||
| title: `می خواهید دسته ${title} را حذف کنید ؟`, | |||||
| title: `می خواهید دسته ${title ?? ''} را حذف کنید ؟`, | |||||
| icon: "warning", | icon: "warning", | ||||
| showCancelButton: true, | showCancelButton: true, | ||||
| confirmButtonColor: "#3085d6", | confirmButtonColor: "#3085d6", | ||||
| @@ -230,7 +230,7 @@ export default { | |||||
| <tr v-for="cat in cats" :key="cat.id"> | <tr v-for="cat in cats" :key="cat.id"> | ||||
| <td>{{ cat?.translation?.title }}</td> | <td>{{ cat?.translation?.title }}</td> | ||||
| <td>{{ convertToJalali(cat.created_at) }}</td> | |||||
| <td>{{ convertToJalali(cat?.created_at) }}</td> | |||||
| <td> | <td> | ||||
| <button | <button | ||||
| @@ -242,7 +242,7 @@ export default { | |||||
| ویرایش | ویرایش | ||||
| </button> | </button> | ||||
| <button | <button | ||||
| @click="deleteCat(cat.id, cat.title)" | |||||
| @click="deleteCat(cat.id, cat?.translation?.title)" | |||||
| class="btn btn-sm btn-outline-danger" | class="btn btn-sm btn-outline-danger" | ||||
| > | > | ||||
| حذف | حذف | ||||
| @@ -206,12 +206,12 @@ | |||||
| class="d-flex justify-content-between gap-2" | class="d-flex justify-content-between gap-2" | ||||
| style="margin-top: 20px" | style="margin-top: 20px" | ||||
| > | > | ||||
| <button | |||||
| class="btn btn-secondary" | |||||
| @click="step--" | |||||
| > | |||||
| قبلی | |||||
| </button> | |||||
| <!-- <button--> | |||||
| <!-- class="btn btn-secondary"--> | |||||
| <!-- @click="step--"--> | |||||
| <!-- >--> | |||||
| <!-- قبلی--> | |||||
| <!-- </button>--> | |||||
| <button type="submit" class="btn btn-primary" :disabled="loading"> | <button type="submit" class="btn btn-primary" :disabled="loading"> | ||||
| <span | <span | ||||
| @@ -272,6 +272,7 @@ export default { | |||||
| const step = ref(1) | const step = ref(1) | ||||
| const blogCategoryId = ref(null) | const blogCategoryId = ref(null) | ||||
| const locale = ref('fa') | const locale = ref('fa') | ||||
| const quillInstance = ref() | |||||
| const handleSearch = async (searchTerm) => { | const handleSearch = async (searchTerm) => { | ||||
| if (searchTerm.length < 3) return; | if (searchTerm.length < 3) return; | ||||
| @@ -371,11 +372,17 @@ export default { | |||||
| position: "top-right", | position: "top-right", | ||||
| autoClose: 1000, | autoClose: 1000, | ||||
| }); | }); | ||||
| title.value = "" | title.value = "" | ||||
| slug.value = "" | slug.value = "" | ||||
| summary.value = "" | summary.value = "" | ||||
| editorContent.value = "" | |||||
| quillInstance.value.root.innerHTML = "" | |||||
| author.value = "" | author.value = "" | ||||
| locale.value = "fa" | locale.value = "fa" | ||||
| }) | }) | ||||
| @@ -445,6 +452,8 @@ export default { | |||||
| }, | }, | ||||
| }); | }); | ||||
| quillInstance.value = quill | |||||
| quill.root.setAttribute("dir", "rtl"); | quill.root.setAttribute("dir", "rtl"); | ||||
| quill.format("direction", "rtl"); | quill.format("direction", "rtl"); | ||||
| @@ -487,7 +496,8 @@ export default { | |||||
| formattedCategories, | formattedCategories, | ||||
| handlerAddCategory, | handlerAddCategory, | ||||
| blogCategoryId, | blogCategoryId, | ||||
| locale | |||||
| locale, | |||||
| quillInstance | |||||
| }; | }; | ||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -437,6 +437,13 @@ export default { | |||||
| blog.value = updatedCategory; | blog.value = updatedCategory; | ||||
| // title.value = "" | |||||
| // slug.value = "" | |||||
| // quillInstance.value.root.innerHTML = "" | |||||
| // author.value = "" | |||||
| // summary.value = "" | |||||
| // locale.value = "fa" | |||||
| toast.success(resp?.data?.message, { | toast.success(resp?.data?.message, { | ||||
| position: "top-right", | position: "top-right", | ||||
| autoClose: 1000, | autoClose: 1000, | ||||
| @@ -480,7 +487,7 @@ export default { | |||||
| author.value = undefined; | author.value = undefined; | ||||
| quillInstance.value.root.innerHTML = undefined | |||||
| quillInstance.value.root.innerHTML = "" | |||||
| } | } | ||||
| } | } | ||||
| @@ -538,6 +545,12 @@ export default { | |||||
| blog.value = updatedCategory | blog.value = updatedCategory | ||||
| title.value = "" | |||||
| slug.value = "" | |||||
| summary.value = "" | |||||
| quillInstance.value.root.innerHTML = "" | |||||
| author.value = "" | |||||
| toast.success(message) | toast.success(message) | ||||
| } | } | ||||
| } catch (e) { | } catch (e) { | ||||
| @@ -45,6 +45,7 @@ export default { | |||||
| params: { | params: { | ||||
| paginate: paginate.value, | paginate: paginate.value, | ||||
| page: currentPage.value, | page: currentPage.value, | ||||
| title: searchQuery.value, | |||||
| } | } | ||||
| }) | }) | ||||
| @@ -256,31 +257,6 @@ export default { | |||||
| class="form-control form-control-sm d-inline-block me-2" | class="form-control form-control-sm d-inline-block me-2" | ||||
| style="width: 250px; border-radius: 15px" | style="width: 250px; border-radius: 15px" | ||||
| /> | /> | ||||
| <!-- User Role Selector --> | |||||
| <select | |||||
| class="form-select form-select-sm" | |||||
| v-model="selectedRole" | |||||
| style="width: 120px; border-radius: 15px" | |||||
| > | |||||
| <option value="" disabled selected>نقش کاربر</option> | |||||
| <option value="">همه</option> | |||||
| <option value="admin">فقط مدیران</option> | |||||
| <option value="client">فقط مشتریان</option> | |||||
| <option value="operator">فقط اپراتورها</option> | |||||
| </select> | |||||
| <select | |||||
| class="form-select form-select-sm" | |||||
| v-model="selectedStatus" | |||||
| style="width: 120px; border-radius: 15px" | |||||
| > | |||||
| <option value="" disabled selected>وضعیت</option> | |||||
| <option value="">همه</option> | |||||
| <option value="0">فعال</option> | |||||
| <option value="1">بلاک</option> | |||||
| </select> | |||||
| <!-- Add User Button --> | |||||
| </div> | </div> | ||||
| <button | <button | ||||
| v-if="userProfile?.role === 'admin'" | v-if="userProfile?.role === 'admin'" | ||||
| @@ -166,8 +166,8 @@ export default { | |||||
| const formattedCategories = computed(() => | const formattedCategories = computed(() => | ||||
| Array.isArray(categories.value) | Array.isArray(categories.value) | ||||
| ? categories.value.map((category) => ({ | ? categories.value.map((category) => ({ | ||||
| value: category.id, | |||||
| label: category.title, | |||||
| value: category?.id, | |||||
| label: category?.translation?.title || '', | |||||
| })) | })) | ||||
| : [] | : [] | ||||
| ); | ); | ||||
| @@ -181,7 +181,6 @@ export default { | |||||
| ); | ); | ||||
| products.value = response.data.data; | products.value = response.data.data; | ||||
| } catch (error) { | } catch (error) { | ||||
| console.error("Error fetching products:", error); | |||||
| products.value = []; | products.value = []; | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -189,8 +188,8 @@ export default { | |||||
| const formattedProducts = computed(() => | const formattedProducts = computed(() => | ||||
| Array.isArray(products.value) | Array.isArray(products.value) | ||||
| ? products.value.map((product) => ({ | ? products.value.map((product) => ({ | ||||
| value: product.id, | |||||
| label: product.title, | |||||
| value: product?.id, | |||||
| label: product?.translation?.title, | |||||
| })) | })) | ||||
| : [] | : [] | ||||
| ); | ); | ||||
| @@ -260,25 +260,16 @@ | |||||
| </BRow> | </BRow> | ||||
| <div class="d-flex justify-content-between align-items-center mt-4"> | <div class="d-flex justify-content-between align-items-center mt-4"> | ||||
| <div class="d-flex gap-3"> | |||||
| <button | |||||
| @click="step--" | |||||
| class="btn btn-outline btn-primary rounded-pill px-5 py-3" | |||||
| > | |||||
| مرحله قبل | |||||
| </button> | |||||
| <button | |||||
| @click="addImage" | |||||
| class="btn btn-primary rounded-pill px-5 py-3" | |||||
| style=" | |||||
| <button | |||||
| @click="addImage" | |||||
| class="btn btn-primary rounded-pill px-5 py-3" | |||||
| style=" | |||||
| font-size: 16px; | font-size: 16px; | ||||
| box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); | box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); | ||||
| " | " | ||||
| > | |||||
| <i class="fa fa-plus-circle me-2"></i> افزودن عکس جدید | |||||
| </button> | |||||
| </div> | |||||
| > | |||||
| <i class="fa fa-plus-circle me-2"></i> افزودن عکس جدید | |||||
| </button> | |||||
| <button | <button | ||||
| @click="step++" | @click="step++" | ||||
| @@ -296,7 +287,7 @@ | |||||
| @next-step="step++" | @next-step="step++" | ||||
| /> | /> | ||||
| <div class="d-flex justify-content-between"> | |||||
| <div class="d-flex justify-content-between mt-5"> | |||||
| <button class="btn btn-primary" @click="step--">مرحله قبلی</button> | <button class="btn btn-primary" @click="step--">مرحله قبلی</button> | ||||
| <button class="btn btn-primary" @click="step++">مرحله بعد</button> | <button class="btn btn-primary" @click="step++">مرحله بعد</button> | ||||
| </div> | </div> | ||||
| @@ -452,11 +443,11 @@ export default { | |||||
| }; | }; | ||||
| const handleBrandSearch = async (searchTerm) => { | const handleBrandSearch = async (searchTerm) => { | ||||
| if (searchTerm.length < 3) return; | |||||
| if (searchTerm?.length < 3) return; | |||||
| brandSelectorLoader.value = true; | brandSelectorLoader.value = true; | ||||
| try { | try { | ||||
| const response = await ApiServiece.get( | const response = await ApiServiece.get( | ||||
| `admin/brands?title=${searchTerm}` | |||||
| `admin/brands?title=${searchTerm ?? ''}` | |||||
| ); | ); | ||||
| brands.value = response.data.data; | brands.value = response.data.data; | ||||
| brandSelectorLoader.value = false; | brandSelectorLoader.value = false; | ||||
| @@ -661,6 +652,7 @@ export default { | |||||
| // }); | // }); | ||||
| //getAttrebuteValues(); | //getAttrebuteValues(); | ||||
| getAttributeValues(); | getAttributeValues(); | ||||
| handleBrandSearch(); | |||||
| }); | }); | ||||
| const submitForm = () => { | const submitForm = () => { | ||||
| @@ -284,10 +284,10 @@ | |||||
| <ProductInfo | <ProductInfo | ||||
| ref="productInfo" | ref="productInfo" | ||||
| :product-id="productId" | :product-id="productId" | ||||
| :product="product" | |||||
| @previousStep="step--" | @previousStep="step--" | ||||
| @changeLng="handleChangeLanguage" | @changeLng="handleChangeLanguage" | ||||
| @data="(data) => product = data" | @data="(data) => product = data" | ||||
| class="mt-5" | |||||
| /> | /> | ||||
| </BTab> | </BTab> | ||||
| </BTabs> | </BTabs> | ||||
| @@ -376,6 +376,7 @@ export default { | |||||
| const description = ref(null); | const description = ref(null); | ||||
| const step = ref(1); | const step = ref(1); | ||||
| const product = ref(null); | const product = ref(null); | ||||
| const loadingDelete = ref(false); | |||||
| const route = useRoute() | const route = useRoute() | ||||
| @@ -412,11 +413,11 @@ export default { | |||||
| }; | }; | ||||
| const handleBrandSearch = async (searchTerm) => { | const handleBrandSearch = async (searchTerm) => { | ||||
| if (searchTerm.length < 3) return; | |||||
| if (searchTerm?.length < 3) return; | |||||
| brandSelectorLoader.value = true; | brandSelectorLoader.value = true; | ||||
| try { | try { | ||||
| const response = await ApiServiece.get( | const response = await ApiServiece.get( | ||||
| `admin/brands?title=${searchTerm}` | |||||
| `admin/brands?title=${searchTerm ?? ''}` | |||||
| ); | ); | ||||
| brands.value = response.data.data; | brands.value = response.data.data; | ||||
| brandSelectorLoader.value = false; | brandSelectorLoader.value = false; | ||||
| @@ -719,7 +720,7 @@ export default { | |||||
| const handleChangeLanguage = (lang) => { | const handleChangeLanguage = (lang) => { | ||||
| const translation = product.value.translations?.find(item => item?.locale === lang); | const translation = product.value.translations?.find(item => item?.locale === lang); | ||||
| Object.assign(productInfo.value.form, { | |||||
| Object.assign(productInfo.value?.form, { | |||||
| id: translation?.id ?? undefined, | id: translation?.id ?? undefined, | ||||
| title: translation?.title ?? undefined, | title: translation?.title ?? undefined, | ||||
| slug: translation?.slug ?? undefined, | slug: translation?.slug ?? undefined, | ||||
| @@ -733,6 +734,7 @@ export default { | |||||
| getProduct() | getProduct() | ||||
| getAttributeValues(); | getAttributeValues(); | ||||
| handleSearch() | handleSearch() | ||||
| handleBrandSearch() | |||||
| }); | }); | ||||
| watch(categoryId, async (newCategoryId) => { | watch(categoryId, async (newCategoryId) => { | ||||
| @@ -744,8 +746,6 @@ export default { | |||||
| id: spec.id, | id: spec.id, | ||||
| })) | })) | ||||
| //attributesProductRef.value.selectedAttributes = product.value?.product_attributes?.map(item => item.attribute_id) | |||||
| const uniqueAttributes = product.value?.product_attributes?.filter( | const uniqueAttributes = product.value?.product_attributes?.filter( | ||||
| (item, index, self) => | (item, index, self) => | ||||
| index === self.findIndex(t => t.attribute_id === item.attribute_id) | index === self.findIndex(t => t.attribute_id === item.attribute_id) | ||||
| @@ -841,7 +841,8 @@ export default { | |||||
| handleChangeLanguage, | handleChangeLanguage, | ||||
| specificationsProductRef, | specificationsProductRef, | ||||
| loadingProduct, | loadingProduct, | ||||
| attributesProductRef | |||||
| attributesProductRef, | |||||
| loadingDelete | |||||
| }; | }; | ||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -57,20 +57,19 @@ export default { | |||||
| const getProducts = () => { | const getProducts = () => { | ||||
| filterLoading.value = true; | filterLoading.value = true; | ||||
| let isSpecial = 0; | |||||
| let isChosen = 0; | |||||
| let isSpecial; | |||||
| if (selectedProductType.value === "special") { | if (selectedProductType.value === "special") { | ||||
| isSpecial = 1; | isSpecial = 1; | ||||
| } | } | ||||
| if (selectedProductType.value === "chosen") { | if (selectedProductType.value === "chosen") { | ||||
| isChosen = 1; | |||||
| isSpecial = 2; | |||||
| } | } | ||||
| ApiServiece.get( | ApiServiece.get( | ||||
| `admin/products?title=${searchQuery.value || ""}&category_id=${ | `admin/products?title=${searchQuery.value || ""}&category_id=${ | ||||
| selectedcategory.value || "" | selectedcategory.value || "" | ||||
| }&brand_id=${ | }&brand_id=${ | ||||
| selectedBrand.value || "" | selectedBrand.value || "" | ||||
| }&is_chosen=${isChosen}&is_special=${isSpecial}&paginate=${ | |||||
| }&discount_type=${isSpecial || ''}&paginate=${ | |||||
| paginate.value || 10 | paginate.value || 10 | ||||
| }&page=${page.value || 1}` | }&page=${page.value || 1}` | ||||
| ) | ) | ||||
| @@ -232,8 +231,8 @@ export default { | |||||
| const formattedCategories = computed(() => | const formattedCategories = computed(() => | ||||
| Array.isArray(categories.value) | Array.isArray(categories.value) | ||||
| ? categories.value.map((category) => ({ | ? categories.value.map((category) => ({ | ||||
| value: category.id, | |||||
| label: category.title, | |||||
| value: category?.id, | |||||
| label: category?.translation?.title || "", | |||||
| })) | })) | ||||
| : [] | : [] | ||||
| ); | ); | ||||
| @@ -256,8 +255,8 @@ export default { | |||||
| const formattedBrands = computed(() => | const formattedBrands = computed(() => | ||||
| Array.isArray(brands.value) | Array.isArray(brands.value) | ||||
| ? brands.value.map((brand) => ({ | ? brands.value.map((brand) => ({ | ||||
| value: brand.id, | |||||
| label: brand.title, | |||||
| value: brand?.id, | |||||
| label: brand?.translation?.title || '', | |||||
| })) | })) | ||||
| : [] | : [] | ||||
| ); | ); | ||||
| @@ -270,7 +270,6 @@ export default { | |||||
| <option value="" disabled selected>نقش کاربر</option> | <option value="" disabled selected>نقش کاربر</option> | ||||
| <option value="">همه</option> | <option value="">همه</option> | ||||
| <option value="admin">فقط مدیران</option> | <option value="admin">فقط مدیران</option> | ||||
| <option value="client">فقط مشتریان</option> | |||||
| <option value="operator">فقط اپراتورها</option> | <option value="operator">فقط اپراتورها</option> | ||||
| </select> | </select> | ||||
| @@ -1,7 +1,7 @@ | |||||
| const { defineConfig } = require('@vue/cli-service') | const { defineConfig } = require('@vue/cli-service') | ||||
| module.exports = defineConfig({ | module.exports = defineConfig({ | ||||
| transpileDependencies: true, | transpileDependencies: true, | ||||
| publicPath: "/", | |||||
| publicPath: "/panel", | |||||
| chainWebpack: (config) => { | chainWebpack: (config) => { | ||||
| config.plugin('define').tap((definitions) => { | config.plugin('define').tap((definitions) => { | ||||
| Object.assign(definitions[0], { | Object.assign(definitions[0], { | ||||