Выбор времени для собеседования
Выбор времени для собеседования
Ниже отображаются свободные интервалы в рабочее время с 09:00 до 13:00 на ближайшие 3 недели
(будни, без выходных). Шаг слотов — 15 минут.
${interviewInfo}
Если вам нужно изменить время, пожалуйста, свяжитесь с нами — мы перенесём встречу.
`;
alreadyContainer.innerHTML = '';
alreadyContainer.appendChild(card);
const cancelBtn = card.querySelector('#cancel-interview-btn');
if (cancelBtn) {
cancelBtn.addEventListener('click', onCancelInterviewClick);
}
console.log('Отрисован блок "Собеседование уже назначено"', { interviewInfo });
}
// ================== Обработка кликов ==================
function onSlotClick(slot) {
currentSelectedSlot = slot;
renderCurrentPage();
}
async function bookSlot(slot) {
if (!currentCandidateId) {
showError('Не найден идентификатор кандидата. Ссылка некорректна.');
return;
}
const sectionId = await getInvitationsSectionId();
const intervalText = formatHumanInterval(slot.start, slot.end);
const dateFromStr = slot.start.toLocaleString('ru-RU', {
day: '2-digit', month: '2-digit', year: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit'
}).replace(',', '');
const dateToStr = slot.end.toLocaleString('ru-RU', {
day: '2-digit', month: '2-digit', year: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit'
}).replace(',', '');
const candidateLink = getCandidateCardUrl();
const displayName = candidateName || `кандидатом #${currentCandidateId}`;
let eventDescription =
`Интервью с ${displayName}.\n` +
`Карточка кандидата: ${candidateLink || ''}`;
if (candidateLink) {
eventDescription += `\n\n
Открыть карточку кандидата`;
}
const eventResult = await callBitrix('calendar.event.add', {
type: 'user',
ownerId: USER_ID,
section: sectionId,
name: `Собеседование с ${displayName}`,
from: dateFromStr,
to: dateToStr,
skipTime: 'N',
timezone: 'Europe/Moscow',
description: eventDescription
});
const eventId =
typeof eventResult === 'object' && eventResult !== null && eventResult.ID
? parseInt(eventResult.ID, 10)
: parseInt(eventResult, 10);
if (!eventId || isNaN(eventId)) {
console.warn('calendar.event.add вернул странный результат', eventResult);
} else {
currentEventId = eventId;
}
const interviewInfoValue = `Собеседование назначено: ${intervalText}`;
const dtForField = toBitrixDateTimeWithOffset(slot.start);
const fieldsPayload = {
entityTypeId: ENTITY_TYPE_ID,
id: currentCandidateId,
[`fields[${FIELD_INTERVIEW_INFO_UPDATE}]`]: interviewInfoValue,
[`fields[${FIELD_INTERVIEW_FLAG_UPDATE}]`]: 'Да',
[`fields[${FIELD_EVENT_ID_UPDATE}]`]: eventId ? String(eventId) : '',
[`fields[${FIELD_INTERVIEW_DATETIME_UPDATE}]`]: dtForField
};
await callBitrix('crm.item.update', fieldsPayload);
showResult(`Вы успешно записаны на собеседование. ${interviewInfoValue}`);
updateTitleAndSubtitle(true);
renderAlreadyBooked(interviewInfoValue);
}
async function onCancelInterviewClick() {
if (!currentCandidateId) {
showError('Не найден идентификатор кандидата. Ссылка некорректна.');
return;
}
const btn = document.getElementById('cancel-interview-btn');
if (btn) {
btn.disabled = true;
btn.textContent = 'Отменяем...';
}
console.log('Отмена собеседования: старт', {
candidateId: currentCandidateId,
currentEventId
});
if (currentEventId) {
try {
await callBitrix('calendar.event.delete', {
id: currentEventId
});
console.log('Событие календаря удалено', currentEventId);
} catch (e) {
console.error('Не удалось удалить событие календаря', e);
}
}
const fieldsPayload = {
entityTypeId: ENTITY_TYPE_ID,
id: currentCandidateId,
[`fields[${FIELD_INTERVIEW_INFO_UPDATE}]`]: '',
[`fields[${FIELD_INTERVIEW_FLAG_UPDATE}]`]: 'Собеседование отменено',
[`fields[${FIELD_EVENT_ID_UPDATE}]`]: '',
[`fields[${FIELD_INTERVIEW_DATETIME_UPDATE}]`]: ''
};
try {
await callBitrix('crm.item.update', fieldsPayload);
console.log('Отмена собеседования: crm.item.update успешен', fieldsPayload);
currentEventId = null;
showResult('Собеседование отменено. При необходимости выберите новое время для собеседования.');
const selector = document.getElementById('slot-selector');
const alreadyContainer = document.getElementById('already-booked');
if (alreadyContainer) alreadyContainer.innerHTML = '';
if (selector) selector.style.display = 'block';
updateTitleAndSubtitle(false);
await loadFreeSlots();
} catch (e) {
console.error('Ошибка при отмене собеседования', e);
showError('Не удалось отменить собеседование. Пожалуйста, попробуйте ещё раз.');
if (btn) {
btn.disabled = false;
btn.textContent = 'Отменить собеседование';
}
}
}
// ================== Навигация по карусели ==================
function setupNavButtons() {
const prevBtn = document.getElementById('prev-page-btn');
const nextBtn = document.getElementById('next-page-btn');
if (!prevBtn || !nextBtn) return;
prevBtn.addEventListener('click', () => {
if (currentPage > 0) {
currentPage -= 1;
renderCurrentPage();
}
});
nextBtn.addEventListener('click', () => {
const maxPage = Math.floor((allDaysWithSlots.length - 1) / DAYS_PER_PAGE);
if (currentPage {
setupNavButtons();
initPage().catch((e) => {
console.error(e);
showError('Произошла ошибка при инициализации страницы.');
});
});