Продолжение: Интеграции (формы, карты, аналитика)

21. Интеграция форм с отправкой на email

HTML структура формы:

<!-- Форма обратной связи с расширенным функционалом -->
<section class="contact-form-section" id="contact">
    <div class="container">
        <div class="section-header text-center">
            <span class="section-subtitle">Свяжитесь с нами</span>
            <h2 class="section-title">Оставьте заявку</h2>
            <p class="section-description">Заполните форму, и мы свяжемся с вами в течение 15 минут</p>
        </div>

        <div class="contact-wrapper">
            <!-- Форма -->
            <div class="contact-form-container">
                <form id="contactForm" class="contact-form" novalidate>
                    <div class="form-row">
                        <div class="form-group">
                            <label for="name" class="form-label">
                                Ваше имя <span class="required">*</span>
                            </label>
                            <div class="input-wrapper">
                                <i class="fas fa-user input-icon"></i>
                                <input 
                                    type="text" 
                                    id="name" 
                                    name="name" 
                                    class="form-control" 
                                    placeholder="Иван Петров"
                                    required
                                    minlength="2"
                                    maxlength="50"
                                >
                            </div>
                            <span class="error-message"></span>
                        </div>

                        <div class="form-group">
                            <label for="phone" class="form-label">
                                Телефон <span class="required">*</span>
                            </label>
                            <div class="input-wrapper">
                                <i class="fas fa-phone input-icon"></i>
                                <input 
                                    type="tel" 
                                    id="phone" 
                                    name="phone" 
                                    class="form-control" 
                                    placeholder="+7 (999) 123-45-67"
                                    required
                                    data-mask="+7 (999) 999-99-99"
                                >
                            </div>
                            <span class="error-message"></span>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="email" class="form-label">
                            Email <span class="required">*</span>
                        </label>
                        <div class="input-wrapper">
                            <i class="fas fa-envelope input-icon"></i>
                            <input 
                                type="email" 
                                id="email" 
                                name="email" 
                                class="form-control" 
                                placeholder="example@mail.com"
                                required
                            >
                        </div>
                        <span class="error-message"></span>
                    </div>

                    <div class="form-group">
                        <label for="service" class="form-label">
                            Интересующая услуга
                        </label>
                        <div class="input-wrapper">
                            <i class="fas fa-briefcase input-icon"></i>
                            <select id="service" name="service" class="form-control">
                                <option value="">Выберите услугу</option>
                                <option value="landing">Лендинг</option>
                                <option value="corporate">Корпоративный сайт</option>
                                <option value="ecommerce">Интернет-магазин</option>
                                <option value="redesign">Редизайн сайта</option>
                                <option value="support">Техническая поддержка</option>
                                <option value="seo">SEO-продвижение</option>
                                <option value="other">Другое</option>
                            </select>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="budget" class="form-label">
                            Бюджет проекта
                        </label>
                        <div class="budget-options">
                            <label class="budget-option">
                                <input type="radio" name="budget" value="20000-50000">
                                <span>20 000 - 50 000 ₽</span>
                            </label>
                            <label class="budget-option">
                                <input type="radio" name="budget" value="50000-100000">
                                <span>50 000 - 100 000 ₽</span>
                            </label>
                            <label class="budget-option">
                                <input type="radio" name="budget" value="100000+">
                                <span>от 100 000 ₽</span>
                            </label>
                            <label class="budget-option">
                                <input type="radio" name="budget" value="discuss">
                                <span>Обсудим</span>
                            </label>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="message" class="form-label">
                            Сообщение
                        </label>
                        <div class="input-wrapper">
                            <i class="fas fa-comment input-icon"></i>
                            <textarea 
                                id="message" 
                                name="message" 
                                class="form-control" 
                                rows="5"
                                placeholder="Расскажите о вашем проекте..."
                                maxlength="1000"
                            ></textarea>
                        </div>
                        <div class="char-counter">
                            <span class="current">0</span> / <span class="max">1000</span>
                        </div>
                    </div>

                    <div class="form-group">
                        <label class="file-upload">
                            <input type="file" id="attachment" name="attachment" accept=".pdf,.doc,.docx,.txt,.jpg,.png" multiple>
                            <span class="file-upload-btn">
                                <i class="fas fa-paperclip"></i>
                                Прикрепить файлы
                            </span>
                            <span class="file-upload-text">PDF, DOC, TXT, JPG, PNG (макс. 5 МБ)</span>
                        </label>
                        <div class="file-list"></div>
                    </div>

                    <div class="form-group">
                        <label class="checkbox-wrapper">
                            <input type="checkbox" name="agreement" required>
                            <span class="checkbox-custom"></span>
                            <span class="checkbox-label">
                                Я согласен с <a href="#" target="_blank">политикой конфиденциальности</a> <span class="required">*</span>
                            </span>
                        </label>
                        <span class="error-message"></span>
                    </div>

                    <div class="form-group">
                        <label class="checkbox-wrapper">
                            <input type="checkbox" name="subscribe">
                            <span class="checkbox-custom"></span>
                            <span class="checkbox-label">
                                Хочу получать новости и специальные предложения
                            </span>
                        </label>
                    </div>

                    <button type="submit" class="btn btn-primary btn-lg btn-block">
                        <span class="btn-text">Отправить заявку</span>
                        <span class="btn-loader">
                            <i class="fas fa-spinner fa-spin"></i>
                        </span>
                    </button>

                    <p class="form-note">
                        <i class="fas fa-lock"></i>
                        Ваши данные защищены и не будут переданы третьим лицам
                    </p>
                </form>

                <!-- Сообщение об успехе -->
                <div class="form-success" id="formSuccess">
                    <div class="success-icon">
                        <i class="fas fa-check-circle"></i>
                    </div>
                    <h3>Спасибо за заявку!</h3>
                    <p>Мы получили ваше сообщение и свяжемся с вами в ближайшее время.</p>
                    <button class="btn btn-outline" onclick="resetForm()">
                        Отправить еще одну заявку
                    </button>
                </div>
            </div>

            <!-- Контактная информация -->
            <div class="contact-info">
                <div class="info-card">
                    <div class="info-icon">
                        <i class="fas fa-phone-alt"></i>
                    </div>
                    <div class="info-content">
                        <h4>Телефон</h4>
                        <a href="tel:+79991234567">+7 (999) 123-45-67</a>
                        <p>Пн-Пт: 9:00 - 18:00</p>
                    </div>
                </div>

                <div class="info-card">
                    <div class="info-icon">
                        <i class="fas fa-envelope"></i>
                    </div>
                    <div class="info-content">
                        <h4>Email</h4>
                        <a href="mailto:info@example.com">info@example.com</a>
                        <p>Ответим в течение часа</p>
                    </div>
                </div>

                <div class="info-card">
                    <div class="info-icon">
                        <i class="fas fa-map-marker-alt"></i>
                    </div>
                    <div class="info-content">
                        <h4>Адрес</h4>
                        <p>г. Москва, ул. Примерная, д. 1</p>
                        <a href="#map">Показать на карте</a>
                    </div>
                </div>

                <div class="info-card">
                    <div class="info-icon">
                        <i class="fas fa-clock"></i>
                    </div>
                    <div class="info-content">
                        <h4>График работы</h4>
                        <p>Пн-Пт: 9:00 - 18:00</p>
                        <p>Сб-Вс: Выходной</p>
                    </div>
                </div>

                <div class="social-links">
                    <h4>Мы в соцсетях</h4>
                    <div class="social-icons">
                        <a href="#" class="social-icon" aria-label="Telegram">
                            <i class="fab fa-telegram"></i>
                        </a>
                        <a href="#" class="social-icon" aria-label="WhatsApp">
                            <i class="fab fa-whatsapp"></i>
                        </a>
                        <a href="#" class="social-icon" aria-label="VK">
                            <i class="fab fa-vk"></i>
                        </a>
                        <a href="#" class="social-icon" aria-label="Instagram">
                            <i class="fab fa-instagram"></i>
                        </a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>

