import * as React from 'react'; import { Alert } from './Alert'; import { Button } from './Button'; import { ConfirmDialog } from './ConfirmDialog'; import { Modal } from './Modal'; import styles from './Modal.module.scss'; import { texts } from '../../texts'; export interface IFormModalProps { title: string; /** Текст ошибки: и валидации формы, и ответа бэкенда. */ error?: string; isSaving: boolean; /** Подпись кнопки подтверждения — по умолчанию «Сохранить» (см. копирование маршрута). */ submitLabel?: string; /** Подпись той же кнопки во время запроса — по умолчанию «Сохранение...». */ savingLabel?: string; onSubmit: () => void; onClose: () => void; /** * Сбросить черновик формы (см. useFormDraft). Кнопка «Очистить» показывается, * только если передан и canReset — «Отмена» и клик мимо окна черновик не трогают. */ onReset?: () => void; canReset?: boolean; /** * В форме есть несохранённые правки существующей записи: выход (крестик, * «Отмена», клик мимо окна) сначала спрашивает подтверждение. Для форм создания * не нужен — их черновик сохраняется сам (см. useFormDraft). */ isDirty?: boolean; children: React.ReactNode; } /** * Модальное окно формы: одинаковая обвязка «ошибка сверху, Отмена/Сохранить снизу» * для всех справочников, чтобы экраны описывали только поля. */ export const FormModal: React.FC = ({ title, error, isSaving, submitLabel = texts.common.save, savingLabel = texts.common.saving, onSubmit, onClose, onReset, canReset, isDirty, children }) => { const [confirmingClose, setConfirmingClose] = React.useState(false); // Во время сохранения не закрываем и не спрашиваем: запрос уже ушёл. const requestClose = (): void => { if (isSaving) return; if (isDirty) setConfirmingClose(true); else onClose(); }; return ( <> {onReset && canReset && ( )} } > {error && {error}} {children} {confirmingClose && ( setConfirmingClose(false)} /> )} ); };