瀏覽代碼

admin panel updates

master
unknown 9 月之前
父節點
當前提交
b7dcc1506d
共有 23 個文件被更改,包括 1137 次插入478 次删除
  1. +1
    -1
      dist/index.html
  2. +26
    -12
      src/views/live-preview/pages/attributes/attributes.vue
  3. +123
    -65
      src/views/live-preview/pages/banners/addBanner.vue
  4. +26
    -11
      src/views/live-preview/pages/banners/banners.vue
  5. +6
    -6
      src/views/live-preview/pages/banners/editBanner.vue
  6. +26
    -11
      src/views/live-preview/pages/blogCats/blogCat.vue
  7. +89
    -79
      src/views/live-preview/pages/blogs/blogs.vue
  8. +24
    -18
      src/views/live-preview/pages/blogs/editBlog.vue
  9. +33
    -22
      src/views/live-preview/pages/brands/brands.vue
  10. +25
    -17
      src/views/live-preview/pages/calls/calls.vue
  11. +30
    -11
      src/views/live-preview/pages/catrgories/cats.vue
  12. +29
    -12
      src/views/live-preview/pages/comments/comments.vue
  13. +1
    -2
      src/views/live-preview/pages/discounts/addDiscount.vue
  14. +26
    -11
      src/views/live-preview/pages/discounts/discounts.vue
  15. +28
    -11
      src/views/live-preview/pages/faqs/faqs.vue
  16. +26
    -11
      src/views/live-preview/pages/identity/idenities.vue
  17. +384
    -88
      src/views/live-preview/pages/orders/approvedOrders.vue
  18. +76
    -16
      src/views/live-preview/pages/orders/orders.vue
  19. +56
    -41
      src/views/live-preview/pages/orders/singleOrder.vue
  20. +40
    -4
      src/views/live-preview/pages/products/editProduct.vue
  21. +26
    -12
      src/views/live-preview/pages/products/products.vue
  22. +9
    -5
      src/views/live-preview/pages/settings/setting.vue
  23. +27
    -12
      src/views/live-preview/pages/users/users.vue

+ 1
- 1
dist/index.html 查看文件

@@ -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.ae561124.js"></script><script defer="defer" src="/js/app.2907bfa5.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.1ba8209a.js"></script><script defer="defer" src="/js/app.3f68cdfe.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 () {
const faviconUrl = localStorage.getItem("logo");
if (faviconUrl) {
const faviconLink = document.getElementById("favicon");


+ 26
- 12
src/views/live-preview/pages/attributes/attributes.vue 查看文件

@@ -107,8 +107,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -116,7 +123,6 @@ export default {
}
return pages;
});

watch(page, () => {
getAttributes();
});
@@ -298,17 +304,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -324,23 +337,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 123
- 65
src/views/live-preview/pages/banners/addBanner.vue 查看文件

@@ -112,18 +112,16 @@
<BCol v-if="pageType === 'category' && pannel === 'web'" md="6">
<div class="form-group">
<label class="form-label">صفحه دسته</label>
<select

<VueSelect
style="--vs-min-height: 48px; --vs-border-radius: 8px"
v-model="selectedCatPage"
class="form-select"
:class="{ 'is-invalid': errors.selectedCatPage }"
aria-label="Default select example"
:isLoading="categoryPageSelectorLoader"
:options="formattedCategoriesPages"
@change="clearError('selectedCatPage')"
placeholder="انتخاب صفحه دسته"
>
<option :value="cat.id" v-for="cat in cats" :key="cat.id">
{{ cat.title }}
</option>
</select>
placeholder="دسته ای را انتخاب کنید"
@search="handleCategoryPageSearch"
/>
</div>
<small v-if="errors.selectedCatPage" class="text-danger">
{{ errors.selectedCatPage }}
@@ -133,22 +131,16 @@
<BCol v-if="pageType === 'brand' && pannel === 'web'" md="6">
<div class="form-group">
<label class="form-label">صفحه برند</label>
<select

<VueSelect
style="--vs-min-height: 48px; --vs-border-radius: 8px"
v-model="selectedBrandPage"
class="form-select"
:class="{ 'is-invalid': errors.selectedBrandPage }"
aria-label="Default select example"
@change="clearError('selectedBrandPage')"
placeholder="انتخاب صفحه برند ها"
>
<option
:value="brand.id"
v-for="brand in brands"
:key="brand.id"
>
{{ brand.title }}
</option>
</select>
:isLoading="brandSelectorLoader"
:options="formattedBrands"
@change="clearError(`selectedBrandPage`)"
placeholder="برندی را انتخاب کنید"
@search="handleBrandSearch"
/>
</div>
<small v-if="errors.selectedBrandPage" class="text-danger">
{{ errors.selectedBrandPage }}
@@ -190,6 +182,8 @@
margin-top: 7px;
"
v-model="selectedLandingProduct"
:isLoading="productSelectorLoader"
@change="clearError(`selectedLandingProduct`)"
:options="formattedProducts"
placeholder="محصولی را انتخاب کنید"
@search="handleSearch"
@@ -202,18 +196,16 @@
<BCol v-if="landingType === 'cat'" md="6">
<div class="form-group">
<label class="form-label">صفحه کدام دسته</label>
<select
class="form-select"
aria-label="Default select example"
<VueSelect
style="--vs-min-height: 48px; --vs-border-radius: 8px"
v-model="selectedLandingCat"
@change="clearError('selectedLandingCat')"
:class="{ 'is-invalid': errors.selectedLandingCat }"
placeholder="انتخاب صفحه دسته"
>
<option :value="cat.id" v-for="cat in cats" :key="cat.id">
{{ cat.title }}
</option>
</select>
:isLoading="categorySelectorLoader"
:options="formattedCategories"
placeholder="دسته ای را انتخاب کنید"
@search="handleCategorySearch"
/>
</div>
<small v-if="errors.selectedLandingCat" class="text-danger">
{{ errors.selectedLandingCat }}
@@ -386,7 +378,7 @@ import mainPageBanner from "@/components/modals/helperModals/mainPageBanner.vue"
import { toast } from "vue3-toastify";
import "vue3-toastify/dist/index.css";
import ApiServiece from "@/services/ApiService";
import { ref, onMounted, computed } from "vue";
import { ref, computed } from "vue";
import Layout from "@/layout/custom.vue";

