diff --git a/src/api/seedApi.js b/src/api/seedApi.js index db04cd0..7f76cc8 100644 --- a/src/api/seedApi.js +++ b/src/api/seedApi.js @@ -3,5 +3,13 @@ import axiosInstance from './axiosInstance'; export const seedApi = { getStatus: () => axiosInstance.get('/seed/status'), - runSeed: () => axiosInstance.post('/seed', {}, { timeout: 60000 }) + runSeed: () => axiosInstance.post('/seed', {}, { timeout: 60000 }), + importData: (file) => { + const formData = new FormData(); + formData.append('file', file); + return axiosInstance.post('/data-import', formData, { + timeout: 180000, + headers: { 'Content-Type': 'multipart/form-data' } + }); + } }; diff --git a/src/locales/fa.json b/src/locales/fa.json index 3802d62..2cabb04 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -50,13 +50,21 @@ "addUser": "افزودن کاربر جدید", "editUser": "ویرایش کاربر", "name": "نام", - "surname": "نام خانوادگی", + "gender": "جنسیت", "nationalId": "کد ملی", "phone": "شماره همراه", "email": "ایمیل", "preferredMessenger": "پیام‌رسان ترجیحی", "role": "نقش کاربر", "status": "وضعیت حساب", + "fatherName": "نام پدر", + "birthCertificateNumber": "شماره شناسنامه", + "birthDate": "تاریخ تولد", + "placeOfIssue": "محل صدور", + "postalCode": "کد پستی", + "education": "میزان تحصیلات و رشته", + "parentPhoneNumber": "تلفن همراه والد", + "address": "آدرس", "tabInfo": "اطلاعات شخصی", "tabCourses": "دوره‌های ثبت‌نامی", "tabSessions": "حضور و غیاب", diff --git a/src/views/attendances/AttendanceEntryView.vue b/src/views/attendances/AttendanceEntryView.vue index eff0085..855bd27 100644 --- a/src/views/attendances/AttendanceEntryView.vue +++ b/src/views/attendances/AttendanceEntryView.vue @@ -31,7 +31,7 @@ @@ -121,7 +121,8 @@ const fetchSessionAttendance = async () => { return { userId: user._id, name: user.name || '', - surname: user.surname || '', + name: user.name || '', + gender: user.gender || null, nationalIdCode: user.nationalIdCode || '', status: existing?.status || 'present', note: existing?.note || '' diff --git a/src/views/classes/ClassDetailView.vue b/src/views/classes/ClassDetailView.vue index c23bff6..6993aaf 100644 --- a/src/views/classes/ClassDetailView.vue +++ b/src/views/classes/ClassDetailView.vue @@ -47,7 +47,7 @@ - + diff --git a/src/views/classes/ClassFormView.vue b/src/views/classes/ClassFormView.vue index a5f4230..286a381 100644 --- a/src/views/classes/ClassFormView.vue +++ b/src/views/classes/ClassFormView.vue @@ -97,7 +97,7 @@ - + @@ -64,6 +125,12 @@ const isSeeding = ref(false); const isLocked = ref(false); const lockedAt = ref(null); +const fileInputRef = ref(null); +const selectedFile = ref(null); +const selectedFileName = ref(''); +const isImporting = ref(false); +const importResult = ref(null); + const lockedAtLabel = computed(() => { if (!lockedAt.value) return ''; const date = new Date(lockedAt.value); @@ -118,5 +185,48 @@ const confirmSeed = () => { }); }; +const onFileSelected = (event) => { + const file = event.target.files?.[0] || null; + selectedFile.value = file; + selectedFileName.value = file?.name || ''; + importResult.value = null; +}; + +const runImport = async () => { + if (!selectedFile.value) return; + isImporting.value = true; + try { + const response = await seedApi.importData(selectedFile.value); + const data = response?.data || response; + importResult.value = data; + showSuccess('داده‌ها با موفقیت به پایگاه داده اضافه شدند.'); + } catch (err) { + showError(err); + } finally { + isImporting.value = false; + } +}; + +const confirmImport = () => { + if (!selectedFile.value) return; + confirm.require({ + header: 'وارد کردن داده‌ها', + message: 'دوره‌ها، کلاس‌ها و کاربران از فایل JSON به پایگاه داده افزوده می‌شوند. داده‌های موجود حذف نمی‌شوند. ادامه می‌دهید؟', + icon: 'pi pi-upload', + acceptLabel: 'بارگذاری', + rejectLabel: 'انصراف', + acceptClass: 'p-button-primary', + accept: () => { + runImport(); + } + }); +}; + onMounted(loadStatus); + + diff --git a/src/views/users/UserDetailView.vue b/src/views/users/UserDetailView.vue index cfe29f4..ae9ab8d 100644 --- a/src/views/users/UserDetailView.vue +++ b/src/views/users/UserDetailView.vue @@ -1,7 +1,7 @@