|
- <template>
- <div
- class="modal fade"
- id="addBrand"
- tabindex="-1"
- role="dialog"
- aria-labelledby="exampleModalLabel"
- aria-hidden="true"
- >
- <div class="modal-dialog modal-sm" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <h5 class="modal-title" id="exampleModalLabel">
- اضافه کردن برند جدید
- </h5>
- <button
- type="button"
- class="btn-close"
- data-bs-dismiss="modal"
- aria-label="Close"
- @click="step = 1"
- ></button>
- </div>
- <div class="modal-body">
- <Steppy
- v-model:step="step"
- :tabs="[
- { title: 'ثبت دسته بندی', isValid: true },
- { title: 'ترجمه ها', isValid: true },
- ]"
- backText="قبلی"
- nextText="بعدی"
- doneText="ذخیره"
- primaryColor1="#04A9F5"
- circleSize="45"
- >
- <template #1>
- <!-- Brand Image Upload -->
- <div class="form-group">
- <label class="form-label">تصویر برند</label>
-
- <input
- type="file"
- accept="image/*"
- @change="handleImageChange"
- 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"
- />
- <button
- type="button"
- @click="removeImage()"
- class="delete-btn"
- >
- <i class="fa fa-trash f-16"></i>
- </button>
- </div>
-
- <small v-if="errors.image" class="text-danger">
- {{ errors.image }}
- </small>
- </div>
-
- <div
- class="d-flex justify-content-end gap-2"
- style="margin-top: 20px"
- >
- <button :disabled="loadingStep" @click="handlerAddBrand" class="btn btn-primary">
- <span
- v-if="loadingStep"
- class="spinner-border spinner-border-sm"
- role="status"
- aria-hidden="true"
- />
- ذخیره
- </button>
- </div>
- </template>
-
- <template #2>
- <form @submit.prevent="addBrand">
- <BRow class="g-3">
- <!-- Brand Title -->
- <BCol lg="6">
- <div class="form-group">
- <label class="form-label">عنوان برند</label>
- <input
- v-model="title"
- @input="clearError('title')"
- type="text"
- class="form-control"
- placeholder="عنوان برند"
- :class="{ 'is-invalid': errors.title }"
- />
- <small v-if="errors.title" class="text-danger">
- {{ errors.title }}
- </small>
- </div>
- </BCol>
-
- <BCol lg="6">
- <div class="form-group">
- <label class="form-label">انتخاب زبان</label>
- <select
- v-model="locale"
- class="form-control"
- placeholder="انتخاب کنید"
- @change="handlerChangeLocale"
- >
- <option
- key="fa"
- value="fa"
- >
- فارسی
- </option>
- <option
- key="en"
- value="en"
- >
- انگلیسی
- </option>
- <option
- key="ar"
- value="ar"
- >
- عربی
- </option>
- </select>
- </div>
- </BCol>
-
- <!-- Brand Description -->
- <BCol lg="12">
- <div class="form-group">
- <label class="form-label">توضیحات برند</label>
- <textarea
- v-model="description"
- @input="clearError('description')"
- type="text"
- class="form-control"
- placeholder="توضیحات برند"
- :class="{ 'is-invalid': errors.description }"
- ></textarea>
- <small v-if="errors.description" class="text-danger">
- {{ errors.description }}
- </small>
- </div>
- </BCol>
- </BRow>
-
- <!-- Submit Buttons -->
- <div
- class="d-flex justify-content-end gap-2"
- style="margin-top: 20px"
- >
- <button
- type="button"
- class="btn btn-secondary"
- data-bs-dismiss="modal"
- id="close"
- @click="step = 1"
- >
- بستن
- </button>
- <button type="submit" class="btn btn-primary" :disabled="loading">
- <span
- v-if="loading"
- class="spinner-border spinner-border-sm"
- role="status"
- aria-hidden="true"
- ></span>
- ذخیره
- </button>
- </div>
- </form>
- </template>
- </Steppy>
-
-
- </div>
- </div>
- </div>
- </div>
- </template>
-
- <script>
- import { ref } from "vue";
- import { toast } from "vue3-toastify";
- import "vue3-toastify/dist/index.css";
- import ApiServiece from "@/services/ApiService";
- import {Steppy} from "vue3-steppy";
-
- export default {
- components: {Steppy},
- setup(props, { emit }) {
- const image = ref(null);
- const imagePreview = ref(null);
- const description = ref();
- const title = ref();
- const loadingStep = ref(false);
- const step = ref(1);
- const brandId = ref(null);
- const locale = ref('fa');
-
- const errors = ref({});
- const loading = ref(false);
-
- const removeImage = () => {
- image.value = null;
- imagePreview.value = null;
-
- const fileInput = document.querySelector('input[type="file"]');
- if (fileInput) {
- fileInput.value = "";
- }
- };
- const handleImageChange = (event) => {
- const file = event.target.files[0];
-
- if (file) {
- if (!file.type.startsWith("image/")) {
- errors.value.image = "لطفا یک فایل تصویری انتخاب کنید";
- imagePreview.value = null;
- return;
- }
-
- if (file.size > 5 * 1024 * 1024) {
- errors.value.image = "حجم تصویر باید کمتر از 5 مگابایت باشد";
- imagePreview.value = null;
- return;
- }
-
- 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 (!description.value)
- errors.value.description = "وارد کردن توضیحات ضروری می باشد";
- if (!title.value) errors.value.title = "وارد کردن عنوان ضروری می باشد";
- if (!image.value) errors.value.image = "یک عکس انتخاب نمایید";
- return Object.keys(errors.value).length === 0;
- };
-
- const clearError = (field) => {
- errors.value[field] = "";
- };
-
- const addBrand = () => {
- if (!validateForm()) {
- toast.error("لطفا فیلد های لازم را وارد نمایید", {
- position: "top-right",
- autoClose: 1000,
- });
- return;
- }
- loading.value = true;
-
- const params = {
- title: title.value,
- description: description.value,
- locale: locale.value,
- }
-
- ApiServiece.post(`admin/brands/${brandId.value}/translations`, params, {
- headers: {
- Authorization: `Bearer ${localStorage.getItem("token")}`,
- },
- })
- .then((resp) => {
- console.log(resp);
- toast.success("!برند با موفقیت اضافه شد", {
- position: "top-right",
- autoClose: 1000,
- });
- })
- .then(() => {
- setTimeout(() => {
- emit("brand-updated");
- title.value = "";
- description.value = "";
- imagePreview.value = null;
- }, 500);
- })
- .catch((error) => {
- toast.error(`${error.response.data.message}`, {
- position: "top-right",
- autoClose: 1000,
- });
- })
- .finally(() => {
- loading.value = false;
- });
- };
-
- const handlerAddBrand = async () => {
- if (!image.value) {
- toast.error('تصویر برند نمی تواند خالی باشد.')
-
- return
- }
-
- try {
- loadingStep.value = true;
-
- const formData = new FormData();
-
- formData.append("image", image.value);
-
- const { data: { message, success, data } } = await ApiServiece.post(
- `admin/brands`,
- formData,
- {
- headers: {
- "content-type": "multipart",
- Authorization: `Bearer ${localStorage.getItem("token")}`,
- },
- })
-
- if (success) {
- toast.success(message)
-
- brandId.value = data?.id
-
- step.value++
- }
- } catch (e) {
- toast.error(e?.response?.data?.message)
- } finally {
- loadingStep.value = false;
- }
- }
-
- return {
- errors,
- loading,
- clearError,
- addBrand,
- handleImageChange,
- image,
- imagePreview,
- removeImage,
- title,
- description,
- loadingStep,
- step,
- handlerAddBrand,
- brandId,
- locale
- };
- },
- };
- </script>
-
- <style scoped>
- .modal-dialog {
- max-width: 50%;
- }
-
- .modal-content {
- padding: 20px;
- }
-
- .modal-body {
- padding: 20px;
- padding: 1rem 1.5rem;
- }
-
- .form-group {
- margin-bottom: 1rem;
- }
-
- .input-group {
- margin-top: 0.5rem;
- }
-
- .modal-dialog {
- max-width: 50%;
- }
-
- .modal-content {
- padding: 1.5rem;
- }
-
- .modal-header {
- border-bottom: 1px solid #dee2e6;
- padding-bottom: 1rem;
- }
-
- .form-group {
- margin-bottom: 1.5rem;
- }
-
- .input-group {
- margin-top: 0.5rem;
- }
-
- .Image-Preview {
- min-width: 100px;
- max-height: 100px;
- max-width: 100px;
- 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; /* Space between icon and text */
- margin-right: 100px;
- }
-
- .delete-btn:hover {
- background-color: #c0392b;
- transform: scale(1.05);
- }
-
- .delete-btn:active {
- background-color: #a93226;
- }
-
- .delete-btn:focus {
- outline: none;
- }
- </style>
|