Админка, настройки, логин, кабинеты преподавателя и студента полностью переведены на React 19 (модель strangler, docs/REACT_MIGRATION.md). - 15 вкладок админки: lazy-загрузка, общий error boundary, сервисный слой - Удалены legacy-views и переходный слой LegacyTabView (45 файлов) - Сборка esbuild (frontend/scripts/build-react.mjs) с бюджетами gzip на чанки - CSP-хэши, кэширование: chunk'и immutable, CSS/HTML no-cache (react-cache.conf) - Фиксы: lazy-импорт именованных экспортов (краш после авторизации), растяжение #admin-root/#settings-root на всю ширину, возврат subjects/lessonTypes из справочников (краш просмотра расписаний), отказ от заведомо широкого поиска расписания без выбранной цели, центрирование карточки логина - Тесты: 237/237 (npm run check), регрессионные на lazy-вкладки и ширину - Документация: REACT_MIGRATION.md, REACT_MIGRATION_RESULT.md, FRONTEND.md
39 lines
1.3 KiB
JavaScript
39 lines
1.3 KiB
JavaScript
const DEFAULT_COPY = Object.freeze({
|
||
empty: {
|
||
message: 'Здесь пока нет данных',
|
||
title: 'Пусто'
|
||
},
|
||
error: {
|
||
message: 'Попробуйте повторить запрос',
|
||
title: 'Не удалось загрузить данные'
|
||
},
|
||
loading: {
|
||
message: 'Это займёт несколько секунд',
|
||
title: 'Загружаем данные'
|
||
}
|
||
});
|
||
|
||
export function AsyncState({ kind = 'loading', message, onRetry, title }) {
|
||
const copy = DEFAULT_COPY[kind] || DEFAULT_COPY.loading;
|
||
const isError = kind === 'error';
|
||
|
||
return (
|
||
<section
|
||
className={`ui-state ui-state--${kind}`}
|
||
role={isError ? 'alert' : 'status'}
|
||
aria-live={isError ? 'assertive' : 'polite'}
|
||
>
|
||
<span className="ui-state__signal" aria-hidden="true" />
|
||
<div className="ui-state__content">
|
||
<h2 className="ui-state__title">{title || copy.title}</h2>
|
||
<p className="ui-state__message">{message || copy.message}</p>
|
||
</div>
|
||
{isError && onRetry && (
|
||
<button type="button" className="btn btn-md btn-secondary" onClick={onRetry}>
|
||
Повторить
|
||
</button>
|
||
)}
|
||
</section>
|
||
);
|
||
}
|