選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

378 行
9.8 KiB

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