Уведомления назначенным пользователям (#9)
Tests / frontend-test (push) Successful in 43s
Tests / backend-test (push) Successful in 1m54s

Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz>
Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/9
This commit was merged in pull request #9.
This commit is contained in:
2026-08-10 05:16:54 +00:00
parent 11738b6e4a
commit a07338314a
9 changed files with 157 additions and 19 deletions
@@ -23,6 +23,12 @@
animation: toastIn .15s ease-out;
}
.ok {
background: $green-50;
color: $green-600;
border-color: #BBF7D0;
}
.message {
flex: 1;
}
@@ -4,28 +4,30 @@ import { Icon } from './Icon';
export interface IToastProps {
message: string;
/** 'err' (по умолчанию) — красный, для ошибок; 'ok' — зелёный, для успешных действий (см. handleNotify в ManageRequestsScreen). */
kind?: 'err' | 'ok';
onClose: () => void;
}
const AUTO_HIDE_MS = 6000;
/**
* Всплывающее сообщение об ошибке в углу экрана — для действий, которые не
* ломают уже отрисованный экран (переназначение/перестановка/добавление шага):
* пользователь и так видит, что изменение не применилось (см. reloadMatrix
* после ошибки в ManageRequestsScreen), поэтому постоянный Alert-блок сверху
* страницы был бы избыточен. Автоматически прячется через AUTO_HIDE_MS, либо
* закрывается вручную.
* Всплывающее сообщение в углу экрана — для действий, которые не ломают уже
* отрисованный экран (переназначение/перестановка/добавление шага/отправка
* уведомления): пользователь и так видит, что изменение не применилось (см.
* reloadMatrix после ошибки в ManageRequestsScreen), поэтому постоянный
* Alert-блок сверху страницы был бы избыточен. Автоматически прячется через
* AUTO_HIDE_MS, либо закрывается вручную.
*/
export const Toast: React.FC<IToastProps> = ({ message, onClose }) => {
export const Toast: React.FC<IToastProps> = ({ message, kind = 'err', onClose }) => {
React.useEffect(() => {
const timer = window.setTimeout(onClose, AUTO_HIDE_MS);
return () => window.clearTimeout(timer);
}, [message, onClose]);
return (
<div className={styles.toast} role="alert">
<Icon name="warning" size="sm" />
<div className={`${styles.toast} ${kind === 'ok' ? styles.ok : ''}`} role="alert">
<Icon name={kind === 'ok' ? 'check' : 'warning'} size="sm" />
<span className={styles.message}>{message}</span>
<button type="button" className={styles.close} onClick={onClose} aria-label="Закрыть">×</button>
</div>