CSS стили для формы:

/* Секция формы */
.contact-form-section {
    padding: 80px 0;
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
}

.contact-wrapper {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 40px;
    margin-top: 50px;
}

/* Контейнер формы */
.contact-form-container {
    position: relative;
}

.contact-form {
    background: white;
    padding: 40px;
    border-radius: 15px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
}

/* Строка формы */
.form-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
}

/* Группа формы */
.form-group {
    margin-bottom: 25px;
}

.form-label {
    display: block;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-color);
    margin-bottom: 8px;
}

.required {
    color: var(--primary-color);
}

/* Обертка для input с иконкой */
.input-wrapper {
    position: relative;
}

.input-icon {
    position: absolute;
    left: 15px;
    top: 50%;
    transform: translateY(-50%);
    color: #6c757d;
    font-size: 16px;
    pointer-events: none;
    transition: color 0.3s ease;
}

.form-control {
    width: 100%;
    padding: 12px 15px 12px 45px;
    font-size: 15px;
    border: 2px solid #e9ecef;
    border-radius: 8px;
    background: white;
    color: var(--text-color);
    transition: all 0.3s ease;
}

.form-control:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.1);
}

.form-control:focus + .input-icon {
    color: var(--primary-color);
}

.form-control.error {
    border-color: #dc3545;
}

