import { getAppealFieldsConfig, type FeedbackErrors, type IFeedbackData } from './model'; import { TEXTS } from './texts'; /** Ниже этой длины текст не считаем содержательным описанием. */ const MIN_TEXT_LENGTH = 10; /** * Правила заполнения обращения. * Чистая функция: получает данные, возвращает ошибки — её легко покрыть тестами * и она не зависит от React. */ export function validateFeedback(data: IFeedbackData): FeedbackErrors { const errors: FeedbackErrors = {}; if (!data.company) { errors.company = TEXTS.errors.selectRequired; } // Имя и должность спрашиваем только у неанонимных обращений: у анонимного // эти поля скрыты, требовать их было бы противоречием. if (!data.isAnonymous && !data.fullName.trim()) { errors.fullName = TEXTS.errors.required; } if (data.kind === 'other' && !data.kindOther.trim()) { errors.kindOther = TEXTS.errors.required; } // Правило видимости/обязательности общее с формой (AppealSection), поэтому // валидируем по нему же — иначе форма ругалась бы на скрытое или необязательное поле. const fields = getAppealFieldsConfig(data.kind); if (fields.situation.visible) { const value = data.situation.trim(); if (fields.situation.required && !value) { errors.situation = TEXTS.errors.required; } else if (value && value.length < MIN_TEXT_LENGTH) { errors.situation = TEXTS.errors.tooShort; } } if (fields.suggestion.visible) { const value = data.suggestion.trim(); if (fields.suggestion.required && !value) { errors.suggestion = TEXTS.errors.required; } else if (value && value.length < MIN_TEXT_LENGTH) { errors.suggestion = TEXTS.errors.tooShort; } } return errors; }