Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a01533632 | |||
| 28a122667d | |||
| 7fffcde4e6 | |||
| 391ab66229 | |||
| 3583079abb | |||
| 0d7211861e |
@@ -1 +1 @@
|
||||
@tnsu:registry=http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/
|
||||
@tnsu:registry=https://git.tnsu.kz/api/packages/tansu/npm/
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
- React 17 + TypeScript (строгий режим)
|
||||
- Vite 6
|
||||
- SCSS Modules
|
||||
- [`@tnsu/ui-kit`](http://git.tnsu.kz/timur.gorodetskiy/tnsu-ui-kit) — общие UI-компоненты
|
||||
- [`@tnsu/ui-kit`](https://git.tnsu.kz/timur.gorodetskiy/tnsu-ui-kit) — общие UI-компоненты
|
||||
- Vitest — тесты бизнес-логики
|
||||
|
||||
React именно 17-й: `@tnsu/ui-kit` объявляет его в `peerDependencies`.
|
||||
|
||||
Generated
+4
-4
@@ -9,7 +9,7 @@
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@fluentui/react": "^8.106.4",
|
||||
"@tnsu/ui-kit": "^0.8.0",
|
||||
"@tnsu/ui-kit": "^0.14.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"tslib": "^2.3.1"
|
||||
@@ -1701,9 +1701,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tnsu/ui-kit": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "http://git.tnsu.kz/api/packages/timur.gorodetskiy/npm/%40tnsu%2Fui-kit/-/0.8.0/ui-kit-0.8.0.tgz",
|
||||
"integrity": "sha512-PdAxr09JVkbK8XmxSM5Lgfz1Iq56RGFsoz4bI1YBd8quPzM3g/r4gRqqjbhCxyemzfK1d4w4WJD0ZBSs8jJbdA==",
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://git.tnsu.kz/api/packages/tansu/npm/%40tnsu%2Fui-kit/-/0.14.0/ui-kit-0.14.0.tgz",
|
||||
"integrity": "sha512-Vun9AUM9jL8rttbsbKo5Yh6TUz1srkNqxiO6mmzebrSo1JOASNJqNjJPMTS+8Jt3MTrJPklvh0TbeqGQzw7qxQ==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"@fluentui/react": "^8.106.4",
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluentui/react": "^8.106.4",
|
||||
"@tnsu/ui-kit": "^0.8.0",
|
||||
"@tnsu/ui-kit": "^0.14.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"tslib": "^2.3.1"
|
||||
|
||||
+15
-1
@@ -11,6 +11,19 @@ export interface ICompany {
|
||||
Name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Компании из справочника, которые по сути не действуют и не должны попадать
|
||||
* в форму (просьба HR, 2026-09-09): СЛМ (CL MANAGEMENT), Selin Invest,
|
||||
* ОСН Беркут, ТехЛаб, Seline Holding Ltd.
|
||||
*/
|
||||
const EXCLUDED_COMPANY_IDS = new Set<string>([
|
||||
'9de064a4-44c8-88ef-11ec-831c058b1141', // ТОО CL MANAGEMENT (СЛМ)
|
||||
'15009595-005d-00fa-11ef-11309f5e395d', // ТОО Selin Invest
|
||||
'8028beac-ac23-8fd8-11f0-5351706e5996', // ТОО ОСН Беркут
|
||||
'15009595-005d-00fa-11ef-1131801d9f3e', // ТОО ТехЛаб
|
||||
'03f4deac-f543-e8cf-11f1-84f51483f59e' // Частная компания Seline Holding Ltd
|
||||
]);
|
||||
|
||||
let cached: { companies: ICompany[]; expiresAt: number } | null = null;
|
||||
|
||||
export async function getCompanies(): Promise<ICompany[]> {
|
||||
@@ -29,7 +42,8 @@ export async function getCompanies(): Promise<ICompany[]> {
|
||||
);
|
||||
}
|
||||
|
||||
const companies = (await response.json()) as ICompany[];
|
||||
const allCompanies = (await response.json()) as ICompany[];
|
||||
const companies = allCompanies.filter((company) => !EXCLUDED_COMPANY_IDS.has(company.Id));
|
||||
cached = { companies, expiresAt: Date.now() + CACHE_TTL_MS };
|
||||
return companies;
|
||||
}
|
||||
|
||||
@@ -24,8 +24,26 @@ export interface IFeedbackSubmission {
|
||||
suggestion: string;
|
||||
}
|
||||
|
||||
// 5 рабочих дней от текущей даты, выходные (сб/вс) не считаются днём срока —
|
||||
// используется как крайний срок обработки обращения (AppealDueDate).
|
||||
function addBusinessDays(from: Date, days: number): Date {
|
||||
const result = new Date(from);
|
||||
let remaining = days;
|
||||
|
||||
while (remaining > 0) {
|
||||
result.setDate(result.getDate() + 1);
|
||||
const dayOfWeek = result.getDay(); // 0 = воскресенье, 6 = суббота
|
||||
if (dayOfWeek !== 0 && dayOfWeek !== 6) {
|
||||
remaining -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Имена полей — internal name столбцов списка SharePoint (Company/Name/Position/
|
||||
// Type/IssueDescription/SuggestionText/WantsFeedback), не отображаемые названия.
|
||||
// Type/IssueDescription/SuggestionText/WantsFeedback/AppealDueDate), не
|
||||
// отображаемые названия.
|
||||
async function buildFields(data: IFeedbackSubmission): Promise<Record<string, unknown>> {
|
||||
const typeLabel = data.kind === 'other' ? data.kindOther : KIND_LABELS[data.kind];
|
||||
const name = data.isAnonymous ? '' : data.fullName;
|
||||
@@ -38,7 +56,8 @@ async function buildFields(data: IFeedbackSubmission): Promise<Record<string, un
|
||||
Type: typeLabel,
|
||||
IssueDescription: data.situation,
|
||||
SuggestionText: data.suggestion,
|
||||
WantsFeedback: data.wantsFeedback
|
||||
WantsFeedback: data.wantsFeedback,
|
||||
AppealDueDate: addBusinessDays(new Date(), 5).toISOString()
|
||||
};
|
||||
|
||||
// Состав полей зависит от вида обращения и анонимности, поэтому часть строк
|
||||
|
||||
@@ -20,6 +20,10 @@ export const FeedbackForm: React.FC = () => {
|
||||
// (App.tsx) — второй здесь был бы дублем. Пустая строка убирает текст,
|
||||
// а гэпа не оставляет: у ui-kit пустой title-блок не создаёт строки.
|
||||
<FormCard title="">
|
||||
<div className={styles.notice}>
|
||||
<Alert variant="ok">{TEXTS.helpText}</Alert>
|
||||
</div>
|
||||
|
||||
{formError ? (
|
||||
<div className={styles.notice}>
|
||||
<Alert variant="err">{formError}</Alert>
|
||||
|
||||
@@ -6,6 +6,11 @@ export const TEXTS = {
|
||||
pageTitle: 'Обращение',
|
||||
pageSubtitle: 'Данное обращение будет направлено в HR департамент',
|
||||
|
||||
helpText:
|
||||
'Обращение в HR — единый канал для вопросов, предложений и обратной связи ' +
|
||||
'сотрудников по трудовым отношениям, рабочим процессам, условиям труда, ' +
|
||||
'взаимодействию, адаптации, развитию и другим вопросам, связанным с работой в компании.',
|
||||
|
||||
// Две сноски с разным числом звёздочек — как в исходной форме, чтобы читалось
|
||||
// как два отдельных примечания, а не слитный абзац. Field рендерит их построчно.
|
||||
anonymousHint:
|
||||
|
||||
Reference in New Issue
Block a user