const AccountState = { orders: [], courses: [], tutors: [], currentOrderPage: 1, ordersPerPage: 5, editingOrder: null }; document.addEventListener('DOMContentLoaded', () => { initAccount(); }); // Инициализировать страницу личного кабинета async function initAccount() { await loadAccountData(); setupAccountEventListeners(); } // Загрузить данные аккаунта с сервера async function loadAccountData() { try { AccountState.orders = await apiRequest('/orders'); AccountState.courses = await apiRequest('/courses'); AccountState.tutors = await apiRequest('/tutors'); renderOrders(); updateOrdersCount(); } catch (error) { showNotification('Ошибка загрузки данных: ' + error.message, 'error'); } } // Настроить обработчики событий для страницы function setupAccountEventListeners() { const saveOrderChanges = document.getElementById('saveOrderChanges'); if (saveOrderChanges) { saveOrderChanges.addEventListener('click', saveOrderEdit); } const confirmDelete = document.getElementById('confirmDelete'); if (confirmDelete) { confirmDelete.addEventListener('click', confirmOrderDeletion); } const editCourseStartDate = document.getElementById('editCourseStartDate'); if (editCourseStartDate) { editCourseStartDate.addEventListener('change', updateEditCourseTimeSlots); } const editCourseStartTime = document.getElementById('editCourseStartTime'); if (editCourseStartTime) { editCourseStartTime.addEventListener('change', calculateEditCoursePrice); } const editStudentsNumber = document.getElementById('editStudentsNumber'); if (editStudentsNumber) { editStudentsNumber.addEventListener('input', calculateEditCoursePrice); } const editCheckboxes = ['editSupplementary', 'editPersonalized', 'editExcursions', 'editAssessment', 'editInteractive']; editCheckboxes.forEach(id => { const checkbox = document.getElementById(id); if (checkbox) { checkbox.addEventListener('change', calculateEditCoursePrice); } }); } function updateOrdersCount() { const countBadge = document.getElementById('ordersCount'); if (!countBadge) return; const count = AccountState.orders.length; countBadge.textContent = pluralize(count, 'заявка', 'заявки', 'заявок'); } // Отрисовать таблицу заявок function renderOrders() { const emptyState = document.getElementById('emptyState'); const ordersTable = document.getElementById('ordersTable'); const tbody = document.getElementById('ordersList'); if (AccountState.orders.length === 0) { emptyState.style.display = 'block'; ordersTable.style.display = 'none'; return; } emptyState.style.display = 'none'; ordersTable.style.display = 'block'; tbody.innerHTML = ''; const startIdx = (AccountState.currentOrderPage - 1) * AccountState.ordersPerPage; const endIdx = startIdx + AccountState.ordersPerPage; const ordersToShow = AccountState.orders.slice(startIdx, endIdx); ordersToShow.forEach((order, index) => { const tr = document.createElement('tr'); const orderNumber = startIdx + index + 1; let orderName = ''; if (order.course_id && order.course_id > 0) { const course = AccountState.courses.find( c => c.id === order.course_id ); orderName = course ? course.name : `Курс #${order.course_id}`; } else if (order.tutor_id && order.tutor_id > 0) { const tutor = AccountState.tutors.find( t => t.id === order.tutor_id ); orderName = tutor ? `Репетитор: ${tutor.name}` : `Репетитор #${order.tutor_id}`; } const orderDate = formatDateTimeWithoutSeconds( order.date_start, order.time_start ); tr.innerHTML = ` ${orderNumber} ${orderName} ${orderDate} ${formatPrice(order.price)}
`; tbody.appendChild(tr); }); document.querySelectorAll('.view-order-btn').forEach(btn => { btn.addEventListener('click', (e) => { const orderId = parseInt(e.currentTarget .getAttribute('data-order-id')); viewOrderDetails(orderId); }); }); document.querySelectorAll('.edit-order-btn').forEach(btn => { btn.addEventListener('click', (e) => { const orderId = parseInt(e.currentTarget .getAttribute('data-order-id')); editOrder(orderId); }); }); document.querySelectorAll('.delete-order-btn').forEach(btn => { btn.addEventListener('click', (e) => { const orderId = parseInt(e.currentTarget .getAttribute('data-order-id')); showDeleteConfirmation(orderId); }); }); renderOrdersPagination(); } function renderOrdersPagination() { const container = document.getElementById('ordersPagination'); if (!container) return; container.innerHTML = ''; const totalPages = Math.ceil(AccountState.orders.length / AccountState.ordersPerPage); if (totalPages <= 1) return; const createPageItem = (page, text, disabled = false) => { const li = document.createElement('li'); li.className = `page-item ${disabled ? 'disabled' : ''} ${page === AccountState.currentOrderPage ? 'active' : ''}`; const a = document.createElement('a'); a.className = 'page-link'; a.href = '#'; a.textContent = text || page; if (!disabled) { a.addEventListener('click', (e) => { e.preventDefault(); AccountState.currentOrderPage = page; renderOrders(); }); } li.appendChild(a); return li; }; container.appendChild( createPageItem(AccountState.currentOrderPage - 1, 'Назад', AccountState.currentOrderPage === 1) ); for (let i = 1; i <= totalPages; i++) { container.appendChild(createPageItem(i, i, false)); } container.appendChild( createPageItem(AccountState.currentOrderPage + 1, 'Вперед', AccountState.currentOrderPage === totalPages) ); } // Показать детальную информацию о заявке function viewOrderDetails(orderId) { const order = AccountState.orders.find(o => o.id === orderId); if (!order) return; const modal = new bootstrap.Modal( document.getElementById('orderDetailModal') ); const content = document.getElementById('orderDetailContent'); let orderTitle = ''; let teacherInfo = ''; if (order.course_id && order.course_id > 0) { const course = AccountState.courses.find( c => c.id === order.course_id ); if (course) { orderTitle = course.name; teacherInfo = `

