Merge pull request #1 from smartsoltech/frontend-redesign
Frontend redesign
60
QR_CODE_FEATURE_SUMMARY.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# QR-код механизм для подачи заявок через Telegram бота
|
||||||
|
|
||||||
|
## ✅ Что добавлено:
|
||||||
|
|
||||||
|
### 1. Модальное окно с QR-кодом
|
||||||
|
- **Файл**: `smartsoltech/web/templates/web/services_modern.html`
|
||||||
|
- **Что добавлено**:
|
||||||
|
- Секция QR-кода в модальном окне заявки
|
||||||
|
- JavaScript для обработки формы и генерации QR-кода
|
||||||
|
- Автоматический сброс формы при закрытии модального окна
|
||||||
|
|
||||||
|
### 2. Backend функциональность
|
||||||
|
- **Существующий механизм**: View `generate_qr_code` в `smartsoltech/web/views.py`
|
||||||
|
- **Что работает**:
|
||||||
|
- Создание клиента и заявки на услугу
|
||||||
|
- Генерация уникального токена для заявки
|
||||||
|
- Создание QR-кода с ссылкой на Telegram бота
|
||||||
|
- Сохранение QR-кода в папку static/qr_codes/
|
||||||
|
|
||||||
|
### 3. Telegram бот интеграция
|
||||||
|
- **Файл**: `smartsoltech/comunication/telegram_bot.py`
|
||||||
|
- **Что работает**:
|
||||||
|
- Обработка команды `/start request_{id}_token_{token}`
|
||||||
|
- Подтверждение заявки и связывание с chat_id пользователя
|
||||||
|
- Создание пользователя Django из данных Telegram
|
||||||
|
- Отправка подтверждающего сообщения
|
||||||
|
|
||||||
|
## 🔄 Workflow (Рабочий процесс):
|
||||||
|
|
||||||
|
1. **Пользователь** заполняет форму в модальном окне на странице услуг
|
||||||
|
2. **JavaScript** отправляет POST запрос на `/service/generate_qr_code/{service_id}/`
|
||||||
|
3. **Django** создает:
|
||||||
|
- Client (клиента)
|
||||||
|
- ServiceRequest (заявку на услугу)
|
||||||
|
- QR-код с ссылкой на Telegram бота
|
||||||
|
4. **Модальное окно** показывает QR-код и ссылку "Открыть в Telegram"
|
||||||
|
5. **Пользователь** сканирует QR-код или переходит по ссылке
|
||||||
|
6. **Telegram бот** получает команду `/start` с параметрами заявки
|
||||||
|
7. **Бот** подтверждает заявку, связывает с chat_id и отправляет подтверждение
|
||||||
|
|
||||||
|
## 🧪 Тестирование:
|
||||||
|
|
||||||
|
Откройте файл `test_qr_functionality.html` в браузере для подробных инструкций по тестированию.
|
||||||
|
|
||||||
|
Быстрый тест:
|
||||||
|
1. Перейдите на http://localhost:8000/services/
|
||||||
|
2. Нажмите "Заказать услугу" под любой услугой
|
||||||
|
3. Заполните форму и отправьте
|
||||||
|
4. Должен появиться QR-код
|
||||||
|
5. Перейдите по ссылке в Telegram и нажмите "Start"
|
||||||
|
|
||||||
|
## 📁 Измененные файлы:
|
||||||
|
|
||||||
|
1. `smartsoltech/web/templates/web/services_modern.html` - добавлен QR-код в модальное окно
|
||||||
|
2. Использован существующий механизм в `smartsoltech/web/views.py` - `generate_qr_code`
|
||||||
|
3. Использован существующий Telegram бот в `smartsoltech/comunication/telegram_bot.py`
|
||||||
|
|
||||||
|
## 🎯 Результат:
|
||||||
|
|
||||||
|
Теперь пользователи могут подавать заявки на услуги через современное модальное окно, которое генерирует QR-код для подтверждения заявки через Telegram бота. Весь процесс автоматизирован и интегрирован с существующей системой.
|
||||||
146
real_confirmation_process.html
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>🔄 Реальная проверка подтверждения заявки</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; padding: 20px; line-height: 1.6; background: #f8f9fa; }
|
||||||
|
.container { max-width: 800px; margin: 0 auto; }
|
||||||
|
.card { background: white; padding: 20px; border-radius: 10px; margin: 15px 0; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
|
||||||
|
.improvement { border-left: 5px solid #28a745; }
|
||||||
|
.process { border-left: 5px solid #007bff; }
|
||||||
|
.technical { border-left: 5px solid #ffc107; }
|
||||||
|
.test { border-left: 5px solid #17a2b8; }
|
||||||
|
h1 { color: #333; text-align: center; }
|
||||||
|
h2 { color: #333; border-bottom: 2px solid #007bff; padding-bottom: 5px; }
|
||||||
|
h3 { color: #666; }
|
||||||
|
.emoji { font-size: 1.2em; }
|
||||||
|
.code { background: #f8f9fa; padding: 2px 6px; border-radius: 4px; font-family: monospace; }
|
||||||
|
.success { color: #28a745; font-weight: bold; }
|
||||||
|
.warning { color: #ffc107; font-weight: bold; }
|
||||||
|
.info { color: #007bff; font-weight: bold; }
|
||||||
|
ul li { margin: 8px 0; }
|
||||||
|
.test-btn { display: inline-block; padding: 12px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; margin: 10px 5px; }
|
||||||
|
.test-btn:hover { background: #0056b3; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1><span class="emoji">🔄</span> Реальная проверка подтверждения заявки</h1>
|
||||||
|
|
||||||
|
<div class="card improvement">
|
||||||
|
<h2><span class="emoji">✅</span> Исправленная логика</h2>
|
||||||
|
<p class="success">Теперь система корректно ожидает подтверждения от пользователя через Telegram!</p>
|
||||||
|
|
||||||
|
<h3>Что было неправильно:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>❌ Анимация успеха показывалась сразу после создания заявки</li>
|
||||||
|
<li>❌ Окно закрывалось автоматически через 6 секунд</li>
|
||||||
|
<li>❌ Не учитывалось, что пользователь должен подтвердить в Telegram</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Что исправлено:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>✅ QR-код остается на экране до реального подтверждения</li>
|
||||||
|
<li>✅ Система проверяет статус <span class="code">is_verified</span> каждые 3 секунды</li>
|
||||||
|
<li>✅ Анимация успеха появляется только после подтверждения в Telegram</li>
|
||||||
|
<li>✅ Индикатор "Ожидаем подтверждения..." показывает статус</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card process">
|
||||||
|
<h2><span class="emoji">🔄</span> Новый процесс (правильный)</h2>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li><strong>Пользователь заполняет форму</strong> → нажимает "Отправить заявку"</li>
|
||||||
|
<li><strong>Создается заявка</strong> с <span class="code">is_verified = False</span></li>
|
||||||
|
<li><strong>Показывается QR-код</strong> с индикатором ожидания</li>
|
||||||
|
<li class="info"><strong>Система начинает проверку</strong> статуса каждые 3 секунды</li>
|
||||||
|
<li><strong>Пользователь сканирует QR-код</strong> → переходит в Telegram</li>
|
||||||
|
<li><strong>Telegram бот обрабатывает команду</strong> → устанавливает <span class="code">is_verified = True</span></li>
|
||||||
|
<li class="success"><strong>Система обнаруживает подтверждение</strong> → показывает анимацию успеха</li>
|
||||||
|
<li><strong>Окно закрывается</strong> через 3 секунды после подтверждения</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card technical">
|
||||||
|
<h2><span class="emoji">🛠️</span> Технические изменения</h2>
|
||||||
|
|
||||||
|
<h3>Новый API endpoint:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="code">GET /service/check_status/{request_id}/</span></li>
|
||||||
|
<li>Возвращает <span class="code">{"is_verified": boolean, "chat_id": string}</span></li>
|
||||||
|
<li>Используется для polling проверки статуса</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>JavaScript логика:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Интервал проверки:</strong> каждые 3 секунды</li>
|
||||||
|
<li><strong>Очистка интервала:</strong> при закрытии модального окна или подтверждении</li>
|
||||||
|
<li><strong>Визуальная обратная связь:</strong> спиннер "Ожидаем подтверждения..."</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Обновленные файлы:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="code">web/views.py</span> - добавлен <span class="code">check_request_status</span></li>
|
||||||
|
<li><span class="code">web/urls.py</span> - добавлен URL для проверки статуса</li>
|
||||||
|
<li><span class="code">services_modern.html</span> - обновлен JavaScript и HTML</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card test">
|
||||||
|
<h2><span class="emoji">🧪</span> Тестирование</h2>
|
||||||
|
|
||||||
|
<a href="http://localhost:8000/services/" target="_blank" class="test-btn">
|
||||||
|
<span class="emoji">🛠️</span> Тестировать на странице услуг
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<h3>Сценарий тестирования:</h3>
|
||||||
|
<ol>
|
||||||
|
<li><strong>Откройте страницу услуг</strong> и нажмите "Заказать услугу"</li>
|
||||||
|
<li><strong>Заполните форму</strong> и отправьте</li>
|
||||||
|
<li><strong>Убедитесь, что:</strong>
|
||||||
|
<ul>
|
||||||
|
<li>Появился QR-код с кнопкой "Открыть в Telegram"</li>
|
||||||
|
<li>Показывается "Ожидаем подтверждения в Telegram..."</li>
|
||||||
|
<li>QR-код остается на экране (не исчезает через 3 секунды)</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><strong>Перейдите в Telegram</strong> по QR-коду или ссылке</li>
|
||||||
|
<li><strong>Нажмите "Start"</strong> в боте</li>
|
||||||
|
<li><strong>Вернитесь в браузер</strong> - в течение 3 секунд должна:
|
||||||
|
<ul>
|
||||||
|
<li>Появиться анимированная галочка</li>
|
||||||
|
<li>Показаться "Заявка подтверждена!"</li>
|
||||||
|
<li>Окно автоматически закроется</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3 class="warning">Что проверить дополнительно:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>🔍 <strong>Без подтверждения:</strong> QR-код должен оставаться на экране бесконечно</li>
|
||||||
|
<li>🔍 <strong>Закрытие окна:</strong> Проверка статуса должна прекращаться</li>
|
||||||
|
<li>🔍 <strong>Повторное открытие:</strong> Форма должна быть сброшена</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card improvement">
|
||||||
|
<h2><span class="emoji">🎯</span> Результат</h2>
|
||||||
|
<p class="success">Теперь система корректно работает с реальным подтверждением пользователя через Telegram!</p>
|
||||||
|
|
||||||
|
<p>Пользователь видит визуальную обратную связь на каждом этапе:</p>
|
||||||
|
<ul>
|
||||||
|
<li>📝 Заполнение формы</li>
|
||||||
|
<li>⏳ Отправка заявки</li>
|
||||||
|
<li>📱 QR-код для Telegram</li>
|
||||||
|
<li>🔄 Ожидание подтверждения</li>
|
||||||
|
<li>✅ Успешное подтверждение</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p class="info">Заявка остается в состоянии ожидания до тех пор, пока пользователь не подтвердит её в Telegram боте!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
526
smartsoltech/static/assets/css/modern-styles.css
Normal file
@@ -0,0 +1,526 @@
|
|||||||
|
/* Modern IT Company Design - SmartSolTech */
|
||||||
|
:root {
|
||||||
|
/* Light Theme Colors */
|
||||||
|
--primary-color: #6366f1;
|
||||||
|
--primary-dark: #4f46e5;
|
||||||
|
--secondary-color: #8b5cf6;
|
||||||
|
--accent-color: #06d6a0;
|
||||||
|
--text-dark: #1f2937;
|
||||||
|
--text-light: #6b7280;
|
||||||
|
--bg-light: #ffffff;
|
||||||
|
--bg-gray: #f9fafb;
|
||||||
|
--border-color: #e5e7eb;
|
||||||
|
--shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||||
|
--gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||||
|
--gradient-accent: linear-gradient(135deg, #06d6a0 0%, #34d399 100%);
|
||||||
|
|
||||||
|
/* Dark Theme Colors */
|
||||||
|
--dark-bg: #0f172a;
|
||||||
|
--dark-bg-secondary: #1e293b;
|
||||||
|
--dark-text: #f8fafc;
|
||||||
|
--dark-text-secondary: #cbd5e1;
|
||||||
|
--dark-border: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark theme */
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--text-dark: var(--dark-text);
|
||||||
|
--text-light: var(--dark-text-secondary);
|
||||||
|
--bg-light: var(--dark-bg);
|
||||||
|
--bg-gray: var(--dark-bg-secondary);
|
||||||
|
--border-color: var(--dark-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: var(--text-dark);
|
||||||
|
background-color: var(--bg-light);
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3.75rem;
|
||||||
|
font-weight: 800;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
color: var(--text-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--text-light);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.btn-modern {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary-modern {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
color: white;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary-modern:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 20px 25px -5px rgba(99, 102, 241, 0.4);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary-modern {
|
||||||
|
background: var(--bg-light);
|
||||||
|
color: var(--text-dark);
|
||||||
|
border: 2px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary-modern:hover {
|
||||||
|
background: var(--bg-gray);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cards */
|
||||||
|
.card-modern {
|
||||||
|
background: var(--bg-light);
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-modern:hover {
|
||||||
|
transform: translateY(-8px);
|
||||||
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-modern .card-body {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation */
|
||||||
|
.navbar-modern {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
padding: 1rem 0;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-modern.scrolled {
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand-modern {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link-modern {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-light);
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link-modern:hover,
|
||||||
|
.nav-link-modern.active {
|
||||||
|
color: var(--primary-color);
|
||||||
|
background: rgba(99, 102, 241, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hero Section */
|
||||||
|
.hero-modern {
|
||||||
|
padding: 8rem 0 4rem;
|
||||||
|
background: linear-gradient(135deg, rgba(99, 102, 241, 0.05) 0%, rgba(139, 92, 246, 0.05) 100%);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-modern::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="0.5" fill="%236366f1" opacity="0.1"/><circle cx="75" cy="75" r="0.3" fill="%238b5cf6" opacity="0.1"/><circle cx="75" cy="25" r="0.4" fill="%2306d6a0" opacity="0.1"/><circle cx="25" cy="75" r="0.6" fill="%236366f1" opacity="0.05"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Services Grid */
|
||||||
|
.services-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card {
|
||||||
|
background: var(--bg-light);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
transform: translateX(-100%);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card:hover::before {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-icon {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
color: white;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in-up {
|
||||||
|
animation: fadeInUp 0.6s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-float {
|
||||||
|
animation: float 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode toggle */
|
||||||
|
.theme-toggle {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 2rem;
|
||||||
|
right: 2rem;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-modern {
|
||||||
|
padding: 6rem 0 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.services-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility Classes */
|
||||||
|
.text-gradient {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gradient {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-gradient {
|
||||||
|
border: 2px solid transparent;
|
||||||
|
background: linear-gradient(var(--bg-light), var(--bg-light)) padding-box,
|
||||||
|
var(--gradient-primary) border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-modern {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-padding {
|
||||||
|
padding: 6rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-large {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Animation */
|
||||||
|
#loading-screen {
|
||||||
|
transition: opacity 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loading-screen.hidden {
|
||||||
|
opacity: 0 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 4px solid var(--border-color);
|
||||||
|
border-top: 4px solid var(--primary-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success Checkmark Animation */
|
||||||
|
.success-checkmark {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: block;
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke: #4CAF50;
|
||||||
|
stroke-miterlimit: 10;
|
||||||
|
margin: 10px auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark.animate .icon-circle {
|
||||||
|
stroke-dasharray: 166;
|
||||||
|
stroke-dashoffset: 166;
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-miterlimit: 10;
|
||||||
|
stroke: #4CAF50;
|
||||||
|
fill: none;
|
||||||
|
animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark.animate .icon-line {
|
||||||
|
stroke-dasharray: 48;
|
||||||
|
stroke-dashoffset: 48;
|
||||||
|
animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark.animate .icon-line.line-tip {
|
||||||
|
animation-delay: 1.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark.animate .icon-line.line-long {
|
||||||
|
animation-delay: 1.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark .icon-circle {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #4CAF50;
|
||||||
|
background-color: rgba(76, 175, 80, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark .icon-line {
|
||||||
|
height: 2px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
display: block;
|
||||||
|
border-radius: 2px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark .icon-line.line-tip {
|
||||||
|
top: 46px;
|
||||||
|
left: 14px;
|
||||||
|
width: 25px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
animation: icon-line-tip 0.75s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark .icon-line.line-long {
|
||||||
|
top: 38px;
|
||||||
|
right: 8px;
|
||||||
|
width: 47px;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
animation: icon-line-long 0.75s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-checkmark .icon-fix {
|
||||||
|
top: 8px;
|
||||||
|
width: 5px;
|
||||||
|
left: 26px;
|
||||||
|
z-index: 1;
|
||||||
|
height: 85px;
|
||||||
|
position: absolute;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes stroke {
|
||||||
|
100% {
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes icon-line-tip {
|
||||||
|
0% {
|
||||||
|
width: 0;
|
||||||
|
left: 1px;
|
||||||
|
top: 19px;
|
||||||
|
}
|
||||||
|
54% {
|
||||||
|
width: 0;
|
||||||
|
left: 1px;
|
||||||
|
top: 19px;
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
width: 50px;
|
||||||
|
left: -8px;
|
||||||
|
top: 37px;
|
||||||
|
}
|
||||||
|
84% {
|
||||||
|
width: 17px;
|
||||||
|
left: 21px;
|
||||||
|
top: 48px;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
width: 25px;
|
||||||
|
left: 14px;
|
||||||
|
top: 45px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes icon-line-long {
|
||||||
|
0% {
|
||||||
|
width: 0;
|
||||||
|
right: 46px;
|
||||||
|
top: 54px;
|
||||||
|
}
|
||||||
|
65% {
|
||||||
|
width: 0;
|
||||||
|
right: 46px;
|
||||||
|
top: 54px;
|
||||||
|
}
|
||||||
|
84% {
|
||||||
|
width: 55px;
|
||||||
|
right: 0px;
|
||||||
|
top: 35px;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
width: 47px;
|
||||||
|
right: 8px;
|
||||||
|
top: 38px;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
smartsoltech/static/assets/img/favicon.ico
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<!-- Placeholder for favicon - this would be a binary file in real scenario -->
|
||||||
|
<!-- Create a simple favicon.ico file -->
|
||||||
108
smartsoltech/static/assets/js/modern-scripts.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// Modern Scripts for SmartSolTech Website
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('SmartSolTech: DOM loaded, initializing...');
|
||||||
|
|
||||||
|
// Hide loading screen
|
||||||
|
const loadingScreen = document.getElementById('loading-screen');
|
||||||
|
if (loadingScreen) {
|
||||||
|
console.log('SmartSolTech: Loading screen found, hiding...');
|
||||||
|
setTimeout(() => {
|
||||||
|
loadingScreen.style.opacity = '0';
|
||||||
|
loadingScreen.style.pointerEvents = 'none';
|
||||||
|
setTimeout(() => {
|
||||||
|
loadingScreen.style.display = 'none';
|
||||||
|
loadingScreen.remove(); // Полностью удаляем элемент
|
||||||
|
console.log('SmartSolTech: Loading screen removed');
|
||||||
|
}, 300);
|
||||||
|
}, 500); // Уменьшили время ожидания
|
||||||
|
} else {
|
||||||
|
console.log('SmartSolTech: Loading screen not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theme Toggle Functionality
|
||||||
|
const themeToggle = document.getElementById('theme-toggle');
|
||||||
|
const html = document.documentElement;
|
||||||
|
|
||||||
|
if (themeToggle) {
|
||||||
|
// Check for saved theme preference
|
||||||
|
const currentTheme = localStorage.getItem('theme') || 'light';
|
||||||
|
html.setAttribute('data-theme', currentTheme);
|
||||||
|
updateThemeIcon(currentTheme);
|
||||||
|
|
||||||
|
themeToggle.addEventListener('click', function() {
|
||||||
|
const currentTheme = html.getAttribute('data-theme');
|
||||||
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||||
|
|
||||||
|
html.setAttribute('data-theme', newTheme);
|
||||||
|
localStorage.setItem('theme', newTheme);
|
||||||
|
updateThemeIcon(newTheme);
|
||||||
|
|
||||||
|
// Add animation
|
||||||
|
this.style.transform = 'scale(0.8)';
|
||||||
|
setTimeout(() => {
|
||||||
|
this.style.transform = 'scale(1)';
|
||||||
|
}, 150);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateThemeIcon(theme) {
|
||||||
|
if (!themeToggle) return;
|
||||||
|
const icon = themeToggle.querySelector('i');
|
||||||
|
if (icon) {
|
||||||
|
if (theme === 'dark') {
|
||||||
|
icon.className = 'fas fa-sun';
|
||||||
|
themeToggle.setAttribute('aria-label', 'Переключить на светлую тему');
|
||||||
|
} else {
|
||||||
|
icon.className = 'fas fa-moon';
|
||||||
|
themeToggle.setAttribute('aria-label', 'Переключить на темную тему');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navbar scroll behavior
|
||||||
|
const navbar = document.querySelector('.navbar-modern');
|
||||||
|
if (navbar) {
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
if (window.scrollY > 50) {
|
||||||
|
navbar.classList.add('scrolled');
|
||||||
|
} else {
|
||||||
|
navbar.classList.remove('scrolled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smooth scrolling for anchor links
|
||||||
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||||
|
anchor.addEventListener('click', function (e) {
|
||||||
|
const target = document.querySelector(this.getAttribute('href'));
|
||||||
|
if (target) {
|
||||||
|
e.preventDefault();
|
||||||
|
target.scrollIntoView({
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Intersection Observer for animations
|
||||||
|
const observerOptions = {
|
||||||
|
threshold: 0.1,
|
||||||
|
rootMargin: '0px 0px -50px 0px'
|
||||||
|
};
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
entry.target.style.opacity = '1';
|
||||||
|
entry.target.style.transform = 'translateY(0)';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, observerOptions);
|
||||||
|
|
||||||
|
// Observe cards and service items
|
||||||
|
document.querySelectorAll('.card-modern, .service-card, .step-card').forEach(card => {
|
||||||
|
observer.observe(card);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('SmartSolTech: All scripts loaded successfully');
|
||||||
|
});
|
||||||
@@ -1,29 +1,17 @@
|
|||||||
'use strict';
|
(function($) {
|
||||||
{
|
'use strict';
|
||||||
// Call function fn when the DOM is loaded and ready. If it is already
|
|
||||||
// loaded, call the function now.
|
|
||||||
// http://youmightnotneedjquery.com/#ready
|
|
||||||
function ready(fn) {
|
|
||||||
if (document.readyState !== 'loading') {
|
|
||||||
fn();
|
|
||||||
} else {
|
|
||||||
document.addEventListener('DOMContentLoaded', fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ready(function() {
|
$(document).ready(function() {
|
||||||
function handleClick(event) {
|
$('.cancel-link').click(function(e) {
|
||||||
event.preventDefault();
|
e.preventDefault();
|
||||||
const params = new URLSearchParams(window.location.search);
|
const parentWindow = window.parent;
|
||||||
if (params.has('_popup')) {
|
if (parentWindow && typeof(parentWindow.dismissRelatedObjectModal) === 'function' && parentWindow !== window) {
|
||||||
window.close(); // Close the popup.
|
parentWindow.dismissRelatedObjectModal();
|
||||||
} else {
|
} else {
|
||||||
window.history.back(); // Otherwise, go back.
|
// fallback to default behavior
|
||||||
|
window.history.back();
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
|
||||||
document.querySelectorAll('.cancel-link').forEach(function(el) {
|
|
||||||
el.addEventListener('click', handleClick);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
})(django.jQuery);
|
||||||
|
|||||||
@@ -1,15 +1,44 @@
|
|||||||
'use strict';
|
(function() {
|
||||||
{
|
|
||||||
const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
|
'use strict';
|
||||||
switch(initData.action) {
|
|
||||||
case 'change':
|
var windowRef = window;
|
||||||
opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value);
|
var windowRefProxy;
|
||||||
break;
|
var windowName, widgetName;
|
||||||
case 'delete':
|
var openerRef = windowRef.opener;
|
||||||
opener.dismissDeleteRelatedObjectPopup(window, initData.value);
|
if (!openerRef) {
|
||||||
break;
|
// related modal is active
|
||||||
default:
|
openerRef = windowRef.parent;
|
||||||
opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj);
|
windowName = windowRef.name;
|
||||||
break;
|
widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
|
||||||
|
windowRefProxy = {
|
||||||
|
name: widgetName,
|
||||||
|
location: windowRef.location,
|
||||||
|
close: function() {
|
||||||
|
openerRef.dismissRelatedObjectModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
windowRef = windowRefProxy;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// default django popup_response.js
|
||||||
|
var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
|
||||||
|
switch (initData.action) {
|
||||||
|
case 'change':
|
||||||
|
if (typeof(openerRef.dismissChangeRelatedObjectPopup) === 'function') {
|
||||||
|
openerRef.dismissChangeRelatedObjectPopup(windowRef, initData.value, initData.obj, initData.new_value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
if (typeof(openerRef.dismissDeleteRelatedObjectPopup) === 'function') {
|
||||||
|
openerRef.dismissDeleteRelatedObjectPopup(windowRef, initData.value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (typeof(openerRef.dismissAddRelatedObjectPopup) === 'function') {
|
||||||
|
openerRef.dismissAddRelatedObjectPopup(windowRef, initData.value, initData.obj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
5
smartsoltech/staticfiles/assets/bootstrap/css/bootstrap.min.css
vendored
Normal file
1
smartsoltech/staticfiles/assets/css/modal-styles.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import url('https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css');
|
||||||
378
smartsoltech/staticfiles/assets/css/modern-styles.css
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
/* Modern IT Company Design - SmartSolTech */
|
||||||
|
:root {
|
||||||
|
/* Light Theme Colors */
|
||||||
|
--primary-color: #6366f1;
|
||||||
|
--primary-dark: #4f46e5;
|
||||||
|
--secondary-color: #8b5cf6;
|
||||||
|
--accent-color: #06d6a0;
|
||||||
|
--text-dark: #1f2937;
|
||||||
|
--text-light: #6b7280;
|
||||||
|
--bg-light: #ffffff;
|
||||||
|
--bg-gray: #f9fafb;
|
||||||
|
--border-color: #e5e7eb;
|
||||||
|
--shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||||
|
--gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||||
|
--gradient-accent: linear-gradient(135deg, #06d6a0 0%, #34d399 100%);
|
||||||
|
|
||||||
|
/* Dark Theme Colors */
|
||||||
|
--dark-bg: #0f172a;
|
||||||
|
--dark-bg-secondary: #1e293b;
|
||||||
|
--dark-text: #f8fafc;
|
||||||
|
--dark-text-secondary: #cbd5e1;
|
||||||
|
--dark-border: #334155;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark theme */
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--text-dark: var(--dark-text);
|
||||||
|
--text-light: var(--dark-text-secondary);
|
||||||
|
--bg-light: var(--dark-bg);
|
||||||
|
--bg-gray: var(--dark-bg-secondary);
|
||||||
|
--border-color: var(--dark-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: var(--text-dark);
|
||||||
|
background-color: var(--bg-light);
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3.75rem;
|
||||||
|
font-weight: 800;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
color: var(--text-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--text-light);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.btn-modern {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary-modern {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
color: white;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary-modern:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 20px 25px -5px rgba(99, 102, 241, 0.4);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary-modern {
|
||||||
|
background: var(--bg-light);
|
||||||
|
color: var(--text-dark);
|
||||||
|
border: 2px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary-modern:hover {
|
||||||
|
background: var(--bg-gray);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cards */
|
||||||
|
.card-modern {
|
||||||
|
background: var(--bg-light);
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-modern:hover {
|
||||||
|
transform: translateY(-8px);
|
||||||
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-modern .card-body {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation */
|
||||||
|
.navbar-modern {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
padding: 1rem 0;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-modern.scrolled {
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand-modern {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link-modern {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-light);
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link-modern:hover,
|
||||||
|
.nav-link-modern.active {
|
||||||
|
color: var(--primary-color);
|
||||||
|
background: rgba(99, 102, 241, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hero Section */
|
||||||
|
.hero-modern {
|
||||||
|
padding: 8rem 0 4rem;
|
||||||
|
background: linear-gradient(135deg, rgba(99, 102, 241, 0.05) 0%, rgba(139, 92, 246, 0.05) 100%);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-modern::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="0.5" fill="%236366f1" opacity="0.1"/><circle cx="75" cy="75" r="0.3" fill="%238b5cf6" opacity="0.1"/><circle cx="75" cy="25" r="0.4" fill="%2306d6a0" opacity="0.1"/><circle cx="25" cy="75" r="0.6" fill="%236366f1" opacity="0.05"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Services Grid */
|
||||||
|
.services-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card {
|
||||||
|
background: var(--bg-light);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
transform: translateX(-100%);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card:hover::before {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-icon {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
color: white;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in-up {
|
||||||
|
animation: fadeInUp 0.6s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-float {
|
||||||
|
animation: float 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode toggle */
|
||||||
|
.theme-toggle {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 2rem;
|
||||||
|
right: 2rem;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-modern {
|
||||||
|
padding: 6rem 0 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.services-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility Classes */
|
||||||
|
.text-gradient {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gradient {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-gradient {
|
||||||
|
border: 2px solid transparent;
|
||||||
|
background: linear-gradient(var(--bg-light), var(--bg-light)) padding-box,
|
||||||
|
var(--gradient-primary) border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-modern {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-padding {
|
||||||
|
padding: 6rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-large {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Animation */
|
||||||
|
.loading-spinner {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 4px solid var(--border-color);
|
||||||
|
border-top: 4px solid var(--primary-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/* Добавляем стили для анимации появления модального окна */
|
||||||
|
#serviceModal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
position: relative;
|
||||||
|
background-color: #fefefe;
|
||||||
|
margin: auto;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #888;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 600px;
|
||||||
|
transform: scale(0);
|
||||||
|
transition: transform 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal.show .modal-content {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
230
smartsoltech/staticfiles/assets/css/styles.min.css
vendored
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/* Font Face Definitions */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Kaushan Script';
|
||||||
|
src: url('{% static "fonts/Kaushan%20Script-3db770c46931b64b6e281dcb2a7d0586.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Kaushan Script';
|
||||||
|
src: url('{% static "fonts/Kaushan%20Script-ba85b3a237ebd28058cd515071c02485.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
src: url('{% static "fonts/Montserrat-99764e33f03a95926b938c6f56e08a4f.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
src: url('{% static "fonts/Montserrat-cc6c968bcebf02819ee3afff266119d9.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
src: url('{% static "fonts/Montserrat-f32ddc894c166fbd8bc0d500ff2aeb3d.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
src: url('{% static "fonts/Montserrat-bcb799eba0c324e431d5daac3e5ea6bf.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Montserrat';
|
||||||
|
src: url('{% static "fonts/Montserrat-5cfb114945f0457bd5a940932bb8156d.woff2" %}') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility Classes */
|
||||||
|
.fit-cover {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer Styles */
|
||||||
|
footer {
|
||||||
|
background-color: #343a40;
|
||||||
|
color: #fff;
|
||||||
|
padding-top: 5rem;
|
||||||
|
padding-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer h5 {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a, footer p {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer hr {
|
||||||
|
border-top: 1px solid #fff;
|
||||||
|
width: 100%;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .list-inline-item a {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button Hover Styles */
|
||||||
|
button.btn-primary:hover {
|
||||||
|
background: rgb(20, 87, 187);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation Styles */
|
||||||
|
ul.main-nav {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0;
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li > a {
|
||||||
|
display: block;
|
||||||
|
padding: 20px 30px;
|
||||||
|
position: relative;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li:hover {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li:hover > a {
|
||||||
|
color: #333;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li ul.sub-menu-lists {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li ul.sub-menu-lists > li {
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav > li ul.sub-menu-lists > li > a {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Navigation */
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.ic.menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav {
|
||||||
|
z-index: 2;
|
||||||
|
padding: 50px 0;
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 0;
|
||||||
|
background-color: #000;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
transition: width 0.6s, background 0.6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ic.menu:focus ~ ul.main-nav {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 769px) {
|
||||||
|
.ic.menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.main-nav {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-star {
|
||||||
|
font-size: 20px;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked {
|
||||||
|
color: gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.project-card, .review-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 350px;
|
||||||
|
margin: auto;
|
||||||
|
font-size: 0.5rem; /* Make font size smaller */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 0.85rem; /* Reduce text size in paragraphs */
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-muted {
|
||||||
|
font-size: 0.8rem; /* Make muted text slightly smaller */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.carousel-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5); /* Затемнение */
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item img {
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
BIN
smartsoltech/staticfiles/assets/img/about/1.jpg
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
smartsoltech/staticfiles/assets/img/about/2.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
smartsoltech/staticfiles/assets/img/about/3.jpg
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
smartsoltech/staticfiles/assets/img/about/4.jpg
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
smartsoltech/staticfiles/assets/img/clients/creative-market.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
smartsoltech/staticfiles/assets/img/clients/designmodo.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
smartsoltech/staticfiles/assets/img/clients/envato.jpg
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
smartsoltech/staticfiles/assets/img/clients/themeforest.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
smartsoltech/staticfiles/assets/img/header-bg.jpg
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
smartsoltech/staticfiles/assets/img/map-image.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/1-full.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/1-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/2-full.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/2-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/3-full.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/3-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/4-full.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/4-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/5-full.jpg
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/5-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/6-full.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
smartsoltech/staticfiles/assets/img/portfolio/6-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
smartsoltech/staticfiles/assets/img/team/1.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
smartsoltech/staticfiles/assets/img/team/2.jpg
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
smartsoltech/staticfiles/assets/img/team/3.jpg
Normal file
|
After Width: | Height: | Size: 56 KiB |
18
smartsoltech/staticfiles/assets/js/get-csrf-token.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Функция для получения CSRF токена из куков
|
||||||
|
function getCookie(name) {
|
||||||
|
let cookieValue = null;
|
||||||
|
if (document.cookie && document.cookie !== '') {
|
||||||
|
const cookies = document.cookie.split(';');
|
||||||
|
for (let i = 0; i < cookies.length; i++) {
|
||||||
|
const cookie = cookies[i].trim();
|
||||||
|
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализация переменной csrftoken, которая будет доступна глобально
|
||||||
|
const csrftoken = getCookie('csrftoken');
|
||||||
49
smartsoltech/staticfiles/assets/js/modal-init.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// Работа с модальным окном заявки
|
||||||
|
var modalElement = document.getElementById('orderModal');
|
||||||
|
if (modalElement) {
|
||||||
|
var modal = new bootstrap.Modal(modalElement);
|
||||||
|
|
||||||
|
// Инициализация модального окна
|
||||||
|
modalElement.addEventListener('show.bs.modal', function () {
|
||||||
|
console.log("Модальное окно открыто");
|
||||||
|
});
|
||||||
|
|
||||||
|
modalElement.addEventListener('hide.bs.modal', function () {
|
||||||
|
console.log("Модальное окно закрыто");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Открытие модального окна для заявки на услугу
|
||||||
|
const openModalBtn = document.getElementById('openModalBtn');
|
||||||
|
const serviceModal = document.getElementById('serviceModal');
|
||||||
|
|
||||||
|
if (openModalBtn && serviceModal) {
|
||||||
|
openModalBtn.addEventListener('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const serviceId = openModalBtn.getAttribute('data-service-id');
|
||||||
|
console.log("Service ID при открытии модального окна:", serviceId);
|
||||||
|
|
||||||
|
if (!serviceId) {
|
||||||
|
alert("Идентификатор услуги не найден. Обновите страницу и попробуйте снова.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
generateQrButton.dataset.serviceId = serviceId;
|
||||||
|
|
||||||
|
serviceModal.classList.add('show');
|
||||||
|
serviceModal.style.display = 'block';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll('.close').forEach(closeBtn => {
|
||||||
|
closeBtn.addEventListener('click', function () {
|
||||||
|
if (serviceModal) {
|
||||||
|
serviceModal.classList.remove('show');
|
||||||
|
setTimeout(() => {
|
||||||
|
serviceModal.style.display = 'none';
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
326
smartsoltech/staticfiles/assets/js/modern-scripts.js
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
// Modern Scripts for SmartSolTech Website
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
|
// Hide loading screen
|
||||||
|
const loadingScreen = document.getElementById('loading-screen');
|
||||||
|
if (loadingScreen) {
|
||||||
|
setTimeout(() => {
|
||||||
|
loadingScreen.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
loadingScreen.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theme Toggle Functionality
|
||||||
|
const themeToggle = document.getElementById('theme-toggle');
|
||||||
|
const html = document.documentElement;
|
||||||
|
|
||||||
|
// Check for saved theme preference
|
||||||
|
const currentTheme = localStorage.getItem('theme') || 'light';
|
||||||
|
html.setAttribute('data-theme', currentTheme);
|
||||||
|
updateThemeIcon(currentTheme);
|
||||||
|
|
||||||
|
themeToggle.addEventListener('click', function() {
|
||||||
|
const currentTheme = html.getAttribute('data-theme');
|
||||||
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||||
|
|
||||||
|
html.setAttribute('data-theme', newTheme);
|
||||||
|
localStorage.setItem('theme', newTheme);
|
||||||
|
updateThemeIcon(newTheme);
|
||||||
|
|
||||||
|
// Add animation
|
||||||
|
this.style.transform = 'scale(0.8)';
|
||||||
|
setTimeout(() => {
|
||||||
|
this.style.transform = 'scale(1)';
|
||||||
|
}, 150);
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateThemeIcon(theme) {
|
||||||
|
const icon = themeToggle.querySelector('i');
|
||||||
|
if (theme === 'dark') {
|
||||||
|
icon.className = 'fas fa-sun';
|
||||||
|
themeToggle.setAttribute('aria-label', 'Переключить на светлую тему');
|
||||||
|
} else {
|
||||||
|
icon.className = 'fas fa-moon';
|
||||||
|
themeToggle.setAttribute('aria-label', 'Переключить на темную тему');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navbar scroll behavior
|
||||||
|
const navbar = document.querySelector('.navbar-modern');
|
||||||
|
let lastScrollTop = 0;
|
||||||
|
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||||
|
|
||||||
|
// Add/remove scrolled class
|
||||||
|
if (scrollTop > 50) {
|
||||||
|
navbar.classList.add('scrolled');
|
||||||
|
} else {
|
||||||
|
navbar.classList.remove('scrolled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide/show navbar on scroll
|
||||||
|
if (scrollTop > lastScrollTop && scrollTop > 100) {
|
||||||
|
navbar.style.transform = 'translateY(-100%)';
|
||||||
|
} else {
|
||||||
|
navbar.style.transform = 'translateY(0)';
|
||||||
|
}
|
||||||
|
|
||||||
|
lastScrollTop = scrollTop;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scroll to top button
|
||||||
|
const scrollToTopBtn = document.getElementById('scroll-to-top');
|
||||||
|
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
if (window.pageYOffset > 300) {
|
||||||
|
scrollToTopBtn.style.display = 'block';
|
||||||
|
scrollToTopBtn.style.opacity = '1';
|
||||||
|
} else {
|
||||||
|
scrollToTopBtn.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
if (window.pageYOffset <= 300) {
|
||||||
|
scrollToTopBtn.style.display = 'none';
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
scrollToTopBtn.addEventListener('click', function() {
|
||||||
|
window.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Smooth scrolling for anchor links
|
||||||
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||||
|
anchor.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const target = document.querySelector(this.getAttribute('href'));
|
||||||
|
if (target) {
|
||||||
|
const offsetTop = target.offsetTop - 80; // Account for fixed navbar
|
||||||
|
window.scrollTo({
|
||||||
|
top: offsetTop,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Intersection Observer for animations
|
||||||
|
const observerOptions = {
|
||||||
|
threshold: 0.1,
|
||||||
|
rootMargin: '0px 0px -50px 0px'
|
||||||
|
};
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(function(entries) {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
entry.target.classList.add('animate-fade-in-up');
|
||||||
|
// Add stagger delay for child elements
|
||||||
|
const children = entry.target.querySelectorAll('.service-card, .feature-list > *, .step-card');
|
||||||
|
children.forEach((child, index) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
child.classList.add('animate-fade-in-up');
|
||||||
|
}, index * 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, observerOptions);
|
||||||
|
|
||||||
|
// Observe elements for animation
|
||||||
|
document.querySelectorAll('.service-card, .card-modern, .step-card').forEach(el => {
|
||||||
|
observer.observe(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form enhancements
|
||||||
|
const forms = document.querySelectorAll('form');
|
||||||
|
forms.forEach(form => {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
|
if (submitBtn) {
|
||||||
|
const originalContent = submitBtn.innerHTML;
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Отправляем...';
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
// Re-enable after 3 seconds (in case of slow response)
|
||||||
|
setTimeout(() => {
|
||||||
|
submitBtn.innerHTML = originalContent;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Parallax effect for hero section
|
||||||
|
window.addEventListener('scroll', function() {
|
||||||
|
const scrolled = window.pageYOffset;
|
||||||
|
const parallaxElements = document.querySelectorAll('.animate-float');
|
||||||
|
|
||||||
|
parallaxElements.forEach(element => {
|
||||||
|
const speed = 0.5;
|
||||||
|
element.style.transform = `translateY(${scrolled * speed}px)`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Service cards hover effect
|
||||||
|
document.querySelectorAll('.service-card').forEach(card => {
|
||||||
|
card.addEventListener('mouseenter', function() {
|
||||||
|
this.style.transform = 'translateY(-10px) scale(1.02)';
|
||||||
|
});
|
||||||
|
|
||||||
|
card.addEventListener('mouseleave', function() {
|
||||||
|
this.style.transform = 'translateY(0) scale(1)';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Card modern hover effects
|
||||||
|
document.querySelectorAll('.card-modern').forEach(card => {
|
||||||
|
card.addEventListener('mouseenter', function() {
|
||||||
|
this.style.boxShadow = '0 25px 50px -12px rgba(0, 0, 0, 0.25)';
|
||||||
|
});
|
||||||
|
|
||||||
|
card.addEventListener('mouseleave', function() {
|
||||||
|
this.style.boxShadow = 'var(--shadow)';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add loading animation to buttons
|
||||||
|
document.querySelectorAll('.btn-primary-modern, .btn-secondary-modern').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function(e) {
|
||||||
|
// Create ripple effect
|
||||||
|
const ripple = document.createElement('span');
|
||||||
|
const rect = this.getBoundingClientRect();
|
||||||
|
const size = Math.max(rect.width, rect.height);
|
||||||
|
const x = e.clientX - rect.left - size / 2;
|
||||||
|
const y = e.clientY - rect.top - size / 2;
|
||||||
|
|
||||||
|
ripple.style.cssText = `
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
transform: scale(0);
|
||||||
|
animation: ripple 0.6s linear;
|
||||||
|
width: ${size}px;
|
||||||
|
height: ${size}px;
|
||||||
|
left: ${x}px;
|
||||||
|
top: ${y}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
this.style.position = 'relative';
|
||||||
|
this.style.overflow = 'hidden';
|
||||||
|
this.appendChild(ripple);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ripple.remove();
|
||||||
|
}, 600);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Typing animation for hero text (optional)
|
||||||
|
const typingText = document.querySelector('.typing-text');
|
||||||
|
if (typingText) {
|
||||||
|
const text = typingText.textContent;
|
||||||
|
typingText.textContent = '';
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
function typeWriter() {
|
||||||
|
if (i < text.length) {
|
||||||
|
typingText.textContent += text.charAt(i);
|
||||||
|
i++;
|
||||||
|
setTimeout(typeWriter, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(typeWriter, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile menu enhancements
|
||||||
|
const navbarToggler = document.querySelector('.navbar-toggler');
|
||||||
|
const navbarCollapse = document.querySelector('.navbar-collapse');
|
||||||
|
|
||||||
|
if (navbarToggler && navbarCollapse) {
|
||||||
|
navbarToggler.addEventListener('click', function() {
|
||||||
|
const isExpanded = this.getAttribute('aria-expanded') === 'true';
|
||||||
|
|
||||||
|
// Animate the toggler icon
|
||||||
|
this.style.transform = 'rotate(180deg)';
|
||||||
|
setTimeout(() => {
|
||||||
|
this.style.transform = 'rotate(0deg)';
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close menu when clicking on a link
|
||||||
|
document.querySelectorAll('.navbar-nav .nav-link').forEach(link => {
|
||||||
|
link.addEventListener('click', () => {
|
||||||
|
const bsCollapse = new bootstrap.Collapse(navbarCollapse, {
|
||||||
|
hide: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Newsletter form
|
||||||
|
const newsletterForm = document.querySelector('footer form');
|
||||||
|
if (newsletterForm) {
|
||||||
|
newsletterForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const email = this.querySelector('input[type="email"]').value;
|
||||||
|
|
||||||
|
if (email) {
|
||||||
|
// Show success message
|
||||||
|
const button = this.querySelector('button');
|
||||||
|
const originalContent = button.innerHTML;
|
||||||
|
button.innerHTML = '<i class="fas fa-check"></i>';
|
||||||
|
button.style.background = '#10b981';
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
button.innerHTML = originalContent;
|
||||||
|
button.style.background = '';
|
||||||
|
this.reset();
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add CSS for ripple animation
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = `
|
||||||
|
@keyframes ripple {
|
||||||
|
to {
|
||||||
|
transform: scale(2);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fade-in-up {
|
||||||
|
opacity: 1 !important;
|
||||||
|
transform: translateY(0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smooth transitions */
|
||||||
|
.navbar-modern {
|
||||||
|
transition: transform 0.3s ease, background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card, .card-modern {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
transition: all 0.6s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-card {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-30px);
|
||||||
|
transition: all 0.6s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-card:nth-child(even) {
|
||||||
|
transform: translateX(30px);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
1
smartsoltech/staticfiles/assets/js/script.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
!function(){"use strict";var e=document.querySelector("#mainNav");if(e){var o=e.querySelector(".navbar-collapse");if(o){var n=new bootstrap.Collapse(o,{toggle:!1}),t=o.querySelectorAll("a");for(var a of t)a.addEventListener("click",(function(e){n.hide()}))}var r=function(){(void 0!==window.pageYOffset?window.pageYOffset:(document.documentElement||document.body.parentNode||document.body).scrollTop)>100?e.classList.add("navbar-shrink"):e.classList.remove("navbar-shrink")};r(),document.addEventListener("scroll",r);var d=document.querySelectorAll(".portfolio-modal");for(var s of d)s.addEventListener("shown.bs.modal",(function(o){e.classList.add("d-none")})),s.addEventListener("hidden.bs.modal",(function(o){e.classList.remove("d-none")}))}}();
|
||||||
116
smartsoltech/staticfiles/assets/js/service_request.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
// service-request.js
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// Открытие модального окна
|
||||||
|
const openModalBtn = document.getElementById('openModalBtn');
|
||||||
|
const serviceModal = document.getElementById('serviceModal');
|
||||||
|
const generateQrButton = document.getElementById('generateQrButton');
|
||||||
|
|
||||||
|
if (openModalBtn && serviceModal) {
|
||||||
|
openModalBtn.addEventListener('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
// Логирование значения serviceId при открытии модального окна
|
||||||
|
const serviceId = openModalBtn.getAttribute('data-service-id');
|
||||||
|
console.log("Service ID при открытии модального окна:", serviceId);
|
||||||
|
|
||||||
|
// Проверяем, если serviceId отсутствует
|
||||||
|
if (!serviceId) {
|
||||||
|
alert("Идентификатор услуги не найден. Обновите страницу и попробуйте снова.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохраняем serviceId для дальнейшего использования
|
||||||
|
generateQrButton.dataset.serviceId = serviceId;
|
||||||
|
|
||||||
|
// Показываем модальное окно
|
||||||
|
serviceModal.classList.add('show');
|
||||||
|
serviceModal.style.display = 'block';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Не удалось найти элемент с id openModalBtn или serviceModal.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Закрытие модального окна
|
||||||
|
document.querySelectorAll('.close').forEach(closeBtn => {
|
||||||
|
closeBtn.addEventListener('click', function () {
|
||||||
|
if (serviceModal) {
|
||||||
|
serviceModal.classList.remove('show');
|
||||||
|
setTimeout(() => {
|
||||||
|
serviceModal.style.display = 'none';
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработчик кнопки "Создать заявку"
|
||||||
|
if (generateQrButton) {
|
||||||
|
generateQrButton.addEventListener('click', function () {
|
||||||
|
// Получение значений полей
|
||||||
|
const clientEmail = document.getElementById('clientEmail').value.trim();
|
||||||
|
const clientPhone = document.getElementById('clientPhone').value.trim();
|
||||||
|
const clientName = document.getElementById('clientName').value.trim();
|
||||||
|
const description = document.getElementById('description').value.trim();
|
||||||
|
|
||||||
|
// Получаем serviceId из кнопки открытия модального окна
|
||||||
|
const serviceId = generateQrButton.dataset.serviceId;
|
||||||
|
|
||||||
|
// Логируем для проверки значения serviceId перед отправкой
|
||||||
|
console.log("Service ID перед отправкой запроса:", serviceId);
|
||||||
|
|
||||||
|
// Проверка заполненности полей
|
||||||
|
if (!clientEmail || !clientPhone || !clientName || !description || !serviceId) {
|
||||||
|
let errorMessage = 'Пожалуйста, заполните все поля формы перед продолжением.\n';
|
||||||
|
if (!serviceId) {
|
||||||
|
errorMessage += 'Идентификатор услуги не найден. Обновите страницу и попробуйте снова.\n';
|
||||||
|
}
|
||||||
|
alert(errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отправка POST запроса на создание заявки
|
||||||
|
fetch(`/service/generate_qr_code/${serviceId}/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': csrftoken // Используем глобально инициализированный CSRF токен
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
client_email: clientEmail,
|
||||||
|
client_phone: clientPhone,
|
||||||
|
client_name: clientName,
|
||||||
|
description: description
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Ошибка при создании заявки');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.qr_code_url) {
|
||||||
|
// Обновляем src изображения QR-кода и показываем его
|
||||||
|
const qrCodeImg = document.getElementById('qrCodeImg');
|
||||||
|
if (qrCodeImg) {
|
||||||
|
qrCodeImg.src = data.qr_code_url;
|
||||||
|
qrCodeImg.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Начинаем проверку статуса заявки
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
checkVerificationStatus(data.service_request_id, interval);
|
||||||
|
}, 5000);
|
||||||
|
} else if (data.status === 'existing_request') {
|
||||||
|
alert(data.message);
|
||||||
|
} else {
|
||||||
|
alert('Неизвестная ошибка. Пожалуйста, попробуйте снова.');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Ошибка при создании заявки:', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Не удалось найти элемент с id generateQrButton.');
|
||||||
|
}
|
||||||
|
});
|
||||||
37
smartsoltech/staticfiles/assets/js/verification_status.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// verification-status.js
|
||||||
|
|
||||||
|
function checkVerificationStatus(serviceRequestId, interval) {
|
||||||
|
console.log(`Проверка статуса для заявки с ID: ${serviceRequestId}`); // Лог для проверки
|
||||||
|
|
||||||
|
fetch(`/service/request_status/${serviceRequestId}/`)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Ошибка при проверке статуса заявки');
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.is_verified) {
|
||||||
|
// Закрываем форму и показываем окно подтверждения
|
||||||
|
const serviceModal = document.getElementById('serviceModal');
|
||||||
|
const confirmationModal = document.getElementById('confirmationModal');
|
||||||
|
|
||||||
|
if (serviceModal) {
|
||||||
|
serviceModal.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmationModal) {
|
||||||
|
confirmationModal.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Останавливаем интервал проверки статуса
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Ошибка при проверке статуса заявки:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Делаем функцию доступной глобально
|
||||||
|
window.checkVerificationStatus = checkVerificationStatus;
|
||||||
BIN
smartsoltech/staticfiles/img/1.png
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
smartsoltech/staticfiles/img/10.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
smartsoltech/staticfiles/img/11.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
smartsoltech/staticfiles/img/12.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
smartsoltech/staticfiles/img/13.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
smartsoltech/staticfiles/img/2.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
smartsoltech/staticfiles/img/3.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
smartsoltech/staticfiles/img/4.png
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
smartsoltech/staticfiles/img/5.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
smartsoltech/staticfiles/img/6.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
smartsoltech/staticfiles/img/7.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
smartsoltech/staticfiles/img/8.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
smartsoltech/staticfiles/img/9.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
1
smartsoltech/staticfiles/img/logo.svg
Normal file
|
After Width: | Height: | Size: 25 KiB |
18
smartsoltech/staticfiles/manifest.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"short_name": "sst",
|
||||||
|
"name": "Smartsoltech",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/static/img/photo_2024-10-06_10-06-08.jpg",
|
||||||
|
"type": "image/jpeg",
|
||||||
|
"sizes": "1011x702"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/static/img/photo_2024-10-06_10-06-08.jpg",
|
||||||
|
"type": "image/jpeg",
|
||||||
|
"sizes": "1011x702"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "fullscreen"
|
||||||
|
}
|
||||||
BIN
smartsoltech/staticfiles/qr_codes/request_3.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/staticfiles/qr_codes/request_4.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/staticfiles/qr_codes/request_5.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
smartsoltech/staticfiles/qr_codes/request_6.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
556
smartsoltech/web/templates/web/about_modern.html
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
{% extends 'web/base_modern.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% block title %}О нас - SmartSolTech{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<section class="hero-modern">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
🚀 О нас
|
||||||
|
</span>
|
||||||
|
<h1 class="display-4 fw-bold mb-4">
|
||||||
|
Мы создаем <span class="text-gradient">цифровое будущее</span>
|
||||||
|
</h1>
|
||||||
|
<p class="lead text-muted mb-4">
|
||||||
|
SmartSolTech - это команда профессионалов, которые превращают идеи в инновационные IT-решения.
|
||||||
|
Мы помогаем бизнесу расти и развиваться в цифровую эпоху.
|
||||||
|
</p>
|
||||||
|
<div class="d-flex flex-wrap gap-3">
|
||||||
|
<a href="#team" class="btn btn-primary-modern">
|
||||||
|
<i class="fas fa-users me-2"></i>
|
||||||
|
Наша команда
|
||||||
|
</a>
|
||||||
|
<a href="#contact" class="btn btn-secondary-modern">
|
||||||
|
<i class="fas fa-envelope me-2"></i>
|
||||||
|
Связаться с нами
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="position-relative">
|
||||||
|
<!-- Company illustration -->
|
||||||
|
<div class="about-graphic">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card bg-white rounded-4 p-4 shadow animate-float">
|
||||||
|
<div class="stat-icon bg-primary rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-code text-white fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-gradient fw-bold">50+</h3>
|
||||||
|
<p class="mb-0 text-muted">Проектов</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card bg-white rounded-4 p-4 shadow animate-float" style="animation-delay: 0.5s;">
|
||||||
|
<div class="stat-icon bg-success rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-users text-white fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-gradient fw-bold">30+</h3>
|
||||||
|
<p class="mb-0 text-muted">Клиентов</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card bg-white rounded-4 p-4 shadow animate-float" style="animation-delay: 1s;">
|
||||||
|
<div class="stat-icon bg-warning rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-award text-white fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-gradient fw-bold">3+</h3>
|
||||||
|
<p class="mb-0 text-muted">Лет опыта</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card bg-white rounded-4 p-4 shadow animate-float" style="animation-delay: 1.5s;">
|
||||||
|
<div class="stat-icon bg-info rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-rocket text-white fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-gradient fw-bold">24/7</h3>
|
||||||
|
<p class="mb-0 text-muted">Поддержка</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Mission & Vision -->
|
||||||
|
<section class="section-padding bg-light">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row g-5">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="pe-lg-4">
|
||||||
|
<span class="badge bg-primary text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
🎯 Наша миссия
|
||||||
|
</span>
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Делаем технологии <span class="text-gradient">доступными</span>
|
||||||
|
</h2>
|
||||||
|
<p class="text-muted mb-4">
|
||||||
|
Мы верим, что каждый бизнес заслуживает доступа к современным технологиям.
|
||||||
|
Наша миссия — демократизировать IT-решения и помочь компаниям любого размера
|
||||||
|
достичь цифрового совершенства.
|
||||||
|
</p>
|
||||||
|
<div class="mission-points">
|
||||||
|
<div class="d-flex align-items-start mb-3">
|
||||||
|
<i class="fas fa-check-circle text-success me-3 mt-1"></i>
|
||||||
|
<div>
|
||||||
|
<h6>Инновационные решения</h6>
|
||||||
|
<p class="text-muted mb-0 small">Используем передовые технологии для создания уникальных продуктов</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-start mb-3">
|
||||||
|
<i class="fas fa-check-circle text-success me-3 mt-1"></i>
|
||||||
|
<div>
|
||||||
|
<h6>Клиентоориентированность</h6>
|
||||||
|
<p class="text-muted mb-0 small">Фокусируемся на потребностях и целях каждого клиента</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
<i class="fas fa-check-circle text-success me-3 mt-1"></i>
|
||||||
|
<div>
|
||||||
|
<h6>Непрерывное развитие</h6>
|
||||||
|
<p class="text-muted mb-0 small">Постоянно совершенствуем наши навыки и знания</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="ps-lg-4">
|
||||||
|
<span class="badge bg-secondary text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
🔮 Наше видение
|
||||||
|
</span>
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Будущее начинается <span class="text-gradient">сегодня</span>
|
||||||
|
</h2>
|
||||||
|
<p class="text-muted mb-4">
|
||||||
|
Мы стремимся стать ведущей IT-компанией в Корее, известной своими инновационными решениями,
|
||||||
|
высоким качеством сервиса и способностью трансформировать бизнес-идеи в успешные цифровые продукты.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Progress bars -->
|
||||||
|
<div class="skills-progress">
|
||||||
|
<div class="skill-item mb-3">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<span class="fw-semibold">Веб-разработка</span>
|
||||||
|
<span class="text-muted">95%</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" style="height: 8px;">
|
||||||
|
<div class="progress-bar bg-gradient" role="progressbar" style="width: 95%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item mb-3">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<span class="fw-semibold">Мобильная разработка</span>
|
||||||
|
<span class="text-muted">90%</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" style="height: 8px;">
|
||||||
|
<div class="progress-bar bg-gradient" role="progressbar" style="width: 90%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item mb-3">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<span class="fw-semibold">UI/UX Дизайн</span>
|
||||||
|
<span class="text-muted">85%</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" style="height: 8px;">
|
||||||
|
<div class="progress-bar bg-gradient" role="progressbar" style="width: 85%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skill-item">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<span class="fw-semibold">DevOps</span>
|
||||||
|
<span class="text-muted">80%</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress" style="height: 8px;">
|
||||||
|
<div class="progress-bar bg-gradient" role="progressbar" style="width: 80%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Team Section -->
|
||||||
|
<section class="section-padding" id="team">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="text-center mb-5">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
👥 Команда
|
||||||
|
</span>
|
||||||
|
<h2 class="display-5 fw-bold mb-3">
|
||||||
|
Познакомьтесь с <span class="text-gradient">нашей командой</span>
|
||||||
|
</h2>
|
||||||
|
<p class="lead text-muted max-width-600 mx-auto">
|
||||||
|
Талантливые профессионалы, которые воплощают ваши идеи в реальность
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-4">
|
||||||
|
<!-- Team Member 1 -->
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<div class="card-modern text-center h-100">
|
||||||
|
<div class="position-relative">
|
||||||
|
<div class="team-avatar mx-auto mb-3" style="width: 120px; height: 120px; background: var(--gradient-primary); border-radius: 50%; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-user text-white fa-3x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="mb-2">Алексей Чой</h5>
|
||||||
|
<p class="text-primary mb-3">CEO & Founder</p>
|
||||||
|
<p class="text-muted small mb-3">
|
||||||
|
Визионер и лидер команды с более чем 5-летним опытом в IT-индустрии.
|
||||||
|
Специализируется на стратегическом планировании и управлении проектами.
|
||||||
|
</p>
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-linkedin-in"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-telegram-plane"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Team Member 2 -->
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<div class="card-modern text-center h-100">
|
||||||
|
<div class="position-relative">
|
||||||
|
<div class="team-avatar mx-auto mb-3" style="width: 120px; height: 120px; background: var(--gradient-accent); border-radius: 50%; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-user text-white fa-3x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="mb-2">Анна Ким</h5>
|
||||||
|
<p class="text-success mb-3">Lead Developer</p>
|
||||||
|
<p class="text-muted small mb-3">
|
||||||
|
Опытный full-stack разработчик со страстью к созданию масштабируемых
|
||||||
|
и эффективных веб-приложений. Эксперт в React, Django и cloud технологиях.
|
||||||
|
</p>
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-linkedin-in"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Team Member 3 -->
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<div class="card-modern text-center h-100">
|
||||||
|
<div class="position-relative">
|
||||||
|
<div class="team-avatar mx-auto mb-3" style="width: 120px; height: 120px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center;">
|
||||||
|
<i class="fas fa-user text-white fa-3x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="mb-2">Дмитрий Пак</h5>
|
||||||
|
<p class="text-warning mb-3">UI/UX Designer</p>
|
||||||
|
<p class="text-muted small mb-3">
|
||||||
|
Креативный дизайнер, создающий интуитивные и привлекательные пользовательские интерфейсы.
|
||||||
|
Специализируется на UX-исследованиях и современном веб-дизайне.
|
||||||
|
</p>
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-dribbble"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-primary btn-sm rounded-circle" style="width: 40px; height: 40px;">
|
||||||
|
<i class="fab fa-behance"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Technologies Section -->
|
||||||
|
<section class="section-padding bg-light">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="text-center mb-5">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
⚡ Технологии
|
||||||
|
</span>
|
||||||
|
<h2 class="display-6 fw-bold mb-3">
|
||||||
|
Современный <span class="text-gradient">технологический стек</span>
|
||||||
|
</h2>
|
||||||
|
<p class="lead text-muted">
|
||||||
|
Мы используем проверенные и инновационные технологии для создания качественных решений
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-4">
|
||||||
|
<!-- Frontend -->
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<h5 class="mb-3">Frontend</h5>
|
||||||
|
<div class="d-flex flex-wrap justify-content-center gap-3">
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-react text-info fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">React</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-vue text-success fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Vue.js</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-html5 text-danger fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">HTML5</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-css3-alt text-primary fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">CSS3</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Backend -->
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<h5 class="mb-3">Backend</h5>
|
||||||
|
<div class="d-flex flex-wrap justify-content-center gap-3">
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-python text-warning fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Python</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fas fa-server text-success fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Django</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-node-js text-success fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Node.js</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fas fa-database text-info fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">PostgreSQL</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile -->
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<h5 class="mb-3">Mobile</h5>
|
||||||
|
<div class="d-flex flex-wrap justify-content-center gap-3">
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-react text-info fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">React Native</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-android text-success fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Android</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-apple text-dark fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">iOS</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fas fa-mobile-alt text-primary fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Flutter</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- DevOps -->
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<h5 class="mb-3">DevOps</h5>
|
||||||
|
<div class="d-flex flex-wrap justify-content-center gap-3">
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-docker text-primary fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">Docker</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-aws text-warning fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">AWS</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fab fa-github text-dark fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">GitHub</small>
|
||||||
|
</div>
|
||||||
|
<div class="tech-icon">
|
||||||
|
<i class="fas fa-cogs text-secondary fa-2x"></i>
|
||||||
|
<small class="d-block mt-1">CI/CD</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Contact Section -->
|
||||||
|
<section class="section-padding bg-gradient text-white" id="contact">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="text-center mb-5">
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Начнем сотрудничество?
|
||||||
|
</h2>
|
||||||
|
<p class="lead opacity-90 mb-5">
|
||||||
|
Свяжитесь с нами для обсуждения вашего проекта
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-md-4 text-center">
|
||||||
|
<div class="contact-item">
|
||||||
|
<i class="fas fa-envelope fa-2x mb-3 opacity-75"></i>
|
||||||
|
<h5>Email</h5>
|
||||||
|
<a href="mailto:info@smartsoltech.kr" class="text-white text-decoration-none opacity-75">
|
||||||
|
info@smartsoltech.kr
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 text-center">
|
||||||
|
<div class="contact-item">
|
||||||
|
<i class="fas fa-phone fa-2x mb-3 opacity-75"></i>
|
||||||
|
<h5>Телефон</h5>
|
||||||
|
<a href="tel:+82-10-XXXX-XXXX" class="text-white text-decoration-none opacity-75">
|
||||||
|
+82-10-XXXX-XXXX
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 text-center">
|
||||||
|
<div class="contact-item">
|
||||||
|
<i class="fab fa-telegram-plane fa-2x mb-3 opacity-75"></i>
|
||||||
|
<h5>Telegram</h5>
|
||||||
|
<a href="https://t.me/smartsoltech" class="text-white text-decoration-none opacity-75">
|
||||||
|
@smartsoltech
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-5">
|
||||||
|
<a href="{% url 'services' %}" class="btn btn-light btn-lg text-primary">
|
||||||
|
<i class="fas fa-rocket me-2"></i>
|
||||||
|
Начать проект
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_scripts %}
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Animate progress bars when they come into view
|
||||||
|
const observerOptions = {
|
||||||
|
threshold: 0.5
|
||||||
|
};
|
||||||
|
|
||||||
|
const progressObserver = new IntersectionObserver(function(entries) {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
const progressBars = entry.target.querySelectorAll('.progress-bar');
|
||||||
|
progressBars.forEach(bar => {
|
||||||
|
const width = bar.style.width;
|
||||||
|
bar.style.width = '0%';
|
||||||
|
setTimeout(() => {
|
||||||
|
bar.style.width = width;
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, observerOptions);
|
||||||
|
|
||||||
|
const skillsSection = document.querySelector('.skills-progress');
|
||||||
|
if (skillsSection) {
|
||||||
|
progressObserver.observe(skillsSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animate stat cards
|
||||||
|
const statCards = document.querySelectorAll('.stat-card');
|
||||||
|
statCards.forEach((card, index) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
card.classList.add('animate-fade-in-up');
|
||||||
|
}, index * 200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.max-width-600 {
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icon {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: var(--bg-light);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icon:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
transition: width 1.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item {
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item:hover i {
|
||||||
|
transform: scale(1.1);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-avatar {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-modern:hover .team-avatar {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.about-graphic .row {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icon {
|
||||||
|
margin: 0.25rem;
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
72
smartsoltech/web/templates/web/base_modern.html
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{% load static %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru" data-theme="light">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="SmartSolTech - Современные IT-решения для вашего бизнеса">
|
||||||
|
<meta name="keywords" content="IT, разработка, веб-дизайн, мобильные приложения, SmartSolTech">
|
||||||
|
<meta name="author" content="SmartSolTech">
|
||||||
|
|
||||||
|
<!-- Preconnect to Google Fonts for performance -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
|
||||||
|
<!-- Google Fonts -->
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Font Awesome for icons -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom Styles -->
|
||||||
|
<link rel="stylesheet" href="{% static 'assets/css/modern-styles.css' %}">
|
||||||
|
<link rel="stylesheet" href="{% static 'assets/css/modal-styles.css' %}">
|
||||||
|
|
||||||
|
<!-- Manifest -->
|
||||||
|
<link rel="manifest" href="/static/manifest.json">
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' fill='%236366f1'/><text y='70' font-size='60' fill='white' font-family='Arial,sans-serif' text-anchor='middle' x='50'>S</text></svg>">>
|
||||||
|
|
||||||
|
<title>{% block title %}SmartSolTech - Современные IT-решения{% endblock %}</title>
|
||||||
|
|
||||||
|
{% block extra_head %}{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Loading Screen -->
|
||||||
|
<div id="loading-screen" class="position-fixed top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center" style="background: var(--bg-light); z-index: 9999;">
|
||||||
|
<div class="loading-spinner"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Navigation -->
|
||||||
|
{% include 'web/navbar_modern.html' %}
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
{% include 'web/footer_modern.html' %}
|
||||||
|
|
||||||
|
<!-- Theme Toggle Button -->
|
||||||
|
<button id="theme-toggle" class="theme-toggle" aria-label="Переключить тему">
|
||||||
|
<i class="fas fa-moon"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Scroll to Top Button -->
|
||||||
|
<button id="scroll-to-top" class="position-fixed bottom-0 end-0 m-4 btn btn-primary-modern rounded-circle" style="width: 50px; height: 50px; display: none; z-index: 999;">
|
||||||
|
<i class="fas fa-arrow-up"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Scripts -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="{% static 'assets/js/modern-scripts.js' %}"></script>
|
||||||
|
<script src="{% static 'assets/js/modal-init.js' %}"></script>
|
||||||
|
|
||||||
|
{% block extra_scripts %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
189
smartsoltech/web/templates/web/footer_modern.html
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
{% load static %}
|
||||||
|
<footer class="bg-dark text-light section-padding mt-5">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row g-4">
|
||||||
|
<!-- Company Info -->
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<div class="mb-4">
|
||||||
|
<h4 class="text-gradient mb-3">
|
||||||
|
<i class="fas fa-code me-2"></i>
|
||||||
|
SmartSolTech
|
||||||
|
</h4>
|
||||||
|
<p class="text-light opacity-75 mb-4">
|
||||||
|
Мы создаем инновационные IT-решения, которые помогают бизнесу расти и развиваться в цифровую эпоху.
|
||||||
|
</p>
|
||||||
|
<div class="d-flex gap-3">
|
||||||
|
<a href="#" class="btn btn-outline-light rounded-circle" style="width: 45px; height: 45px;">
|
||||||
|
<i class="fab fa-telegram-plane"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-light rounded-circle" style="width: 45px; height: 45px;">
|
||||||
|
<i class="fab fa-instagram"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-light rounded-circle" style="width: 45px; height: 45px;">
|
||||||
|
<i class="fab fa-linkedin-in"></i>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="btn btn-outline-light rounded-circle" style="width: 45px; height: 45px;">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Services -->
|
||||||
|
<div class="col-lg-2 col-md-6">
|
||||||
|
<h5 class="mb-3 text-light">Услуги</h5>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="{% url 'services' %}" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
Веб-разработка
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="{% url 'services' %}" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
Мобильные приложения
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="{% url 'services' %}" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
UI/UX Дизайн
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="{% url 'services' %}" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
DevOps
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Company -->
|
||||||
|
<div class="col-lg-2 col-md-6">
|
||||||
|
<h5 class="mb-3 text-light">Компания</h5>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="{% url 'about' %}" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
О нас
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="#" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
Портфолио
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="#" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
Команда
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<a href="#" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
Карьера
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Contact Info -->
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<h5 class="mb-3 text-light">Контакты</h5>
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="d-flex align-items-center mb-2">
|
||||||
|
<i class="fas fa-envelope me-3 text-primary"></i>
|
||||||
|
<a href="mailto:info@smartsoltech.kr" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
info@smartsoltech.kr
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center mb-2">
|
||||||
|
<i class="fas fa-phone me-3 text-primary"></i>
|
||||||
|
<a href="tel:+82-10-XXXX-XXXX" class="text-light opacity-75 text-decoration-none hover-primary">
|
||||||
|
+82-10-XXXX-XXXX
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-start mb-2">
|
||||||
|
<i class="fas fa-map-marker-alt me-3 text-primary mt-1"></i>
|
||||||
|
<span class="text-light opacity-75">
|
||||||
|
Seoul, South Korea
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Newsletter -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<h6 class="text-light mb-2">Подписаться на новости</h6>
|
||||||
|
<form class="d-flex">
|
||||||
|
<input type="email" class="form-control me-2 bg-transparent border-light text-light"
|
||||||
|
placeholder="Ваш email" style="border-radius: 10px;">
|
||||||
|
<button type="submit" class="btn btn-primary-modern">
|
||||||
|
<i class="fas fa-paper-plane"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr class="my-5 border-light opacity-25">
|
||||||
|
|
||||||
|
<!-- Copyright -->
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p class="mb-0 text-light opacity-75">
|
||||||
|
© 2025 SmartSolTech. Все права защищены.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-md-flex justify-content-md-end">
|
||||||
|
<ul class="list-inline mb-0">
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<a href="#" class="text-light opacity-75 text-decoration-none hover-primary small">
|
||||||
|
Политика конфиденциальности
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item ms-3">
|
||||||
|
<a href="#" class="text-light opacity-75 text-decoration-none hover-primary small">
|
||||||
|
Условия использования
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hover-primary {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover-primary:hover {
|
||||||
|
color: var(--primary-color) !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%) !important;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="10" height="10" patternUnits="userSpaceOnUse"><circle cx="5" cy="5" r="0.5" fill="%236366f1" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>');
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .container-modern {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-light:hover {
|
||||||
|
background: var(--gradient-primary) !important;
|
||||||
|
border-color: transparent !important;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
370
smartsoltech/web/templates/web/home_modern.html
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
{% extends 'web/base_modern.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% block title %}SmartSolTech - Современные IT-решения для вашего бизнеса{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<section class="hero-modern" id="home">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row align-items-center min-vh-100">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="animate-fade-in-up">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill fs-6">
|
||||||
|
🚀 Инновационные IT-решения
|
||||||
|
</span>
|
||||||
|
<h1 class="display-3 fw-bold mb-4">
|
||||||
|
Создаем <span class="text-gradient">будущее</span> вашего бизнеса
|
||||||
|
</h1>
|
||||||
|
<p class="lead mb-4 text-muted">
|
||||||
|
Мы разрабатываем современные веб-приложения, мобильные решения и системы автоматизации,
|
||||||
|
которые помогают компаниям расти и быть конкурентоспособными.
|
||||||
|
</p>
|
||||||
|
<div class="d-flex flex-wrap gap-3 mb-5">
|
||||||
|
<a href="{% url 'services' %}" class="btn btn-primary-modern btn-lg">
|
||||||
|
<i class="fas fa-rocket me-2"></i>
|
||||||
|
Начать проект
|
||||||
|
</a>
|
||||||
|
<a href="{% url 'about' %}" class="btn btn-secondary-modern btn-lg">
|
||||||
|
<i class="fas fa-play-circle me-2"></i>
|
||||||
|
Узнать больше
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="row text-center">
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="stat-item">
|
||||||
|
<h3 class="text-gradient fw-bold mb-1">50+</h3>
|
||||||
|
<p class="small text-muted mb-0">Проектов</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="stat-item">
|
||||||
|
<h3 class="text-gradient fw-bold mb-1">3+</h3>
|
||||||
|
<p class="small text-muted mb-0">Лет опыта</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="stat-item">
|
||||||
|
<h3 class="text-gradient fw-bold mb-1">24/7</h3>
|
||||||
|
<p class="small text-muted mb-0">Поддержка</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="text-center animate-float">
|
||||||
|
<div class="position-relative">
|
||||||
|
<!-- 3D Graphic Placeholder -->
|
||||||
|
<div class="hero-graphic p-5">
|
||||||
|
<div class="position-relative">
|
||||||
|
<!-- Code Window -->
|
||||||
|
<div class="code-window bg-dark rounded-4 p-4 mb-4 shadow-lg"
|
||||||
|
style="transform: rotate(-5deg); max-width: 400px;">
|
||||||
|
<div class="d-flex gap-2 mb-3">
|
||||||
|
<div class="rounded-circle bg-danger" style="width: 12px; height: 12px;"></div>
|
||||||
|
<div class="rounded-circle bg-warning" style="width: 12px; height: 12px;"></div>
|
||||||
|
<div class="rounded-circle bg-success" style="width: 12px; height: 12px;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="text-light font-monospace small">
|
||||||
|
<div class="text-info">def create_future():</div>
|
||||||
|
<div class="ms-3 text-success">return innovation + passion</div>
|
||||||
|
<div class="text-warning">// SmartSolTech</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile App Preview -->
|
||||||
|
<div class="mobile-preview bg-light rounded-4 p-3 shadow-lg position-absolute"
|
||||||
|
style="transform: rotate(10deg); top: 50px; right: 50px; width: 200px;">
|
||||||
|
<div class="bg-gradient rounded-3 p-3 text-white text-center">
|
||||||
|
<i class="fas fa-mobile-alt fa-3x mb-2"></i>
|
||||||
|
<h6 class="mb-1">Мобильные</h6>
|
||||||
|
<p class="small mb-0 opacity-75">приложения</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Floating Icons -->
|
||||||
|
<div class="floating-icon position-absolute"
|
||||||
|
style="top: 20px; left: 20px; animation: float 2s ease-in-out infinite;">
|
||||||
|
<div class="bg-primary rounded-3 p-3 text-white shadow">
|
||||||
|
<i class="fab fa-react fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="floating-icon position-absolute"
|
||||||
|
style="bottom: 100px; left: 100px; animation: float 3s ease-in-out infinite reverse;">
|
||||||
|
<div class="bg-success rounded-3 p-3 text-white shadow">
|
||||||
|
<i class="fab fa-python fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Services Preview Section -->
|
||||||
|
<section class="section-padding bg-light">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="text-center mb-5">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
⚡ Наши услуги
|
||||||
|
</span>
|
||||||
|
<h2 class="display-5 fw-bold mb-3">
|
||||||
|
Полный спектр <span class="text-gradient">IT-услуг</span>
|
||||||
|
</h2>
|
||||||
|
<p class="lead text-muted max-width-600 mx-auto">
|
||||||
|
От идеи до реализации - мы предоставляем комплексные решения для вашего цифрового успеха
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="services-grid">
|
||||||
|
{% for service in services %}
|
||||||
|
<div class="service-card">
|
||||||
|
<div class="service-icon">
|
||||||
|
<i class="fas fa-{% cycle 'code' 'mobile-alt' 'paint-brush' 'server' 'chart-line' 'shield-alt' %}"></i>
|
||||||
|
</div>
|
||||||
|
<h4 class="mb-3">{{ service.name }}</h4>
|
||||||
|
<p class="text-muted mb-4">{{ service.description|truncatewords:20 }}</p>
|
||||||
|
<a href="{% url 'service_detail' service.pk %}" class="btn btn-outline-primary">
|
||||||
|
Подробнее <i class="fas fa-arrow-right ms-2"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-5">
|
||||||
|
<a href="{% url 'services' %}" class="btn btn-primary-modern btn-lg">
|
||||||
|
<i class="fas fa-th-large me-2"></i>
|
||||||
|
Все услуги
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Why Choose Us Section -->
|
||||||
|
<section class="section-padding">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="pe-lg-5">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
🎯 Почему мы
|
||||||
|
</span>
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Ваш надежный <span class="text-gradient">IT-партнер</span>
|
||||||
|
</h2>
|
||||||
|
<p class="text-muted mb-4">
|
||||||
|
Мы не просто выполняем проекты - мы создаем долгосрочные партнерские отношения
|
||||||
|
и помогаем бизнесу расти с помощью технологий.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="feature-list">
|
||||||
|
<div class="d-flex align-items-start mb-4">
|
||||||
|
<div class="feature-icon bg-primary rounded-3 p-2 me-3 text-white">
|
||||||
|
<i class="fas fa-rocket"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5 class="mb-2">Быстрая разработка</h5>
|
||||||
|
<p class="text-muted mb-0">Agile-методология и современные инструменты для быстрой доставки результата</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-start mb-4">
|
||||||
|
<div class="feature-icon bg-success rounded-3 p-2 me-3 text-white">
|
||||||
|
<i class="fas fa-shield-alt"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5 class="mb-2">Высокое качество</h5>
|
||||||
|
<p class="text-muted mb-0">Тщательное тестирование и code review обеспечивают надежность решений</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-start mb-4">
|
||||||
|
<div class="feature-icon bg-warning rounded-3 p-2 me-3 text-white">
|
||||||
|
<i class="fas fa-headset"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5 class="mb-2">24/7 Поддержка</h5>
|
||||||
|
<p class="text-muted mb-0">Постоянная техническая поддержка и сопровождение проектов</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="position-relative">
|
||||||
|
<!-- Process Steps -->
|
||||||
|
<div class="process-steps">
|
||||||
|
<div class="step-card active bg-white rounded-4 p-4 shadow mb-4">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="step-number bg-primary text-white rounded-circle me-3"
|
||||||
|
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
1
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-1">Анализ требований</h6>
|
||||||
|
<p class="small text-muted mb-0">Детальное изучение ваших потребностей</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="step-card bg-white rounded-4 p-4 shadow mb-4">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="step-number bg-secondary text-white rounded-circle me-3"
|
||||||
|
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
2
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-1">Проектирование</h6>
|
||||||
|
<p class="small text-muted mb-0">Создание архитектуры и дизайна</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="step-card bg-white rounded-4 p-4 shadow mb-4">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="step-number bg-success text-white rounded-circle me-3"
|
||||||
|
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
3
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-1">Разработка</h6>
|
||||||
|
<p class="small text-muted mb-0">Программирование и тестирование</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="step-card bg-white rounded-4 p-4 shadow">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="step-number bg-warning text-white rounded-circle me-3"
|
||||||
|
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
|
||||||
|
4
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-1">Запуск и поддержка</h6>
|
||||||
|
<p class="small text-muted mb-0">Деплой и техническая поддержка</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CTA Section -->
|
||||||
|
<section class="section-padding bg-gradient text-white">
|
||||||
|
<div class="container-modern text-center">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Готовы начать свой проект?
|
||||||
|
</h2>
|
||||||
|
<p class="lead mb-5 opacity-90">
|
||||||
|
Свяжитесь с нами сегодня и получите бесплатную консультацию по вашему проекту
|
||||||
|
</p>
|
||||||
|
<div class="d-flex flex-wrap gap-3 justify-content-center">
|
||||||
|
<a href="{% url 'services' %}" class="btn btn-light btn-lg text-primary">
|
||||||
|
<i class="fas fa-comments me-2"></i>
|
||||||
|
Получить консультацию
|
||||||
|
</a>
|
||||||
|
<a href="tel:+82-10-XXXX-XXXX" class="btn btn-outline-light btn-lg">
|
||||||
|
<i class="fas fa-phone me-2"></i>
|
||||||
|
Позвонить сейчас
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_scripts %}
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Animate elements on scroll
|
||||||
|
const observerOptions = {
|
||||||
|
threshold: 0.1,
|
||||||
|
rootMargin: '0px 0px -50px 0px'
|
||||||
|
};
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(function(entries) {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
entry.target.classList.add('animate-fade-in-up');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, observerOptions);
|
||||||
|
|
||||||
|
// Observe service cards
|
||||||
|
document.querySelectorAll('.service-card, .step-card').forEach(card => {
|
||||||
|
observer.observe(card);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.max-width-600 {
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-graphic {
|
||||||
|
perspective: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-window {
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-icon {
|
||||||
|
animation-delay: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-card {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
transition: all 0.6s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-card.animate-fade-in-up {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.hero-graphic {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-window {
|
||||||
|
transform: rotate(0deg) !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-preview {
|
||||||
|
position: relative !important;
|
||||||
|
transform: rotate(0deg) !important;
|
||||||
|
margin-top: 1rem;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-icon {
|
||||||
|
position: relative !important;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
127
smartsoltech/web/templates/web/navbar_modern.html
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{% load static %}
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-modern">
|
||||||
|
<div class="container-modern">
|
||||||
|
<a class="navbar-brand-modern" href="{% url 'home' %}">
|
||||||
|
<i class="fas fa-code me-2"></i>
|
||||||
|
SmartSolTech
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||||
|
aria-controls="navbarNav" aria-expanded="false" aria-label="Переключить навигацию">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link-modern {% if request.resolver_match.url_name == 'home' %}active{% endif %}"
|
||||||
|
href="{% url 'home' %}">
|
||||||
|
<i class="fas fa-home me-2"></i>Главная
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link-modern {% if request.resolver_match.url_name == 'services' %}active{% endif %}"
|
||||||
|
href="{% url 'services' %}">
|
||||||
|
<i class="fas fa-cog me-2"></i>Услуги
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link-modern {% if request.resolver_match.url_name == 'about' %}active{% endif %}"
|
||||||
|
href="{% url 'about' %}">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>О нас
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link-modern" href="#contact">
|
||||||
|
<i class="fas fa-envelope me-2"></i>Контакты
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item ms-3">
|
||||||
|
<a class="btn btn-primary-modern" href="{% url 'services' %}">
|
||||||
|
<i class="fas fa-rocket me-2"></i>Начать проект
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.navbar-toggler {
|
||||||
|
position: relative;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: none !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler:focus {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler-icon {
|
||||||
|
display: block;
|
||||||
|
width: 25px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: var(--text-dark);
|
||||||
|
position: relative;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler-icon::before,
|
||||||
|
.navbar-toggler-icon::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 25px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: var(--text-dark);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler-icon::before {
|
||||||
|
top: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler-icon::after {
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler[aria-expanded="true"] .navbar-toggler-icon {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler[aria-expanded="true"] .navbar-toggler-icon::before {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler[aria-expanded="true"] .navbar-toggler-icon::after {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
.navbar-collapse {
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
background: var(--bg-light);
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link-modern {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary-modern {
|
||||||
|
margin-top: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
657
smartsoltech/web/templates/web/services_modern.html
Normal file
@@ -0,0 +1,657 @@
|
|||||||
|
{% extends 'web/base_modern.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% block title %}Наши услуги - SmartSolTech{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<section class="hero-modern">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row justify-content-center text-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
|
||||||
|
⚡ Полный спектр услуг
|
||||||
|
</span>
|
||||||
|
<h1 class="display-4 fw-bold mb-4">
|
||||||
|
Наши <span class="text-gradient">IT-услуги</span>
|
||||||
|
</h1>
|
||||||
|
<p class="lead text-muted mb-5">
|
||||||
|
От концепции до запуска - мы предоставляем комплексные IT-решения для роста вашего бизнеса
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Services Grid -->
|
||||||
|
<section class="section-padding">
|
||||||
|
<div class="container-modern">
|
||||||
|
<!-- Service Categories Filter -->
|
||||||
|
<div class="text-center mb-5">
|
||||||
|
<div class="btn-group" role="group" aria-label="Категории услуг">
|
||||||
|
<button type="button" class="btn btn-outline-primary active" data-filter="all">
|
||||||
|
Все услуги
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary" data-filter="web">
|
||||||
|
Веб-разработка
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary" data-filter="mobile">
|
||||||
|
Мобильные приложения
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary" data-filter="design">
|
||||||
|
Дизайн
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-primary" data-filter="other">
|
||||||
|
Другое
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-4" id="services-container">
|
||||||
|
{% for service in services %}
|
||||||
|
<div class="col-lg-4 col-md-6 service-item" data-category="{{ service.category.name|lower }}">
|
||||||
|
<div class="card-modern h-100">
|
||||||
|
<div class="position-relative overflow-hidden" style="height: 200px;">
|
||||||
|
{% if service.image %}
|
||||||
|
<img src="{{ service.image.url }}" class="w-100 h-100" style="object-fit: cover;" alt="{{ service.name }}">
|
||||||
|
{% else %}
|
||||||
|
<div class="w-100 h-100 bg-gradient d-flex align-items-center justify-content-center">
|
||||||
|
<i class="fas fa-cogs text-white" style="font-size: 3rem;"></i>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="position-absolute top-0 start-0 p-3">
|
||||||
|
<span class="badge bg-primary">{{ service.category.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<h5 class="mb-3">{{ service.name }}</h5>
|
||||||
|
<p class="text-muted flex-grow-1">{{ service.description|truncatewords:15 }}</p>
|
||||||
|
|
||||||
|
<!-- Service Features -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<small class="text-muted d-block mb-2">Что входит:</small>
|
||||||
|
<div class="d-flex flex-wrap gap-1">
|
||||||
|
<span class="badge bg-light text-dark">Консультация</span>
|
||||||
|
<span class="badge bg-light text-dark">Разработка</span>
|
||||||
|
<span class="badge bg-light text-dark">Тестирование</span>
|
||||||
|
<span class="badge bg-light text-dark">Поддержка</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Price Range -->
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<div>
|
||||||
|
<small class="text-muted">От</small>
|
||||||
|
<span class="h5 text-primary mb-0">₩ {{ service.price|default:"По запросу" }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-end">
|
||||||
|
<small class="text-muted">Срок</small>
|
||||||
|
<div class="fw-semibold">2-4 недели</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<a href="{% url 'service_detail' service.pk %}" class="btn btn-outline-primary flex-grow-1">
|
||||||
|
Подробнее
|
||||||
|
</a>
|
||||||
|
<button class="btn btn-primary-modern"
|
||||||
|
onclick="openServiceModal({{ service.pk }}, '{{ service.name }}')">
|
||||||
|
<i class="fas fa-paper-plane"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Why Choose Our Services -->
|
||||||
|
<section class="section-padding bg-light">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row justify-content-center text-center mb-5">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Почему выбирают <span class="text-gradient">наши услуги</span>
|
||||||
|
</h2>
|
||||||
|
<p class="lead text-muted">
|
||||||
|
Мы обеспечиваем высокое качество и профессиональный подход в каждом проекте
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="service-icon mx-auto mb-3 bg-primary">
|
||||||
|
<i class="fas fa-clock text-white"></i>
|
||||||
|
</div>
|
||||||
|
<h5>Быстро</h5>
|
||||||
|
<p class="text-muted">Соблюдаем сроки и работаем оперативно</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="service-icon mx-auto mb-3 bg-success">
|
||||||
|
<i class="fas fa-shield-alt text-white"></i>
|
||||||
|
</div>
|
||||||
|
<h5>Надежно</h5>
|
||||||
|
<p class="text-muted">Гарантия качества и стабильность работы</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="service-icon mx-auto mb-3 bg-warning">
|
||||||
|
<i class="fas fa-headset text-white"></i>
|
||||||
|
</div>
|
||||||
|
<h5>Поддержка</h5>
|
||||||
|
<p class="text-muted">24/7 техническая поддержка проектов</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-6">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="service-icon mx-auto mb-3 bg-info">
|
||||||
|
<i class="fas fa-chart-line text-white"></i>
|
||||||
|
</div>
|
||||||
|
<h5>Результативно</h5>
|
||||||
|
<p class="text-muted">Фокус на бизнес-результате клиента</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Process Section -->
|
||||||
|
<section class="section-padding">
|
||||||
|
<div class="container-modern">
|
||||||
|
<div class="row justify-content-center text-center mb-5">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Как мы <span class="text-gradient">работаем</span>
|
||||||
|
</h2>
|
||||||
|
<p class="lead text-muted">
|
||||||
|
Простой и прозрачный процесс от идеи до готового решения
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="position-relative">
|
||||||
|
<!-- Timeline -->
|
||||||
|
<div class="timeline">
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-marker bg-primary">1</div>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<h5>Анализ и планирование</h5>
|
||||||
|
<p class="text-muted">Изучаем ваши потребности и составляем техническое задание</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-marker bg-secondary">2</div>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<h5>Дизайн и прототипирование</h5>
|
||||||
|
<p class="text-muted">Создаем дизайн-макеты и интерактивные прототипы</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-marker bg-success">3</div>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<h5>Разработка и тестирование</h5>
|
||||||
|
<p class="text-muted">Программируем решение и тщательно тестируем</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="timeline-marker bg-warning">4</div>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<h5>Запуск и сопровождение</h5>
|
||||||
|
<p class="text-muted">Запускаем проект и обеспечиваем техническую поддержку</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CTA Section -->
|
||||||
|
<section class="section-padding bg-gradient text-white">
|
||||||
|
<div class="container-modern text-center">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h2 class="display-6 fw-bold mb-4">
|
||||||
|
Начнем ваш проект сегодня
|
||||||
|
</h2>
|
||||||
|
<p class="lead mb-5 opacity-90">
|
||||||
|
Получите бесплатную консультацию и расчет стоимости проекта
|
||||||
|
</p>
|
||||||
|
<div class="d-flex flex-wrap gap-3 justify-content-center">
|
||||||
|
<button class="btn btn-light btn-lg text-primary" onclick="openServiceModal(0, 'Консультация')">
|
||||||
|
<i class="fas fa-comments me-2"></i>
|
||||||
|
Бесплатная консультация
|
||||||
|
</button>
|
||||||
|
<a href="#" class="btn btn-outline-light btn-lg">
|
||||||
|
<i class="fas fa-download me-2"></i>
|
||||||
|
Скачать прайс-лист
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Service Request Modal -->
|
||||||
|
<div class="modal fade" id="serviceModal" tabindex="-1" aria-labelledby="serviceModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content border-0 shadow-lg">
|
||||||
|
<div class="modal-header bg-gradient text-white border-0">
|
||||||
|
<h5 class="modal-title" id="serviceModalLabel">
|
||||||
|
<i class="fas fa-paper-plane me-2"></i>
|
||||||
|
Заказать услугу
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body p-4">
|
||||||
|
<form id="serviceRequestForm">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" id="serviceId" name="service_id">
|
||||||
|
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="firstName" class="form-label">Имя *</label>
|
||||||
|
<input type="text" class="form-control" id="firstName" name="first_name" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="lastName" class="form-label">Фамилия *</label>
|
||||||
|
<input type="text" class="form-control" id="lastName" name="last_name" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="email" class="form-label">Email *</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="phone" class="form-label">Телефон</label>
|
||||||
|
<input type="tel" class="form-control" id="phone" name="phone">
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="description" class="form-label">Описание проекта *</label>
|
||||||
|
<textarea class="form-control" id="description" name="description" rows="4"
|
||||||
|
placeholder="Опишите ваш проект, цели и требования..." required></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="budget" class="form-label">Примерный бюджет</label>
|
||||||
|
<select class="form-select" id="budget" name="budget">
|
||||||
|
<option value="">Не определен</option>
|
||||||
|
<option value="1000-5000">₩ 1,000,000 - 5,000,000</option>
|
||||||
|
<option value="5000-10000">₩ 5,000,000 - 10,000,000</option>
|
||||||
|
<option value="10000+">₩ 10,000,000+</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="timeline" class="form-label">Желаемые сроки</label>
|
||||||
|
<select class="form-select" id="timeline" name="timeline">
|
||||||
|
<option value="">Не определены</option>
|
||||||
|
<option value="urgent">Срочно (1-2 недели)</option>
|
||||||
|
<option value="normal">Обычно (1-2 месяца)</option>
|
||||||
|
<option value="flexible">Гибкие сроки</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- QR Code Section (Hidden by default) -->
|
||||||
|
<div class="mt-4" id="qrCodeSection" style="display: none;">
|
||||||
|
<div class="alert alert-info text-center">
|
||||||
|
<h6><i class="fas fa-qrcode me-2"></i>Завершите регистрацию через Telegram</h6>
|
||||||
|
<p class="mb-3">Отсканируйте QR-код или перейдите по ссылке для подтверждения заявки:</p>
|
||||||
|
<div class="d-flex justify-content-center mb-3">
|
||||||
|
<img id="qrCodeImage" src="" alt="QR Code" class="img-fluid border rounded" style="max-width: 200px; min-width: 200px; height: 200px; object-fit: contain; display: none;">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<a id="telegramLink" href="" target="_blank" class="btn btn-info">
|
||||||
|
<i class="fab fa-telegram-plane me-2"></i>Открыть в Telegram
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="spinner-border spinner-border-sm text-primary me-2" role="status" aria-hidden="true"></div>
|
||||||
|
<small class="text-muted">Ожидаем подтверждения в Telegram...</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Success Animation Section (Hidden by default) -->
|
||||||
|
<div class="mt-4" id="successSection" style="display: none;">
|
||||||
|
<div class="text-center py-5">
|
||||||
|
<div class="success-checkmark">
|
||||||
|
<div class="check-icon">
|
||||||
|
<span class="icon-line line-tip"></span>
|
||||||
|
<span class="icon-line line-long"></span>
|
||||||
|
<div class="icon-circle"></div>
|
||||||
|
<div class="icon-fix"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4 class="text-success mt-3 mb-2">Заявка подана успешно!</h4>
|
||||||
|
<p class="text-muted">Мы свяжемся с вами в ближайшее время</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="agreeTerms" required>
|
||||||
|
<label class="form-check-label small" for="agreeTerms">
|
||||||
|
Я соглашаюсь с <a href="#" class="text-primary">условиями обработки персональных данных</a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer border-0">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||||
|
<button type="submit" form="serviceRequestForm" class="btn btn-primary-modern">
|
||||||
|
<i class="fas fa-paper-plane me-2"></i>
|
||||||
|
Отправить заявку
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_scripts %}
|
||||||
|
<script>
|
||||||
|
// Service filtering
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const filterButtons = document.querySelectorAll('[data-filter]');
|
||||||
|
const serviceItems = document.querySelectorAll('.service-item');
|
||||||
|
|
||||||
|
filterButtons.forEach(button => {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
const filter = this.getAttribute('data-filter');
|
||||||
|
|
||||||
|
// Update active button
|
||||||
|
filterButtons.forEach(btn => btn.classList.remove('active'));
|
||||||
|
this.classList.add('active');
|
||||||
|
|
||||||
|
// Filter services
|
||||||
|
serviceItems.forEach(item => {
|
||||||
|
if (filter === 'all' || item.getAttribute('data-category').includes(filter)) {
|
||||||
|
item.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
item.style.opacity = '1';
|
||||||
|
item.style.transform = 'translateY(0)';
|
||||||
|
}, 50);
|
||||||
|
} else {
|
||||||
|
item.style.opacity = '0';
|
||||||
|
item.style.transform = 'translateY(20px)';
|
||||||
|
setTimeout(() => {
|
||||||
|
item.style.display = 'none';
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Service modal
|
||||||
|
function openServiceModal(serviceId, serviceName) {
|
||||||
|
document.getElementById('serviceId').value = serviceId;
|
||||||
|
document.getElementById('serviceModalLabel').innerHTML =
|
||||||
|
'<i class="fas fa-paper-plane me-2"></i>Заказать услугу: ' + serviceName;
|
||||||
|
|
||||||
|
const modal = new bootstrap.Modal(document.getElementById('serviceModal'));
|
||||||
|
modal.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form submission
|
||||||
|
document.getElementById('serviceRequestForm').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData(this);
|
||||||
|
const submitBtn = document.querySelector('button[type="submit"][form="serviceRequestForm"]');
|
||||||
|
const originalContent = submitBtn.innerHTML;
|
||||||
|
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Отправляем...';
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
// Получаем CSRF токен
|
||||||
|
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
|
||||||
|
|
||||||
|
// Подготавливаем данные для отправки
|
||||||
|
const serviceId = document.getElementById('serviceId').value;
|
||||||
|
const requestData = {
|
||||||
|
client_name: formData.get('first_name') + ' ' + formData.get('last_name'),
|
||||||
|
client_email: formData.get('email'),
|
||||||
|
client_phone: formData.get('phone') || '',
|
||||||
|
description: formData.get('description'),
|
||||||
|
budget: formData.get('budget') || '',
|
||||||
|
timeline: formData.get('timeline') || ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// Отправляем запрос на создание QR-кода
|
||||||
|
fetch(`/service/generate_qr_code/${serviceId}/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': csrfToken
|
||||||
|
},
|
||||||
|
body: JSON.stringify(requestData)
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.qr_code_url) {
|
||||||
|
// Показываем секцию с QR-кодом
|
||||||
|
const qrSection = document.getElementById('qrCodeSection');
|
||||||
|
const qrImage = document.getElementById('qrCodeImage');
|
||||||
|
const telegramLink = document.getElementById('telegramLink');
|
||||||
|
|
||||||
|
qrImage.src = data.qr_code_url;
|
||||||
|
qrImage.style.display = 'block';
|
||||||
|
telegramLink.href = data.registration_link;
|
||||||
|
qrSection.style.display = 'block';
|
||||||
|
|
||||||
|
// Обновляем кнопку
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-telegram-plane me-2"></i>Перейдите в Telegram для подтверждения';
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
// Начинаем проверку статуса подтверждения
|
||||||
|
const serviceRequestId = data.service_request_id;
|
||||||
|
confirmationCheckInterval = setInterval(() => {
|
||||||
|
checkConfirmationStatus(serviceRequestId, confirmationCheckInterval);
|
||||||
|
}, 3000); // Проверяем каждые 3 секунды
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || 'Ошибка при создании заявки');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
submitBtn.innerHTML = originalContent;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.classList.remove('btn-success');
|
||||||
|
submitBtn.classList.add('btn-primary-modern');
|
||||||
|
|
||||||
|
showNotification('Произошла ошибка при создании заявки. Попробуйте еще раз.', 'error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Функция проверки статуса подтверждения
|
||||||
|
function checkConfirmationStatus(serviceRequestId, checkInterval) {
|
||||||
|
fetch(`/service/check_status/${serviceRequestId}/`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.is_verified) {
|
||||||
|
// Останавливаем проверку
|
||||||
|
clearInterval(checkInterval);
|
||||||
|
|
||||||
|
// Скрываем QR-код
|
||||||
|
const qrSection = document.getElementById('qrCodeSection');
|
||||||
|
qrSection.style.display = 'none';
|
||||||
|
|
||||||
|
// Показываем анимацию успеха
|
||||||
|
const successSection = document.getElementById('successSection');
|
||||||
|
successSection.style.display = 'block';
|
||||||
|
|
||||||
|
// Запускаем анимацию галочки
|
||||||
|
setTimeout(() => {
|
||||||
|
const checkmark = successSection.querySelector('.success-checkmark');
|
||||||
|
checkmark.classList.add('animate');
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Закрываем модальное окно через 3 секунды
|
||||||
|
setTimeout(() => {
|
||||||
|
const modal = bootstrap.Modal.getInstance(document.getElementById('serviceModal'));
|
||||||
|
modal.hide();
|
||||||
|
showNotification('Заявка подтверждена! Спасибо за регистрацию в Telegram.', 'success');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log('Ожидаем подтверждения...', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showNotification(message, type) {
|
||||||
|
const notification = document.createElement('div');
|
||||||
|
notification.className = `alert alert-${type} position-fixed top-0 end-0 m-3`;
|
||||||
|
notification.style.zIndex = '9999';
|
||||||
|
notification.innerHTML = `
|
||||||
|
<i class="fas fa-${type === 'success' ? 'check-circle' : 'exclamation-triangle'} me-2"></i>
|
||||||
|
${message}
|
||||||
|
<button type="button" class="btn-close" onclick="this.parentElement.remove()"></button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
notification.remove();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset modal when it's hidden
|
||||||
|
let confirmationCheckInterval = null;
|
||||||
|
|
||||||
|
document.getElementById('serviceModal').addEventListener('hidden.bs.modal', function() {
|
||||||
|
// Останавливаем проверку подтверждения
|
||||||
|
if (confirmationCheckInterval) {
|
||||||
|
clearInterval(confirmationCheckInterval);
|
||||||
|
confirmationCheckInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сброс формы
|
||||||
|
document.getElementById('serviceRequestForm').reset();
|
||||||
|
|
||||||
|
// Скрытие всех секций
|
||||||
|
document.getElementById('qrCodeSection').style.display = 'none';
|
||||||
|
document.getElementById('qrCodeImage').style.display = 'none';
|
||||||
|
document.getElementById('successSection').style.display = 'none';
|
||||||
|
|
||||||
|
// Убираем анимацию галочки
|
||||||
|
const checkmark = document.querySelector('.success-checkmark');
|
||||||
|
if (checkmark) {
|
||||||
|
checkmark.classList.remove('animate');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сброс кнопки отправки
|
||||||
|
const submitBtn = document.querySelector('button[type="submit"][form="serviceRequestForm"]');
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Отправить заявку';
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
submitBtn.classList.remove('btn-success');
|
||||||
|
submitBtn.classList.add('btn-primary-modern');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.timeline {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 30px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 2px;
|
||||||
|
background: var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 80px;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-marker {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-content {
|
||||||
|
background: var(--bg-light);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-item {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group .btn {
|
||||||
|
border-radius: 25px !important;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group .btn.active {
|
||||||
|
background: var(--gradient-primary);
|
||||||
|
border-color: transparent;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.timeline::before {
|
||||||
|
left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-marker {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group .btn {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
@@ -12,8 +12,9 @@ urlpatterns = [
|
|||||||
path('blog/<int:pk>/', views.blog_post_detail, name='blog_post_detail'),
|
path('blog/<int:pk>/', views.blog_post_detail, name='blog_post_detail'),
|
||||||
path('services/', views.services_view, name='services'),
|
path('services/', views.services_view, name='services'),
|
||||||
# path('create_order/<int:pk>/', views.create_order, name='create_order'),
|
# path('create_order/<int:pk>/', views.create_order, name='create_order'),
|
||||||
path('about/', views.about_view, name="about_view"),
|
path('about/', views.about_view, name="about"),
|
||||||
path('service/generate_qr_code/<int:service_id>/', views.generate_qr_code, name='generate_qr_code'),
|
path('service/generate_qr_code/<int:service_id>/', views.generate_qr_code, name='generate_qr_code'),
|
||||||
|
path('service/check_status/<int:request_id>/', views.check_request_status, name='check_request_status'),
|
||||||
path('service/request_status/<int:service_id>/', views.request_status, name='request_status'),
|
path('service/request_status/<int:service_id>/', views.request_status, name='request_status'),
|
||||||
path('service/request/<int:service_id>/', views.create_service_request, name='create_service_request'),
|
path('service/request/<int:service_id>/', views.create_service_request, name='create_service_request'),
|
||||||
path('complete_registration/<int:request_id>/', views.complete_registration, name='complete_registration'),
|
path('complete_registration/<int:request_id>/', views.complete_registration, name='complete_registration'),
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ except Exception as e:
|
|||||||
logger.error(f"Failed to initialize Telegram bot: {str(e)}")
|
logger.error(f"Failed to initialize Telegram bot: {str(e)}")
|
||||||
|
|
||||||
def home(request):
|
def home(request):
|
||||||
services = Service.objects.all()
|
services = Service.objects.all()[:6] # Показываем только первые 6 услуг на главной
|
||||||
return render(request, 'web/home.html', {'services': services})
|
return render(request, 'web/home_modern.html', {'services': services})
|
||||||
|
|
||||||
def service_detail(request, pk):
|
def service_detail(request, pk):
|
||||||
service = get_object_or_404(Service, pk=pk)
|
service = get_object_or_404(Service, pk=pk)
|
||||||
@@ -64,10 +64,10 @@ def blog_post_detail(request, pk):
|
|||||||
|
|
||||||
def services_view(request):
|
def services_view(request):
|
||||||
services = Service.objects.all()
|
services = Service.objects.all()
|
||||||
return render(request, 'web/services.html', {'services': services})
|
return render(request, 'web/services_modern.html', {'services': services})
|
||||||
|
|
||||||
def about_view(request):
|
def about_view(request):
|
||||||
return render(request, 'web/about.html')
|
return render(request, 'web/about_modern.html')
|
||||||
|
|
||||||
def create_service_request(request, service_id):
|
def create_service_request(request, service_id):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@@ -299,3 +299,19 @@ def complete_registration(request, request_id):
|
|||||||
return JsonResponse({'status': 'success', 'message': 'Регистрация успешно завершена.'})
|
return JsonResponse({'status': 'success', 'message': 'Регистрация успешно завершена.'})
|
||||||
|
|
||||||
return render(request, 'web/complete_registration.html', {'service_request': service_request})
|
return render(request, 'web/complete_registration.html', {'service_request': service_request})
|
||||||
|
|
||||||
|
|
||||||
|
def check_request_status(request, request_id):
|
||||||
|
"""API endpoint для проверки статуса подтверждения заявки"""
|
||||||
|
try:
|
||||||
|
service_request = get_object_or_404(ServiceRequest, pk=request_id)
|
||||||
|
return JsonResponse({
|
||||||
|
'is_verified': service_request.is_verified,
|
||||||
|
'chat_id': service_request.chat_id,
|
||||||
|
'created_at': service_request.created_at.isoformat() if service_request.created_at else None
|
||||||
|
})
|
||||||
|
except ServiceRequest.DoesNotExist:
|
||||||
|
return JsonResponse({'error': 'Заявка не найдена'}, status=404)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка при проверке статуса заявки {request_id}: {str(e)}")
|
||||||
|
return JsonResponse({'error': 'Ошибка сервера'}, status=500)
|
||||||
|
|||||||