.form-control.success {
    border-color: #28a745;
}

/* Select */
select.form-control {
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236c757d' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 15px center;
    padding-right: 40px;
}

/* Textarea */
textarea.form-control {
    resize: vertical;
    min-height: 120px;
    padding-top: 15px;
}

/* Счетчик символов */
.char-counter {
    text-align: right;
    font-size: 12px;
    color: #6c757d;
    margin-top: 5px;
}

.char-counter .current {
    font-weight: 600;
}

/* Опции бюджета */
.budget-options {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}

.budget-option {
    position: relative;
    cursor: pointer;
}

.budget-option input[type="radio"] {
    position: absolute;
    opacity: 0;
}

.budget-option span {
    display: block;
    padding: 12px 15px;
    background: #f8f9fa;
    border: 2px solid #e9ecef;
    border-radius: 8px;
    text-align: center;
    font-size: 14px;
    font-weight: 500;
    transition: all 0.3s ease;
}

.budget-option:hover span {
    border-color: var(--primary-color);
    background: rgba(255, 107, 107, 0.05);
}

.budget-option input[type="radio"]:checked + span {
    background: var(--primary-color);
    border-color: var(--primary-color);
    color: white;
}

/* Загрузка файлов */
.file-upload {
    display: block;
    cursor: pointer;
}

.file-upload input[type="file"] {
    display: none;
}

.file-upload-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    background: #f8f9fa;
    border: 2px dashed #e9ecef;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 500;
    color: var(--text-color);
    transition: all 0.3s ease;
}

.file-upload:hover .file-upload-btn {
    border-color: var(--primary-color);
    background: rgba(255, 107, 107, 0.05);
    color: var(--primary-color);
}

.file-upload-text {
    display: block;
    margin-top: 8px;
    font-size: 12px;
    color: #6c757d;
}

.file-list {
    margin-top: 15px;
}

.file-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 15px;
    background: #f8f9fa;
    border-radius: 8px;
    margin-bottom: 8px;
}

.file-item-info {
    display: flex;
    align-items: center;
    gap: 10px;
}

.file-item-icon {
    color: var(--primary-color);
}

.file-item-name {
    font-size: 14px;
    color: var(--text-color);
}

