Панель со списками заявок (#1)

Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz>
Reviewed-on: http://git.tnsu.kz/timur.gorodetskiy/request-portal/pulls/1
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tnsu.kz>
Co-committed-by: gorbenko.pavel <gorbenko.pavel@tnsu.kz>
This commit was merged in pull request #1.
This commit is contained in:
2026-08-04 12:02:11 +00:00
committed by timur.gorodetskiy
parent ba4e3feee5
commit 0aa0a60e40
21 changed files with 1442 additions and 121 deletions
@@ -0,0 +1,39 @@
import * as React from 'react';
import styles from './Drawer.module.scss';
import { Icon } from '../../shared/ui/Icon/Icon';
interface IDrawerProps {
title: string;
onClose: () => void;
children: React.ReactNode;
}
// Выезжающая справа панель: открывается по клику на строку таблицы заявок,
// внутри — заявка в режиме просмотра/согласования. Закрывается крестиком,
// кликом по затемнению и клавишей Esc.
export const Drawer: React.FC<IDrawerProps> = ({ title, onClose, children }) => {
React.useEffect(() => {
const onKeyDown = (e: KeyboardEvent): void => {
if (e.key === 'Escape') onClose();
};
window.addEventListener('keydown', onKeyDown);
return () => window.removeEventListener('keydown', onKeyDown);
}, [onClose]);
return (
<div className={styles.overlay}>
{/* Затемнение — не кнопка (внутри панели свои интерактивные элементы),
поэтому клик обрабатываем на этом слое напрямую. */}
<div className={styles.backdrop} onClick={onClose} aria-hidden="true" />
<aside className={styles.drawer} role="dialog" aria-modal="true" aria-label={title}>
<div className={styles.header}>
<span className={styles.title}>{title}</span>
<button type="button" className={styles.close} onClick={onClose} aria-label="Закрыть">
<Icon name="close" size="sm" />
</button>
</div>
<div className={styles.body}>{children}</div>
</aside>
</div>
);
};