Фронтенд для сервиса (#5)
Tests / test (push) Successful in 2m26s

Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz>
Reviewed-on: http://git.tnsu.kz/gorbenko.pavel/tnsu-approval-route/pulls/5
This commit was merged in pull request #5.
This commit is contained in:
2026-07-30 06:11:24 +00:00
parent 5476c1bab5
commit da158cfd84
114 changed files with 26045 additions and 2 deletions
@@ -0,0 +1,38 @@
import { Employee, HeadType, ProjectRole, StepExecutorKind, TemplateRouteStep } from '../models';
import { headTypeLabels, projectRoleLabels, texts } from '../texts';
import { findEmployeeByEmail } from './employee';
/** Каким из четырёх взаимоисключающих способов у шага задан исполнитель. */
export function detectExecutorKind(step: {
executorEmail?: string | null;
position?: string | null;
projectRole?: ProjectRole | null;
headType?: HeadType | null;
}): StepExecutorKind {
if (step.executorEmail) return 'email';
if (step.position) return 'position';
if (step.projectRole && step.projectRole !== ProjectRole.None) return 'projectRole';
return 'headType';
}
export interface StepExecutorDisplay {
primary: string;
/** Email под ФИО — только когда исполнитель задан конкретным сотрудником и тот найден в справочнике. */
secondary?: string;
}
/** Колонка «Исполнитель» в таблице шагов шаблона маршрута. */
export function describeStepExecutor(step: TemplateRouteStep, employees: Employee[]): StepExecutorDisplay {
if (step.executorEmail) {
const employee = findEmployeeByEmail(employees, step.executorEmail);
return employee ? { primary: employee.fio, secondary: employee.email } : { primary: step.executorEmail };
}
if (step.position) return { primary: step.position };
if (step.projectRole && step.projectRole !== ProjectRole.None) {
return { primary: texts.routeSteps.executorRole(projectRoleLabels[step.projectRole]) };
}
if (step.headType && step.headType !== HeadType.None) {
return { primary: texts.routeSteps.executorHead(headTypeLabels[step.headType]) };
}
return { primary: texts.common.empty };
}