.file-item-size {
    font-size: 12px;
    color: #6c757d;
}

.file-item-remove {
    background: none;
    border: none;
    color: #dc3545;
    cursor: pointer;
    padding: 5px;
    transition: transform 0.2s ease;
}

.file-item-remove:hover {
    transform: scale(1.2);
}

/* Checkbox */
.checkbox-wrapper {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    cursor: pointer;
    user-select: none;
}

.checkbox-wrapper input[type="checkbox"] {
    position: absolute;
    opacity: 0;
}

.checkbox-custom {
    position: relative;
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    border: 2px solid #e9ecef;
    border-radius: 4px;
    background: white;
    transition: all 0.3s ease;
}

.checkbox-custom::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) scale(0);
    width: 10px;
    height: 10px;
    background: white;
    border-radius: 2px;
    transition: transform 0.2s ease;
}

.checkbox-wrapper input[type="checkbox"]:checked + .checkbox-custom {
    background: var(--primary-color);
    border-color: var(--primary-color);
}

.checkbox-wrapper input[type="checkbox"]:checked + .checkbox-custom::after {
    transform: translate(-50%, -50%) scale(1);
}

.checkbox-wrapper:hover .checkbox-custom {
    border-color: var(--primary-color);
}

.checkbox-label {
    font-size: 14px;
    line-height: 1.5;
    color: #6c757d;
}

.checkbox-label a {
    color: var(--primary-color);
    text-decoration: none;
}

.checkbox-label a:hover {
    text-decoration: underline;
}

/* Сообщения об ошибках */
.error-message {
    display: block;
    font-size: 12px;
    color: #dc3545;
    margin-top: 5px;
    min-height: 18px;
}

/* Заметка формы */
.form-note {
    text-align: center;
    font-size: 13px;
    color: #6c757d;
    margin-top: 20px;
}

.form-note i {
    color: #28a745;
    margin-right: 5px;
}

/* Кнопка отправки */
.btn-block {
    width: 100%;
}

.btn-lg {
    padding: 15px 30px;
    font-size: 16px;
}

.btn[type="submit"] {
    position: relative;
}

.btn-loader {
    display: none;
}

.btn.loading .btn-text {
    opacity: 0;
}

.btn.loading .btn-loader {
    display: inline-block;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

/* Сообщение об успехе */
.form-success {
    display: none;
    text-align: center;
    padding: 60px 40px;
    background: white;
    border-radius: 15px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
}

.form-success.show {
    display: block;
    animation: fadeIn 0.5s ease;
}

.success-icon {
    width: 80px;
    height: 80px;
    margin: 0 auto 30px;
    background: linear-gradient(135deg, #28a745, #20c997);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 40px;
    animation: scaleIn 0.5s ease;
}

.form-success h3 {
    font-size: 28px;
    color: var(--text-color);
    margin-bottom: 15px;
}

.form-success p {
    font-size: 16px;
    color: #6c757d;
    margin-bottom: 30px;
}

@keyframes scaleIn {
    from {
        transform: scale(0);
    }
    to {
        transform: scale(1);
    }
}

/* Контактная информация */
.contact-info {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.info-card {
    display: flex;
    gap: 15px;
    padding: 25px;
    background: white;
    border-radius: 12px;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.05);
    transition: all 0.3s ease;
}

.info-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}

.info-icon {
    width: 50px;
    height: 50px;
    flex-shrink: 0;
    background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 20px;
}

.info-content h4 {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-color);
    margin-bottom: 8px;
}

.info-content p {
    font-size: 14px;
    color: #6c757d;
    margin: 5px 0;
}

.info-content a {
    color: var(--primary-color);
    text-decoration: none;
    font-weight: 500;
    transition: color 0.3s ease;
}

.info-content a:hover {
    color: var(--secondary-color);
}

/* Социальные ссылки */
.social-links {
    padding: 25px;
    background: white;
    border-radius: 12px;
    box-shadow: 0 5px 20px rgba(0, 0, 0, 0.05);
}

