fix: делает "Предложение по улучшению" необязательным для жалобы, убирает дубль заголовка

Каждый вид обращения раньше показывал одинаковый набор обязательных полей.
getAppealFieldsConfig теперь описывает и видимость, и обязательность отдельно:
жалоба — предложение по-прежнему можно оставить, но требовать его как для
самостоятельного вида "Предложение" неверно. validateFeedback читает то же
правило, что и форма, — иначе одно поле могло бы требовать то, что другое
не показывает.

FormCard в FeedbackForm дублировал заголовок и подзаголовок PageShell — убран
(пустой title у ui-kit не создаёт строки, гэпа не остаётся).

Подсказка у переключателя "Обращение анонимное" разбита на две сноски (* и **),
как в исходной форме, а не слитный абзац.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-21 09:44:48 +05:00
parent 51339b3f9a
commit 05cd491769
6 changed files with 53 additions and 29 deletions
+12 -10
View File
@@ -1,4 +1,4 @@
import { getVisibleAppealFields, type FeedbackErrors, type IFeedbackData } from './model';
import { getAppealFieldsConfig, type FeedbackErrors, type IFeedbackData } from './model';
import { TEXTS } from './texts';
/** Ниже этой длины текст не считаем содержательным описанием. */
@@ -26,22 +26,24 @@ export function validateFeedback(data: IFeedbackData): FeedbackErrors {
errors.kindOther = TEXTS.errors.required;
}
// Спрашиваем только то, что реально показано для выбранного вида обращения:
// иначе форма ругалась бы на скрытое поле, и пользователь не понял бы, где ошибка.
const visible = getVisibleAppealFields(data.kind);
// Правило видимости/обязательности общее с формой (AppealSection), поэтому
// валидируем по нему же — иначе форма ругалась бы на скрытое или необязательное поле.
const fields = getAppealFieldsConfig(data.kind);
if (visible.situation) {
if (!data.situation.trim()) {
if (fields.situation.visible) {
const value = data.situation.trim();
if (fields.situation.required && !value) {
errors.situation = TEXTS.errors.required;
} else if (data.situation.trim().length < MIN_TEXT_LENGTH) {
} else if (value && value.length < MIN_TEXT_LENGTH) {
errors.situation = TEXTS.errors.tooShort;
}
}
if (visible.suggestion) {
if (!data.suggestion.trim()) {
if (fields.suggestion.visible) {
const value = data.suggestion.trim();
if (fields.suggestion.required && !value) {
errors.suggestion = TEXTS.errors.required;
} else if (data.suggestion.trim().length < MIN_TEXT_LENGTH) {
} else if (value && value.length < MIN_TEXT_LENGTH) {
errors.suggestion = TEXTS.errors.tooShort;
}
}