Преподаватель: ${course.teacher}

`; } } else if (order.tutor_id && order.tutor_id > 0) { const tutor = AccountState.tutors.find( t => t.id === order.tutor_id ); if (tutor) { orderTitle = `Репетитор: ${tutor.name}`; } } const options = []; if (order.early_registration) options.push('Ранняя регистрация (-10%)'); if (order.group_enrollment) options.push('Групповая скидка (-15%)'); if (order.intensive_course) options.push('Интенсивный курс (+20%)'); if (order.supplementary) options.push('Дополнительные учебные материалы (+2000₽/студ.)'); if (order.personalized) options.push('Индивидуальные занятия (+1500₽/нед.)'); if (order.excursions) options.push('Культурные экскурсии (+25%)'); if (order.assessment) options.push('Оценка уровня владения языком (+300₽)'); if (order.interactive) options.push('Доступ к интерактивной онлайн-платформе (+50%)'); const optionsBadges = options.map(opt => `${opt}` ).join(''); const contactData = ContactDataStorage.get(order.id); let contactInfo = ''; if (contactData) { contactInfo = `
Контактные данные:

Имя: ${contactData.name}

Телефон: ${contactData.phone}

Email: ${contactData.email}

${contactData.message ? `

Сообщение: ${contactData.message}

` : ''} `; } let detailsHTML = `
${orderTitle}
${teacherInfo}`; let priceLabel = ''; if (order.course_id && order.course_id > 0) { detailsHTML += `

Дата: ${formatDate(order.date_start)}

Время: ${formatTime(order.time_start)}

Продолжительность: ${order.duration} часов

Количество студентов: ${order.persons}

${options.length > 0 ? `

Выбранные опции:
${optionsBadges}

` : ''} `; priceLabel = `Итоговая стоимость: ${formatPrice(order.price)}`; } else if (order.tutor_id && order.tutor_id > 0) { detailsHTML += `

Заявка на индивидуальные занятия с репетитором