.social-links h4 {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-color);
    margin-bottom: 15px;
}

.social-icons {
    display: flex;
    gap: 10px;
}

.social-icon {
    width: 45px;
    height: 45px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
    border-radius: 10px;
    color: var(--text-color);
    font-size: 20px;
    text-decoration: none;
    transition: all 0.3s ease;
}

.social-icon:hover {
    background: var(--primary-color);
    color: white;
    transform: translateY(-3px);
}

/* Адаптивность */
@media (max-width: 992px) {
    .contact-wrapper {
        grid-template-columns: 1fr;
    }
    
    .contact-info {
        order: -1;
    }
}

@media (max-width: 768px) {
    .contact-form-section {
        padding: 60px 0;
    }
    
    .contact-form {
        padding: 30px 20px;
    }
    
    .form-row {
        grid-template-columns: 1fr;
    }
    
    .budget-options {
        grid-template-columns: 1fr;
    }
    
    .form-success {
        padding: 40px 20px;
    }
    
    .success-icon {
        width: 60px;
        height: 60px;
        font-size: 30px;
    }
    
    .form-success h3 {
        font-size: 24px;
    }
}

JavaScript для обработки формы:

// ============================================
// ОБРАБОТКА ФОРМЫ ОБРАТНОЙ СВЯЗИ
// ============================================

class ContactForm {
    constructor(formId) {
        this.form = document.getElementById(formId);
        if (!this.form) return;
        
        this.submitBtn = this.form.querySelector('button[type="submit"]');
        this.successMessage = document.getElementById('formSuccess');
        this.fileInput = this.form.querySelector('input[type="file"]');
        this.fileList = this.form.querySelector('.file-list');
        this.messageField = this.form.querySelector('#message');
        this.charCounter = this.form.querySelector('.char-counter');
        
        this.attachedFiles = [];
        this.maxFileSize = 5 * 1024 * 1024; // 5 МБ
        
        this.init();
    }
    
    init() {
        // Обработка отправки формы
        this.form.addEventListener('submit', (e) => this.handleSubmit(e));
        
        // Валидация в реальном времени
        this.form.querySelectorAll('input, textarea, select').forEach(field => {
            field.addEventListener('blur', () => this.validateField(field));
            field.addEventListener('input', () => {
                if (field.classList.contains('error')) {
                    this.validateField(field);
                }
            });
        });
        
        // Маска для телефона
        const phoneInput = this.form.querySelector('input[type="tel"]');
        if (phoneInput) {
            this.initPhoneMask(phoneInput);
        }
        
        // Загрузка файлов
        if (this.fileInput) {
            this.fileInput.addEventListener('change', (e) => this.handleFiles(e));
        }
        
        // Счетчик символов
        if (this.messageField && this.charCounter) {
            this.messageField.addEventListener('input', () => this.updateCharCounter());
        }
        
        // Предотвращение множественной отправки
        this.isSubmitting = false;
    }
    
    // Валидация поля
    validateField(field) {
        const value = field.value.trim();
        const fieldName = field.name;
        let isValid = true;
        let errorMessage = '';
        
        // Проверка обязательных полей
        if (field.hasAttribute('required') && !value) {
            isValid = false;
            errorMessage = 'Это поле обязательно для заполнения';
        }
        
        // Специфичная валидация
        if (value && isValid) {
            switch (field.type) {
                case 'email':
                    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                    if (!emailRegex.test(value)) {
                        isValid = false;
                        errorMessage = 'Введите корректный email';
                    }
                    break;
                    
                case 'tel':
                    const phoneRegex = /^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/;
                    if (!phoneRegex.test(value)) {
                        isValid = false;
                        errorMessage = 'Введите корректный номер телефона';
                    }
                    break;
                    
                case 'text':
                    if (fieldName === 'name') {
                        if (value.length < 2) {
                            isValid = false;
                            errorMessage = 'Имя должно содержать минимум 2 символа';
                        } else if (!/^[а-яА-ЯёЁa-zA-Z\s-]+$/.test(value)) {
                            isValid = false;
                            errorMessage = 'Имя может содержать только буквы';
                        }
                    }
                    break;
                    
                case 'checkbox':
                    if (field.hasAttribute('required') && !field.checked) {
                        isValid = false;
                        errorMessage = 'Необходимо согласие';
                    }
                    break;
            }
        }
        
        // Отображение результата валидации
        this.showFieldValidation(field, isValid, errorMessage);
        
        return isValid;
    }
    
