feat: примечание для согласующих в заявке на приём

Инициатору нужно передать согласующим важную информацию так, чтобы её не
пропустили. Новый раздел «6. Примечание для согласующих» (текст + «Важное»);
у согласующих и исполнителей заполненное примечание показывается плашкой
над разделами заявки, важное выделено цветом и иконкой. Сделано общим
модулем shared/approverNote, чтобы подключать в другие формы. Колонки
HireApproverNote (Note) и HireApproverNoteImportant (Boolean).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-10-08 15:02:11 +05:00
parent 8a22767dd3
commit 545db1aee6
14 changed files with 307 additions and 3 deletions
@@ -71,6 +71,7 @@ import { CandidateSection } from './sections/CandidateSection';
import { PpeSection } from './sections/PpeSection';
import { ConditionsSection } from './sections/ConditionsSection';
import { AgencySection } from './sections/AgencySection';
import { NoteSection } from './sections/NoteSection';
import { useStableCallback } from '../../shared/useStableCallback';
const RecruitingHireForm: React.FC<IRequestFormProps> = ({
@@ -411,6 +412,7 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({
<PpeSection {...sectionProps} />
<ConditionsSection {...sectionProps} />
<AgencySection {...sectionProps} />
<NoteSection {...sectionProps} />
</FormModeProvider>
</FieldChangesProvider>
@@ -59,6 +59,8 @@ import { CandidateSection } from './sections/CandidateSection';
import { PpeSection } from './sections/PpeSection';
import { ConditionsSection } from './sections/ConditionsSection';
import { AgencySection } from './sections/AgencySection';
import { NoteSection } from './sections/NoteSection';
import { ApproverNoteBanner } from '../../shared/approverNote';
import { useStableCallback } from '../../shared/useStableCallback';
interface IRecruitingHireViewProps {
@@ -374,6 +376,9 @@ const RecruitingHireView: React.FC<IRecruitingHireViewProps> = ({ context, itemI
}
headerRight={status ? <StatusBadge status={status} /> : undefined}
>
{/* Сохранённое значение, а не редактируемое: плашка — то, что написал
инициатор, и не должна меняться по ходу набора правок согласующим. */}
<ApproverNoteBanner text={savedData.HireApproverNote} important={savedData.HireApproverNoteImportant} />
<FieldChangesBanner changes={approverChanges} />
<FieldChangesProvider changes={toChangeMap(approverChanges)}>
<FormModeProvider readOnly={!fullEditable}>
@@ -382,6 +387,7 @@ const RecruitingHireView: React.FC<IRecruitingHireViewProps> = ({ context, itemI
<PpeSection {...sectionProps} />
<ConditionsSection {...sectionProps} />
<AgencySection {...sectionProps} />
<NoteSection {...sectionProps} />
</FormModeProvider>
</FieldChangesProvider>
@@ -25,7 +25,7 @@ const SCALAR_FIELDS: (keyof IFormData)[] = [
'HireCandidateName', 'HireHireDate', 'Position',
'Department', 'SiteLocation', 'PpeHeight', 'PpeClothingSize', 'PpeShoeSize', 'ProbationPeriod', 'ProbationPeriodOther',
'SalaryProbation', 'SalaryAfterProbation', 'WorkSchedule', 'WorkScheduleOther',
'AgencyName', 'AgencyTerms',
'AgencyName', 'AgencyTerms', 'HireApproverNote',
'SelectionRequestId', 'SelectionRequestListId', 'SelectionRequestCode'
];
@@ -62,6 +62,7 @@ export async function loadHireRequest(itemId: number, listId?: string): Promise<
'ProjectCode',
'RecruitingAgency',
'HireOnArrival',
'HireApproverNoteImportant',
APPROVER_CHANGES_FIELD,
'RequestStatus',
'RequestUniqueCode'
@@ -78,6 +79,7 @@ export async function loadHireRequest(itemId: number, listId?: string): Promise<
// Флаг агентства — булево поле (Yes/No), не строка.
(data as unknown as Record<string, unknown>).RecruitingAgency = !!item.RecruitingAgency;
(data as unknown as Record<string, unknown>).HireOnArrival = !!item.HireOnArrival;
data.HireApproverNoteImportant = !!item.HireApproverNoteImportant;
SCALAR_FIELDS.forEach((key) => {
const value = item[key];
@@ -79,6 +79,10 @@ export interface IFormData {
RecruitingAgency: boolean;
AgencyName: string;
AgencyTerms: string;
// Примечание для согласующих (shared/approverNote): текст + «Важное».
// Префикс Hire — чтобы internalName не совпал с одноимёнными колонками других форм.
HireApproverNote: string;
HireApproverNoteImportant: boolean;
}
/** Обновление одного поля формы с сохранением типа значения. */
@@ -119,7 +123,9 @@ export const EMPTY_DATA: IFormData = {
WorkScheduleOther: '',
RecruitingAgency: false,
AgencyName: '',
AgencyTerms: ''
AgencyTerms: '',
HireApproverNote: '',
HireApproverNoteImportant: false
};
/** Подпись флажка HireOnArrival рядом с датой приёма. */
@@ -44,6 +44,9 @@
{ "internalName": "RecruitingAgency", "title": "Рекрутинговое агентство", "type": "Boolean" },
{ "internalName": "AgencyName", "title": "Название компании (агентство)", "type": "Text" },
{ "internalName": "AgencyTerms", "title": "Условия (агентство)", "type": "Note" }
{ "internalName": "AgencyTerms", "title": "Условия (агентство)", "type": "Note" },
{ "internalName": "HireApproverNote", "title": "Примечание для согласующих", "type": "Note" },
{ "internalName": "HireApproverNoteImportant", "title": "Примечание — важное", "type": "Boolean" }
]
}
@@ -0,0 +1,22 @@
import * as React from 'react';
import { ApproverNoteSection, IApproverNoteFieldKeys } from '../../../shared/approverNote';
import { ISectionProps } from '../model';
/** Колонки примечания в списке данных приёма (см. provisioning.json). */
const NOTE_FIELD_KEYS: IApproverNoteFieldKeys = {
text: 'HireApproverNote',
important: 'HireApproverNoteImportant'
};
/** 6. Примечание для согласующих — общий раздел shared/approverNote на полях приёма. */
export const NoteSection: React.FC<ISectionProps> = ({ data, set }) => (
<ApproverNoteSection
title="6. Примечание для согласующих"
value={{ text: data.HireApproverNote, important: data.HireApproverNoteImportant }}
onChange={(note) => {
set('HireApproverNote', note.text);
set('HireApproverNoteImportant', note.important);
}}
fieldKeys={NOTE_FIELD_KEYS}
/>
);