Добавлен индикатор загрузки на главной странице и обновлен компонент ProtectedRoute для проверки аутентификации. Изменены стили загрузочного оверлея и добавлен анимированный спиннер для улучшения пользовательского опыта.

This commit is contained in:
Fovway 2025-11-02 23:07:56 +07:00
parent f59cd87ede
commit 10f7fe3556
4 changed files with 94 additions and 14 deletions

View File

@ -160,7 +160,75 @@
<link rel="manifest" href="/manifest.json" />
</head>
<body>
<div id="root"></div>
<div id="root">
<!-- Индикатор загрузки до монтирования React -->
<div id="initial-loading" style="
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--bg-primary);
color: var(--text-primary);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
">
<style>
#initial-loading-spinner {
width: 50px;
height: 50px;
border: 4px solid transparent;
border-top: 4px solid var(--accent-color, #007bff);
border-right: 4px solid var(--accent-color, #007bff);
border-bottom: 4px solid transparent;
border-left: 4px solid transparent;
border-radius: 50%;
animation: initial-loading-spin 0.8s linear infinite;
opacity: 0.8;
}
@keyframes initial-loading-spin {
to { transform: rotate(360deg); }
}
</style>
<div id="initial-loading-spinner"></div>
</div>
</div>
<script type="module" src="/src/main.tsx"></script>
<script>
// Скрываем индикатор загрузки сразу после загрузки DOM
// React удалит этот элемент при первом рендере через createRoot
(function() {
// Используем MutationObserver для отслеживания изменений в #root
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// Если React начал добавлять элементы в #root, удаляем индикатор
if (mutation.addedNodes.length > 0) {
const loadingEl = document.getElementById('initial-loading');
if (loadingEl && loadingEl.parentNode) {
loadingEl.parentNode.removeChild(loadingEl);
}
observer.disconnect();
}
});
});
// Начинаем наблюдение за изменениями в #root
const root = document.getElementById('root');
if (root) {
observer.observe(root, { childList: true, subtree: true });
// Фолбэк: если через 2 секунды элемент все еще есть, удаляем вручную
setTimeout(function() {
const loadingEl = document.getElementById('initial-loading');
if (loadingEl && loadingEl.parentNode) {
loadingEl.parentNode.removeChild(loadingEl);
}
observer.disconnect();
}, 2000);
}
})();
</script>
</body>
</html>

View File

@ -33,12 +33,10 @@ export const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({
}
};
if (isAuthenticated) {
// Всегда проверяем статус аутентификации при монтировании,
// независимо от начального состояния Redux (localStorage может быть устаревшим)
checkAuth();
} else {
setIsChecking(false);
}
}, [dispatch, isAuthenticated]);
}, [dispatch]);
if (isChecking) {
return <LoadingOverlay />;

View File

@ -4,7 +4,7 @@ export const LoadingOverlay: React.FC = () => {
return (
<div className="loading-overlay">
<div className="loading-content">
<div className="loading-text">Загрузка...</div>
<div className="loading-spinner"></div>
</div>
</div>
);

View File

@ -4866,14 +4866,28 @@ textarea:focus {
display: flex;
align-items: center;
justify-content: center;
min-width: 150px;
min-width: 80px;
min-height: 80px;
}
.loading-text {
color: var(--text-color);
font-size: 16px;
font-weight: 500;
text-align: center;
/* Анимированный спиннер */
.loading-spinner {
width: 50px;
height: 50px;
border: 4px solid transparent;
border-top: 4px solid var(--accent-color, #007bff);
border-right: 4px solid var(--accent-color, #007bff);
border-bottom: 4px solid transparent;
border-left: 4px solid transparent;
border-radius: 50%;
animation: loading-spin 0.8s linear infinite;
opacity: 0.8;
}
@keyframes loading-spin {
to {
transform: rotate(360deg);
}
}
/* Темная тема для загрузочного оверлея */