    // Отображение результата валидации
    showFieldValidation(field, isValid, errorMessage) {
        const formGroup = field.closest('.form-group') || field.closest('.checkbox-wrapper')?.parentElement;
        const errorElement = formGroup?.querySelector('.error-message');
        
        if (isValid) {
            field.classList.remove('error');
            field.classList.add('success');
            if (errorElement) errorElement.textContent = '';
        } else {
            field.classList.remove('success');
            field.classList.add('error');
            if (errorElement) errorElement.textContent = errorMessage;
        }
    }
    
    // Валидация всей формы
    validateForm() {
        let isValid = true;
        const fields = this.form.querySelectorAll('input, textarea, select');
        
        fields.forEach(field => {
            if (!this.validateField(field)) {
                isValid = false;
            }
        });
        
        return isValid;
    }
    
    // Маска для телефона
    initPhoneMask(input) {
        input.addEventListener('input', (e) => {
            let value = e.target.value.replace(/\D/g, '');
            
            if (value.length > 0) {
                if (value[0] !== '7') {
                    value = '7' + value;
                }
                
                let formatted = '+7';
                
                if (value.length > 1) {
                    formatted += ' (' + value.substring(1, 4);
                }
                if (value.length >= 5) {
                    formatted += ') ' + value.substring(4, 7);
                }
                if (value.length >= 8) {
                    formatted += '-' + value.substring(7, 9);
                }
                if (value.length >= 10) {
                    formatted += '-' + value.substring(9, 11);
                }
                
                e.target.value = formatted;
            }
        });
        
        input.addEventListener('keydown', (e) => {
            if (e.key === 'Backspace' && e.target.value === '+7 (') {
                e.target.value = '';
            }
        });
    }
    
    // Обработка файлов
    handleFiles(e) {
        const files = Array.from(e.target.files);
        
        files.forEach(file => {
            // Проверка размера файла
            if (file.size > this.maxFileSize) {
                if (window.toast) {
                    window.toast.error('Ошибка', `Файл "${file.name}" слишком большой. Максимальный размер: 5 МБ`);
                }
                return;
            }
            
            // Добавление файла
            this.attachedFiles.push(file);
            this.renderFileItem(file);
        });
        
        // Очистка input
        e.target.value = '';
    }
    
    // Отображение файла
    renderFileItem(file) {
        const fileItem = document.createElement('div');
        fileItem.className = 'file-item';
        fileItem.innerHTML = `
            <div class="file-item-info">
                <i class="fas fa-file file-item-icon"></i>
                <div>
                    <div class="file-item-name">${file.name}</div>
                    <div class="file-item-size">${this.formatFileSize(file.size)}</div>
                </div>
            </div>
            <button type="button" class="file-item-remove" data-file-name="${file.name}">
                <i class="fas fa-times"></i>
            </button>
        `;
        
        // Обработчик удаления
        fileItem.querySelector('.file-item-remove').addEventListener('click', (e) => {
            const fileName = e.currentTarget.dataset.fileName;
            this.removeFile(fileName);
            fileItem.remove();
        });
        
        this.fileList.appendChild(fileItem);
    }
    
    // Удаление файла
    removeFile(fileName) {
        this.attachedFiles = this.attachedFiles.filter(file => file.name !== fileName);
    }
    
