f3b0f0ad48
Модалки по жёлтым кнопкам теряли введённое при случайном клике мимо окна. **Формы создания** (типы заявок, доступ к заявкам, маршруты, шаги маршрута) - Черновик полей хранится в localStorage (useFormDraft) и переживает закрытие окна, «Отмену» и F5. - Окно, открытое в момент F5, открывается снова (usePersistedOpen); закрытие сбрасывает только признак, черновик остаётся. - Черновик стирается после успешного сохранения или кнопкой «Очистить» в подвале. **Формы редактирования** - Не персистятся — открываются с данными сервера. - При выходе с несохранёнными правками (крестик, «Отмена», клик мимо) — диалог «Закрыть без сохранения?» (isDirty в FormModal). **Устойчивость к старым данным в localStorage** - coerceStored приводит сохранённое значение к форме текущего дефолта по полям: новое поле — дефолт, удалённое отбрасывается, значение другого типа и null заменяются дефолтом. Покрыто тестами. **Прочее** - Modal и ConfirmDialog рендерятся порталом в body поверх шапки SharePoint — на живой странице верх высокого окна уезжал под шапку. - Убраны Sass-предупреждения mixed-decls в Card.module.scss. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/30
26 lines
1.3 KiB
TypeScript
26 lines
1.3 KiB
TypeScript
import * as React from 'react';
|
|
import * as ReactDOM from 'react-dom';
|
|
import styles from './Modal.module.scss';
|
|
|
|
export interface IModalOverlayProps {
|
|
/** Клик по подложке (не по содержимому окна). */
|
|
onBackdropClick: () => void;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Затемнение под модалкой — порталом в document.body, а не внутри веб-части.
|
|
* На живой странице SharePoint канва веб-части лежит в своём контексте наложения
|
|
* ниже шапки (suite bar), и position: fixed-оверлей изнутри неё оказывался ПОД
|
|
* шапкой: верх окна, центрированного по высоте экрана, уезжал за неё. В workbench
|
|
* шапки нет — там было незаметно.
|
|
*/
|
|
export const ModalOverlay: React.FC<IModalOverlayProps> = ({ onBackdropClick, children }) =>
|
|
ReactDOM.createPortal(
|
|
// Клик по подложке закрывает окно, клик внутри — нет (проверяем сам currentTarget).
|
|
<div className={styles.overlay} onClick={e => { if (e.target === e.currentTarget) onBackdropClick(); }}>
|
|
{children}
|
|
</div>,
|
|
document.body
|
|
);
|