feat: Реализован полный CRUD для админ-панели и улучшена функциональность

- Portfolio CRUD: добавление, редактирование, удаление, переключение публикации
- Services CRUD: полное управление услугами с возможностью активации/деактивации
- Banner system: новая модель Banner с CRUD операциями и аналитикой кликов
- Telegram integration: расширенные настройки бота, обнаружение чатов, отправка сообщений
- Media management: улучшенная загрузка файлов с оптимизацией изображений и превью
- UI improvements: обновлённые админ-панели с rich-text редактором и drag&drop загрузкой
- Database: добавлена таблица banners с полями для баннеров и аналитики
This commit is contained in:
2025-10-22 20:32:16 +09:00
parent 150891b29d
commit 9477ff6de0
69 changed files with 11451 additions and 2321 deletions

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%- __(title || 'meta.title') %></title>
<title><%- title || 'SmartSolTech - Innovative Technology Solutions' %></title>
<!-- SEO Meta Tags -->
<meta name="description" content="<%- __('meta.description') %>">
@@ -17,15 +17,39 @@
<!-- PWA -->
<meta name="theme-color" content="#3B82F6">
<link rel="manifest" href="/manifest.json">
<link rel="apple-touch-icon" href="/images/icons/icon-192x192.png">
<link rel="apple-touch-icon" href="/images/icon-192x192.png">
<!-- Styles -->
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
<!-- Custom CSS (load first) -->
<link href="/css/base.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/fixes.css" rel="stylesheet">
<link href="/css/dark-theme.css" rel="stylesheet">
<!-- Tailwind CSS via CDN -->
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script>
<!-- Font Awesome -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous">
<!-- AOS Animation Library -->
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
<!-- Tailwind Configuration -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'primary': '#3B82F6',
'secondary': '#8B5CF6',
'accent': '#10B981',
},
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
}
}
}
}
</script>
</head>
<body class="font-sans dark:bg-gray-900 dark:text-gray-100">
<%- include('partials/navigation') %>
@@ -337,64 +361,34 @@
<!-- Scripts -->
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
<script src="/js/main.js"></script>
<!-- Initialize AOS -->
<script>
// Initialize AOS
AOS.init({
duration: 800,
once: true,
offset: 100
});
// Blob animation
const style = document.createElement('style');
style.textContent = `
@keyframes blob {
0% { transform: translate(0px, 0px) scale(1); }
33% { transform: translate(30px, -50px) scale(1.1); }
66% { transform: translate(-20px, 20px) scale(0.9); }
100% { transform: translate(0px, 0px) scale(1); }
}
.animate-blob {
animation: blob 7s infinite;
}
.animation-delay-2000 {
animation-delay: 2s;
}
.animation-delay-4000 {
animation-delay: 4s;
}
`;
document.head.appendChild(style);
// Contact form handler
document.getElementById('quick-contact-form').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch('/contact', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('<%- __("contact.form.success") %>');
this.reset();
} else {
alert('<%- __("contact.form.error") %>');
}
})
.catch(error => {
console.error('Error:', error);
alert('<%- __("contact.form.error") %>');
});
});
// Theme initialization
document.addEventListener('DOMContentLoaded', function() {
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.className = theme === 'dark' ? 'dark' : '';
if (typeof AOS !== 'undefined') {
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true
});
}
});
</script>
<!-- PWA Service Worker -->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('SW registered: ', registration);
})
.catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
</script>
</body>
</html>
</html>