|
- <template>
- <Layout>
- <BRow>
- <BCol sm="12">
- <BCard no-body>
- <BCardHeader>
- <div class="d-flex justify-content-between align-items-center">
- <h5>ایجاد بنر</h5>
-
- <!-- Help and Modal buttons -->
- <div>
- <button
- v-if="pageType === 'main_page'"
- data-bs-toggle="modal"
- data-bs-target="#mainPageBanner"
- class="btn btn-info btn-sm mx-2"
- @click="showHelp"
- >
- <i class="fa fa-question-circle"></i> راهنمایی بنر صفحه اصلی
- </button>
- <button
- data-bs-toggle="modal"
- data-bs-target="#catBanner"
- class="btn btn-info btn-sm mx-2"
- @click="showModal"
- v-if="pageType === 'category'"
- >
- <i class="fa fa-info-circle"></i> راهنمایی بنر دسته ها
- </button>
- <button
- data-bs-toggle="modal"
- data-bs-target="#specialPageBanner"
- class="btn btn-info btn-sm mx-2"
- @click="showModal"
- v-if="pageType === 'special_page'"
- >
- <i class="fa fa-info-circle"></i> راهنمایی بنر فروش ویژه
- </button>
- <button
- v-if="pageType === 'brand'"
- data-bs-toggle="modal"
- data-bs-target="#brandBanner"
- class="btn btn-info btn-sm mx-2"
- @click="showModal"
- >
- <i class="fa fa-info-circle"></i> راهنمایی بنر برند
- </button>
- <button
- data-bs-toggle="modal"
- data-bs-target="#specialPageBanner"
- class="btn btn-info btn-sm mx-2"
- @click="showModal"
- v-if="pageType === 'blog_page'"
- >
- <i class="fa fa-info-circle"></i> راهنمایی بنر بلاگ
- </button>
- </div>
- </div>
- </BCardHeader>
- <BCardBody>
- <BRow class="g-3">
- <BCol md="6">
- <div class="form-group">
- <label class="form-label">عنوان</label>
- <input
- type="text"
- v-model="title"
- class="form-control"
- placeholder="عنوان بنر"
- :class="{ 'is-invalid': errors.title }"
- @input="clearError('title')"
- />
- </div>
- <small v-if="errors.title" class="text-danger">
- {{ errors.title }}
- </small>
- </BCol>
-
- <BCol md="6">
- <div class="form-group">
- <label class="form-label">پنل نمایش</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="pannel"
- @change="clearError('pannel')"
- :class="{ 'is-invalid': errors.pannel }"
- placeholder="انتخاب پنل"
- >
- <option value="wholesale">پنل عمده فروشی</option>
- <option value="web">وب سایت و اپلیکیشن</option>
- </select>
- </div>
- <small v-if="errors.pannel" class="text-danger">
- {{ errors.pannel }}
- </small>
- </BCol>
-
- <BCol v-if="pannel === 'web'" md="6">
- <div class="form-group">
- <label class="form-label">نمایش در</label>
- <select
- v-model="pageType"
- :class="{ 'is-invalid': errors.pageType }"
- class="form-select"
- aria-label="Default select example"
- placeholder="انتخاب صفحه"
- @change="clearError('pageType')"
- >
- <option value="main_page">صفحه اصلی</option>
- <option value="category">صفحه دسته</option>
- <option value="special_page">صفحه فروش ویژه</option>
- <option value="brand">صفحه برند</option>
- <option value="blog_page">صفحه بلاگ</option>
- </select>
- </div>
- <small v-if="errors.pageType" class="text-danger">
- {{ errors.pageType }}
- </small>
- </BCol>
-
- <BCol v-if="pageType === 'category' && pannel === 'web'" md="6">
- <div class="form-group">
- <label class="form-label">صفحه دسته</label>
-
- <VueSelect
- style="--vs-min-height: 48px; --vs-border-radius: 8px"
- v-model="selectedCatPage"
- :isLoading="categoryPageSelectorLoader"
- :options="formattedCategoriesPages"
- @change="clearError('selectedCatPage')"
- placeholder="دسته ای را انتخاب کنید"
- @search="handleCategoryPageSearch"
- />
- </div>
- <small v-if="errors.selectedCatPage" class="text-danger">
- {{ errors.selectedCatPage }}
- </small>
- </BCol>
-
- <BCol v-if="pageType === 'brand' && pannel === 'web'" md="6">
- <div class="form-group">
- <label class="form-label">صفحه برند</label>
-
- <VueSelect
- style="--vs-min-height: 48px; --vs-border-radius: 8px"
- v-model="selectedBrandPage"
- :isLoading="brandSelectorLoader"
- :options="formattedBrands"
- @change="clearError(`selectedBrandPage`)"
- placeholder="برندی را انتخاب کنید"
- @search="handleBrandSearch"
- />
- </div>
- <small v-if="errors.selectedBrandPage" class="text-danger">
- {{ errors.selectedBrandPage }}
- </small>
- </BCol>
-
- <BCol v-if="pannel != 'wholesale' && pannel" md="6">
- <div class="form-group">
- <label class="form-label">انتخاب صفحه فرود</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="landingType"
- @change="clearError('landingType')"
- :class="{ 'is-invalid': errors.landingType }"
- placeholder="انتخاب صفحه فرود"
- >
- <option value="product">صفحه محصولات</option>
- <option value="cat">صفحه دسته ها</option>
- </select>
- </div>
- <small v-if="errors.landingType" class="text-danger">
- {{ errors.landingType }}
- </small>
- </BCol>
-
- <BCol
- v-if="landingType === 'product'"
- sm="6"
- class="mt-3"
- style="margin-top: 30px"
- >
- <label for="token">صفحه کدام محصول</label>
-
- <VueSelect
- style="
- --vs-min-height: 48px;
- --vs-border-radius: 8px;
- margin-top: 7px;
- "
- v-model="selectedLandingProduct"
- :isLoading="productSelectorLoader"
- @change="clearError(`selectedLandingProduct`)"
- :options="formattedProducts"
- placeholder="محصولی را انتخاب کنید"
- @search="handleSearch"
- />
- <small v-if="errors.selectedLandingProduct" class="text-danger">
- {{ errors.selectedLandingProduct }}
- </small>
- </BCol>
-
- <BCol v-if="landingType === 'cat'" md="6">
- <div class="form-group">
- <label class="form-label">صفحه کدام دسته</label>
-
- <VueSelect
- style="--vs-min-height: 48px; --vs-border-radius: 8px"
- v-model="selectedLandingCat"
- @change="clearError('selectedLandingCat')"
- :isLoading="categorySelectorLoader"
- :options="formattedCategories"
- placeholder="دسته ای را انتخاب کنید"
- @search="handleCategorySearch"
- />
- </div>
- <small v-if="errors.selectedLandingCat" class="text-danger">
- {{ errors.selectedLandingCat }}
- </small>
- </BCol>
-
- <BCol v-if="pageType === 'main_page' && pannel === 'web'" md="6">
- <div class="form-group">
- <label class="form-label">موقعیت در صفحه اصلی</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="selectedLoc"
- @change="clearError('selectedLoc')"
- :class="{ 'is-invalid': errors.selectedLoc }"
- placeholder="موقعیت بنر"
- >
- <option value="A">َA-Slideshow</option>
- <option value="B">B-Banner</option>
- <option value="C">C-Banner</option>
- <option value="D">D-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>
- </div>
- <small v-if="errors.selectedLoc" class="text-danger">
- {{ errors.selectedLoc }}
- </small>
- </BCol>
-
- <BCol v-if="pageType === 'category' && pannel === 'web'" md="6">
- <div class="form-group">
- <label class="form-label">موقعیت در صفحه دسته ها</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="selectedLoc"
- @change="clearError('selectedLoc')"
- :class="{ 'is-invalid': errors.selectedLoc }"
- placeholder="موقعیت بنر"
- >
- <option value="A">َA-Slideshow</option>
- <option value="B">B-Banner</option>
- <option value="C">C-Banner</option>
- <option value="D">D-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>
- </select>
- </div>
- <small v-if="errors.selectedLoc" class="text-danger">
- {{ errors.selectedLoc }}
- </small>
- </BCol>
-
- <BCol
- v-if="pageType === 'special_page' && pannel === 'web'"
- md="6"
- >
- <div class="form-group">
- <label class="form-label">موقعیت در صفحه فروش ویژه</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="selectedLoc"
- @change="clearError('selectedLoc')"
- :class="{ 'is-invalid': errors.selectedLoc }"
- placeholder="موقعیت بنر"
- :value="(selectedLoc = 'A')"
- >
- <option value="A">A-Slideshow</option>
- </select>
- </div>
- <small v-if="errors.selectedLoc" class="text-danger">
- {{ errors.selectedLoc }}
- </small>
- </BCol>
-
- <BCol
- v-if="pageType === 'blog_page' && pannel === 'web'"
- md="6"
- >
- <div class="form-group">
- <label class="form-label">موقعیت در صفحه بلاگ</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="selectedLoc"
- @change="clearError('selectedLoc')"
- :class="{ 'is-invalid': errors.selectedLoc }"
- placeholder="موقعیت بنر"
- :value="(selectedLoc = 'A')"
- >
- <option value="A">A-Banner</option>
- </select>
- </div>
- <small v-if="errors.selectedLoc" class="text-danger">
- {{ errors.selectedLoc }}
- </small>
- </BCol>
-
- <BCol v-if="pageType === 'brand' && pannel === 'web'" md="6">
- <div class="form-group">
- <label class="form-label">موقعیت در صفحه برند</label>
- <select
- class="form-select"
- aria-label="Default select example"
- v-model="selectedLoc"
- @change="clearError('selectedLoc')"
- :class="{ 'is-invalid': errors.selectedLoc }"
- placeholder="موقعیت بنر"
- >
- <option value="A">َA-Slideshow</option>
- <option value="B">B-Banner</option>
- <option value="C">C-Banner</option>
- <option value="D">D-Banner</option>
- <option value="E">E-Banner</option>
- <option value="F">F-Banner</option>
- </select>
- </div>
- <small v-if="errors.selectedLoc" class="text-danger">
- {{ errors.selectedLoc }}
- </small>
- </BCol>
-
- <BCol md="6" v-if="pannel">
- <div class="form-group">
- <label class="form-label">تصویر بنر</label>
-
- <input
- type="file"
- accept="image/*"
- @change="handleImageUpload"
- class="form-control"
- :class="{ 'is-invalid': errors.image }"
- />
-
- <div v-if="imagePreview" class="mt-2">
- <img
- :src="imagePreview"
- alt="Image Preview"
- class="img-fluid rounded shadow-sm Image-Preview"
- />
- </div>
-
- <small v-if="errors.image" class="text-danger">
- {{ errors.image }}
- </small>
- </div>
- </BCol>
- </BRow>
- </BCardBody>
- <BCardFooter>
- <div class="d-flex justify-content-center">
- <div class="text-center">
- <button
- type="submit"
- class="btn btn-primary"
- @click.prevent="submitForm"
- :disabled="loading"
- >
- <span v-if="loading">
- <i class="fa fa-spinner fa-spin"></i> بارگذاری...
- </span>
- <span v-else>ایجاد</span>
- </button>
- </div>
- </div>
- </BCardFooter>
- </BCard>
- </BCol>
- </BRow>
-
- <mainPageBanner />
- <catBanner />
- <specialBanner/>
- <brandBanner/>
- </Layout>
- </template>
-
- <script>
- import VueSelect from "vue3-select-component";
- import catBanner from "@/components/modals/helperModals/catBanner.vue";
- import mainPageBanner from "@/components/modals/helperModals/mainPageBanner.vue";
- import specialBanner from "@/components/modals/helperModals/specialBanner.vue";
- import brandBanner from "@/components/modals/helperModals/brandBanner.vue";
- import { toast } from "vue3-toastify";
- import "vue3-toastify/dist/index.css";
- import ApiServiece from "@/services/ApiService";
- import { ref, computed } from "vue";
- import Layout from "@/layout/custom.vue";
-
- export default {
- name: "SAMPLE-PAGE",
- components: {
- Layout,
- mainPageBanner,
- catBanner,
- VueSelect,
- specialBanner,
- brandBanner
- },
- setup() {
- const title = ref();
- const pageType = ref();
- const products = ref([]);
- const cats = ref([]);
- const categoryPages = ref([]);
- const brands = ref([]);
- const landingType = ref();
- const selectedCatPage = ref();
- const selectedBrandPage = ref();
- const selectedLandingCat = ref();
- const selectedLandingProduct = ref();
- const selectedLoc = ref();
- 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 handleSearch = async (searchTerm) => {
- if (searchTerm.length < 3) return;
- productSelectorLoader.value = true;
-
- try {
- const response = await ApiServiece.get(
- `admin/products?title=${searchTerm}`
- );
- 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) {
- brands.value = [];
- brandSelectorLoader.value = false;
- }
- };
-
- const formattedProducts = computed(() =>
- Array.isArray(products.value) // ✅ Check if products.value is an array
- ? products.value.map((product) => ({
- value: product.id,
- label: product.title,
- }))
- : []
- );
-
- 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/parents?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];
-
- if (file) {
- errors.value.image = null;
-
- image.value = file;
-
- const reader = new FileReader();
- reader.onload = () => {
- imagePreview.value = reader.result;
- };
- reader.readAsDataURL(file);
- }
- };
-
- const validateForm = () => {
- errors.value = {};
- if (!title.value) errors.value.title = "وارد کردن عنوان بنر الزامی است";
- if (!pageType.value && pannel.value != "wholesale")
- errors.value.pageType = "مشخص کنید بنر کجا نشان داده شود";
- if (pageType.value === "category" && !selectedCatPage.value)
- errors.value.selectedCatPage = "صفحه دسته را انتخاب کنید";
- if (pageType.value === "brand" && !selectedBrandPage.value)
- errors.value.selectedBrandPage = "صفحه برند را انتخاب کنید";
- if (!landingType.value && pannel.value != "wholesale")
- errors.value.landingType = "صفحه فرود را انتخاب نمایید";
- if (
- landingType.value === "cat" &&
- !selectedLandingCat.value &&
- pannel.value != "wholesale"
- )
- errors.value.selectedLandingCat = "صفحه فرود دسته را انتخاب کنید";
- if (
- landingType.value === "product" &&
- !selectedLandingProduct.value &&
- pannel.value != "wholesale"
- )
- errors.value.selectedLandingProduct = "صفحه فرود محصول را انتخاب کنید";
-
- if (!selectedLoc.value && pannel.value != "wholesale")
- errors.value.selectedLoc = "موقعیت بنر را انتخاب کنید";
-
- if (!pannel.value) errors.value.pannel = "پنل نمایش بنر را انتخاب کنید";
-
- if (!image.value) errors.value.image = "عکس بنر را وارد نمایید";
-
- return Object.keys(errors.value).length === 0;
- };
-
- const clearError = (field) => {
- errors.value[field] = "";
- };
-
- const submitForm = () => {
- if (!validateForm()) {
- toast.error("لطفا فیلد های لازم را وارد نمایید", {
- position: "top-right",
- autoClose: 1000,
- });
- return;
- }
- loading.value = true;
- const formData = new FormData();
- formData.append("title", title.value);
-
- if (pageType.value === "category") {
- formData.append("page_id", selectedCatPage.value);
- }
-
- if (pageType.value === "brand") {
- formData.append("page_id", selectedBrandPage.value);
- }
-
- if (landingType.value === "product" && pannel.value != "wholesale") {
- formData.append("product_id", selectedLandingProduct.value);
- }
-
- if (landingType.value === "cat" && pannel.value != "wholesale") {
- formData.append("category_id", selectedLandingCat.value);
- }
-
- if (selectedLoc.value === "A") {
- formData.append("type", pageType.value === 'blog_page' ? "banner" :"slider");
- }
-
- if (selectedLoc.value !== "A") {
- formData.append("type", "banner");
- }
-
- if (pannel.value === "wholesale") {
- formData.append("type", "slider");
- formData.append("location", "A");
- }
-
- if (selectedLoc.value) {
- formData.append("location", selectedLoc.value);
- }
- formData.append("panel", pannel.value);
- if (pannel.value == "wholesale") {
- formData.append("page_type", "main_page");
- }
-
- if (pannel.value !== "wholesale") {
- formData.append("page_type", pageType.value);
- }
-
- formData.append("image", image.value);
- formData.append("sort", 1);
-
- ApiServiece.post(`admin/banners`, formData, {
- headers: {
- "content-type": "multipart",
- Authorization: `Bearer ${localStorage.getItem("token")}`,
- },
- })
- .then((resp) => {
- toast.success("!بنر با موفقیت اضافه شد", {
- position: "top-right",
- autoClose: 1000,
- });
- console.log(resp);
- loading.value = false;
-
- resetForm();
- })
- .catch((error) => {
- loading.value = false;
- console.log(error.response.message);
- toast.error(`${error.response.data.message}`, {
- position: "top-right",
- autoClose: 1000,
- });
- });
- };
- const resetForm = () => {
- title.value = "";
- selectedCatPage.value = "";
- selectedBrandPage.value = "";
- selectedLandingProduct.value = "";
- selectedLandingCat.value = "";
- selectedLoc.value = "";
- pannel.value = "";
- pageType.value = "";
- landingType.value = "";
- image.value = null;
- imagePreview.value = null;
- loading.value = false;
- };
- return {
- cats,
- errors,
- title,
- products,
- selectedCatPage,
- selectedBrandPage,
- submitForm,
- clearError,
- pageType,
- formattedProducts,
- landingType,
- selectedLandingCat,
- selectedLandingProduct,
- selectedLoc,
- pannel,
- handleImageUpload,
- image,
- imagePreview,
- loading,
- brands,
- handleSearch,
- productSelectorLoader,
- handleCategorySearch,
- categorySelectorLoader,
- formattedCategories,
- handleCategoryPageSearch,
- formattedCategoriesPages,
- categoryPageSelectorLoader,
- brandSelectorLoader,
- formattedBrands,
- handleBrandSearch,
- };
- },
- };
- </script>
-
- <style scoped>
- .ql-editor {
- direction: rtl;
- text-align: right;
- }
-
- .ql-editor::before {
- content: attr(placeholder);
- direction: rtl !important;
- text-align: right;
- }
- .Image-Preview {
- min-width: 200px;
- max-height: 200px;
- min-height: 200px;
- max-width: 200px;
- object-fit: cover;
- border-radius: 8px;
- border: 1px solid #ddd;
- }
- .delete-btn {
- display: flex;
- align-items: center;
- padding: 3px;
- font-size: 10px;
- background-color: #e74c3c;
- color: white;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- transition: background-color 0.3s ease, transform 0.2s ease;
- gap: 8px;
- margin-right: 200px;
- }
-
- .delete-btn:hover {
- background-color: #c0392b;
- transform: scale(1.05);
- }
-
- .delete-btn:active {
- background-color: #a93226;
- }
-
- .delete-btn:focus {
- outline: none;
- }
- </style>
|