export default {
@@ -402,6 +394,7 @@ export default {
const pageType = ref();
const products = ref([]);
const cats = ref([]);
const categoryPages = ref([]);
const brands = ref([]);
const landingType = ref();
const selectedCatPage = ref();
@@ -412,33 +405,16 @@ export default {
const pannel = ref();
const image = ref();
const imagePreview = ref();

const productSelectorLoader = ref(false);
const categorySelectorLoader = ref(false);
const categoryPageSelectorLoader = ref(false);
const brandSelectorLoader = ref(false);
const loading = ref(false);
const errors = ref({});

const getCats = () => {
ApiServiece.get(`admin/categories`)
.then((resp) => {
cats.value = resp.data.data;
})
.catch((err) => {
console.log(err);
});
};

const getBrands = () => {
ApiServiece.get(`admin/brands`)
.then((resp) => {
brands.value = resp.data.data;
console.log(brands.value, "brands");
})
.catch((err) => {
console.log(err);
});
};

const handleSearch = async (searchTerm) => {
if (searchTerm.length < 3) return;
productSelectorLoader.value = true;

try {
const response = await ApiServiece.get(
@@ -446,9 +422,35 @@ export default {
);
products.value = response.data.data;
console.log(products.value, "products");
productSelectorLoader.value = false;
} catch (error) {
products.value = [];
productSelectorLoader.value = false;
}
};

const formattedBrands = computed(() =>
Array.isArray(brands.value) // ✅ Check if products.value is an array
? brands.value.map((brand) => ({
value: brand.id,
label: brand.title,
}))
: []
);

const handleBrandSearch = async (searchTerm) => {
if (searchTerm.length < 3) return;
brandSelectorLoader.value = true;

try {
const response = await ApiServiece.get(
`admin/brands?title=${searchTerm}`
);
brands.value = response.data.data;
brandSelectorLoader.value = false;
} catch (error) {
console.error("Error fetching products:", error);
products.value = []; // ✅ Reset to an empty array on error
brands.value = [];
brandSelectorLoader.value = false;
}
};

@@ -461,6 +463,56 @@ export default {
: []
);

const handleCategorySearch = async (searchTerm) => {
if (searchTerm.length < 3) return;
categorySelectorLoader.value = true;

try {
const response = await ApiServiece.get(
`admin/categories?title=${searchTerm}`
);
cats.value = response.data.data;
categorySelectorLoader.value = false;
} catch (error) {
cats.value = [];
categorySelectorLoader.value = false;
}
};

const formattedCategories = computed(() =>
Array.isArray(cats.value)
? cats.value.map((cat) => ({
value: cat.id,
label: cat.title,
}))
: []
);

const handleCategoryPageSearch = async (searchTerm) => {
if (searchTerm.length < 3) return;
categoryPageSelectorLoader.value = true;

try {
const response = await ApiServiece.get(
`admin/categories?title=${searchTerm}`
);
categoryPages.value = response.data.data;
categoryPageSelectorLoader.value = false;
} catch (error) {
categoryPages.value = [];
categoryPageSelectorLoader.value = false;
}
};

const formattedCategoriesPages = computed(() =>
Array.isArray(categoryPages.value)
? categoryPages.value.map((categoryPage) => ({
value: categoryPage.id,
label: categoryPage.title,
}))
: []
);

const handleImageUpload = (event) => {
const file = event.target.files[0];

@@ -515,11 +567,6 @@ export default {
errors.value[field] = "";
};

onMounted(() => {
getCats();
getBrands();
});

const submitForm = () => {
console.log(errors.value);
if (!validateForm()) {
@@ -613,6 +660,7 @@ export default {
pageType.value = "";
landingType.value = "";
image.value = null;
imagePreview.value = null;
loading.value = false;
};
return {
@@ -637,6 +685,16 @@ export default {
loading,
brands,
handleSearch,
productSelectorLoader,
handleCategorySearch,
categorySelectorLoader,
formattedCategories,
handleCategoryPageSearch,
formattedCategoriesPages,
categoryPageSelectorLoader,
brandSelectorLoader,
formattedBrands,
handleBrandSearch,
};
},
};


+ 26
- 11
src/views/live-preview/pages/banners/banners.vue 查看文件

@@ -78,8 +78,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -363,17 +370,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -389,23 +403,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 6
- 6
src/views/live-preview/pages/banners/editBanner.vue 查看文件

@@ -495,14 +495,15 @@ export default {
selectedLandingCat.value = data?.category_id;
selectedLandingProduct.value = data?.product_id;
pageType.value = data.page_type;
if (data.page_id) {
pageType.value = "category";
if (data.page_id && pageType.value === 'category') {
selectedCatPage.value = data?.page_id;
console.log(data);
}
if (!data.page_id) {
pageType.value = "main_page ";


if (data.page_id && pageType.value === 'barnd') {
selectedBrandPage.value = data?.page_id;
}

if (selectedLandingProduct.value) {
landingType.value = "product";
@@ -510,7 +511,6 @@ export default {

if (selectedLandingCat.value) {
landingType.value = "cat";
console.log("Asd");
}

if (!selectedCatPage.value && !selectedLandingProduct.value) {


+ 26
- 11
src/views/live-preview/pages/blogCats/blogCat.vue 查看文件

@@ -75,8 +75,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -268,17 +275,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -294,23 +308,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 89
- 79
src/views/live-preview/pages/blogs/blogs.vue 查看文件

@@ -75,8 +75,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -84,7 +91,6 @@ export default {
}
return pages;
});

const deleteBlog = (id, title) => {
Swal.fire({
text: `می خواهید بلاگ ${title} را حذف کنید؟`,
@@ -127,8 +133,6 @@ export default {
}
}


watch(page, () => {
getBlogs();
});
@@ -175,7 +179,7 @@ export default {
<div class="col-md-12">
<div class="card shadow-sm border-0 rounded">
<div
class="card-header d-flex justify-content-between align-items-center p-3 "
class="card-header d-flex justify-content-between align-items-center p-3"
dir="rtl"
>
<div class="d-flex align-items-center">
@@ -186,14 +190,13 @@ export default {
class="form-control form-control-sm d-inline-block me-2"
style="width: 250px; border-radius: 15px"
/>
</div>
<router-link
to="/addBlog"
class="btn btn-light text-primary btn-sm px-3"
>
افزودن بلاگ
</router-link>
<router-link
to="/addBlog"
class="btn btn-light text-primary btn-sm px-3"
>
افزودن بلاگ
</router-link>
</div>
<div v-if="!filterLoading" class="card-body table-border-style p-0">
<div class="table-responsive">
@@ -247,77 +250,84 @@ export default {
</div>
</BRow>
<BRow>
<BCol sm="12">
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>
<BCol sm="12">
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<span class="page-link">...</span>
</li>
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<li
v-for="n in visiblePages"
:key="n"
class="page-item"
:class="{ active: currentPage === n }"
<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
class="page-item"
:class="{ active: currentPage === n }"
>
<a
class="page-link"
href="javascript:void(0)"
@click="page = n"
>
<a
class="page-link"
href="javascript:void(0)"
@click="page = n"
>
{{ n }}
</a>
</li>
{{ n }}
</a>
</li>

<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
</li>
<!-- Trailing dots and last page -->
<li
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"
>
<span class="page-link" @click="nextPage">بعدی</span>
</li>
</ul>
</nav>
</div>
</BCol>
<BCol sm="4">
<div class="ms-0 search-number">
<input
v-model="searchPage"
type="text"
class="form-control"
placeholder="برو به صفحه"
:max="totalPages"
min="1"
@input="handlePageInput"
/>
</div>
</BCol>
<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"
>
<span class="page-link" @click="nextPage">بعدی</span>
</li>
</ul>
</nav>
</div>
</BCol>
<BCol sm="4">
<div class="ms-0 search-number">
<input
v-model="searchPage"
type="text"
class="form-control"
placeholder="برو به صفحه"
:max="totalPages"
min="1"
@input="handlePageInput"
/>
</div>
</BCol>
</BRow>
</Layout>
</template>


+ 24
- 18
src/views/live-preview/pages/blogs/editBlog.vue 查看文件

@@ -175,6 +175,7 @@ export default {
VueSelect,
},
setup() {
const quillInstance = ref(null);
const blog = ref();
const route = useRoute();
const loading = ref(false);
@@ -270,24 +271,29 @@ export default {
blogCat.value = blog.value.blog_category_id;
author.value = blog.value.author;
if (editor.value) {
const quill = new Quill(editor.value, {
theme: "snow",
modules: {
toolbar: [
[{ header: "1" }, { header: "2" }, { font: [] }],
[{ list: "ordered" }, { list: "bullet" }],
[{ align: [] }],
["bold", "italic", "underline"],
["link", "image"],
[{ script: "sub" }, { script: "super" }],
[{ direction: "rtl" }],
],
},
});

quill.root.innerHTML = blog.value.content;
editorContent.value = quill.root.innerHTML;
}
quillInstance.value = new Quill(editor.value, {
theme: "snow",
modules: {
toolbar: [
[{ header: "1" }, { header: "2" }, { font: [] }],
[{ list: "ordered" }, { list: "bullet" }],
[{ align: [] }],
["bold", "italic", "underline"],
["link", "image"],
[{ script: "sub" }, { script: "super" }],
[{ direction: "rtl" }],
],
},
});

quillInstance.value.root.innerHTML = blog.value.content;
editorContent.value = blog.value.content;

// ✨ Update content on change
quillInstance.value.on("text-change", () => {
editorContent.value = quillInstance.value.root.innerHTML;
});
}
})
.catch((err) => {
console.log(err);


+ 33
- 22
src/views/live-preview/pages/brands/brands.vue 查看文件

@@ -37,7 +37,6 @@ export default {
.format("YYYY/MM/DD");
};


const handleSearchChange = () => {
clearTimeout(searchTimeout);

@@ -50,7 +49,7 @@ export default {
watch(searchQuery, () => {
handleSearchChange();
});
const getBrands = () => {
filterLoading.value = true;
ApiServiece.get(
@@ -153,8 +152,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -163,8 +169,6 @@ export default {
return pages;
});


onMounted(() => {
getBrands();
});
@@ -211,15 +215,14 @@ export default {
class="form-control form-control-sm d-inline-block me-2"
style="width: 250px; border-radius: 15px"
/>
</div>
<button
data-bs-toggle="modal"
data-bs-target="#addBrand"
class="btn btn-light text-primary btn-sm px-3"
>
افزودن برند
</button>
data-bs-toggle="modal"
data-bs-target="#addBrand"
class="btn btn-light text-primary btn-sm px-3"
>
افزودن برند
</button>
</div>
<div v-if="!filterLoading" class="card-body table-border-style p-0">
<div class="table-responsive">
@@ -309,17 +312,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -335,23 +345,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 25
- 17
src/views/live-preview/pages/calls/calls.vue 查看文件

@@ -61,8 +61,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -259,10 +266,7 @@ export default {
></i>
</td>
<td>{{ call?.subject }}</td>
<td
class="text-center"
style=" background: transparent"
>
<td class="text-center" style="background: transparent">
{{ call.text }}
</td>
<td>
@@ -342,15 +346,19 @@ export default {
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<!-- Page numbers with dots logic -->
<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Page numbers -->
<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -366,21 +374,21 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->


+ 30
- 11
src/views/live-preview/pages/catrgories/cats.vue 查看文件

@@ -69,8 +69,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -91,6 +98,10 @@ export default {
}
}

watch(page, () => {
getCats();
});

const nextPage = () => {
if (currentPage.value < totalPages.value) {
page.value++;
@@ -356,17 +367,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -382,23 +400,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 29
- 12
src/views/live-preview/pages/comments/comments.vue 查看文件

@@ -127,8 +127,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -289,7 +296,7 @@ export default {
handleProductsSearch,
selectedProduct,
productSeletorLoader,
blogSelectorLoader
blogSelectorLoader,
};
},
};
@@ -498,15 +505,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>
<li v-if="currentPage > 2" class="page-item" @click="page = 1">

<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -522,23 +538,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 1
- 2
src/views/live-preview/pages/discounts/addDiscount.vue 查看文件

@@ -308,8 +308,7 @@ export default {
errors.value.selectedCat = "انتخاب دسته برای تخفیف الزامی می باشد";
if (!selectedProduct.value && whichPart.value === "product")
errors.value.selectedProduct = "انتخاب محصول برای تخفیف الزامی می باشد";
if (!startDate.value)
errors.value.startDate = "انتخاب تاریخ اعمال تخفیف الزامی می باشد ";

if (!whichPart.value)
errors.value.whichPart = "مشخص کنید تخفیف بر چه بخشی اعمال شود";


+ 26
- 11
src/views/live-preview/pages/discounts/discounts.vue 查看文件

@@ -86,8 +86,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -387,17 +394,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -413,23 +427,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 28
- 11
src/views/live-preview/pages/faqs/faqs.vue 查看文件

@@ -69,8 +69,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -276,15 +283,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>
<li v-if="currentPage > 2" class="page-item" @click="page = 1">

<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -300,23 +316,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 26
- 11
src/views/live-preview/pages/identity/idenities.vue 查看文件

@@ -150,8 +150,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -348,17 +355,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -374,23 +388,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 384
- 88
src/views/live-preview/pages/orders/approvedOrders.vue 查看文件

@@ -4,15 +4,21 @@ import ApiServiece from "@/services/ApiService";
import { onMounted, ref, watch, computed } from "vue";
import DatePicker from "vue3-persian-datetime-picker";
import VueSelect from "vue3-select-component";
import showDescription from "@/components/modals/commonModals/showDescription.vue";
import moment from "jalali-moment";
import { toast } from "vue3-toastify";
import "vue3-toastify/dist/index.css";
import Swal from "sweetalert2";
export default {
name: "PRODUCT-LIST",
components: {
Layout,
VueSelect,
DatePicker,
showDescription,
},
setup() {
const productDescription = ref("");
const selectorLoader = ref(false);
const isLoading = ref(false);
const date = ref([]);
@@ -24,8 +30,46 @@ export default {
const page = ref(1);
const filterLoading = ref(false);
const selectedBrand = ref();
const allProducts = ref([]);
const getAllProducts = () => {
const orders = ref([]);
const changeStatus = (id, status) => {
Swal.fire({
text: `آیا می خواهید وضعیت سبد خرید را به ${getStatusLabel(
status
)} تغییر دهید؟ `,
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "بله!",
cancelButtonText: "خیر",
}).then((result) => {
if (result.isConfirmed) {
const formData = new FormData();
formData.append("status", status);
ApiServiece.put(`admin/orders/${id}`, formData)
.then(() => {
toast.success("تغییر وضعیت سبد خرید با موفقیت انجام شد", {
position: "top-right",
autoClose: 3000,
});
})
.then(() => {
getAllOrders();
})
.catch((err) => {
console.log(err);
toast.error("!مشکلی در تغییر وضعیت سبد خرید پیش آمد", {
position: "top-right",
autoClose: 3000,
});
});
}
});
};
const descriptionModal = (desc) => {
productDescription.value = desc;
};
const getAllOrders = () => {
if (date.value[0]) {
date.value[0] = moment(date.value[0], "YYYY-MM-DD HH:mm:ss").format(
"YYYY/MM/DD HH:mm:ss"
@@ -48,7 +92,7 @@ export default {
)
.then((resp) => {
filterLoading.value = false;
allProducts.value = resp.data.data.data;
orders.value = resp.data.data.data;

currentPage.value = resp.data.data.current_page;
totalPages.value = resp.data.data.last_page;
@@ -64,6 +108,38 @@ export default {
.format("jYYYY/jMM/jDD HH:mm:ss");
};

const getStatusLabel = (status) => {
const statusLabels = {
waiting: "در انتظار",
paid: "پرداخت‌شده",
un_paid: "پرداخت‌نشده",
approved: "تأیید‌شده",
processing: "در حال پردازش",
shipping: "در حال ارسال",
delivered: "تحویل‌شده",
canceled: "لغو‌شده",
in_cart: "در سبد خرید",
done: "کامل شده",
};
return statusLabels[status] || "نامشخص";
};

const getStatusClass = (status) => {
const statusClasses = {
waiting: "badge-waiting",
paid: "badge-paid",
un_paid: "badge-un_paid",
approved: "badge-approved",
processing: "badge-processing",
shipping: "badge-shipping",
delivered: "badge-delivered",
canceled: "badge-canceled",
in_cart: "badge-in-cart",
done: "badge-in-done",
};
return statusClasses[status] || "badge-secondary";
};

const getFile = () => {
isLoading.value = true;
ApiServiece.post(
@@ -94,7 +170,7 @@ export default {
};

watch(selectedBrand, () => {
getAllProducts();
getAllOrders();
page.value = 1;
});

@@ -108,8 +184,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -131,28 +214,28 @@ export default {
}

watch(selectedBrand, () => {
getAllProducts();
getAllOrders();
});

watch(date, () => {
getAllProducts();
getAllOrders();
});

watch(page, () => {
getAllProducts();
getAllOrders();
});

const nextPage = () => {
if (currentPage.value < totalPages.value) {
page.value++;
getAllProducts();
getAllOrders();
}
};

const prevPage = () => {
if (currentPage.value > 1) {
page.value--;
getAllProducts();
getAllOrders();
}
};

@@ -185,10 +268,10 @@ export default {
);

onMounted(() => {
getAllProducts();
getAllOrders();
});
return {
allProducts,
orders,
visiblePages,
nextPage,
prevPage,
@@ -208,6 +291,11 @@ export default {
handleBrandSearch,
filterLoading,
selectorLoader,
productDescription,
descriptionModal,
getStatusLabel,
getStatusClass,
changeStatus,
};
},
};
@@ -262,113 +350,249 @@ export default {
</div>

<div v-if="!filterLoading">
<table class="table table-hover tbl-product" id="pc-dt-simple">
<thead>
<table
class="table table-hover align-middle text-center"
id="pc-dt-simple"
>
<thead class="table-light">
<tr>
<th class="text-end">#</th>
<th>جزییات محصول</th>
<th>تاریخ ایحاد</th>
<th class="text-end">قیمت عمده</th>
<th class="text-end">قیمت تک</th>
<th class="text-end">تعداد سفارش</th>
<th class="text-end">تعداد ارسال شده</th>
<th class="text-center">عنوان برند</th>
<th class="text-center">تصویر برند</th>
<th class="text-start">جزییات محصول</th>
<th>توضیحات</th>
<th>وضعیت</th>
<th>تاریخ ایجاد</th>
<th>قیمت عمده</th>
<th>قیمت تک</th>
<th>تعداد سفارش</th>
<th>تعداد ارسال شده</th>
<th>عنوان برند</th>
<th>تصویر برند</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
<tr v-for="product in allProducts" :key="product?.id">
<td class="text-end">5</td>
<tr v-for="order in orders" :key="order?.id">
<!-- Product Details -->
<td class="text-start">
<div class="d-flex align-items-center gap-3">
<img
:src="order?.product?.image"
alt="product"
class="rounded"
style="width: 50px; height: 50px; object-fit: cover"
/>
<div>
<div class="fw-semibold">
{{ order?.product?.title }}
</div>
<div class="text-muted small">
{{ order.product.description.slice(0, 25) }}
<span v-if="order.product.description.length > 25"
>...</span
>
</div>
</div>
</div>
</td>

<!-- Description -->
<td>
<BRow>
<BCol class="col-auto pe-5">
<img
:src="product?.product?.image"
alt="user-image"
class="wid-40 rounded product-img"
/>
</BCol>
<BCol>
<h6 class="mb-1">{{ product?.product?.title }}</h6>
<p class="text-muted f-12 mb-0">
{{ product.product.description.slice(0, 25)
}}{{
product.product.description.length > 25
? "..."
: ""
}}
</p>
</BCol>
</BRow>
<div
type="button"
data-bs-target="#showDescription"
data-bs-toggle="modal"
@click="descriptionModal(order?.description)"
class="subject-box"
>
<i class="fas fa-comments subject-icon"></i>
<span class="subject-text">
{{ order?.description?.slice(0, 20)
}}{{ order?.description?.length > 20 ? "..." : "" }}
</span>
</div>
</td>
<td>{{ convertToJalali(product.created_at) }}</td>
<td
v-if="product?.product?.wholesale_price"
class="text-end"
>
{{
formatWithCommas(product?.product?.wholesale_price)
}}تومان

<!-- Status -->
<td>
<span class="badge" :class="getStatusClass(order.status)">
{{ getStatusLabel(order.status) }}
</span>
</td>
<td
v-if="!product?.product?.wholesale_price"
class="text-end"
>

<!-- Created Date -->
<td>{{ convertToJalali(order.created_at) }}</td>

<!-- Wholesale Price -->
<td>
<span v-if="order?.product?.wholesale_price">
{{ formatWithCommas(order?.product?.wholesale_price) }}
تومان
</span>
<i
class="ph-duotone ph-x-circle text-danger f-24"
data-bs-toggle="tooltip"
data-bs-title="danger"
v-else
class="ph-duotone ph-x-circle text-danger fs-5"
title="قیمت نامشخص"
></i>
</td>
<td v-if="product?.product?.retail_price" class="text-end">
{{ formatWithCommas(product?.product?.retail_price) }}
</td>
<td v-if="!product?.product?.retail_price" class="text-end">

<!-- Retail Price -->
<td>
<span v-if="order?.product?.retail_price">
{{ formatWithCommas(order?.product?.retail_price) }}
</span>
<i
class="ph-duotone ph-x-circle text-danger f-24"
data-bs-toggle="tooltip"
data-bs-title="danger"
v-else
class="ph-duotone ph-x-circle text-danger fs-5"
title="قیمت نامشخص"
></i>
</td>
<td class="text-end">{{ product.count }}</td>
<td class="text-end">{{ product.send_count }}</td>
<td class="text-center">
{{ product.product?.brand?.title }}
</td>
<td class="text-center">

<!-- Order Count -->
<td>{{ order.count }}</td>

<!-- Sent Count -->
<td>{{ order.send_count }}</td>

<!-- Brand Title -->
<td>{{ order.product?.brand?.title }}</td>

<!-- Brand Image -->
<td>
<img
:src="product.product?.brand?.image"
alt="user-image"
class="wid-40 brand-img"
:src="order.product?.brand?.image"
alt="brand"
class="rounded"
style="width: 40px; height: 40px; object-fit: cover"
/>
</td>

<!-- Operations -->
<td>
<router-link
:to="`/singleOrder/${order?.id}`"
class="btn btn-sm btn-outline-primary me-1"
>
مشاهده و ویرایش
</router-link>
<button
class="btn btn-sm btn-outline-warning dropdown-toggle me-1"
type="button"
id="dropdownMenuButton"
data-bs-toggle="dropdown"
aria-expanded="false"
>
ویرایش وضعیت
</button>
<ul
class="dropdown-menu"
aria-labelledby="dropdownMenuButton"
style="cursor: pointer"
>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'waiting')"
>
<span class="badge badge-waiting">در انتظار</span>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'paid')"
>
<span class="badge badge-paid">پرداخت‌شده</span>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'un_paid')"
>
<span class="badge badge-un_paid">پرداخت‌نشده</span>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'approved')"
>
<span class="badge badge-approved">تأیید‌شده</span>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'processing')"
>
<span class="badge badge-processing"
>در حال پردازش</span
>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'shipping')"
>
<span class="badge badge-shipping"
>در حال ارسال</span
>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'delivered')"
>
<span class="badge badge-delivered">تحویل‌شده</span>
</a>
</li>
<li>
<a
class="dropdown-item d-flex justify-content-center align-items-center"
@click="changeStatus(order?.id, 'canceled')"
>
<span class="badge badge-canceled">لغو‌شده</span>
</a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<div
v-else
class="filter-loader card table-card user-profile-list"
class="filter-loader card table-card user-profile-list"
></div>
</BCardBody>
</BCard>
</BCol>
</BRow>
<showDescription :desc="productDescription" />
<BRow>
<BCol sm="12">
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>
<li v-if="currentPage > 2" class="page-item" @click="page = 1">

<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -384,23 +608,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"
@@ -488,4 +713,75 @@ export default {
.custom-datepicker {
min-width: 340px;
}
.subject-box {
padding: 8px 14px;
background: linear-gradient(135deg, #fff3e0, #ffe0b2);
color: #ef6c00;
font-weight: 600;
border-radius: 10px;
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.1);
display: inline-flex;
align-items: center;
gap: 8px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.subject-box i {
color: #ef6c00;
font-size: 1rem;
}

.subject-box:hover {
transform: translateY(-2px);
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.15);
}
.badge {
display: inline-block;
padding: 5px 10px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 500;
text-transform: capitalize;
color: white;
}

.badge-waiting {
background-color: #ffc107;
}
.badge-paid {
background-color: #28a745;
}
.badge-un_paid {
background-color: #dc3545;
}
.badge-approved {
background-color: #17a2b8;
}
.badge-processing {
background-color: #007bff;
}
.badge-shipping {
background-color: #6f42c1;
}
.badge-delivered {
background-color: #20c997;
}
.badge-canceled {
background-color: #6c757d;
}
.badge-in-cart {
background-color: #0620c6; /* You can choose any color you prefer */
}
.badge-in-done {
background-color: #a2ca2c; /* You can choose any color you prefer */
}
.filter-loader {
border: 4px solid rgba(0, 123, 255, 0.3);
border-top: 4px solid #007bff;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 20px auto;
}

</style>

+ 76
- 16
src/views/live-preview/pages/orders/orders.vue 查看文件

@@ -19,7 +19,6 @@ export default {
const totalPages = ref(1);
const paginate = ref(20);
const page = ref(1);

const filterLoading = ref(false);
const searchQuery = ref("");
const orders = ref();
@@ -29,6 +28,34 @@ export default {
.locale("fa")
.format("YYYY/MM/DD");
};

const loadingId = ref(null);

const getExport = (id) => {
loadingId.value = id;

ApiServiece.post(`admin/orders/${id}/export`, { responseType: "blob" })
.then((resp) => {
const excelBlob = resp.data;
const url = window.URL.createObjectURL(excelBlob);

const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "order-items-export.xlsx");
document.body.appendChild(link);

link.click();

window.URL.revokeObjectURL(url);
document.body.removeChild(link);
loadingId.value = null;
})
.catch((err) => {
console.error(err, "export err");
loadingId.value = null;
});
};

watch(searchQuery, () => {
getOrders();
page.value = 1;
@@ -62,8 +89,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -227,6 +261,8 @@ export default {
getStatusClass,
getStatusLabel,
selectedStatus,
getExport,
loadingId,
};
},
};
@@ -272,7 +308,6 @@ export default {
<table class="table table-hover table-bordered m-0" dir="rtl">
<thead class="table-light">
<tr>
<th>وضعیت</th>
<th>قیمت</th>
<th>کاربر</th>
@@ -283,7 +318,6 @@ export default {
</thead>
<tbody>
<tr v-for="order in orders" :key="order.id">
<td>
<span class="badge" :class="getStatusClass(order.status)">
{{ getStatusLabel(order.status) }}
@@ -313,6 +347,28 @@ export default {
>
ویرایش وضعیت
</button>

<button
class="btn btn-sm me-1"
:class="
loadingId === order.id
? 'btn-outline-secondary'
: 'btn-outline-success'
"
type="button"
:disabled="loadingId === order.id"
@click="getExport(order.id)"
>
<span v-if="loadingId === order.id">
<span
class="spinner-border spinner-border-sm me-1"
role="status"
aria-hidden="true"
></span>
در حال خروجی...
</span>
<span v-else> خروجی </span>
</button>
<ul
class="dropdown-menu"
aria-labelledby="dropdownMenuButton"
@@ -417,15 +473,19 @@ export default {
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<!-- Page numbers with dots logic -->
<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Page numbers -->
<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -441,21 +501,21 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->


+ 56
- 41
src/views/live-preview/pages/orders/singleOrder.vue 查看文件

@@ -48,8 +48,17 @@ export default {
const getOrder = () => {
ApiServiece.get(`admin/orders/${route.params.id}`)
.then((resp) => {
order.value = resp.data.data;
console.log(order.value, "order");
const rawOrder = resp.data.data;

if (Array.isArray(rawOrder.order_items)) {
rawOrder.order_items = rawOrder.order_items.map((item) => ({
...item,
description: item.description ?? "",
}));
}

order.value = rawOrder;
})
.catch((error) => {
console.error("Failed to fetch order details:", error);
@@ -58,7 +67,7 @@ export default {

const updateShippedCount = (item) => {
const formData = new FormData();
formData.append("send_count", item.send_count);
formData.append("send_count", item.send_count || 0);
ApiServiece.put(`admin/orders/order-items/${item.id}`, formData)
.then(() => {
console.log("Shipped quantity updated successfully.");
@@ -93,9 +102,6 @@ export default {
console.error("Failed to update status:", error);
});
};
function formatWithCommas(number) {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

onMounted(() => {
getOrder();
@@ -109,7 +115,6 @@ export default {
updateShippedCount,
updateNote,
updateStatus,
formatWithCommas,
};
},
};
@@ -126,43 +131,53 @@ export default {
<h5 class="mb-0">جزئیات سفارش</h5>
</BCardHeader>
<BCardBody v-if="order">
<div class="mb-4">
<BRow class="mb-2">
<BCol md="6"
><strong>نام مشتری:</strong>
{{ order?.user || "بدون نام" }}</BCol
>
<div class="p-3 mb-4 border rounded">
<BRow class="mb-3">
<BCol md="6">
<strong class="me-2">نام مشتری:</strong>
<span>{{ order?.user?.name || "بدون نام" }}</span>
</BCol>
</BRow>
<BRow class="mb-2">
<BCol md="6"
><strong>آدرس:</strong>
{{ order?.user_address || "بدون آدرس" }}</BCol
>

<BRow class="mb-3">
<BCol md="6">
<strong class="me-2">آدرس:</strong>
<span>{{ order?.user_address?.address || "بدون آدرس" }}</span>
</BCol>
<BCol md="6">
<strong class="me-2">شهر:</strong>
<span>{{ order?.user_address?.city || "بدون شهر" }}</span>
</BCol>
</BRow>
<BRow class="mb-2">
<BCol md="6"
><strong>هزینه ارسال:</strong>
{{ formatWithCommas(order.shipping_price) }} تومان</BCol
>
<BCol md="6"
><strong>تخفیف:</strong>
{{ formatWithCommas(order.discount) }} تومان</BCol
>

<BRow class="mb-3">
<BCol md="6">
<strong class="me-2">هزینه ارسال:</strong>
<span>
{{
order?.shipping_price != null
? order.shipping_price + " تومان"
: "بدون قیمت"
}}
</span>
</BCol>
<BCol md="6">
<strong class="me-2">تخفیف:</strong>
<span>
{{
order?.discount != null
? order.discount + " تومان"
: "بدون تخفیف"
}}
</span>
</BCol>
</BRow>
<BRow class="mb-2">
<BCol md="6"
><strong>قیمت کل:</strong>
{{
formatWithCommas(
order.total_price + order.shipping_price - order.discount
)
}}
تومان

<BRow>
<BCol md="6">
<strong class="me-2">رنگ سفارش:</strong>
<span>{{ order.color || "---" }}</span>
</BCol>
<BCol md="6"
><strong>رنگ سفارش:</strong> {{ order.color || "---" }}</BCol
>
</BRow>
</div>

@@ -187,7 +202,7 @@ export default {
>
<!-- Price formatting -->
<template #cell(price)="data">
{{ formatWithCommas(data.item.price) }} تومان
{{ data.item.price }} تومان
</template>

<template #cell(title)="data">


+ 40
- 4
src/views/live-preview/pages/products/editProduct.vue 查看文件

@@ -292,6 +292,7 @@
:reduce="(option) => option.value"
:options="formattedCategories"
placeholder="دسته ای را انتخاب کنید"
@search="handleSearch"
/>
</div>
<small v-if="errors.selectedCat" class="text-danger">
@@ -327,7 +328,6 @@
md="6"
lg="4"
>
<div class="card shadow-sm">
<div class="card-body">
<!-- Card Header with Delete Icon -->
@@ -394,7 +394,11 @@
<button
class="btn btn-primary"
@click="
editAttribute(attrebute.id, attrebute.value , attrebute.attribute_value_id)
editAttribute(
attrebute.id,
attrebute.value,
attrebute.attribute_value_id
)
"
>
ویرایش
@@ -896,6 +900,21 @@ export default {
: []
);

const handleSearch = async (searchTerm) => {
if (searchTerm.length < 3) return;
categorySelectorLoader.value = true;
try {
const response = await ApiServiece.get(
`admin/categories?title=${searchTerm}`
);
categories.value = response.data.data;
categorySelectorLoader.value = false;
} catch (error) {
categorySelectorLoader.value = false;
categories.value = [];
}
};

const formattedBrands = computed(() =>
Array.isArray(brands.value)
? brands.value.map((brand) => ({
@@ -905,6 +924,21 @@ export default {
: []
);

const handleBrandSearch = async (searchTerm) => {
if (searchTerm.length < 3) return;
brandSelectorLoader.value = true;
try {
const response = await ApiServiece.get(
`admin/brands?title=${searchTerm}`
);
brands.value = response.data.data;
brandSelectorLoader.value = false;
} catch (error) {
brandSelectorLoader.value = false;
brands.value = [];
}
};

watch(selectedCat, () => {
ApiServiece.get(`admin/attributes?category_id=${selectedCat.value}`)
.then((resp) => {
@@ -920,7 +954,7 @@ export default {
ApiServiece.get(`admin/attributes?category_id=${selectedCat.value}`)
.then((resp) => {
identities.value = resp.data.data;
console.log(identities.value , "identities");
console.log(identities.value, "identities");
})
.then(() => {
localIdentitiesIds.value = localIdentities.value.map(
@@ -1303,7 +1337,7 @@ export default {
});
};

const editAttribute = (id, inventory , attrebuteValueId) => {
const editAttribute = (id, inventory, attrebuteValueId) => {
Swal.fire({
text: "آیا برای ویرایش ویژگی اطمینان دارید؟",
icon: "warning",
@@ -1616,6 +1650,8 @@ export default {
formattedCategories,
formattedBrands,
brandSelectorLoader,
handleSearch,
handleBrandSearch,
};
},
};


+ 26
- 12
src/views/live-preview/pages/products/products.vue 查看文件

@@ -96,8 +96,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -105,7 +112,6 @@ export default {
}
return pages;
});

const deleteProduct = (id, title) => {
Swal.fire({
text: `می خواهید محصول ${title} را حذف کنید؟`,
@@ -473,17 +479,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -499,23 +512,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


+ 9
- 5
src/views/live-preview/pages/settings/setting.vue 查看文件

@@ -9,6 +9,7 @@ import Quill from "quill";
import "quill/dist/quill.snow.css";
import ApiService from "@/services/ApiService";
import DatePicker from "vue3-persian-datetime-picker";
const isFirstLoad = ref(true);

const settings = ref([]);
const editors = ref({});
@@ -18,17 +19,20 @@ const getSettings = async () => {
try {
const response = await ApiService.get("admin/settings");
settings.value = response.data.data;

settings.value.forEach((setting) => {
if (setting.type === "image" && setting.value) {
setting.preview = setting.value;
localStorage.setItem("logo" , setting.value)
localStorage.setItem("logo", setting.value);
}

loading.value[setting.id] = false;
});

await nextTick();
initQuillEditors();
if (isFirstLoad.value) {
initQuillEditors();
isFirstLoad.value = false;
}
} catch (error) {
console.error("Error fetching settings:", error);
}
@@ -36,7 +40,7 @@ const getSettings = async () => {

const initQuillEditors = () => {
settings.value.forEach((setting) => {
if (setting.type === "longtext") {
if (setting.type === "longtext" && !editors.value[setting.id]) {
const quillContainer = document.getElementById(`editor-${setting.id}`);
if (quillContainer) {
const quill = new Quill(quillContainer, {
@@ -47,7 +51,7 @@ const initQuillEditors = () => {
[{ list: "ordered" }, { list: "bullet" }],
[{ align: [] }],
["bold", "italic", "underline"],
["link", "image"],
["link"], // Removed "image" from here
[{ script: "sub" }, { script: "super" }],
[{ direction: "rtl" }],
],


+ 27
- 12
src/views/live-preview/pages/users/users.vue 查看文件

@@ -43,7 +43,7 @@ export default {
`admin/users?name=${searchQuery.value || ""}&paginate=${
paginate.value || 10
}&page=${page.value || 1}&role=${
selectedRole.value || "admin"
selectedRole.value || ""
}&trashed=${selectedStatus.value || ""}`
)
.then((resp) => {
@@ -82,8 +82,15 @@ export default {
let start = currentPage.value - 2;
let end = currentPage.value + 2;

if (start < 1) start = 1;
if (end > totalPages.value) end = totalPages.value;
if (start < 1) {
end += 1 - start;
start = 1;
}
if (end > totalPages.value) {
start -= end - totalPages.value;
end = totalPages.value;
}
start = Math.max(start, 1);

for (let i = start; i <= end; i++) {
pages.push(i);
@@ -402,17 +409,24 @@ export default {
<div class="d-flex justify-content-center">
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- Previous page -->
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<span class="page-link" @click="prevPage">قبلی</span>
</li>

<li v-if="currentPage > 2" class="page-item" @click="page = 1">
<!-- First page and leading dots -->
<li
v-if="visiblePages[0] > 1"
class="page-item"
@click="page = 1"
>
<a class="page-link" href="javascript:void(0)">1</a>
</li>
<li v-if="currentPage > 3" class="page-item" disabled>
<li v-if="visiblePages[0] > 2" class="page-item disabled">
<span class="page-link">...</span>
</li>

<!-- Visible pages -->
<li
v-for="n in visiblePages"
:key="n"
@@ -428,23 +442,24 @@ export default {
</a>
</li>

<!-- Trailing dots and last page -->
<li
v-if="currentPage < totalPages - 2"
class="page-item"
disabled
v-if="visiblePages[visiblePages.length - 1] < totalPages - 1"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-if="currentPage < totalPages - 1"
v-if="visiblePages[visiblePages.length - 1] < totalPages"
class="page-item"
@click="page = totalPages"
>
<a class="page-link" href="javascript:void(0)">{{
totalPages
}}</a>
<a class="page-link" href="javascript:void(0)">
{{ totalPages }}
</a>
</li>

<!-- Next page -->
<li
class="page-item"
:class="{ disabled: currentPage === totalPages }"


Loading…
取消
儲存