51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import * as React from 'react';
|
|
import { Alert } from './Alert';
|
|
import { Button } from './Button';
|
|
import { Modal } from './Modal';
|
|
import { texts } from '../../texts';
|
|
|
|
export interface IFormModalProps {
|
|
title: string;
|
|
/** Текст ошибки: и валидации формы, и ответа бэкенда. */
|
|
error?: string;
|
|
isSaving: boolean;
|
|
/** Подпись кнопки подтверждения — по умолчанию «Сохранить» (см. копирование маршрута). */
|
|
submitLabel?: string;
|
|
/** Подпись той же кнопки во время запроса — по умолчанию «Сохранение...». */
|
|
savingLabel?: string;
|
|
onSubmit: () => void;
|
|
onClose: () => void;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Модальное окно формы: одинаковая обвязка «ошибка сверху, Отмена/Сохранить снизу»
|
|
* для всех справочников, чтобы экраны описывали только поля.
|
|
*/
|
|
export const FormModal: React.FC<IFormModalProps> = ({
|
|
title,
|
|
error,
|
|
isSaving,
|
|
submitLabel = texts.common.save,
|
|
savingLabel = texts.common.saving,
|
|
onSubmit,
|
|
onClose,
|
|
children
|
|
}) => (
|
|
<Modal
|
|
title={title}
|
|
onClose={onClose}
|
|
footer={
|
|
<>
|
|
<Button variant="secondary" onClick={onClose} disabled={isSaving}>{texts.common.cancel}</Button>
|
|
<Button variant="accent" icon="check" onClick={onSubmit} disabled={isSaving}>
|
|
{isSaving ? savingLabel : submitLabel}
|
|
</Button>
|
|
</>
|
|
}
|
|
>
|
|
{error && <Alert kind="err">{error}</Alert>}
|
|
{children}
|
|
</Modal>
|
|
);
|