| @@ -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="/favicon.svg"/><link rel="stylesheet" href="/fonts/vazir.css"/><script defer="defer" src="https://bazarce.liara.run/script.js" data-website-id="7baabdd5-3224-41c1-9267-d2a1abd29d01"></script><title>NovinPlast</title><script defer="defer" src="/js/chunk-vendors.b16869db.js"></script><script defer="defer" src="/js/app.fa8072f6.js"></script><link href="/css/chunk-vendors.fd1119e3.css" rel="stylesheet"><link href="/css/app.cbef7f68.css" rel="stylesheet"></head><body lang><noscript><strong>We're sorry but NovinPlast 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="/favicon.svg"/><link rel="stylesheet" href="/fonts/vazir.css"/><script defer="defer" src="https://bazarce.liara.run/script.js" data-website-id="7baabdd5-3224-41c1-9267-d2a1abd29d01"></script><title>NovinPlast</title><script defer="defer" src="/js/chunk-vendors.0a758772.js"></script><script defer="defer" src="/js/app.7f7271d2.js"></script><link href="/css/chunk-vendors.8ada15f4.css" rel="stylesheet"><link href="/css/app.fed18238.css" rel="stylesheet"></head><body lang><noscript><strong>We're sorry but NovinPlast 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"); | |||
| if (faviconUrl) { | |||
| const faviconLink = document.getElementById("favicon"); | |||
| @@ -375,7 +375,7 @@ export default { | |||
| </span> | |||
| <span class="pc-mtext">سفارشات</span> | |||
| <span class="pc-arrow"> | |||
| <ChevronDownIcon></ChevronDownIcon> | |||
| <ChevronDownIcon /> | |||
| </span> | |||
| </BLink> | |||
| <div class="collapse" id="collapse-orders"> | |||
| @@ -28,14 +28,10 @@ | |||
| <label class="form-label">نام</label> | |||
| <input | |||
| v-model="name" | |||
| @input="clearError('name')" | |||
| type="text" | |||
| class="form-control" | |||
| placeholder="نام را وارد نمایید" | |||
| /> | |||
| <small v-if="errors.name" class="text-danger">{{ | |||
| errors.name | |||
| }}</small> | |||
| </div> | |||
| </BCol> | |||
| @@ -158,7 +154,6 @@ export default { | |||
| const validateForm = () => { | |||
| errors.value = {}; | |||
| if (!name.value) errors.value.name = "وارد کردن نام ضروری می باشد"; | |||
| if (!mobile.value) errors.value.mobile = "وارد کردن موبایل ضروری می باشد"; | |||
| if (!role.value) errors.value.role = "انتخاب نقش ضروری می باشد"; | |||
| @@ -191,7 +186,8 @@ export default { | |||
| const formData = new FormData(); | |||
| formData.append("mobile", mobile.value); | |||
| formData.append("name", name.value); | |||
| if (name.value) | |||
| formData.append("name", name.value); | |||
| formData.append("role", role.value); | |||
| formData.append("password", password.value); | |||
| formData.append("password_confirmation", repeatPassword.value); | |||
| @@ -107,6 +107,9 @@ | |||
| class="form-control" | |||
| placeholder="انتخاب کنید" | |||
| > | |||
| <option :value="null"> | |||
| ندارد | |||
| </option> | |||
| <option | |||
| v-for="parent in localParents" | |||
| :key="parent.id" | |||
| @@ -100,6 +100,9 @@ | |||
| class="form-control" | |||
| placeholder="انتخاب کنید" | |||
| > | |||
| <option :value="null"> | |||
| ندارد | |||
| </option> | |||
| <option | |||
| v-for="parent in allLocalParents" | |||
| :key="parent.id" | |||
| @@ -26,14 +26,10 @@ | |||
| <label class="form-label">نام</label> | |||
| <input | |||
| v-model="localName" | |||
| @input="clearError('localName')" | |||
| type="text" | |||
| class="form-control" | |||
| placeholder="نام را وارد نمایید" | |||
| /> | |||
| <small v-if="errors.localName" class="text-danger">{{ | |||
| errors.localName | |||
| }}</small> | |||
| </div> | |||
| </BCol> | |||
| @@ -174,8 +170,6 @@ export default { | |||
| const validateForm = () => { | |||
| errors.value = {}; | |||
| if (!localName.value) | |||
| errors.value.localName = "وارد کردن نام ضروری می باشد"; | |||
| if (!localMobile.value) | |||
| errors.value.localMobile = "وارد کردن موبایل ضروری می باشد"; | |||
| if (!localRole.value) | |||
| @@ -202,7 +196,8 @@ export default { | |||
| const formData = new FormData(); | |||
| formData.append("mobile", localMobile.value); | |||
| formData.append("name", localName.value); | |||
| if (localName.value) | |||
| formData.append("name", localName.value); | |||
| formData.append("role", localRole.value); | |||
| if (password.value) { | |||
| formData.append("password", password.value); | |||
| @@ -49,9 +49,11 @@ | |||
| style="--vs-min-height: 48px; --vs-border-radius: 8px" | |||
| v-model="localCatId" | |||
| :options="formattedCategories" | |||
| :isLoading="categorySelectorLoader" | |||
| label="label" | |||
| :reduce="(option) => option.value" | |||
| placeholder="دسته ای را انتخاب کنید" | |||
| @search="handleSearch" | |||
| /> | |||
| </div> | |||
| <small v-if="errors.selectedCat" class="text-danger"> | |||
| @@ -104,8 +106,8 @@ export default { | |||
| type: String, | |||
| Required: true, | |||
| }, | |||
| catId: { | |||
| type: String, | |||
| cat: { | |||
| type: Object, | |||
| Required: true, | |||
| }, | |||
| id: { | |||
| @@ -123,14 +125,17 @@ export default { | |||
| setup(props, { emit }) { | |||
| const localCat = toRef(props.cats); | |||
| const localTitle = toRef(props.title); | |||
| const localCatId = toRef(props.catId); | |||
| const localCatId = toRef(props.cat); | |||
| const localId = toRef(props.id); | |||
| const errors = ref({}); | |||
| const loading = ref(false); | |||
| const categorySelectorLoader = ref(false); | |||
| watch( | |||
| () => props.cats, | |||
| (newVal) => (localCat.value = newVal) | |||
| (newVal) => { | |||
| localCat.value = newVal | |||
| } | |||
| ); | |||
| watch( | |||
| @@ -140,13 +145,32 @@ export default { | |||
| watch( | |||
| () => props.id, | |||
| (newVal) => (localId.value = newVal) | |||
| (newVal) => { | |||
| localId.value = newVal | |||
| } | |||
| ); | |||
| watch( | |||
| () => props.catId, | |||
| (newVal) => (localCatId.value = newVal) | |||
| ); | |||
| () => props.cat, | |||
| (newVal) => { | |||
| localCatId.value = newVal?.id; | |||
| localCat.value = [{ title: newVal?.title, id: newVal?.id }]; | |||
| },{ immediate: true }); | |||
| const handleSearch = async (searchTerm) => { | |||
| if (searchTerm?.length < 3) return; | |||
| categorySelectorLoader.value = true; | |||
| try { | |||
| const response = await ApiServiece.get( | |||
| `admin/categories?title=${searchTerm}` | |||
| ); | |||
| localCat.value = response.data.data; | |||
| categorySelectorLoader.value = false; | |||
| } catch (error) { | |||
| categorySelectorLoader.value = false; | |||
| localCat.value = []; | |||
| } | |||
| }; | |||
| const formattedCategories = computed(() => | |||
| Array.isArray(localCat.value) | |||
| @@ -218,6 +242,8 @@ export default { | |||
| localId, | |||
| localCatId, | |||
| formattedCategories, | |||
| categorySelectorLoader, | |||
| handleSearch, | |||
| }; | |||
| }, | |||
| }; | |||
| @@ -1,4 +1,5 @@ | |||
| import axios from "axios"; | |||
| import Swal from "sweetalert2"; | |||
| const url = process.env.VUE_APP_ROOT_URL; | |||
| const state = { | |||
| @@ -77,7 +78,6 @@ export const actions = { | |||
| ); | |||
| if (response.data.success) { | |||
| console.log(response.data.data); | |||
| const token = response.data.data.token; | |||
| const user = response.data.data.user; | |||
| @@ -91,14 +91,26 @@ export const actions = { | |||
| commit("SET_USER", user); | |||
| return response.data; | |||
| } else { | |||
| throw new Error("خطا در تایید کد"); | |||
| const errorMsg = response.data.message || "خطا در تایید کد"; | |||
| console.log(errorMsg, 'errorMsg') | |||
| throw new Error(errorMsg); | |||
| } | |||
| } catch (error) { | |||
| console.error( | |||
| "OTP verification failed:", | |||
| error.response?.data || error.message | |||
| // console.error( | |||
| // "OTP verification failed:", | |||
| // error.response?.data || error.message | |||
| // ); | |||
| Swal.fire({ | |||
| icon: "error", | |||
| title: "انگار چیزی اشتباه شد", | |||
| text: `${error?.response?.data?.message}`, | |||
| confirmButtonText: "باشه", | |||
| }); | |||
| throw new Error( | |||
| error.response?.data?.message || | |||
| "ورود با مشکل مواجه شد ...! لطفا دوباره امتحان کنید" | |||
| ); | |||
| throw new Error(error.response?.data?.msg || "خطا در تایید کد"); | |||
| } | |||
| }, | |||
| @@ -160,7 +172,7 @@ export const actions = { | |||
| if (response.data.success) { | |||
| console.log(response.data.message); | |||
| } else { | |||
| console.error("Logout failed: " + response.data.message); | |||
| } | |||
| @@ -84,12 +84,6 @@ export default { | |||
| router.push({ name: "products" }); | |||
| } catch (error) { | |||
| verifyOtpLoading.value = false; | |||
| Swal.fire({ | |||
| icon: "error", | |||
| title: "انگار چیزی اشتباه شد", | |||
| text: `${error.message}`, | |||
| confirmButtonText: "باشه", | |||
| }); | |||
| } | |||
| }; | |||
| @@ -227,10 +227,10 @@ | |||
| <option value="B">B-Banner</option> | |||
| <option value="C">C-Banner</option> | |||
| <option value="D">D-Banner</option> | |||
| <option value="F">E-Banner</option> | |||
| <option value="G">F-Banner</option> | |||
| <option value="H">G-Banner</option> | |||
| <option value="G">H-Banner</option> | |||
| <option value="E">E-Banner</option> | |||
| <option value="F">F-Banner</option> | |||
| <option value="G">G-Banner</option> | |||
| <option value="H">H-Banner</option> | |||
| <option value="I">I-Banner</option> | |||
| <option value="J">J-Banner</option> | |||
| </select> | |||
| @@ -305,12 +305,8 @@ | |||
| <option value="B">B-Banner</option> | |||
| <option value="C">C-Banner</option> | |||
| <option value="D">D-Banner</option> | |||
| <option value="F">E-Banner</option> | |||
| <option value="G">F-Banner</option> | |||
| <option value="H">G-Banner</option> | |||
| <option value="G">H-Banner</option> | |||
| <option value="I">I-Banner</option> | |||
| <option value="J">J-Banner</option> | |||
| <option value="E">E-Banner</option> | |||
| <option value="F">F-Banner</option> | |||
| </select> | |||
| </div> | |||
| <small v-if="errors.selectedLoc" class="text-danger"> | |||
| @@ -500,7 +496,7 @@ export default { | |||
| try { | |||
| const response = await ApiServiece.get( | |||
| `admin/categories?title=${searchTerm}` | |||
| `admin/categories/parents?title=${searchTerm}` | |||
| ); | |||
| categoryPages.value = response.data.data; | |||
| categoryPageSelectorLoader.value = false; | |||
| @@ -234,10 +234,10 @@ | |||
| <option value="B">B-Banner</option> | |||
| <option value="C">C-Banner</option> | |||
| <option value="D">D-Banner</option> | |||
| <option value="F">E-Banner</option> | |||
| <option value="G">F-Banner</option> | |||
| <option value="H">G-Banner</option> | |||
| <option value="G">H-Banner</option> | |||
| <option value="E">E-Banner</option> | |||
| <option value="F">F-Banner</option> | |||
| <option value="G">G-Banner</option> | |||
| <option value="H">H-Banner</option> | |||
| <option value="I">I-Banner</option> | |||
| <option value="J">J-Banner</option> | |||
| </select> | |||
| @@ -312,10 +312,10 @@ | |||
| <option value="B">B-Banner</option> | |||
| <option value="C">C-Banner</option> | |||
| <option value="D">D-Banner</option> | |||
| <option value="F">E-Banner</option> | |||
| <option value="G">F-Banner</option> | |||
| <option value="H">G-Banner</option> | |||
| <option value="G">H-Banner</option> | |||
| <option value="E">E-Banner</option> | |||
| <option value="F">F-Banner</option> | |||
| <option value="G">G-Banner</option> | |||
| <option value="H">H-Banner</option> | |||
| <option value="I">I-Banner</option> | |||
| <option value="J">J-Banner</option> | |||
| </select> | |||
| @@ -485,12 +485,14 @@ export default { | |||
| : [] | |||
| ); | |||
| console.log(formattedCatPages.value,'formattedCatPages') | |||
| const handleCategoryPageSearch = async (searchTerm) => { | |||
| if (searchTerm.length < 3) return; | |||
| categoryPageSelectorLoader.value = true; | |||
| try { | |||
| const response = await ApiServiece.get( | |||
| `admin/categories?title=${searchTerm}` | |||
| `admin/categories/parents?title=${searchTerm}` | |||
| ); | |||
| catPages.value = response.data.data; | |||
| categoryPageSelectorLoader.value = false; | |||
| @@ -260,8 +260,8 @@ export default { | |||
| ApiServiece.get(`admin/blogs/${route.params.id}`) | |||
| .then((resp) => { | |||
| blog.value = resp.data.data; | |||
| categories.value[0].id = blog.value.blog_category_id; | |||
| categories.value[0].title = "test"; | |||
| categories.value[0].id = blog.value?.blog_category_id; | |||
| categories.value[0].title = blog.value?.blog_category?.title; | |||
| title.value = blog.value.title; | |||
| slug.value = blog.value.slug; | |||
| @@ -2,13 +2,15 @@ | |||
| import Layout from "@/layout/custom.vue"; | |||
| import ApiServiece from "@/services/ApiService"; | |||
| import moment from "jalali-moment"; | |||
| import { onMounted, ref, watch, computed } from "vue"; | |||
| import {onMounted, ref, watch, computed, nextTick} from "vue"; | |||
| import { toast } from "vue3-toastify"; | |||
| import "vue3-toastify/dist/index.css"; | |||
| import Swal from "sweetalert2"; | |||
| import VueSelect from "vue3-select-component"; | |||
| import addIdentity from "@/components/modals/identity/addIdentity.vue"; | |||
| import editIdentity from "@/components/modals/identity/editIdentity.vue"; | |||
| import { Modal } from "bootstrap"; | |||
| export default { | |||
| name: "BORDER", | |||
| components: { | |||
| @@ -105,7 +107,6 @@ export default { | |||
| const getCategories = () => { | |||
| ApiServiece.get("admin/categories").then((resp) => { | |||
| console.log(resp.data.data); | |||
| cats.value = resp.data.data; | |||
| }); | |||
| }; | |||
| @@ -204,14 +205,19 @@ export default { | |||
| }; | |||
| const editModalData = (id, title, cat) => { | |||
| attributeId.value = id; | |||
| attributeTitle.value = title; | |||
| attrebuteCat.value = cat; | |||
| nextTick(()=> { | |||
| attributeId.value = id; | |||
| attributeTitle.value = title; | |||
| attrebuteCat.value = cat; | |||
| }) | |||
| const modal = new Modal(document.getElementById('editIdentity')); | |||
| modal?.show(); | |||
| }; | |||
| onMounted(() => { | |||
| getAttributes(); | |||
| getCategories(); | |||
| //getCategories(); | |||
| }); | |||
| return { | |||
| attributes, | |||
| @@ -313,11 +319,9 @@ export default { | |||
| editModalData( | |||
| attribute?.id, | |||
| attribute?.title, | |||
| attribute.category_id | |||
| attribute?.category, | |||
| ) | |||
| " | |||
| data-bs-toggle="modal" | |||
| data-bs-target="#editIdentity" | |||
| class="btn btn-sm btn-outline-warning me-1" | |||
| > | |||
| ویرایش | |||
| @@ -345,7 +349,7 @@ export default { | |||
| <editIdentity | |||
| @identity-updated="handleAttributeUpdated()" | |||
| :title="attributeTitle" | |||
| :catId="attrebuteCat" | |||
| :cat="attrebuteCat" | |||
| :id="attributeId" | |||
| :cats="cats" | |||
| /> | |||
| @@ -370,7 +370,7 @@ export default { | |||
| <tbody> | |||
| <tr v-for="order in orders" :key="order?.id"> | |||
| <!-- Product Details --> | |||
| <td class="text-start"> | |||
| <td class="text-start" style="max-width: 200px; white-space: normal !important;"> | |||
| <div class="d-flex align-items-center gap-3"> | |||
| <img | |||
| :src="order?.product?.image" | |||
| @@ -329,7 +329,7 @@ export default { | |||
| </span> | |||
| </td> | |||
| <td>{{ order?.total_price || "" }}</td> | |||
| <td>{{ Number(order?.total_price).toLocaleString() || "" }}</td> | |||
| <td>{{ order?.user?.mobile || "مهمان" }}</td> | |||
| <td>{{ order?.tracking_code || "" }}</td> | |||
| @@ -4,6 +4,7 @@ import Layout from "@/layout/custom.vue"; | |||
| import ApiServiece from "@/services/ApiService"; | |||
| import { useRoute } from "vue-router"; | |||
| import { onMounted, ref } from "vue"; | |||
| import moment from "jalali-moment"; | |||
| export default { | |||
| name: "OrderDetails", | |||
| @@ -43,7 +44,9 @@ export default { | |||
| }; | |||
| const formatDate = (date) => { | |||
| return new Date(date).toLocaleDateString("fa-IR"); | |||
| return moment(date,"YYYY-MM-DD HH:mm:ss") | |||
| .locale("fa") | |||
| .format("HH:mm:ss YYYY/MM/DD"); | |||
| }; | |||
| const getOrder = () => { | |||
| @@ -187,7 +190,7 @@ export default { | |||
| </BCol> | |||
| <BCol md="6"> | |||
| <strong class="me-2">رنگ سفارش:</strong> | |||
| <strong class="me-2">وضعیت سفارش:</strong> | |||
| <span>{{ order?.status || "-" }}</span> | |||
| </BCol> | |||
| </BRow> | |||
| @@ -195,7 +198,7 @@ export default { | |||
| <BRow class="mb-3"> | |||
| <BCol md="6"> | |||
| <strong class="me-2">قیمت کل:</strong> | |||
| <span>{{ order?.total_price ? order?.total_price + 'تومان' : '0' }}</span> | |||
| <span>{{ order?.total_price ? Number(order?.total_price).toLocaleString() + 'تومان' : '0' }}</span> | |||
| </BCol> | |||
| </BRow> | |||
| @@ -215,6 +218,7 @@ export default { | |||
| { key: 'color', label: 'رنگ محصول' }, | |||
| { key: 'count', label: 'تعداد در خواستی ' }, | |||
| { key: 'price', label: 'قیمت' }, | |||
| { key: 'discount', label: 'مبلغ تخفیف' }, | |||
| { key: 'created_at', label: 'تاریخ ثبت' }, | |||
| { key: 'edit_count', label: 'تعداد فرستاده شده' }, | |||
| { key: 'description', label: 'یادداشت' }, | |||
| @@ -223,11 +227,14 @@ export default { | |||
| > | |||
| <!-- Price formatting --> | |||
| <template #cell(price)="data"> | |||
| {{ formatPrice(data.item.price) }} تومان | |||
| {{ formatPrice(data?.item?.product?.retail_price) }} تومان | |||
| </template> | |||
| <template #cell(discount)="data"> | |||
| {{ formatPrice(data?.item?.price) }} تومان | |||
| </template> | |||
| <template #cell(title)="data"> | |||
| {{ data.item?.product?.title }} | |||
| {{ data?.item?.product?.title }} | |||
| </template> | |||
| <!-- Created Date formatting --> | |||
| @@ -238,11 +238,11 @@ | |||
| <BCol v-if="spescial == 1" md="6"> | |||
| <div class="form-group"> | |||
| <label class="form-label"> تخفیف ویژه درصد</label> | |||
| <label class="form-label">درصد تخفیف ویژه</label> | |||
| <input | |||
| type="number" | |||
| class="form-control" | |||
| placeholder="قیمت" | |||
| placeholder="درصد" | |||
| :class="{ 'is-invalid': errors.spescialPrice }" | |||
| @input="clearError('spescialPrice')" | |||
| v-model="spescialPrice" | |||
| @@ -231,11 +231,11 @@ | |||
| <BCol v-if="spescial == 1" md="6"> | |||
| <div class="form-group"> | |||
| <label class="form-label"> تخفیف ویژه درصد </label> | |||
| <label class="form-label"> درصد تخفیف ویژه</label> | |||
| <input | |||
| type="number" | |||
| class="form-control" | |||
| placeholder="قیمت" | |||
| placeholder="درصد" | |||
| :class="{ 'is-invalid': errors.spescialPrice }" | |||
| @input="clearError('spescialPrice')" | |||
| v-model="spescialPrice" | |||
| @@ -812,7 +812,6 @@ | |||
| <script> | |||
| import VueSelect from "vue3-select-component"; | |||
| import Quill from "quill"; | |||
| import "quill/dist/quill.snow.css"; | |||
| import Swal from "sweetalert2"; | |||
| import { useRoute } from "vue-router"; | |||
| @@ -846,7 +845,6 @@ export default { | |||
| attribute_value_id: null, | |||
| }, | |||
| ]); | |||
| const quillInstance = ref(null); | |||
| const localIdentities = ref([]); | |||
| const countInCarton = ref(); | |||