feat: Оптимизация навигации AdminJS в логические группы

- Объединены ресурсы в 5 логических групп: Контент сайта, Бронирования, Отзывы и рейтинги, Персонал и гиды, Администрирование
- Удалены дублирующие настройки navigation для чистой группировки
- Добавлены CSS стили для визуального отображения иерархии с отступами
- Добавлены эмодзи-иконки для каждого типа ресурсов через CSS
- Улучшена навигация с правильной вложенностью элементов
This commit is contained in:
2025-11-30 21:57:58 +09:00
parent 1e7d7c06eb
commit 13c752b93a
47 changed files with 14148 additions and 61 deletions

View File

@@ -0,0 +1,282 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Планировщик рабочих смен - Корея Тур Агентство</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
min-height: 100vh;
padding: 20px 0;
}
.main-container {
background: white;
border-radius: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
.header-section {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px;
text-align: center;
}
.header-title {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 10px;
}
.header-subtitle {
font-size: 1.1rem;
opacity: 0.9;
}
.back-button {
position: absolute;
top: 20px;
left: 20px;
color: white;
text-decoration: none;
padding: 10px 15px;
background: rgba(255,255,255,0.2);
border-radius: 8px;
transition: all 0.3s;
}
.back-button:hover {
background: rgba(255,255,255,0.3);
color: white;
text-decoration: none;
}
.content-section {
padding: 30px;
}
.loading-spinner {
text-align: center;
padding: 60px;
}
.spinner-border {
width: 4rem;
height: 4rem;
}
.error-message {
text-align: center;
padding: 60px;
color: #dc3545;
}
.error-icon {
font-size: 4rem;
margin-bottom: 20px;
}
/* Адаптивность */
@media (max-width: 768px) {
.header-title {
font-size: 2rem;
}
.content-section {
padding: 20px;
}
body {
padding: 10px;
}
}
/* Анимации */
.main-container {
animation: slideUp 0.6s ease-out;
}
@keyframes slideUp {
from {
transform: translateY(30px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.fade-in {
animation: fadeIn 0.8s ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-12">
<div class="main-container">
<!-- Header -->
<div class="header-section position-relative">
<a href="/admin" class="back-button">
<i class="fas fa-arrow-left me-2"></i>Назад в админку
</a>
<div class="header-title">
<i class="fas fa-calendar-week me-3"></i>
Планировщик рабочих смен
</div>
<div class="header-subtitle">
Управление расписанием работы гидов
</div>
</div>
<!-- Content -->
<div class="content-section">
<!-- Loading State -->
<div id="loading" class="loading-spinner">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Загрузка...</span>
</div>
<div class="mt-3">
<h5>Загрузка планировщика смен...</h5>
<p class="text-muted">Подождите, пожалуйста</p>
</div>
</div>
<!-- Error State -->
<div id="error" class="error-message" style="display: none;">
<div class="error-icon">
<i class="fas fa-exclamation-triangle"></i>
</div>
<h4>Ошибка загрузки</h4>
<p>Не удалось загрузить планировщик смен. Попробуйте перезагрузить страницу.</p>
<button class="btn btn-primary" onclick="location.reload()">
<i class="fas fa-redo me-2"></i>Перезагрузить
</button>
</div>
<!-- Schedule Manager Container -->
<div id="scheduleManagerContainer" class="fade-in" style="display: none;">
<!-- Компонент будет загружен здесь -->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Schedule Manager Component -->
<script src="/components/guide-schedule-manager.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
let retryCount = 0;
const maxRetries = 3;
async function initializeScheduleManager() {
try {
// Проверяем доступность компонента
if (typeof GuideScheduleManager === 'undefined') {
throw new Error('GuideScheduleManager component not loaded');
}
// Инициализируем планировщик смен
const scheduleManager = new GuideScheduleManager({
container: document.getElementById('scheduleManagerContainer'),
onScheduleChange: function(scheduleData) {
console.log('Расписание изменено:', scheduleData);
// Можно добавить уведомления об успешном сохранении
showNotification('Расписание успешно сохранено!', 'success');
}
});
// Показываем контейнер и скрываем загрузку
document.getElementById('loading').style.display = 'none';
document.getElementById('scheduleManagerContainer').style.display = 'block';
console.log('Планировщик смен инициализирован успешно');
} catch (error) {
console.error('Ошибка инициализации планировщика смен:', error);
if (retryCount < maxRetries) {
retryCount++;
console.log(`Попытка повторной загрузки ${retryCount}/${maxRetries}`);
setTimeout(initializeScheduleManager, 2000);
} else {
// Показываем ошибку
document.getElementById('loading').style.display = 'none';
document.getElementById('error').style.display = 'block';
}
}
}
// Функция для показа уведомлений
function showNotification(message, type = 'info') {
// Создаем контейнер для уведомлений если его нет
let container = document.getElementById('notification-container');
if (!container) {
container = document.createElement('div');
container.id = 'notification-container';
container.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 9999;';
document.body.appendChild(container);
}
// Создаем уведомление
const notification = document.createElement('div');
notification.className = `alert alert-${type} alert-dismissible fade show`;
notification.style.cssText = 'min-width: 300px; margin-bottom: 10px;';
notification.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
container.appendChild(notification);
// Автоматически удаляем через 5 секунд
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 5000);
}
// Глобальная функция для уведомлений
window.showNotification = showNotification;
// Запускаем инициализацию после небольшой задержки
setTimeout(initializeScheduleManager, 500);
});
// Обработка ошибок загрузки скриптов
window.addEventListener('error', function(e) {
if (e.filename && e.filename.includes('guide-schedule-manager.js')) {
console.error('Ошибка загрузки компонента планировщика смен:', e);
document.getElementById('loading').style.display = 'none';
document.getElementById('error').style.display = 'block';
}
});
</script>
</body>
</html>