    // Форматирование размера файла
    formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
    }
    
    // Счетчик символов
    updateCharCounter() {
        const current = this.messageField.value.length;
        const max = this.messageField.maxLength;
        const currentSpan = this.charCounter.querySelector('.current');
        
        currentSpan.textContent = current;
        
        if (current >= max) {
            this.charCounter.style.color = '#dc3545';
        } else {
            this.charCounter.style.color = '#6c757d';
        }
    }
    
    // Обработка отправки формы
    async handleSubmit(e) {
        e.preventDefault();
        
        // Предотвращение множественной отправки
        if (this.isSubmitting) return;
        
        // Валидация
        if (!this.validateForm()) {
            if (window.toast) {
                window.toast.error('Ошибка', 'Пожалуйста, заполните все обязательные поля');
            }
            
            // Прокрутка к первой ошибке
            const firstError = this.form.querySelector('.error');
            if (firstError) {
                firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
                firstError.focus();
            }
            
            return;
        }
        
        // Начало отправки
        this.isSubmitting = true;
        this.submitBtn.classList.add('loading');
        this.submitBtn.disabled = true;
        
        try {
            // Сбор данных формы
            const formData = new FormData(this.form);
            
            // Добавление файлов
            this.attachedFiles.forEach(file => {
                formData.append('files[]', file);
            });
            
            // Отправка на сервер
            const response = await this.sendForm(formData);
            
            if (response.success) {
                // Успешная отправка
                this.showSuccess();
                
                // Отправка события в аналитику
                if (window.gtag) {
                    gtag('event', 'form_submit', {
                        'event_category': 'Contact Form',
                        'event_label': 'Success'
                    });
                }
                
                // Отправка в Яндекс.Метрику
                if (window.ym) {
                    ym(YANDEX_METRIKA_ID, 'reachGoal', 'form_submit');
                }
            } else {
                throw new Error(response.message || 'Ошибка отправки формы');
            }
            
        } catch (error) {
            console.error('Form submission error:', error);
            
            if (window.toast) {
                window.toast.error('Ошибка', error.message || 'Не удалось отправить форму. Попробуйте позже.');
            }
            
        } finally {
            // Завершение отправки
            this.isSubmitting = false;
            this.submitBtn.classList.remove('loading');
            this.submitBtn.disabled = false;
        }
    }
    
    // Отправка формы на сервер
    async sendForm(formData) {
        // Вариант 1: Отправка на PHP скрипт
        const response = await fetch('send-form.php', {
            method: 'POST',
            body: formData
        });
        
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        
        return await response.json();
        
        // Вариант 2: Отправка через EmailJS (без бэкенда)
        /*
        const templateParams = {
            name: formData.get('name'),
            email: formData.get('email'),
            phone: formData.get('phone'),
            service: formData.get('service'),
            budget: formData.get('budget'),
            message: formData.get('message')
        };
        
        await emailjs.send('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', templateParams);
        return { success: true };
        */
        
        // Вариант 3: Имитация отправки (для демо)
        /*
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve({ success: true });
            }, 2000);
        });
        */
    }
    
    // Отображение успешной отправки
    showSuccess() {
        this.form.style.display = 'none';
        this.successMessage.classList.add('show');
        
        if (window.toast) {
            window.toast.success('Успешно', 'Ваша заявка отправлена!');
        }
    }
    
    // Сброс формы
    reset() {
        this.form.reset();
        this.form.style.display = 'block';
        this.successMessage.classList.remove('show');
        
        // Очистка файлов
        this.attachedFiles = [];
        this.fileList.innerHTML = '';
        
        // Очистка валидации
        this.form.querySelectorAll('.error, .success').forEach(field => {
            field.classList.remove('error', 'success');
        });
        
        this.form.querySelectorAll('.error-message').forEach(error => {
            error.textContent = '';
        });
        
        // Сброс счетчика символов
        if (this.charCounter) {
            this.charCounter.querySelector('.current').textContent = '0';
            this.charCounter.style.color = '#6c757d';
        }
    }
}

