Files
hr-appeals/src/features/feedback/model.ts
T
gorbenko.pavel 05cd491769 fix: делает "Предложение по улучшению" необязательным для жалобы, убирает дубль заголовка
Каждый вид обращения раньше показывал одинаковый набор обязательных полей.
getAppealFieldsConfig теперь описывает и видимость, и обязательность отдельно:
жалоба — предложение по-прежнему можно оставить, но требовать его как для
самостоятельного вида "Предложение" неверно. validateFeedback читает то же
правило, что и форма, — иначе одно поле могло бы требовать то, что другое
не показывает.

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

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

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 09:44:48 +05:00

101 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ISelectOption } from '@tnsu/ui-kit';
/** Вид обращения. Union вместо строк, чтобы опечатку поймал компилятор. */
export type AppealKind = 'complaint' | 'suggestion' | 'other';
/** Данные формы обращения. Одна плоская структура — один источник истины. */
export interface IFeedbackData {
company: string;
/** true — автор не указывает себя и не получит ответ. */
isAnonymous: boolean;
fullName: string;
position: string;
wantsFeedback: boolean;
kind: AppealKind;
/** Заполняется только при kind === 'other'. */
kindOther: string;
situation: string;
suggestion: string;
}
/**
* Компании группы. В value — реальный Id из справочника, а не slug: именно его
* ждёт бэкенд, когда появится отправка. Порядок как в источнике (по алфавиту).
*/
export const COMPANY_OPTIONS: ISelectOption[] = [
{ value: '8028abac-ac23-8fd8-11ef-cb57631a9ab0', label: 'ТОО AFL Engineering' },
{ value: '9de064a4-44c8-88ef-11ec-831c058b1141', label: 'ТОО CL MANAGEMENT' },
{ value: '9de064a4-44c8-88ef-11ec-8287fb7737a2', label: 'ТОО KazPromService' },
{ value: 'ec3c78a7-29ef-4725-11ed-a6d8fcd0911d', label: 'ТОО QAZGEOMAX' },
{ value: '15009595-005d-00fa-11ef-11309f5e395d', label: 'ТОО Selin Invest' },
{ value: '03f4deac-f543-e8cf-11f1-84eb25329fc3', label: 'ТОО Selin Studio' },
{ value: '9de064a4-44c8-88ef-11ec-8284930fad96', label: 'ТОО TANSU Construction' },
{ value: '9de064a4-44c8-88ef-11ec-8285925d83d2', label: 'ТОО АСТЕЛ-К' },
{ value: '15009595-005d-00fa-11ef-0b8bb5ec1a88', label: 'ТОО ГеоТрек' },
{ value: '15009595-005d-00fa-11ef-0b8714483372', label: 'ТОО Монтажник-Т' },
{ value: '8028beac-ac23-8fd8-11f0-5351706e5996', label: 'ТОО ОСН Беркут' },
{ value: '8028b0ac-ac23-8fd8-11ef-dcdb24b82e02', label: 'ТОО СТ Global' },
{ value: '15009595-005d-00fa-11ef-1131801d9f3e', label: 'ТОО ТехЛаб' },
{ value: '03f4deac-f543-e8cf-11f1-84f51483f59e', label: 'Частная компания Seline Holding Ltd' }
];
export const KIND_OPTIONS: ISelectOption[] = [
{ value: 'complaint', label: 'Жалоба' },
{ value: 'suggestion', label: 'Предложение' },
{ value: 'other', label: 'Другое' }
];
/** Показывать поле или нет, и если показывать — обязательно ли оно. */
export interface IAppealFieldConfig {
visible: boolean;
required: boolean;
}
/** Настройка текстовых полей для выбранного вида обращения. */
export interface IAppealFieldsConfig {
situation: IAppealFieldConfig;
suggestion: IAppealFieldConfig;
}
/**
* Состав полей зависит от вида обращения:
* жалоба — обязательно описание, а предложение — на желание автора;
* предложение — только само предложение, «ситуации» ещё нет;
* другое — свободное описание, без предложения.
* Одно правило на форму и на валидацию, чтобы они не разошлись.
*/
export function getAppealFieldsConfig(kind: AppealKind): IAppealFieldsConfig {
switch (kind) {
case 'complaint':
return {
situation: { visible: true, required: true },
suggestion: { visible: true, required: false }
};
case 'suggestion':
return {
situation: { visible: false, required: false },
suggestion: { visible: true, required: true }
};
case 'other':
return {
situation: { visible: true, required: true },
suggestion: { visible: false, required: false }
};
}
}
export const EMPTY_FEEDBACK: IFeedbackData = {
company: '',
isAnonymous: false,
fullName: '',
position: '',
wantsFeedback: false,
kind: 'complaint',
kindOther: '',
situation: '',
suggestion: ''
};
/** Ключи полей, по которым показываем ошибку валидации. */
export type FeedbackErrors = Partial<Record<keyof IFeedbackData, string>>;