`; priceLabel = `Стоимость: ${formatPrice(order.price)}/час`; } detailsHTML += ` ${contactInfo}
${priceLabel}
`; content.innerHTML = detailsHTML; modal.show(); } // Открыть модальное окно редактирования заявки function editOrder(orderId) { const order = AccountState.orders.find(o => o.id === orderId); if (!order) return; AccountState.editingOrder = order; const modal = new bootstrap.Modal( document.getElementById('editOrderModal') ); document.getElementById('editOrderId').value = order.id; const editCourseFields = document.getElementById('editCourseFields'); const editTutorFields = document.getElementById('editTutorFields'); const contactData = ContactDataStorage.get(order.id); if (contactData) { document.getElementById('editStudentName').value = contactData.name || ''; document.getElementById('editStudentPhone').value = contactData.phone || ''; document.getElementById('editStudentEmail').value = contactData.email || ''; document.getElementById('editStudentMessage').value = contactData.message || ''; } if (order.course_id && order.course_id > 0) { editCourseFields.style.display = 'block'; editTutorFields.style.display = 'none'; const course = AccountState.courses.find( c => c.id === order.course_id ); if (course) { document.getElementById('editCourseId').value = course.id; document.getElementById('editCourseName').value = course.name; document.getElementById('editCourseTeacher').value = course.teacher; // Получить уникальные даты const uniqueDates = [...new Set(course.start_dates.map(dt => dt.split('T')[0]))]; const startDateSelect = document.getElementById('editCourseStartDate'); startDateSelect.innerHTML = ''; uniqueDates.forEach(dateStr => { const option = document.createElement('option'); option.value = dateStr; option.textContent = formatDate(dateStr); startDateSelect.appendChild(option); }); // Установить текущую дату и время заказа startDateSelect.value = order.date_start; updateEditCourseTimeSlots(); // Установить время после обновления списка времён const timeSelect = document.getElementById('editCourseStartTime'); if (order.time_start && timeSelect) { timeSelect.value = order.time_start; } const durationText = `${course.total_length} недель, ${course.week_length} ч/нед`; document.getElementById('editCourseDuration').value = durationText; document.getElementById('editStudentsNumber').value = order.persons; document.getElementById('editEarlyRegistration').checked = order.early_registration; document.getElementById('editGroupEnrollment').checked = order.group_enrollment; document.getElementById('editIntensiveCourse').checked = order.intensive_course; document.getElementById('editSupplementary').checked = order.supplementary; document.getElementById('editPersonalized').checked = order.personalized; document.getElementById('editExcursions').checked = order.excursions; document.getElementById('editAssessment').checked = order.assessment; document.getElementById('editInteractive').checked = order.interactive; } } else if (order.tutor_id && order.tutor_id > 0) { editCourseFields.style.display = 'none'; editTutorFields.style.display = 'block'; const tutor = AccountState.tutors.find( t => t.id === order.tutor_id ); if (tutor) { document.getElementById('editTutorId').value = tutor.id; document.getElementById('editTutorName').value = tutor.name; } } modal.show(); setTimeout(() => { if (order.course_id && order.course_id > 0) { calculateEditCoursePrice(); } else if (order.tutor_id && order.tutor_id > 0) { const tutor = AccountState.tutors.find( t => t.id === order.tutor_id ); const price = tutor ? tutor.price_per_hour : order.price; document.getElementById('editTotalPrice').textContent = price; } }, 100); } function updateEditCourseTimeSlots() { const selectedDate = document.getElementById('editCourseStartDate').value; const timeSelect = document.getElementById('editCourseStartTime'); if (!selectedDate) { timeSelect.disabled = true; timeSelect.innerHTML = ''; document.getElementById('editCourseEndDate').value = ''; return; } timeSelect.disabled = false; timeSelect.innerHTML = ''; const courseId = parseInt( document.getElementById('editCourseId').value ); const course = AccountState.courses.find(c => c.id === courseId); if (course) { const duration = course.week_length; // Фильтруем времена для выбранной даты const timesForDate = course.start_dates .filter(dt => dt.split('T')[0] === selectedDate) .map(dt => dt.split('T')[1].substring(0, 5)); timesForDate.forEach(timeStr => { const startHour = parseInt(timeStr.split(':')[0]); const startMinute = parseInt(timeStr.split(':')[1]); const endHour = startHour + duration; const endTimeStr = `${String(endHour).padStart(2, '0')}:${String(startMinute).padStart(2, '0')}`; const surcharge = getTimeSurcharge(timeStr); let surchargeText = surcharge > 0 ? ` (+${surcharge}₽)` : ''; const option = document.createElement('option'); option.value = timeStr; option.textContent = `${timeStr} - ${endTimeStr}${surchargeText}`; timeSelect.appendChild(option); }); // Устанавливаем дату окончания курса const endDate = formatEndDate(selectedDate, course.total_length); document.getElementById('editCourseEndDate').value = endDate; } calculateEditCoursePrice(); } // Рассчитать итоговую цену при редактировании function calculateEditCoursePrice() { const courseId = parseInt( document.getElementById('editCourseId').value ); const course = AccountState.courses.find(c => c.id === courseId); if (!course) return; const startDate = document.getElementById('editCourseStartDate').value; const startTime = document.getElementById('editCourseStartTime').value; const persons = parseInt( document.getElementById('editStudentsNumber').value ) || 1; if (!startDate || !startTime) { document.getElementById('editTotalPrice').textContent = '0'; document.getElementById('editCourseEndDate').value = ''; return; } // Устанавливаем дату окончания курса const endDate = formatEndDate(startDate, course.total_length); document.getElementById('editCourseEndDate').value = endDate; const courseFeePerHour = course.course_fee_per_hour; const totalHours = course.total_length * course.week_length; const weekendMultiplier = getWeekendMultiplier(startDate); const timeSurcharge = getTimeSurcharge(startTime); let basePrice = (courseFeePerHour * totalHours * weekendMultiplier + timeSurcharge) * persons; const earlyReg = isEarlyRegistration(startDate); const groupEnroll = persons >= 5; const intensive = course.week_length > 20; document.getElementById('editEarlyRegistration').checked = earlyReg; document.getElementById('editGroupEnrollment').checked = groupEnroll; document.getElementById('editIntensiveCourse').checked = intensive; if (earlyReg) basePrice *= 0.9; if (groupEnroll) basePrice *= 0.85; if (intensive) basePrice *= 1.2; if (document.getElementById('editSupplementary').checked) { basePrice += 2000 * persons; } if (document.getElementById('editPersonalized').checked) { basePrice += 1500 * course.total_length; } if (document.getElementById('editExcursions').checked) { basePrice *= 1.25; } if (document.getElementById('editAssessment').checked) { basePrice += 300; } if (document.getElementById('editInteractive').checked) { basePrice *= 1.5; } document.getElementById('editTotalPrice').textContent = Math.round(basePrice); } // Сохранить изменения заявки на сервер async function saveOrderEdit() { const form = document.getElementById('editOrderForm'); if (!form.checkValidity()) { form.reportValidity(); return; } const orderId = parseInt( document.getElementById('editOrderId').value ); const order = AccountState.editingOrder; const contactData = { name: document.getElementById('editStudentName').value, phone: document.getElementById('editStudentPhone').value, email: document.getElementById('editStudentEmail').value, message: document.getElementById('editStudentMessage').value }; let orderData = { price: parseInt( document.getElementById('editTotalPrice').textContent ) }; if (order.course_id && order.course_id > 0) { const courseId = parseInt( document.getElementById('editCourseId').value ); const course = AccountState.courses.find( c => c.id === courseId ); const startDate = document.getElementById('editCourseStartDate').value .split('T')[0]; const startTime = document.getElementById('editCourseStartTime').value; const persons = parseInt( document.getElementById('editStudentsNumber').value ); orderData = { ...orderData, course_id: courseId, tutor_id: 0, date_start: startDate, time_start: startTime, duration: course.total_length * course.week_length, persons: persons, early_registration: document.getElementById('editEarlyRegistration').checked, group_enrollment: document.getElementById('editGroupEnrollment').checked, intensive_course: document.getElementById('editIntensiveCourse').checked, supplementary: document.getElementById('editSupplementary').checked, personalized: document.getElementById('editPersonalized').checked, excursions: document.getElementById('editExcursions').checked, assessment: document.getElementById('editAssessment').checked, interactive: document.getElementById('editInteractive').checked }; } else if (order.tutor_id && order.tutor_id > 0) { const tutorId = parseInt( document.getElementById('editTutorId').value ); const tutor = AccountState.tutors.find(t => t.id === tutorId); // Используем текущую дату как плейсхолдер или сохраняем существующую const dateStr = order.date_start || new Date().toISOString().split('T')[0]; const timeStr = order.time_start || '10:00'; orderData = { ...orderData, tutor_id: tutorId, course_id: 0, date_start: dateStr, time_start: timeStr, duration: 1, persons: 1, price: tutor ? tutor.price_per_hour : order.price, early_registration: false, group_enrollment: false, intensive_course: false, supplementary: false, personalized: false, excursions: false, assessment: false, interactive: false }; } try { await updateOrder(orderId, orderData, contactData); const modal = bootstrap.Modal.getInstance( document.getElementById('editOrderModal') ); modal.hide(); await loadAccountData(); } catch (error) { console.error('Error updating order:', error); } } function showDeleteConfirmation(orderId) { const modal = new bootstrap.Modal( document.getElementById('deleteOrderModal') ); document.getElementById('deleteOrderId').value = orderId; modal.show(); } // Подтвердить удаление заявки async function confirmOrderDeletion() { const orderId = parseInt( document.getElementById('deleteOrderId').value ); try { await deleteOrder(orderId); const modal = bootstrap.Modal.getInstance( document.getElementById('deleteOrderModal') ); modal.hide(); await loadAccountData(); } catch (error) { console.error('Error deleting order:', error); } } function updateUserInfo() { updateOrdersCount(); }