Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

391 строка
9.4 KiB

  1. <template>
  2. <div
  3. class="modal fade"
  4. id="editUser"
  5. tabindex="-1"
  6. role="dialog"
  7. aria-labelledby="exampleModalLabel"
  8. aria-hidden="true"
  9. >
  10. <div class="modal-dialog modal-sm" role="document">
  11. <div class="modal-content">
  12. <div class="modal-header">
  13. <h5 class="modal-title" id="exampleModalLabel">ویرایش کاربر</h5>
  14. <button
  15. type="button"
  16. class="btn-close"
  17. data-bs-dismiss="modal"
  18. aria-label="Close"
  19. ></button>
  20. </div>
  21. <div class="modal-body">
  22. <form @submit.prevent="editUser">
  23. <BRow class="g-3">
  24. <BCol class="col-lg-6">
  25. <div class="form-group">
  26. <label class="form-label">نام</label>
  27. <input
  28. v-model="localName"
  29. type="text"
  30. class="form-control"
  31. placeholder="نام را وارد نمایید"
  32. />
  33. </div>
  34. </BCol>
  35. <BCol class="col-lg-6">
  36. <div class="form-group">
  37. <label class="form-label">موبایل</label>
  38. <input
  39. v-model="localMobile"
  40. @input="clearError('localMobile')"
  41. type="text"
  42. class="form-control"
  43. placeholder="موبایل را وارد نمایید"
  44. />
  45. <small v-if="errors.localMobile" class="text-danger">{{
  46. errors.localMobile
  47. }}</small>
  48. </div>
  49. </BCol>
  50. <BCol class="col-lg-6">
  51. <div class="form-group">
  52. <label class="form-label">نقش</label>
  53. <select
  54. class="form-select"
  55. v-model="localRole"
  56. @change="clearError('role')"
  57. placeholder="نوع کاربر"
  58. >
  59. <option value="admin">مدیر</option>
  60. <option value="client">مشتری</option>
  61. <option value="operator">اپراتور</option>
  62. </select>
  63. <small v-if="errors.role" class="text-danger">{{
  64. errors.role
  65. }}</small>
  66. </div>
  67. </BCol>
  68. <BCol class="col-lg-6">
  69. <div class="form-group">
  70. <label class="form-label">رمز عبور</label>
  71. <input
  72. v-model="password"
  73. type="password"
  74. class="form-control"
  75. placeholder="رمز عبور را وارد نمایید"
  76. />
  77. <small v-if="errors.password" class="text-danger">{{
  78. errors.password
  79. }}</small>
  80. </div>
  81. </BCol>
  82. </BRow>
  83. <div
  84. class="d-flex justify-content-end gap-2"
  85. style="margin-top: 20px"
  86. >
  87. <button
  88. type="button"
  89. class="btn btn-secondary"
  90. data-bs-dismiss="modal"
  91. id="close"
  92. >
  93. بستن
  94. </button>
  95. <button type="submit" class="btn btn-primary" :disabled="loading">
  96. <span
  97. v-if="loading"
  98. class="spinner-border spinner-border-sm"
  99. role="status"
  100. aria-hidden="true"
  101. ></span>
  102. ذخیره
  103. </button>
  104. </div>
  105. </form>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </template>
  111. <script>
  112. import ApiServiece from "@/services/ApiService";
  113. import { ref, toRef, watch } from "vue";
  114. import { toast } from "vue3-toastify";
  115. import "vue3-toastify/dist/index.css";
  116. export default {
  117. props: {
  118. name: {
  119. type: String,
  120. required: true,
  121. },
  122. mobile: {
  123. type: String,
  124. required: true,
  125. },
  126. id: {
  127. type: String,
  128. required: true,
  129. },
  130. role: {
  131. type: String,
  132. required: true,
  133. },
  134. },
  135. setup(props, { emit }) {
  136. const password = ref();
  137. const localName = toRef(props.name);
  138. const localMobile = toRef(props.mobile);
  139. const localRole = toRef(props.role);
  140. const localId = toRef(props.id);
  141. const errors = ref({});
  142. const loading = ref(false);
  143. watch(
  144. () => props.name,
  145. (newVal) => (localName.value = newVal)
  146. );
  147. watch(
  148. () => props.mobile,
  149. (newVal) => (localMobile.value = newVal)
  150. );
  151. watch(
  152. () => props.id,
  153. (newVal) => (localId.value = newVal)
  154. );
  155. watch(
  156. () => props.role,
  157. (newVal) => (localRole.value = newVal)
  158. );
  159. const validateForm = () => {
  160. errors.value = {};
  161. if (!localMobile.value)
  162. errors.value.localMobile = "وارد کردن موبایل ضروری می باشد";
  163. if (!localRole.value)
  164. errors.value.localMobile = "انتخاب کردن نقش کاربر ضروری می باشد";
  165. if (password.value && password.value.length < 8) {
  166. errors.value.password = " رمز عبور باید حداقل 8 کاراکتر باشد";
  167. }
  168. return Object.keys(errors.value).length === 0;
  169. };
  170. const clearError = (field) => {
  171. errors.value[field] = "";
  172. };
  173. const editUser = () => {
  174. if (!validateForm()) {
  175. toast.error("لطفا فیلد های لازم را وارد نمایید", {
  176. position: "top-right",
  177. autoClose: 1000,
  178. });
  179. return;
  180. }
  181. loading.value = true;
  182. const formData = new FormData();
  183. formData.append("mobile", localMobile.value);
  184. if (localName.value)
  185. formData.append("name", localName.value);
  186. formData.append("role", localRole.value);
  187. if (password.value) {
  188. formData.append("password", password.value);
  189. }
  190. ApiServiece.put(`admin/users/${localId.value}`, formData)
  191. .then(() => {
  192. toast.success("!کاربر با موفقیت ویرایش شد", {
  193. position: "top-right",
  194. autoClose: 1000,
  195. onClose: () => emit("user-updated"),
  196. });
  197. })
  198. .then(() => {
  199. setTimeout(() => {
  200. document.getElementById("close").click();
  201. emit("user-updated");
  202. }, 500);
  203. })
  204. .catch((error) => {
  205. console.error(error);
  206. toast.error("!ویرایش کاربر با مشکل مواحه شد", {
  207. position: "top-right",
  208. autoClose: 1000,
  209. onClose: () => emit("user-updated"),
  210. });
  211. })
  212. .finally(() => {
  213. loading.value = false;
  214. });
  215. };
  216. return {
  217. errors,
  218. loading,
  219. clearError,
  220. localName,
  221. localMobile,
  222. password,
  223. editUser,
  224. localRole,
  225. };
  226. },
  227. };
  228. </script>
  229. <style scoped>
  230. .profile-upload-wrapper {
  231. display: flex;
  232. flex-direction: column;
  233. align-items: center;
  234. }
  235. .profile-upload-icon {
  236. font-size: 64px;
  237. color: #6c757d;
  238. border: 2px dashed #6c757d;
  239. border-radius: 50%;
  240. width: 120px;
  241. height: 120px;
  242. display: flex;
  243. align-items: center;
  244. justify-content: center;
  245. margin-bottom: 10px;
  246. }
  247. .modal-dialog {
  248. max-width: 50%;
  249. }
  250. .modal-content {
  251. padding: 20px;
  252. }
  253. .modal-header {
  254. border-bottom: 1px solid #dee2e6;
  255. }
  256. .modal-body {
  257. padding: 20px;
  258. }
  259. .form-group {
  260. margin-bottom: 1rem;
  261. }
  262. .input-group {
  263. margin-top: 0.5rem;
  264. }
  265. .profile-upload-wrapper {
  266. display: flex;
  267. flex-direction: column;
  268. align-items: center;
  269. }
  270. .profile-upload-btn {
  271. width: 50px;
  272. height: 50px;
  273. display: flex;
  274. align-items: center;
  275. justify-content: center;
  276. cursor: pointer;
  277. border: 2px solid #007bff;
  278. background-color: #ffffff;
  279. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  280. }
  281. .profile-upload-btn i {
  282. font-size: 20px;
  283. color: #007bff;
  284. }
  285. .profile-image-preview {
  286. display: flex;
  287. justify-content: center;
  288. align-items: center;
  289. }
  290. .profile-placeholder {
  291. border: 2px dashed #007bff;
  292. }
  293. .d-none {
  294. display: none;
  295. }
  296. .profile-upload-wrapper {
  297. display: flex;
  298. flex-direction: column;
  299. align-items: center;
  300. }
  301. .profile-upload-btn {
  302. width: 30px; /* اندازه دکمه را کوچک‌تر کنید */
  303. height: 30px;
  304. padding: 0;
  305. display: flex;
  306. align-items: center;
  307. justify-content: center;
  308. border: 1px solid #ccc; /* کمی خط دور دکمه برای بهتر دیده شدن */
  309. background-color: #fff;
  310. cursor: pointer;
  311. }
  312. .profile-upload-btn i {
  313. font-size: 16px; /* اندازه آیکون را کوچک‌تر کنید */
  314. color: #007bff; /* رنگ آیکون را تغییر دهید */
  315. }
  316. .profile-image-preview img,
  317. .profile-placeholder {
  318. width: 80px;
  319. height: 80px;
  320. }
  321. .profile-placeholder i {
  322. font-size: 40px;
  323. }
  324. .modal-dialog {
  325. max-width: 50%;
  326. }
  327. .modal-content {
  328. padding: 1.5rem; /* Increased padding for better spacing */
  329. }
  330. .modal-header {
  331. border-bottom: 1px solid #dee2e6;
  332. padding-bottom: 1rem; /* Added padding-bottom to separate the header from the content */
  333. }
  334. .modal-body {
  335. padding: 1rem 1.5rem; /* Adjusted padding for a more balanced layout */
  336. }
  337. .form-group {
  338. margin-bottom: 1.5rem; /* Increased margin between form groups */
  339. }
  340. .input-group {
  341. margin-top: 0.5rem;
  342. }
  343. .profile-image-preview:hover .overlay {
  344. opacity: 1;
  345. }
  346. .profile-image-preview:hover img,
  347. .profile-image-preview:hover .profile-placeholder {
  348. opacity: 0.7;
  349. }
  350. </style>