// Инициализация формы
const contactForm = new ContactForm('contactForm');

// Функция для сброса формы (вызывается из HTML)
function resetForm() {
    contactForm.reset();
}

// ============================================
// PHP СКРИПТ ДЛЯ ОБРАБОТКИ ФОРМЫ (send-form.php)
// ============================================
/*
<?php
// Настройки
$to = 'your-email@example.com'; // Email получателя
$subject = 'Новая заявка с сайта';
$from = 'noreply@example.com'; // Email отправителя

// Проверка метода запроса
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['success' => false, 'message' => 'Method not allowed']);
    exit;
}

// Получение данных
$name = isset($_POST['name']) ? strip_tags(trim($_POST['name'])) : '';
$email = isset($_POST['email']) ? filter_var(trim($_POST['email']), FILTER_SANITIZE_EMAIL) : '';
$phone = isset($_POST['phone']) ? strip_tags(trim($_POST['phone'])) : '';
$service = isset($_POST['service']) ? strip_tags(trim($_POST['service'])) : '';
$budget = isset($_POST['budget']) ? strip_tags(trim($_POST['budget'])) : '';
$message = isset($_POST['message']) ? strip_tags(trim($_POST['message'])) : '';
$subscribe = isset($_POST['subscribe']) ? 'Да' : 'Нет';

// Валидация
if (empty($name) || empty($email) || empty($phone)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Заполните все обязательные поля']);
    exit;
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Некорректный email']);
    exit;
}

// Формирование письма
$email_content = "Новая заявка с сайта\n\n";
$email_content .= "Имя: $name\n";
$email_content .= "Email: $email\n";
$email_content .= "Телефон: $phone\n";
$email_content .= "Услуга: $service\n";
$email_content .= "Бюджет: $budget\n";
$email_content .= "Подписка на новости: $subscribe\n\n";
$email_content .= "Сообщение:\n$message\n";

// Заголовки письма
$headers = "From: $from\r\n";
$headers .= "Reply-To: $email\r\n";
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";

// Обработка файлов
$attachments = [];
if (!empty($_FILES['files'])) {
    $upload_dir = 'uploads/';
    
    // Создание директории если не существует
    if (!is_dir($upload_dir)) {
        mkdir($upload_dir, 0755, true);
    }
    
    foreach ($_FILES['files']['tmp_name'] as $key => $tmp_name) {
        $file_name = $_FILES['files']['name'][$key];
        $file_size = $_FILES['files']['size'][$key];
        $file_tmp = $_FILES['files']['tmp_name'][$key];
        $file_type = $_FILES['files']['type'][$key];
        
        // Проверка размера (5 МБ)
        if ($file_size > 5242880) {
            continue;
        }
        
        // Безопасное имя файла
        $file_name = preg_replace("/[^a-zA-Z0-9._-]/", "", $file_name);
        $file_path = $upload_dir . uniqid() . '_' . $file_name;
        
        if (move_uploaded_file($file_tmp, $file_path)) {
            $attachments[] = $file_path;
        }
    }
}

// Отправка письма
$mail_sent = mail($to, $subject, $email_content, $headers);

if ($mail_sent) {
    // Сохранение в базу данных (опционально)
    // saveToDatabase($name, $email, $phone, $service, $budget, $message);
    
    // Отправка уведомления в Telegram (опционально)
    // sendTelegramNotification($name, $email, $phone, $service);
    
    echo json_encode(['success' => true, 'message' => 'Заявка успешно отправлена']);
} else {
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Ошибка отправки письма']);
}

// Удаление временных файлов
foreach ($attachments as $file) {
    if (file_exists($file)) {
        unlink($file);
    }
}
?>
*/