chore: initial import for test contour with k3s CI

This commit is contained in:
sova-bootstrap
2026-05-28 12:09:28 +03:00
commit d77d0a872f
423 changed files with 35401 additions and 0 deletions
@@ -0,0 +1,103 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
const alertSystem = this.element;
loader.loadSDK('system').then(function(webSDK) {
webSDK.on('init', function() {
runWebSDK(alertSystem, webSDK);
});
})
if (location.pathname.indexOf('/case-history') != '-1') {
if (location.hash == '#error') {
var msg = 'Что то пошло не так, повторите попытку позже.';
helper.addAlert(msg, alertSystem, 'alert-case-history-error');
}
if (location.hash == '#online') {
var msg = 'При отсутствии оплаты в течение 5 мин. онлайн консультация будет автоматически отменена';
helper.addAlert(msg, alertSystem, 'alert-case-history-online');
}
if (location.hash == '#pay-success') {
var msg = 'Спасибо, оплата прошла успешно.';
helper.addAlert(msg, alertSystem, 'alert-case-history-info', 'alert-success');
}
if (location.hash == '#doctor-success') {
var msg = 'Спасибо, вы успешно записались на прием.';
helper.addAlert(msg, alertSystem, 'alert-case-history-info', 'alert-success');
}
}
if (window.location.href.includes("sovamed")) {
const osa = `Онлайн консультация проводится через личный кабинет, никаких приложений устанавливать не нужно. Рекомендуем изучить <a href="/docs/online.pdf">инструкцию по онлайн консультированию</a> или <a href="/docs/onlinegos.pdf">инструкцию по онлайн консультированию через Госуслуги</a><br>
Возврат средств при несостоявшейся консультации производится в разделе приемы – история записей. <a href="/docs/vozvrat.pdf">Инструкция по возврату средств</a>`;
if (window.location.href.includes("onlineMode")) {
if (alertSystem.dataset.auth === "false") {
const onlineSpecialstAlert = `Для онлайн-консультации рекомендуем пройти авторизацию через <a href="/login">Госуслуги</a>.</br>
Если Вы уже были в клинике и у Вас есть логин и пароль, при авторизации Вы можете использовать его.
Ознакомиться с инструкцией по онлайн-консультированию вы можете, пройдя по <a href="/docs/online.pdf">ссылке</a>.
`;
helper.addAlert(onlineSpecialstAlert, alertSystem, 'alert-online-mode', 'alert-info');
} else {
helper.addAlert(osa, alertSystem, 'alert-online-mode', 'alert-info');
}
}
if (window.location.href.includes("/online-specialists")) {
helper.addAlert(osa, alertSystem, 'alert-online-mode', 'alert-info');
}
}
if (alertSystem.dataset.auth === "false") {
if (location.pathname.indexOf('/info') != '-1') {
var msg = 'Если Вы хотите, чтобы справка была направлена сразу в ФНС, в Ваш кабинет налогоплательщика, то авторизуйтесь через имеющийся логин/пароль или с помощью Госуслуг и заполните данные пациента.';
helper.addAlert(msg, alertSystem, 'alert-info');
}
if (location.pathname.indexOf('/specialist') != '-1' & !window.location.href.includes("onlineMode")) {
var msg = '* вы можете записать себя или другого человека без авторизации, но при этом запись не сохранится в личном кабинете и отменить/перенести ее в случае необходимости будет возможно только по звонку в колл-центр.';
helper.addAlert(msg, alertSystem, 'alert-not-auth');
}
}
let runWebSDK = function (alertSystem, webSDK) {
if (alertSystem.dataset.techMaintenance === 'true') {
var msg = 'Ведутся технические работы, функционал может быть доступен не полностью';
helper.addAlert(msg, alertSystem, 'alert-warning');
}
if (webSDK.data.user.authenticated) {
const userAllows = webSDK.data.user.allows;
if (userAllows.caseHistory == false || userAllows.payments == false || userAllows.reservation == false) {
var msg = 'Ваша учетная запись имеет статус "Неподтвержденная регистрация", запись на прием через портал работает в ограниченном режиме. Вы можете записаться на прием не более одного раза к одному специалисту. Полный доступ на портал Вам будет предоставлен в регистратуре при следующем посещении клиники.';
helper.addAlert(msg, alertSystem, 'alert-info');
}
}
}
}
}
@@ -0,0 +1,31 @@
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var bannerWrap = this.element;
$.ajax({
dataType: "json",
method: 'GET',
url: '/api/banner/' + Cookies.get('region'),
success(response) {
if (response.active == true) {
var a = document.createElement('a');
a.href = response.href;
a.target = "_blank";
a.innerHTML = '<img src="/banners/' + response.src + '" alt="баннер">'
bannerWrap.append(a);
}
}
});
}
}
+28
View File
@@ -0,0 +1,28 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="calendar" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* calendar_controller.js -> "calendar"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var modal = document.getElementById('detail-specialist');
this.element.addEventListener('click', function (evn) {
modal.dataset.specialistid = evn.target.dataset.specialistid;
modal.dataset.filialid = evn.target.dataset.filialid;
modal.dataset.onlinemode = evn.target.dataset.onlinemode;
modal.dataset.docname = (evn.target.dataset.docName ?? evn.target.dataset.docname ?? '').toString();
modal.dataset.address = (evn.target.dataset.address ?? '').toString();
modal.dataset.comment = (evn.target.dataset.comment ?? '').toString();
$(modal).modal('show');
})
// this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
}
}
@@ -0,0 +1,451 @@
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
const misSession = require("./../components/misSession.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="caseHistory" attribute will cause
* this controller to be executed. The name "caseHistory" comes from the filename:
* caseHistory_controller.js -> "caseHistory"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
async cashBack(evn) {
loader.btnLoader(evn.target, true)
var popup = document.getElementById('popup');
popup.querySelector('.modal-title').innerHTML = 'Возврат средств';
popup.querySelector('.modal-dialog').classList = 'modal-dialog modal-md';
try {
const response = await fetch('/refund?filial=' + evn.target.dataset.filial);
if (response.ok) {
const text = await response.text();
popup.querySelector('.modal-body').innerHTML = text;
loader.btnLoader(evn.target, false);
$(popup).modal('show');
popup.querySelector('#refund_address').value = window.webSDK.data.user.address;
popup.querySelector('#refund_phone').value = window.webSDK.data.user.phone;
popup.querySelector('#refund_email').value = window.webSDK.data.user.email;
popup.querySelector('#refund_schedident').value = evn.target.dataset.schedident;
popup.querySelector('#refund_time').value = evn.target.dataset.time;
popup.querySelector('#refund_doc_name').value = evn.target.dataset.docName;
document.getElementById('refund-form').querySelector('button').addEventListener('click', function() {
if ($('#refund-form')[0].checkValidity()) {
$(popup).modal('hide');
}
})
}
} catch (error) {
console.error('Error:', error);
loader.btnLoader(evn.target, false);
}
}
connect() {
loader.loadSDK('caseHistory').then(function(webSDK) {
webSDK.on('init', function() {
if (this.data.user.authenticated) {
runWebSDK(webSDK);
} else {
window.location.pathname = '/logout'
}
});
})
var securityRecord = this.element;
var popup = document.getElementById('popup');
let runWebSDK = function (webSDK) {
scheduleRecordList(webSDK, securityRecord);
}
var securityTabs = document.getElementById('security-tabs');
var tabsDecktop = securityTabs.querySelectorAll('a');
var alertInfo = document.getElementById('alert-case-history-info');
if (tabsDecktop.length > 0) {
tabsDecktop.forEach(function (el) {
el.addEventListener('click', function (evn) {
evn.target.classList = 'tab-item tab-item--active';
if (evn.target.dataset.alert === 'true') alertInfo.classList.remove('d-none');
securityTabs.querySelectorAll('a').forEach(function (a) {
if (evn.target.dataset.allowRemove != a.dataset.allowRemove) {
a.classList.remove('tab-item--active');
}
});
var history = (evn.target.dataset.allowRemove == 'true');
filter(history, securityRecord);
});
});
} else {
securityTabs.addEventListener('change', function(evn) {
if (evn.target.alert === 'true') alertInfo.classList.remove('d-none');
var history = (evn.target.value == 'true');
filter(history, securityRecord);
});
}
function filter(history, securityRecord) {
var items = securityRecord.querySelectorAll('.item-record');
if (items) {
var count = 0;
items.forEach(function (item) {
if (history == true) {
item.classList.add('d-none');
if (item.dataset.workDate >= window.dateFormat(new Date())) {
item.classList.remove('d-none');
count++;
}
} else {
item.classList.add('d-none');
if (item.dataset.workDate < window.dateFormat(new Date())) {
if (item.dataset.onlinemode == '1') {
item.querySelector('.btn-conference').classList.remove('d-inline');
item.querySelector('.btn-conference').classList.add('d-none');
item.querySelector('.online-warning').classList.remove('d-none');
console.log(item.querySelector('.online-warning'));
var refundBtn = item.querySelector('.btn-cash-back')
refundBtn.classList.add('d-inline');
refundBtn.dataset.schedident = item.dataset.schedident
refundBtn.dataset.filial = item.dataset.filial
refundBtn.dataset.time = item.dataset.time
refundBtn.dataset.docName = item.dataset.docName
}
item.classList.remove('d-none');
count++;
}
}
notItems(count);
});
}
}
function notItems(count) {
var load = securityRecord.querySelector('.load');
load.classList.add('d-none');
if (count == 0) {
load.innerHTML = 'Записей не найдено';
load.classList.remove('d-none');
}
}
var renderItems = function(items, securityWrap) {
var count = 0;
items.forEach(function(data, i) {
var blockItem = securityRecord.querySelector('.item-record').cloneNode(true);
blockItem.dataset.workDate = data.workDate;
blockItem.dataset.onlinemode = data.onlineType ?? 0;
blockItem.dataset.docName = data.docName;
blockItem.dataset.time = data.startTime+ ' '+ data.endTime;
blockItem.dataset.schedident = data.schedident;
blockItem.dataset.filial = data.filial;
blockItem.dataset.dcode = data.dcode;
if (blockItem.dataset.dcode) {
helper.sendRequest({
'sid': blockItem.dataset.dcode,
'onlineMode': blockItem.dataset.onlineType ?? 0
}, "/api/doctor", "GET").then(function (response) {
if (response.data) {
blockItem.querySelector('.img-vr').style.background = 'url(' + response.data.img + ') center -5px / cover';
blockItem.querySelector('.position').innerHTML = response.data.speciality;
if (response.data.kinder != null) {
var kinder = blockItem.querySelector('.kinder');
kinder.classList.remove('d-none');
kinder.querySelector('.val').innerHTML = response.data.kinder;
}
if (response.data.expirience != null) {
var kinder = blockItem.querySelector('.expirience');
kinder.classList.remove('d-none');
kinder.querySelector('.val').innerHTML = response.data.expirience;
}
blockItem.querySelectorAll('.link-specialist').forEach(function (el) {
el.href = '/specialist/' + response.data.alias;
});
} else {
blockItem.querySelector('.img-vr').style.background = 'url(/images/no_img.png) center -5px / cover';
blockItem.querySelector('.position').innerHTML = '';
}
});
}
var date = window.newDate(data.workDate);
if (Cookies.get('region') == 91) {
var timeZona = '<br>время саратовское';
} else {
var timeZona = '<br>время московское';
}
blockItem.querySelector('.month').innerHTML = getWeekDay(date);
blockItem.querySelector('.date').innerHTML = window.dateFormat(date, 'd-m-Y') + ' '
+ data.startTime + timeZona;
blockItem.querySelector('.address').innerHTML = (data.filialName == 'Онлайн клиника') ? 'Онлайн-консультация' : data.filialName;
blockItem.querySelector('.section-favorite').dataset.sid = data.dcode;
blockItem.querySelector('.specialist').innerHTML = data.docName;
var btnClose = blockItem.querySelector('.btn-close');
btnClose.classList.add('d-none');
if (data.allowRemove) {
btnClose.classList.remove('d-none');
btnClose.dataset.id = data.id;
btnClose.dataset.filial = data.filial;
btnClose.addEventListener('click', function () {
if (confirm("Подтвердите удаление")) {
webSDK.scheduleRecRemove({
'reserveId': btnClose.dataset.id,
'filialId': btnClose.dataset.filial
}).then(function (resolve) {
document.location.reload();
}).catch(function (error) {
helper.sendRequest({
data: {'error': error, method: 'scheduleRecRemove'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
})
}
});
}
var btnConfirence = blockItem.querySelector('.btn-conference');
var accept = blockItem.querySelector('.accept');
var licenseLink = helper.getLicenseLink(Cookies.get('region'));
var license = document.createElement('p');
if (data.onlineType && data?.payment?.status?.id != 0) {
license.innerHTML = `Пожалуйста, не забудете за 5 минут до начала консультации войти в личный кабинет и потом нажать кнопку «Онлайн прием» для начала консультации.`;
accept.append(license);
var warning = document.createElement('p');
warning.innerHTML=`<b>Внимание!</b> В начале онлайн-консультации вам будет необходимо подтвердить своё согласие с информированным добровольным согласием на медицинское вмешательство (ИДС).`;
accept.append(warning);
btnConfirence.classList.remove('d-none')
btnConfirence.classList.add('d-inline')
btnConfirence.setAttribute('data-id' , data.id)
btnConfirence.setAttribute('data-filial' , data.filial)
btnConfirence.addEventListener('click', function () {
popup.querySelector('#popup-body').innerHTML = '';
misSession.ensureAuthenticated(webSDK).then(function() {
return webSDK.openConference({
schedid: btnConfirence.dataset.id
});
}).then(function () {
if (!misSession.mountConferenceInPopup(popup)) {
throw { data: { message: 'Не удалось открыть окно онлайн-консультации.' } };
}
}).catch(function (e) {
if (misSession.handleMisSessionFailure(popup, e)) {
helper.sendRequest({
data: {'error': e, method: 'openConference', reason: 'mis_session_expired'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
return;
}
if (typeof e.data?.message !== 'undefined') {
var msg = e.data.message.replace('UTC+3', 'UTC+3 (московское время)');
popup.querySelector('#popup-body').innerHTML = msg;
popup.querySelector('.modal-dialog').classList = 'modal-dialog';
popup.querySelector('.modal-content').classList = 'modal-content';
popup.querySelector('.modal-title').innerHTML = 'Уведомление';
$(popup).modal('show');
}
helper.sendRequest({
data: {'error': e, method: 'openConference'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
});
});
} else {
btnConfirence.classList.add('d-none')
}
var btnPayment = blockItem.querySelector('.btn-pay');
if (data.payment && data.payment.status.id == 0 && data.allowRemove) {
license.innerHTML = `Для получения возможности провести оплату консультации - подтвердите согласие на присоединение к договору оферты:`;
accept.append(license);
blockItem.querySelector('.online-warning').classList.remove('d-none');
console.log(blockItem.querySelector('.online-warning'));
var politics = document.createElement('div');
politics.classList = "form-check";
var politicsInput = document.createElement('input');
politicsInput.type="checkbox";
politicsInput.classList="form-check-input";
politicsInput.id="accept-btn";
politics.append(politicsInput);
var politicsLabel = document.createElement('label');
politicsLabel.classList = "form-check-label";
politicsLabel.htmlFor="accept-btn";
politics.append(politicsLabel);
politicsLabel.innerHTML = `Согласен с <a href="${licenseLink}" target="_blank">политикой в отношении обработки персональных данных</a>`;
politics.addEventListener('click', function () {
console.log('politics', politicsInput.checked, personalInput.checked, ofertaInput.checked);
btnPayment.classList.add('disabled');
btnPayment.disabled = true;
if (politicsInput.checked && personalInput.checked && ofertaInput.checked) {
btnPayment.classList.remove('disabled');
btnPayment.disabled = false;
}
});
accept.append(politics);
var personal = document.createElement('div');
personal.classList = "form-check";
var personalInput = document.createElement('input');
personalInput.type="checkbox";
personalInput.classList="form-check-input";
personalInput.id="accept-personal";
personal.append(personalInput);
var personalLabel = document.createElement('label');
personalLabel.classList = "form-check-label";
personalLabel.htmlFor="accept-personal";
personal.append(personalLabel);
personalLabel.innerHTML = `Согласен с <a href="${licenseLink}" target="_blank">обработкой персональных данных</a>.`;
personal.addEventListener('click', function () {
btnPayment.classList.add('disabled');
btnPayment.disabled = true;
if (politicsInput.checked && personalInput.checked && ofertaInput.checked) {
btnPayment.classList.remove('disabled');
btnPayment.disabled = false;
}
});
accept.append(personal);
var oferta = document.createElement('div');
oferta.classList = "form-check";
var ofertaInput = document.createElement('input');
ofertaInput.type="checkbox";
ofertaInput.classList="form-check-input";
ofertaInput.id="accept-oferta";
oferta.append(ofertaInput);
var ofertaLabel = document.createElement('label');
ofertaLabel.classList = "form-check-label";
ofertaLabel.htmlFor="accept-oferta";
oferta.append(ofertaLabel);
ofertaLabel.innerHTML = `Присоединяюсь к договору <a href="/docs/oferta.pdf" target="_blank">оферты</a>`;
oferta.addEventListener('click', function () {
btnPayment.classList.add('disabled');
btnPayment.disabled = true;
if (politicsInput.checked && personalInput.checked && ofertaInput.checked) {
btnPayment.classList.remove('disabled');
btnPayment.disabled = false;
}
});
accept.append(oferta);
btnPayment.classList.remove('d-none');
btnPayment.classList.add('d-inline');
btnPayment.querySelector('.amt').innerHTML = data.payment.amt;
btnPayment.setAttribute('data-id' , data.payment.id);
btnPayment.setAttribute('data-filial' , data.filial);
btnPayment.setAttribute('data-amt' , data.payment.amt);
btnPayment.setAttribute('data-payprofileid' , data.payment.magazineId);
btnPayment.addEventListener('click', function () {
var params = {
'orderid': Number(btnPayment.dataset.id) ,
'payprofileid': btnPayment.dataset.payprofileid,
'payamount': btnPayment.dataset.amt,
'paymethod': 'AC',
'filial': Number(btnPayment.dataset.filial),
'pcode': webSDK.data.user.id,
'successurl': document.location.origin + '/case-history#pay-success',
'errorurl': document.location.origin + '/case-history#error',
'containerId': 'popup-body',
};
misSession.ensureAuthenticated(webSDK).then(function() {
webSDK.loadPaymentView(params);
popup.querySelector('#popup-body').innerHTML = '';
popup.querySelector('.modal-title').innerHTML = 'Оплата';
$(popup).modal('show');
}).catch(function(e) {
if (misSession.handleMisSessionFailure(popup, e)) {
helper.sendRequest({
data: {'error': e, method: 'loadPaymentView', reason: 'mis_session_expired'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
return;
}
helper.sendRequest({
data: {'error': e, method: 'loadPaymentView'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
});
});
} else {
btnPayment.classList.add('d-none');
}
if (data.workDate >= window.dateFormat(new Date())) {
blockItem.classList.remove('d-none');
count++;
}
securityWrap.append(blockItem);
});
notItems(count);
}
function scheduleRecordList(webSDK, securityRecord) {
// Если страница загружена после создания записи, добавляем небольшую задержку
// чтобы дать серверу время обработать новую запись
var delay = (location.hash === '#doctor-success' || location.hash === '#online') ? 500 : 0;
setTimeout(function() {
webSDK.loadScheduleRecList({
st: 20170101,
en: window.dateFormat(new Date((new Date()).getFullYear(), (new Date()).getMonth() + 6, 0)),
start: 0,
length: 500
}).then(function (resolve) {
renderItems(resolve.data, securityRecord.querySelector('.section-wrap'));
}).catch(function(e) {
helper.sendRequest({
data: {'error': e, method: 'loadScheduleRecList'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
securityRecord.querySelector('.load').innerHTML = 'Записей не найдено';
});
}, delay);
}
}
}
@@ -0,0 +1,123 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
loader.loadSDK('system').then(function(webSDK) {
webSDK.on('init', function() {
if (this.data.user.authenticated) {
runWebSDK(webSDK);
}
});
})
let runWebSDK = function (webSDK) {
this.showNamePatient(webSDK.data.user.fullName);
this.element.addEventListener('click', function () {
this.changeResponsible(webSDK);
}.bind(this))
}.bind(this)
$(popup).on('hidden.bs.modal', function () {
this.querySelector('.modal-title').innerHTML = '';
this.querySelector('.modal-dialog').classList.add('modal-lg');
this.querySelector('.modal-body').innerHTML = '';
if (this.querySelector('.modal-footer')) {
this.querySelector('.modal-footer').remove();
}
});
}
showNamePatient(fullName) {
document.getElementById('fullName').innerHTML = fullName;
}
changeResponsible(webSDK) {
var popup = document.getElementById('popup');
popup.querySelector('.modal-title').innerHTML = 'Выбор пациента';
popup.querySelector('.modal-dialog').classList.remove('modal-lg');
var popupBody = document.getElementById('popup-body');
popupBody.innerHTML = '';
webSDK.data.user.represents.forEach(function (represent) {
var div = document.createElement('div');
div.classList = 'form-check';
var input = document.createElement('input');
input.id = represent.pcode;
input.classList = 'form-check-input';
input.value = represent.pcode;
input.type = "radio";
input.name = "changePatient";
if (webSDK.data.user.representId == represent.pcode) {
input.checked = 'true';
}
div.append(input);
var label = document.createElement('label');
label.setAttribute('for', represent.pcode);
label.classList = 'form-check-label';
label.innerHTML = represent.fullName;
div.append(label);
popupBody.append(div);
});
var div = document.createElement('div');
div.classList = 'modal-footer';
var button = document.createElement('button');
button.classList = 'btn btn-outline-secondary';
button.innerHTML = 'Выбрать';
button.addEventListener('click', function() {
loader.btnLoader(this, true);
window.webSDK.selectClient({
id: document.querySelector('input[name="changePatient"]:checked').value
}).then(function (user) {
$.ajax({
method: "POST",
crossDomain: false,
url: "/api/authenticated",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: {
user: user,
uid: user.id
},
success(response) {
if (response.data.success == true) {
var parser = document.createElement('a');
parser.href = response.data.redirect;
window.location.replace(document.location.origin + parser.pathname + parser.search);
}
}
});
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'selectClient'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
})
});
div.append(button);
popup.querySelector('.modal-content').append(div);
$(popup).modal('show');
}
}
@@ -0,0 +1,65 @@
"use strict";
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="changeRegion" attribute will cause
* this controller to be executed. The name "changeRegion" comes from the filename:
* changeRegion_controller.js -> "changeRegion"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var currentUrl = new URL(window.location);
if (currentUrl.searchParams.get('region') !== null) {
Cookies.set('region', currentUrl.searchParams.get('region'), {expires: 1});
currentUrl.searchParams.delete('region');
location.replace(currentUrl);
}
var checkboxes = this.element.querySelectorAll('input');
this.element.querySelector('button.submit').addEventListener('click', function() {
checkboxes.forEach(function(el) {
if (el.checked) {
origin = currentUrl.origin.split('.');
origin[1] = (el.value == '94')? 'wmtmed' : 'sovamed';
currentUrl.search = 'region=' + el.value
Cookies.set('region', el.value, {expires: 1});
location.replace(origin.join('.') + currentUrl.pathname + currentUrl.search + location.hash);
}
});
});
if (/sovamed\.ru/m.test(location.hostname)) {
if (typeof Cookies.get('region') === 'undefined' || Cookies.get('region') == '94') {
$('#chengeRegion').modal('show');
}
} else {
Cookies.set('region', 94, {expires: 1});
}
if (Cookies.get('region')) {
var item = this.element.querySelector('#regionItem' + Cookies.get('region'));
item.checked = true;
if (document.getElementById('regionName')) {
document.getElementById('regionName').innerText = item.dataset.text;
}
}
$('#chengeRegion').on('hide.bs.modal', function (e) {
if (!Cookies.get('region')) {
if (/sovamed\.ru/m.test(location.hostname)) {
Cookies.set('region', 91, {expires: 1});
} else {
Cookies.set('region', 94, {expires: 1});
}
}
})
}
}
@@ -0,0 +1,81 @@
import { Controller } from 'stimulus';
const helper = require("./../components/helper.js");
const record = require("./../components/record.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="checkScheduleBitrix" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* calendar_checkSchedule.js -> "checkScheduleBitrix"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var popup = document.getElementById('popup');
if (! popup) {
renderModal();
}
function renderModal() {
var popup = document.createElement('div');
popup.id = 'popup';
popup.classList = 'fancybox-content';
popup.style = "display: none; width: 700px;"
document.body.append(popup);
var modalDialog = document.createElement('div');
modalDialog.classList = 'modal-dialog';
modalDialog.setAttribute('role', 'document');
popup.append(modalDialog);
var modalContent = document.createElement('div');
modalContent.classList = 'modal-content';
modalDialog.append(modalContent);
var modalHeader = document.createElement('div');
modalHeader.classList = 'modal-header';
modalContent.append(modalHeader);
var modalTitle = document.createElement('h5');
modalTitle.classList = 'modal-title';
modalHeader.append(modalTitle);
var popupBody = document.createElement('div');
popupBody.id = 'popup-body';
popupBody.classList = 'modal-body';
modalContent.append(popupBody);
if (location.host == 'sovenok.sovamed.ru') {
var modalTitleDesc = document.createElement('p');
modalTitleDesc.innerHTML = 'Внимание! Сопровождать ребенка на прием могут только законные представители пациента.';
modalHeader.append(modalTitleDesc);
var modalFooter = document.createElement('div');
modalFooter.classList = 'modal-footer';
modalFooter.innerHTML = '*При первом посещении клиники не забудьте паспорт и свидетельство о рождении ребенка.';
modalContent.append(modalFooter);
}
return true;
}
}
show() {
const popup = document.getElementById('popup');
var date = window.newDate(this.element.dataset.workDate.replace(/\D/g, ""));
this.element.dataset.workDate = window.dateFormat(date, 'Y-m-d');
if (record.renderFormRecord(window.userInfo, this.element.dataset, false)) {
ym(48780536,'reachGoal','pram-zapis');
$.fancybox.open({
src : '#popup',
type : 'inline',
});
}
}
}
@@ -0,0 +1,345 @@
import { Controller } from 'stimulus';
const helper = require("./../components/helper.js");
const record = require("./../components/record.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="checSchedule" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* calendar_checkSchedule.js -> "checSchedule"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
getClinicPhone() {
// primary source: menu_controller.js tel() sets window.clinicPhone
if (typeof window !== 'undefined' && window.clinicPhone) {
return String(window.clinicPhone).trim();
}
// fallback: read what tel() puts into the header button
const el = document.getElementById('btn-callback-clinic');
const phone = el ? (el.textContent || '').trim() : '';
return phone || '';
}
setTitleWithPhone(titleEl) {
if (!titleEl) return;
const phone = this.getClinicPhone();
const phoneText = phone ? phone : '______';
titleEl.textContent = `К этому специалисту возможна запись по тел.${phoneText} или через кнопку «записаться».`;
// If phone not ready yet, retry briefly (tel() is async).
if (!phone) {
let tries = 0;
const timer = setInterval(() => {
tries++;
const p = this.getClinicPhone();
if (p) {
titleEl.textContent = `К этому специалисту возможна запись по тел.${p} или через кнопку «записаться».`;
clearInterval(timer);
} else if (tries >= 20) {
clearInterval(timer);
}
}, 250);
}
}
connect() {
let run = function (intervalBlock, id, filialName) {
this.show(intervalBlock, id, filialName)
}.bind(this)
// Функция для получения intervalBlock по текущему data-id
const getIntervalBlock = () => {
return document.getElementById(this.element.dataset.id);
};
var intervalBlock = getIntervalBlock();
if (!intervalBlock) {
return; // Если блок не найден, выходим
}
var wrap = intervalBlock.querySelector('.intervals-wrap');
wrap.classList.remove('grid-list');
wrap.classList.add('grid-none');
wrap.innerHTML = "Идет загрузка...";
var select = this.element.querySelector('.select-schedule');
if (select) {
// Получаем значение department из URL параметра specialist_search[department]
const urlParams = new URLSearchParams(window.location.search);
const departmentParam = urlParams.get('specialist_search[department]') ||
urlParams.get('specialist_search%5Bdepartment%5D');
let optionFound = false;
// Если есть параметр department в URL, выбираем соответствующую опцию
if (departmentParam) {
const departmentId = parseInt(departmentParam);
for (let i = 0; i < select.options.length; i++) {
const optionValue = select.options[i].value;
// Формат значения: dcode:filial:department:onlineMode:infoclinica
const parts = optionValue.split(':');
if (parts.length >= 3 && parseInt(parts[2]) === departmentId) {
select.value = optionValue;
optionFound = true;
// Обновляем data-id родительского элемента в формате dcode:onlineMode:infoclinica
if (parts.length >= 5) {
this.element.dataset.id = `${parts[0]}:${parts[3]}:${parts[4]}`;
// Обновляем ссылку на intervalBlock после изменения data-id
intervalBlock = getIntervalBlock();
if (intervalBlock) {
wrap = intervalBlock.querySelector('.intervals-wrap');
}
}
// Обновляем bootstrap-select если он используется
// Используем setTimeout чтобы дать время bootstrap-select инициализироваться
setTimeout(() => {
if (typeof $ !== 'undefined' && $(select).data('selectpicker')) {
$(select).selectpicker('refresh');
}
}, 100);
// Запускаем загрузку расписания для выбранной опции
if (intervalBlock) {
run(intervalBlock, optionValue, select.options[i].text);
}
break;
}
}
}
// Если параметра нет или опция не найдена, используем дефолтное поведение
if (!optionFound) {
run(intervalBlock, false, false);
}
const controllerElement = this.element; // Сохраняем ссылку на элемент контроллера
select.addEventListener('change', function() {
// Обновляем data-id родительского элемента при изменении селекта
const optionValue = this.value;
const parts = optionValue.split(':');
// Формат значения: dcode:filial:department:onlineMode:infoclinica
// Формат data-id: dcode:onlineMode:infoclinica
if (parts.length >= 5) {
controllerElement.dataset.id = `${parts[0]}:${parts[3]}:${parts[4]}`;
// Обновляем ссылку на intervalBlock после изменения data-id
const newIntervalBlock = document.getElementById(controllerElement.dataset.id);
if (newIntervalBlock) {
intervalBlock = newIntervalBlock;
wrap = intervalBlock.querySelector('.intervals-wrap');
}
}
wrap.classList.remove('grid-list');
wrap.classList.add('grid-none');
wrap.innerHTML = "Идет загрузка...";
run(intervalBlock, optionValue, select.options[select.selectedIndex].text)
});
} else {
// Если селекта нет, используем дефолтное поведение
run(intervalBlock, false, false);
}
}
show(intervalBlock, id, filialName) {
// Внутри intervalBlock должны быть:
// - .intervals-wrap (контейнер для интервалов/кнопки)
// - .show-specialist-detail (кнопка "Все даты" с dataset для /api/interval)
// Раньше при пустом расписании мы затирали intervalBlock.innerHTML,
// из-за чего при смене клиники селектом пропадал btn и падало на btn.dataset.
// Теперь никогда не удаляем intervalBlock целиком.
let wrap = intervalBlock.querySelector('.intervals-wrap');
if (!wrap) {
wrap = document.createElement('div');
wrap.className = 'intervals-wrap';
intervalBlock.prepend(wrap);
}
const btn = intervalBlock.querySelector('.show-specialist-detail');
// Кешируем dataset на самом intervalBlock, чтобы можно было работать даже если btn временно скрыт
// data-docName в HTML даёт dataset.docName (camelCase), читаем оба варианта
if (btn) {
intervalBlock.dataset.specialistid = btn.dataset.specialistid || intervalBlock.dataset.specialistid || '';
intervalBlock.dataset.departmentid = btn.dataset.departmentid || intervalBlock.dataset.departmentid || '';
intervalBlock.dataset.filialid = btn.dataset.filialid || intervalBlock.dataset.filialid || '';
intervalBlock.dataset.onlinemode = btn.dataset.onlinemode || intervalBlock.dataset.onlinemode || '';
intervalBlock.dataset.address = btn.dataset.address || intervalBlock.dataset.address || '';
intervalBlock.dataset.company = btn.dataset.company || intervalBlock.dataset.company || '';
intervalBlock.dataset.comment = btn.dataset.comment || intervalBlock.dataset.comment || '';
intervalBlock.dataset.docname = (btn.dataset.docName || btn.dataset.docname || intervalBlock.dataset.docname || '').toString();
}
// Ищем элементы заголовка/даты строго внутри текущей карточки,
// чтобы не зависеть от хрупких parentElement-цепочек.
const timeList = intervalBlock.closest('.time-list');
const titleEl = timeList ? timeList.querySelector('.time-list__title') : null;
// Если в заголовке ранее был текст для "записаться", возвращаем стандартный вид перед загрузкой расписания
if (titleEl && !titleEl.querySelector('.cdate')) {
titleEl.innerHTML = 'Удобное время для записи: <span class="cdate">загружается</span>';
}
const cdate = titleEl ? titleEl.querySelector('.cdate') : null;
const ds = intervalBlock.dataset || {};
if (!ds.specialistid || !ds.departmentid || !ds.filialid) {
// Нет данных для запроса расписания (защитимся от падения)
return;
}
var data = {
'update' : true,
'doctor': ds.specialistid,
'department': ds.departmentid,
'filial': ds.filialid,
'startInterval': document.querySelector('.specialist-items').dataset.st,
'endInterval': document.querySelector('.specialist-items').dataset.en,
'onlineMode': ds.onlinemode
};
if (id) {
var params = id.split(":");
data.doctor = params[0];
data.filial = params[1];
data.department = params[2];
data.onlineMode = params[3];
if (btn) {
btn.dataset.specialistid = params[0];
btn.dataset.filialid = params[1];
btn.dataset.departmentid = params[2];
btn.dataset.onlinemode = params[3];
}
intervalBlock.dataset.specialistid = params[0];
intervalBlock.dataset.filialid = params[1];
intervalBlock.dataset.departmentid = params[2];
intervalBlock.dataset.onlinemode = params[3];
}
if (filialName) {
if (btn) {
btn.dataset.address = filialName;
}
intervalBlock.dataset.address = filialName;
}
helper.sendRequest(data, "/api/interval", "GET").then((resolve) => {
var isNotFree = true;
// если ранее скрывали кнопку "Все даты" — возвращаем обратно при любом новом запросе
if (btn) {
btn.classList.remove('d-none');
}
intervalBlock.classList.remove('space-between');
wrap.classList.add('grid-list');
wrap.classList.remove('grid-none');
wrap.innerHTML = "";
var i = 0;
if (cdate && cdate.dataset && cdate.dataset.nearestDate) {
delete cdate.dataset.nearestDate;
}
// Проверяем, есть ли данные в ответе
if (!resolve.data.intervalsData || resolve.data.intervalsData.length === 0) {
isNotFree = true;
} else {
resolve.data.intervalsData.forEach(function(el) {
if (el.isFree == true) {
var cDate = new Date(el.workDate).toLocaleString('ru', {year: 'numeric',month: 'numeric',day: 'numeric'});
var nearestDate = cdate && cdate.dataset ? cdate.dataset.nearestDate : undefined;
if (i < 6) {
isNotFree = false;
for (let [key, item] of Object.entries(el.intervals)) {
if (item.isFree == true && i < 6 && typeof nearestDate === 'undefined') {
if (i == 0) {
var spanCurrentDate = document.createElement('span');
spanCurrentDate.innerText = cDate;
if (cdate) {
cdate.innerText = cDate;
cdate.dataset.nearestDate = item.nearestDate;
}
}
var spanInterval = document.createElement('span');
spanInterval.classList = 'time available text-center';
spanInterval.innerText = item.startTime;
spanInterval.dataset.workDate = item.workDate;
spanInterval.dataset.schedident = item.schedident;
spanInterval.dataset.time = item.time;
spanInterval.dataset.onlinemode = item.onlineMode;
spanInterval.dataset.rnum = item.rNum;
spanInterval.dataset.specialistid = intervalBlock.dataset.specialistid || btn.dataset.specialistid;
spanInterval.dataset.filialid = intervalBlock.dataset.filialid || btn.dataset.filialid;
spanInterval.dataset.department = btn.dataset.departmentid;
spanInterval.dataset.company = intervalBlock.dataset.company || btn.dataset.company || '';
spanInterval.dataset.comment = intervalBlock.dataset.comment || btn.dataset.comment || '';
spanInterval.dataset.address = intervalBlock.dataset.address || btn.dataset.address || '';
spanInterval.dataset.docname = (intervalBlock.dataset.docname || btn.dataset.docName || btn.dataset.docname || '').toString();
spanInterval.addEventListener('click', function (evn) {
var popupWrap = document.getElementById('popup');
evn.target.dataset.onlinemode = item.onlineMode;
if (record.renderFormRecord(resolve.data.userInfo, evn.target.dataset)) {
if (resolve.data.userInfo) {
evn.target.innerHTML = '<img width="20" src="/images/eclipse.gif">';
record.sendReserve(popupWrap)
} else {
$(popupWrap).modal('show');
}
}
})
wrap.append(spanInterval);
i++;
}
}
}
}
});
}
if (isNotFree) {
// Если расписание пустое, показываем кнопку "Записаться" как при specialist.infoclinica == false
intervalBlock.classList.add('space-between');
// прячем "Все даты", но не удаляем (нужно для переключения селекта)
if (btn) {
btn.classList.add('d-none');
}
var button = document.createElement('button');
// Используем правильные имена атрибутов в camelCase для dataset
// data-docName -> dataset.docName (не docname!)
var docName = btn && btn.dataset.docName ? btn.dataset.docName : '';
var address = btn && btn.dataset.address ? btn.dataset.address : 'null';
var company = btn && btn.dataset.company ? btn.dataset.company : 'null';
var comment = btn && btn.dataset.comment ? btn.dataset.comment : '';
button.setAttribute('data-docName', docName);
button.setAttribute('data-address', address);
button.setAttribute('data-company', company);
button.setAttribute('data-comment', comment);
button.className = 'btn-show-specialist-detail';
button.type = 'button';
button.setAttribute('data-controller', 'uslugi');
button.innerText = 'Записаться';
// кладём кнопку в wrap, чтобы не ломать структуру блока
wrap.classList.remove('grid-list');
wrap.classList.add('grid-none');
wrap.innerHTML = '';
wrap.appendChild(button);
// И если мы показываем кнопку, то заголовок должен быть с телефоном/подсказкой
this.setTitleWithPhone(titleEl);
}
});
}
}
@@ -0,0 +1,26 @@
import { Controller } from 'stimulus';
export default class extends Controller {
connect() {
if (!this.isCookieAccepted()) {
this.element.classList = 'show';
} else {
this.element.classList = 'd-none';
}
}
accept() {
// Устанавливаем куку на 1 год
const date = new Date();
date.setFullYear(date.getFullYear() + 1);
document.cookie = `cookie_accepted=true; expires=${date.toUTCString()}; path=/`;
this.element.classList = 'd-none';
}
isCookieAccepted() {
return document.cookie.split(';').some(cookie =>
cookie.trim().startsWith('cookie_accepted=true')
);
}
}
+175
View File
@@ -0,0 +1,175 @@
import { Controller } from 'stimulus';
import daterangepicker from 'daterangepicker'
import 'daterangepicker/daterangepicker.css'
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="datePicker" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* datePicker_controller.js -> "datePicker"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var locale = {
format: 'DD.MM.YYYY',
"applyLabel": "Ок",
"cancelLabel": "Отмена",
"fromLabel": "От",
"toLabel": "До",
"customRangeLabel": "Произвольный",
"daysOfWeek": [
"Вс",
"Пн",
"Вт",
"Ср",
"Чт",
"Пт",
"Сб"
],
"monthNames": [
"Январь",
"Февраль",
"Март",
"Апрель",
"Май",
"Июнь",
"Июль",
"Август",
"Сентябрь",
"Октябрь",
"Ноябрь",
"Декабрь"
],
firstDay: 1
};
var date = new Date();
var lastDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 7);
// Получаем значение даты из URL параметра или из атрибута value элемента
let currentDateValue = this.element.value || this.element.getAttribute('value');
// Если значение не установлено, пробуем получить из URL
if (!currentDateValue || currentDateValue.trim() === '') {
const urlParams = new URLSearchParams(window.location.search);
currentDateValue = urlParams.get('specialist_search[current_date]') ||
urlParams.get('specialist_search%5Bcurrent_date%5D') ||
decodeURIComponent(urlParams.get('specialist_search%5Bcurrent_date%5D') || '');
}
if (this.element.getAttribute('range') == 'true') {
let startDate = date;
let endDate = lastDate;
// Если есть значение из URL или value, парсим его
if (currentDateValue && currentDateValue.trim() !== '') {
const dateRange = this.parseDateRange(currentDateValue);
if (dateRange && dateRange.start && dateRange.end) {
startDate = dateRange.start;
endDate = dateRange.end;
}
}
// Форматируем даты для daterangepicker (формат DD.MM.YYYY)
const formattedStart = window.dateFormat(startDate, 'd.m.Y');
const formattedEnd = window.dateFormat(endDate, 'd.m.Y');
const picker = jQuery(this.element).daterangepicker({
locale: locale,
"startDate": formattedStart,
"endDate": formattedEnd
}, function(start, end, label) {
// Callback при изменении даты
});
// Устанавливаем значение в поле после инициализации
// daterangepicker автоматически форматирует значение согласно locale.format
// Используем setTimeout чтобы дать время daterangepicker инициализироваться
setTimeout(() => {
if (currentDateValue && currentDateValue.trim() !== '') {
this.element.value = currentDateValue.trim();
} else {
this.element.value = `${formattedStart} - ${formattedEnd}`;
}
}, 100);
} else {
let selectedDate = date;
// Если есть значение, парсим его
if (currentDateValue && currentDateValue.trim() !== '') {
const parsedDate = this.parseSingleDate(currentDateValue);
if (parsedDate) {
selectedDate = parsedDate;
this.element.value = currentDateValue;
}
}
jQuery(this.element).daterangepicker({
singleDatePicker: true,
autoApply: true,
showDropdowns: true,
minYear: 1930,
maxYear: new Date(),
locale: locale,
"startDate": window.dateFormat(selectedDate, 'd-m-Y')
});
}
}
parseDateRange(dateString) {
if (!dateString) return null;
// Парсим формат "13.01.2026 - 20.01.2026" или "13.01.2026+-+20.01.2026"
const match = dateString.match(/^(.+?)\s*[-+]\s*(.+)$/);
if (!match) return null;
const startStr = match[1].trim();
const endStr = match[2].trim();
const startDate = this.parseDateString(startStr);
const endDate = this.parseDateString(endStr);
if (!startDate || !endDate) return null;
return { start: startDate, end: endDate };
}
parseSingleDate(dateString) {
if (!dateString) return null;
return this.parseDateString(dateString.trim());
}
parseDateString(dateStr) {
if (!dateStr) return null;
// Формат "dd.mm.yyyy"
const match = dateStr.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/);
if (match) {
const day = parseInt(match[1], 10);
const month = parseInt(match[2], 10) - 1; // месяцы в JS начинаются с 0
const year = parseInt(match[3], 10);
return new Date(year, month, day);
}
// Формат "yyyy-mm-dd"
const match2 = dateStr.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
if (match2) {
const year = parseInt(match2[1], 10);
const month = parseInt(match2[2], 10) - 1;
const day = parseInt(match2[3], 10);
return new Date(year, month, day);
}
// Пробуем стандартный парсинг
const parsed = new Date(dateStr);
if (!isNaN(parsed.getTime())) {
return parsed;
}
return null;
}
}
@@ -0,0 +1,29 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.addEventListener('click', function () {
const popupWrap = document.getElementById('popup');
popupWrap.querySelector('.modal-title').innerHTML = 'Вызов врача на дом';
popupWrap.querySelector('.modal-dialog').classList.remove('modal-lg');
const popupBody = popupWrap.querySelector('#popup-body');
const iframe = document.createElement('iframe');
iframe.src = '/widget/form/2';
iframe.frameBorder = 0;
iframe.height = "500";
iframe.width = "100%";
popupBody.append(iframe);
$(popupWrap).modal('show');
})
}
}
+33
View File
@@ -0,0 +1,33 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var buttonReferenceModal = this.element.querySelector('button.show-reference-modal');
buttonReferenceModal.addEventListener('click', function () {
$.ajax({
dataType: "HTML",
method: 'GET',
crossDomain: false,
url: '/widget/reference',
success(response) {
var popupWrap = document.getElementById('popup');
popupWrap.querySelector('.modal-title').innerHTML = 'Налоговый вычет на лечение';
popupWrap.querySelector('.modal-dialog').classList.remove('modal-lg');
var popupBody = popupWrap.querySelector('#popup-body');
popupBody.innerHTML = response;
$(popupWrap).modal('show');
}
});
})
}
}
@@ -0,0 +1,21 @@
import { Controller } from 'stimulus';
import Inputmask from "inputmask";
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var a = this.element
var favorites = localStorage.getItem('favorites');
if (favorites) {
this.element.href = '/favorites/?q=' + favorites
}
}
}
@@ -0,0 +1,73 @@
import { Controller } from 'stimulus';
import Inputmask from "inputmask";
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var wrap = this.element
var favorites = localStorage.getItem('favorites');
if (typeof favorites === 'object') {
var favorites = '';
}
if (favorites) {
var left = 0;
favorites.split(',').forEach(function(sid, key) {
$.ajax({
dataType: "json",
method: "GET",
crossDomain: true,
url: "/api/doctor",
data: {
'sid': sid,
},
success(response) {
console.log(response, wrap.id)
if (wrap.id == 'favorites-widget' && key < 8) {
var a = document.createElement('a');
a.classList = 'staff-link';
a.href= "/specialist/" + response.data.alias;
var img = document.createElement('img');
img.classList = "staff-block__img";
img.style.borderRadius = '100%';
img.stylebackgroundRepeat = "no-repeat";
img.style.background = "url(" + response.data.img + ")";
img.style.backgroundSize = "cover";
img.style.backgroundPosition = "center 0px";
a.append(img);
wrap.append(a);
} else {
if (key < 4) {
var a = document.createElement('a');
a.classList = 'favorites-link';
a.href= "/specialist/" + response.data.alias;
var div = document.createElement('img');
div.classList = "img-vr";
div.stylebackgroundRepeat = "no-repeat";
div.style.background = "url(" + response.data.img + ")";
div.style.backgroundSize = "cover";
div.style.backgroundPosition = "center 0px";
a.append(div);
wrap.append(a);
}
}
}
});
})
}
}
}
+157
View File
@@ -0,0 +1,157 @@
import { Controller } from 'stimulus';
import Inputmask from "inputmask";
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
function unic(item, colections) {
var add = true;
var del = false;
colections.forEach(function (val, key) {
if (val == item) {
add = false;
del = key;
}
})
if (add) {
colections.push(item)
}
return colections
}
let sid = this.element.dataset.sid;
let like = this.element.querySelector('.like');
let dislike = this.element.querySelector('.dislike');
var favorites = localStorage.getItem('favorites');
if (typeof favorites === 'object') {
var favorites = '';
}
if (favorites.split(',').indexOf(sid) !== -1) {
like.classList.add('d-none');
dislike.classList.remove('d-none');
this.update();
}
like.addEventListener('click', function(evn) {
var favorites = localStorage.getItem('favorites');
var container = [];
if (typeof favorites === 'object') {
var favorites = '';
}
if (favorites) {
favorites = favorites.split(',')
} else {
favorites = [];
}
favorites.push(sid)
favorites.forEach(function (key) {
container = unic(key, container);
});
localStorage.setItem('favorites', container.join());
like.classList.add('d-none');
dislike.classList.remove('d-none');
this.update();
alert('врач добавлен');
}.bind(this));
dislike.addEventListener('click', function (evn) {
var favorites = localStorage.getItem('favorites');
var favorites = favorites.replace( sid + ',', '');
var favorites = favorites.replace( ',' + sid, '');
var favorites = favorites.replace( sid, '');
localStorage.setItem('favorites', favorites);
like.classList.remove('d-none');
dislike.classList.add('d-none');
this.update();
}.bind(this))
}
update() {
var wrap = document.getElementById('favoritesNaw');
if (wrap == null) {
return false;
}
wrap.innerHTML = "";
var favorites = localStorage.getItem('favorites');
var favoritesBtn = document.getElementById('favoritesBtn');
if (typeof favorites === 'object') {
var favorites = '';
}
if (favorites) {
favoritesBtn.href = '/favorites/?q=' + favorites;
var left = 0;
favorites.split(',').forEach(function(sid, key) {
$.ajax({
dataType: "json",
method: "GET",
crossDomain: true,
url: "/api/doctor",
data: {
'sid': sid,
},
success(response) {
if (wrap.id == 'favorites-widget' && key < 8) {
var a = document.createElement('a');
a.classList = 'staff-link';
a.href= "/specialist/" + response.data.alias;
var img = document.createElement('img');
img.classList = "staff-block__img";
img.style.borderRadius = '100%';
img.stylebackgroundRepeat = "no-repeat";
img.style.background = "url(" + response.data.img + ")";
img.style.backgroundSize = "cover";
img.style.backgroundPosition = "center 0px";
a.append(img);
wrap.append(a);
} else {
if (key < 4) {
var a = document.createElement('a');
a.classList = 'favorites-link';
a.href= "/specialist/" + response.data.alias;
var div = document.createElement('img');
div.classList = "img-vr";
div.stylebackgroundRepeat = "no-repeat";
div.style.background = "url(" + response.data.img + ")";
div.style.backgroundSize = "cover";
div.style.backgroundPosition = "center 0px";
a.append(div);
wrap.append(a);
}
}
}
});
})
}
}
}
@@ -0,0 +1,14 @@
import { Controller } from 'stimulus';
export default class extends Controller {
connect() {
$(this.element).on('click', function(e){
$('.filter').addClass('active');
});
$('.filter__close').on('click', function(){
$('.filter').removeClass('active');
});
}
}
@@ -0,0 +1,24 @@
import { Controller } from 'stimulus';
import Inputmask from "inputmask";
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var params = {mask: "+7(899)999-99-99", definitions: {'8': {validator: "[9]"}}}
if (this.element.dataset.mask) {
params = {mask: this.element.dataset.mask}
}
var im = new Inputmask(params);
im.mask(this.element);
}
}
+30
View File
@@ -0,0 +1,30 @@
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
export default class extends Controller {
connect() {
try {
const region = Cookies.get('region');
if (!region) {
console.warn('Region cookie not found, using default Jivo widget');
}
const widgetUrl = this.getSource(region);
this.element.src = widgetUrl;
} catch (error) {
console.error('Failed to load Jivo widget:', error);
}
}
getSource(region) {
const normalizedRegion = region ? String(region).trim() : '';
switch (normalizedRegion) {
case '93': return 'https://code.jivo.ru/widget/EMlWlFXUZB'; // Воронеж
case '94': return 'https://code.jivo.ru/widget/adPLvIW8rT'; // Краснодар
default: return 'https://code.jivo.ru/widget/IPQcFAX6b5'; // Саратов, Волгоград
}
}
}
@@ -0,0 +1,205 @@
import { Controller } from 'stimulus';
const helper = require("./../components/helper.js");
/*
* Контроллер для динамического обновления списка специализаций
* при изменении фильтра "Детский врач" / "Взрослый врач"
*/
export default class extends Controller {
connect() {
const kinderSelect = this.element.querySelector('[id*="kinder"]');
const departmentSelect = this.element.querySelector('[id*="department"]');
if (!kinderSelect || !departmentSelect) {
return;
}
// Сохраняем ссылку на departmentSelect для использования в методах
this.departmentSelect = departmentSelect;
// Обработчик изменения поля kinder
// Используем событие change от bootstrap-select, если оно доступно
const handleKinderChange = () => {
// Небольшая задержка, чтобы bootstrap-select успел обновить значение
setTimeout(() => {
const kinderValue = kinderSelect.value || '';
console.log('Kinder changed to:', kinderValue);
this.updateDepartments(departmentSelect, kinderValue);
}, 100);
};
// Подписываемся на событие change
kinderSelect.addEventListener('change', handleKinderChange);
// Также подписываемся на событие от bootstrap-select, если оно есть
if (typeof $ !== 'undefined' && $(kinderSelect).data('selectpicker')) {
$(kinderSelect).on('changed.bs.select', handleKinderChange);
}
}
updateDepartments(departmentSelect, kinderValue) {
const kinder = kinderValue === '1' ? 1 : null;
// Сохраняем текущее выбранное значение перед обновлением
const selectedValue = departmentSelect.value;
// Показываем индикатор загрузки
const originalHtml = departmentSelect.innerHTML;
departmentSelect.disabled = true;
// Сохраняем состояние bootstrap-select
const isSelectpicker = typeof $ !== 'undefined' && $(departmentSelect).data('selectpicker');
const hasLiveSearch = departmentSelect.hasAttribute('data-live-search');
// Уничтожаем selectpicker, если он инициализирован
if (isSelectpicker) {
try {
$(departmentSelect).selectpicker('destroy');
// Удаляем data-атрибут, чтобы selectpicker_controller не пытался его инициализировать снова
$(departmentSelect).removeData('selectpicker');
// Удаляем классы и элементы, которые мог создать selectpicker
$(departmentSelect).next('.bootstrap-select').remove();
} catch (e) {
console.warn('Ошибка при уничтожении selectpicker:', e);
}
}
departmentSelect.innerHTML = '<option value="">Загрузка...</option>';
// Получаем список специализаций через API
const data = {
kinder: kinder || 0
};
helper.sendRequest(data, "/api/departments", "GET").then((response) => {
console.log('API Response:', response);
// Очищаем текущие опции
departmentSelect.innerHTML = '';
// Добавляем placeholder
const placeholderOption = document.createElement('option');
placeholderOption.value = '';
placeholderOption.textContent = 'Все специализации';
departmentSelect.appendChild(placeholderOption);
// Добавляем новые опции
let foundSelected = false;
if (response && response.data && Array.isArray(response.data)) {
if (response.data.length > 0) {
console.log('Добавляем', response.data.length, 'специализаций');
response.data.forEach((dept) => {
const option = document.createElement('option');
option.value = String(dept.did);
option.textContent = dept.name;
// Проверяем, есть ли ранее выбранное значение в новом списке
if (selectedValue && selectedValue === String(dept.did)) {
option.selected = true;
foundSelected = true;
}
departmentSelect.appendChild(option);
});
console.log('Опции добавлены, всего опций:', departmentSelect.options.length);
} else {
console.warn('Нет данных о специализациях - пустой массив');
}
} else {
console.error('Неверный формат ответа от API:', response);
}
// Если ранее выбранное значение не найдено в новом списке, сбрасываем выбор
if (selectedValue && !foundSelected) {
departmentSelect.value = '';
}
// Проверяем, что опции действительно добавлены
console.log('Проверка перед инициализацией selectpicker:');
console.log('- Количество опций в select:', departmentSelect.options.length);
console.log('- HTML select:', departmentSelect.outerHTML.substring(0, 200));
// Восстанавливаем bootstrap-select
// Используем setTimeout для гарантии, что DOM обновлен
setTimeout(() => {
try {
if (typeof $ !== 'undefined' && $(departmentSelect).length > 0) {
// Проверяем, что опции все еще есть
if (departmentSelect.options.length === 0) {
console.error('ОШИБКА: Опции не найдены перед инициализацией selectpicker!');
return;
}
// Убеждаемся, что старый selectpicker полностью удален
const $select = $(departmentSelect);
if ($select.data('selectpicker')) {
console.log('Найден старый selectpicker, уничтожаем');
try {
$select.selectpicker('destroy');
} catch (e) {
console.warn('Ошибка при destroy:', e);
}
}
// Удаляем все элементы bootstrap-select из DOM
$select.next('.bootstrap-select').remove();
$select.siblings('.bootstrap-select').remove();
// Удаляем data-атрибуты
$select.removeData('selectpicker');
// Всегда инициализируем заново
const selectpickerOptions = {
noneSelectedText: 'Все специализации'
};
// Добавляем liveSearch, если он был изначально
if (hasLiveSearch) {
selectpickerOptions.liveSearch = true;
}
console.log('Инициализируем selectpicker с опциями:', selectpickerOptions);
console.log('Количество опций перед инициализацией:', departmentSelect.options.length);
// Инициализируем selectpicker
$select.selectpicker(selectpickerOptions);
// Проверяем, что selectpicker инициализирован
if ($select.data('selectpicker')) {
console.log('Selectpicker успешно инициализирован');
// Принудительно обновляем отображение
$select.selectpicker('render');
console.log('Selectpicker отрендерен');
} else {
console.error('ОШИБКА: Selectpicker не инициализирован после вызова!');
}
} else {
console.error('jQuery не доступен или элемент не найден');
}
} catch (e) {
console.error('Ошибка при инициализации bootstrap-select:', e);
console.error('Stack trace:', e.stack);
}
}, 200);
departmentSelect.disabled = false;
}).catch((error) => {
console.error('Ошибка при загрузке специализаций:', error);
departmentSelect.innerHTML = originalHtml;
departmentSelect.disabled = false;
// Восстанавливаем bootstrap-select даже при ошибке
setTimeout(() => {
if (typeof $ !== 'undefined') {
const selectpickerOptions = {
noneSelectedText: 'Все специализации'
};
if (hasLiveSearch) {
selectpickerOptions.liveSearch = true;
}
$(departmentSelect).selectpicker(selectpickerOptions);
}
}, 150);
});
}
}
+190
View File
@@ -0,0 +1,190 @@
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
$(document.querySelector('.login-menu')).on('click', function(){
$(this).toggleClass('active');
});
$(document.querySelector('.burger')).on('click', function(){
$(this).toggleClass('active');
$('.left-sidebar').toggleClass('menu-active');
});
loader.loadSDK('menu').then(function(webSDK) {
webSDK.on('init', function() {
if (this.data.user.authenticated) {
runWebSDK(webSDK);
}
});
})
let runWebSDK = function (webSDK) {
this.bonus(webSDK);
if (location.pathname != '/case-history') {
this.caseHistory(webSDK);
}
}.bind(this)
this.tel().catch(error => {
console.error('Ошибка в tel():', error);
});
}
caseHistory(webSDK) {
let countRecord = document.getElementById('countRecord');
window.webSDK.loadScheduleRecList({
st: 20170101,
en: window.dateFormat(new Date((new Date()).getFullYear(), (new Date()).getMonth() + 6, 0)),
start: 0,
length: 500
}).then(function (resolve) {
if (countRecord) {
if (resolve.data.length > 0) {
var count = 0;
for (var i = 0; i < resolve.data.length; i++) {
if (resolve.data[i].workDate >= window.dateFormat(new Date())) {
count++;
}
}
countRecord.innerHTML = count;
if (count !== 0) {
countRecord.classList.remove('d-none');
}
if (location.pathname == '/') {
var caseHistoryWidget = document.getElementById('case-history-widget');
caseHistoryWidget.innerHTML = '';
if (resolve.data.length > 0) {
var count = 0;
for (var i = 0; i < resolve.data.length; i++) {
if (resolve.data[i].workDate >= window.dateFormat(new Date()) && count < 4) {
var date = window.newDate(resolve.data[i].workDate);
var item = document.createElement('span');
item.innerHTML = window.getWeekDay(date) + ', ' + window.dateFormat(date, 'd-m-Y') + ' ' + resolve.data[i].startTime;
item.classList = 'line-item';
caseHistoryWidget.append(item);
count++;
}
}
if (count == 0) {
var item = document.createElement('span');
item.innerHTML = 'Записей не найдено';
item.classList = 'line-item empty-item';
caseHistoryWidget.append(item);
}
} else {
var item = document.createElement('span');
item.innerHTML = 'Записей не найдено';
item.classList = 'line-item empty-item';
caseHistoryWidget.append(item);
}
}
}
}
});
}
bonus() {
var bonusWidget = document.getElementById('bonus-widget');
var bonusMenu = document.getElementById('bonus-menu');
window.webSDK.loadBonusList().then(function (resolve) {
if (resolve.length > 0) {
if (typeof resolve[0]['amountrub'] !== 'undefined') {
if (bonusMenu) {
bonusMenu.innerHTML = resolve[0]['amountrub'];
bonusMenu.classList.remove('d-none');
}
if (bonusWidget) {
bonusWidget.innerHTML = resolve[0]['amountrub'];
}
}
}
});
}
signOut(event) {
if (event) {
event.preventDefault();
}
const pcode = String(window?.webSDK?.data?.user?.id || '');
const body = new URLSearchParams();
if (pcode) {
body.append('pcode', pcode);
}
fetch('/api/usrlog/logout', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
credentials: 'same-origin',
keepalive: true,
body: body.toString()
}).catch(() => {
//
}).finally(() => {
window.webSDK.logout();
window.location.href = '/logout';
});
}
async tel() {
const apiUrl = helper.getApiHostname();
const regionId = parseInt(Cookies.get('region'));
try {
const response = await fetch(`${apiUrl}/filial/list?regionId=${regionId}`);
if (!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
const result = await response.json();
const btnCallbackClinic = document.getElementById('btn-callback-clinic');
const phone = result.data?.[0]?.phone;
if (!btnCallbackClinic || !phone) {
return;
}
const digits = String(phone).replace(/\D/g, '');
const normalizedDigits = digits.length === 11 && digits.startsWith('8')
? `7${digits.slice(1)}`
: digits;
const displayPhone = normalizedDigits.length === 11 && normalizedDigits.startsWith('7')
? `+7(${normalizedDigits.slice(1, 4)})${normalizedDigits.slice(4, 7)}-${normalizedDigits.slice(7, 9)}-${normalizedDigits.slice(9, 11)}`
: String(phone).trim();
// Делаем номер доступным для других частей фронта (например, карточки специалистов)
window.clinicPhone = displayPhone;
window.clinicPhoneRaw = normalizedDigits;
btnCallbackClinic.innerText = displayPhone;
btnCallbackClinic.href = normalizedDigits ? `tel:+${normalizedDigits}` : `tel:${displayPhone}`;
} catch (error) {
console.error(error.message);
}
}
}
@@ -0,0 +1,43 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="searchOrderByInput" attribute will cause
* this controller to be executed. The name "searchOrderByInput" comes from the filename:
* searchOrderByInput_controller.js -> "searchOrderByInput"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var val = document.getElementById("specialist_search_order_by").value;
var tabs = this.element;
if (val) {
check(val, false);
}
tabs.addEventListener('change', function(evn) {
check(evn.target.value, true);
})
function check(index, redirect) {
console.log(index)
var array = index.split('.');
var id = array[0];
var sort = array[1];
tabs.forEach(function(item) {
if (item.value == id) {
item.selected = 'true';
}
});
document.getElementById("specialist_search_order_by").value = index + '.asc';
if (redirect) {
document.querySelector('.submit-filter').click();
}
};
}
}
+49
View File
@@ -0,0 +1,49 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.querySelector('.full-scren-modal').classList.add('d-none');
var popup = this.element;
popup.addEventListener('click', function (ev) {
var closeBtn = ev.target.closest && ev.target.closest('[data-qa="close-button"]');
if (!closeBtn || !popup.contains(closeBtn)) {
return;
}
if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
$(popup).modal('hide');
}
if (window.location.hash === '#pay-success') {
history.replaceState(null, '', window.location.pathname + window.location.search);
}
}, true);
}
fullScreen() {
var btn = this.element.querySelector('.full-scren-modal')
if (btn.classList.contains('fa-window-maximize')) {
btn.classList.add('fa-window-minimize');
btn.classList.remove('fa-window-maximize');
this.element.style.paddingRight = 0;
this.element.querySelector('.modal-dialog').style.maxWidth = window.innerWidth + 'px';
this.element.querySelector('.modal-dialog').style.height = window.innerHeight + 'px';
this.element.querySelector('.modal-dialog').style.margin = 0;
} else {
btn.classList.remove('fa-window-minimize');
btn.classList.add('fa-window-maximize');
this.element.style.paddingRight = '';
this.element.querySelector('.modal-dialog').style.maxWidth = '';
this.element.querySelector('.modal-dialog').style.height = '';
this.element.querySelector('.modal-dialog').style.margin = '';
}
}
}
@@ -0,0 +1,38 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var eye = document.createElement('i');
eye.setAttribute('aria-hidden', true);
eye.classList = 'fa fa-eye-slash'; //fa-eye
eye.style.position = 'absolute';
eye.dataset.action = 'click->passwordShow#toggle'
eye.style.top = '10px';
eye.style.right = '10px';
this.element.style.position = 'relative';
this.element.append(eye);
}
toggle() {
var btn = this.element.querySelector('input');
var eye = this.element.querySelector('i');
if (eye.classList.contains('fa-eye-slash')) {
eye.classList = 'fa fa-eye';
btn.type = 'text';
} else {
eye.classList = 'fa fa-eye-slash';
btn.type = 'password';
}
}
}
+108
View File
@@ -0,0 +1,108 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="payment" attribute will cause
* this controller to be executed. The name "payment" comes from the filename:
* payment_controller.js -> "payment"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
loader.loadSDK('payment').then(function(webSDK) {
webSDK.on('init', function() {
if (this.data.user.authenticated) {
runWebSDK();
} else {
window.location.pathname = '/logout'
}
});
})
let runWebSDK = function () {
this.finance();
}.bind(this)
}
finance() {
var securityPayment = document.getElementById('security-payment');
webSDK.loadPaymentList({
start: 0,
length: 50
}).then(function (resolve) {
var paymentWrap = securityPayment.querySelector('.payment-wrap');
if (resolve.length > 0) {
resolve.forEach(function(item, index) {
var paymentShow = securityPayment.querySelector('.payment-item').cloneNode(true);
paymentShow.querySelector('.pay-id').innerHTML = item.id;
paymentShow.querySelector('.address').innerHTML = item.filialName;
paymentShow.querySelector('.comment').innerHTML = item.comment;
paymentShow.querySelector('.specialist').innerHTML = item.doctor;
paymentShow.querySelector('.service').innerHTML = item.service;
var date = window.newDate(item.date);
paymentShow.querySelector('.month').innerHTML = getWeekDay(date);
paymentShow.querySelector('.date').innerHTML = window.dateFormat(date, 'd-m-Y')
paymentShow.querySelector('.pay-date').innerHTML = window.dateFormat(date, 'd-m-Y')
paymentShow.querySelectorAll('.amt').forEach(function (el) {
el.innerHTML = item.amt;
if (item.status.id == 0) {
paymentShow.querySelector('.pay').querySelector('.button-revers').classList.remove('d-none');
} else {
paymentShow.querySelector('.pay').querySelector('.button-revers').classList.add('d-none');
paymentShow.querySelector('.pay').querySelector('.price').classList.remove('d-none');
}
});
paymentShow.querySelector('.pay').querySelector('.button-revers').dataset.orderId = item.id;
paymentShow.querySelector('.pay').querySelector('.button-revers').dataset.filial = item.filial;
paymentShow.querySelector('.pay').querySelector('.button-revers').dataset.amt = item.amt;
paymentShow.querySelector('.pay').querySelector('.button-revers').dataset.payprofileid = item.magazineId;
paymentShow.querySelector('.pay').querySelector('.button-revers').addEventListener('click', function (evn) {
var popup = document.getElementById('popup');
var params = {
'orderid': Number(this.dataset.orderId) ,
'payprofileid': this.dataset.payprofileid,
'payamount': this.dataset.amt,
// 'paymethod': 'QW',
'filial': Number(this.dataset.filial),
'pcode': webSDK.data.user.representId,
'successurl': document.location.origin + '/payment?pay=true',
'errorurl': document.location.origin + '/payment?pay=false',
'containerId': 'popup-body',
};
webSDK.loadPaymentView(params);
popup.querySelector('.modal-body').innerHTML = '';
popup.querySelector('.modal-title').innerHTML = 'Оплата';
$(popup).modal('show');
})
paymentShow.classList.add('mt-3')
paymentShow.classList.remove('d-none')
if (index == 0) {
paymentWrap.innerHTML = "";
}
paymentWrap.appendChild(paymentShow);
})
}
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'loadPaymentList'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
})
}
}
@@ -0,0 +1,51 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="priceList" attribute will cause
* this controller to be executed. The name "priceList" comes from the filename:
* priceList_controller.js -> "priceList"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var wrap = this.element;
var priceListSelect = document.getElementById('price_list_admin_form_groupId');
var select = priceListSelect.cloneNode(true);
select.id = 'price_list_update_form';
select.name = 'groupId';
var priceList = this.element.querySelector('.group-update');
priceList.appendChild(select);
var btnUpdatePriceList = this.element.querySelector('#update-price-list');
btnUpdatePriceList.addEventListener('click', function() {
if (select.value == '') {
select.classList.add('is-invalid');
} else {
select.classList.remove('is-invalid');
var msg = wrap.querySelector('.msg');
msg.innerHTML = "Пожалуйста ждите, идет обновление цен!";
msg.classList.add('text-danger');
loader.btnLoader(btnUpdatePriceList, true);
helper.sendRequest({groupId: select.value}, '/update/price-list', "POST").then(function (response) {
loader.btnLoader(btnUpdatePriceList, false);
if (response.status == true) {
msg.innerHTML = "Обновление успешно завершено! <br> Нажмите на кнопку \"Search\" для отображения в таблице.";
msg.classList.remove('text-danger');
msg.classList.add('text-success');
} else {
msg.innerHTML = "Упс, что то пошло не так, попробуйте позже или обратитесь к Администратору.";
}
})
}
});
}
}
@@ -0,0 +1,71 @@
import { Controller } from 'stimulus';
export default class extends Controller {
static targets = ['input'];
today(event) {
event?.preventDefault?.();
const today = this.startOfDay(new Date());
this.setRange(today, today);
}
tomorrow(event) {
event?.preventDefault?.();
const tomorrow = this.addDays(this.startOfDay(new Date()), 1);
this.setRange(tomorrow, tomorrow);
}
setRange(startDate, endDate) {
const input = this.inputTarget;
const formattedStart = this.formatDate(startDate);
const formattedEnd = this.formatDate(endDate);
const value = `${formattedStart} - ${formattedEnd}`;
// If daterangepicker is attached, keep it in sync.
if (typeof $ !== 'undefined') {
const picker = $(input).data('daterangepicker');
if (picker) {
picker.setStartDate(formattedStart);
picker.setEndDate(formattedEnd);
// Ensure UI is refreshed for both calendars & input.
if (typeof picker.updateCalendars === 'function') {
picker.updateCalendars();
}
if (typeof picker.updateView === 'function') {
picker.updateView();
}
}
}
input.value = value;
input.dispatchEvent(new Event('change', { bubbles: true }));
const form = this.element.closest('form');
if (form) {
if (typeof form.requestSubmit === 'function') {
form.requestSubmit();
} else {
form.submit();
}
}
}
startOfDay(date) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}
addDays(date, days) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
}
formatDate(date) {
const dd = String(date.getDate()).padStart(2, '0');
const mm = String(date.getMonth() + 1).padStart(2, '0');
const yyyy = String(date.getFullYear());
return `${dd}.${mm}.${yyyy}`;
}
}
+599
View File
@@ -0,0 +1,599 @@
import { Controller } from 'stimulus';
const validator = require("./../components/validator.js");
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var referenceWrapper = this.element;
window.addEventListener("mousemove",(e) => {
window.parent.postMessage({ type: "user_mousemove" }, "*");
});
window.addEventListener("input",(e) => {
window.parent.postMessage({ type: "user_typing" }, "*");
});
let evnRender = function (responsibleUser, countFilial) {
this.renderResponsibleUser(responsibleUser, countFilial);
}.bind(this)
var changeResponsible = function (countFilial, value) {
var responsibleFilial = referenceWrapper.querySelector('.responsible_filial_' + countFilial);
var responsibleUser = responsibleFilial.querySelector('.responsible_user');
if (value == 1) {
responsibleUser.innerHTML = '';
} else {
evnRender(responsibleUser, countFilial)
}
}
referenceWrapper.querySelector('.reference-responsible').addEventListener('change', function() {
changeResponsible(this.dataset.count, this.value);
})
let evnRenderSending = function (referenceSending) {
this.renderSending(referenceSending);
}.bind(this)
const addFilial = referenceWrapper.querySelector('button.add-filial');
const referenceFilial = referenceWrapper.querySelector('#reference_filial');
const referenceFilialSending = referenceWrapper.querySelector('#reference_filialSending');
const referenceSending = referenceWrapper.querySelector('#reference_sending');
const filialSendingWrapper = referenceWrapper.querySelector('.filial-sending');
const syncSendingUi = () => {
if (!referenceSending || !filialSendingWrapper) return;
// Разрешённые варианты:
// 1 = "Лично в клинике"
// 2 = "Отправка в налоговую инспекцию"
// Любое другое/невалидное значение считаем "1".
const sendingSafe = (referenceSending.value === '2' || referenceSending.value === 2) ? '2' : '1';
// "Лично в клинике" => 1 => показываем выбор клиники получения справки
filialSendingWrapper.classList.toggle('d-none', sendingSafe !== '1');
// При "Лично" синхронизируем филиал получения.
// Если filialSending ещё не выбран (пустой) — НЕ блокируем, чтобы можно было выбрать вручную.
if (sendingSafe === '1') {
if (referenceFilial.selectedIndex > 0) {
referenceFilialSending.selectedIndex = referenceFilial.selectedIndex;
}
referenceFilialSending.disabled = Boolean(referenceFilialSending.value);
} else {
referenceFilialSending.disabled = false;
}
};
if (referenceSending) {
referenceSending.addEventListener('change', syncSendingUi);
}
syncSendingUi();
referenceFilial.addEventListener('change', function(evn) {
// Если выдача "Лично в клинике" — синхронизируем филиал получения
const sendingSafe = (referenceSending && (referenceSending.value === '2' || referenceSending.value === 2)) ? '2' : '1';
if (sendingSafe === '1') {
if (referenceFilial.selectedIndex > 0) {
referenceFilialSending.selectedIndex = referenceFilial.selectedIndex;
}
referenceFilialSending.disabled = Boolean(referenceFilialSending.value);
} else {
referenceFilialSending.selectedIndex = 0;
referenceFilialSending.disabled = false;
}
addFilial.classList.remove('d-none');
});
addFilial.addEventListener('click', function() {
var countFilial = parseInt(this.dataset.count, 10);
var responsibleFilial = referenceWrapper.querySelector('.responsible_filial_' + countFilial)
var newFilialCount = countFilial + 1
this.dataset.count = newFilialCount;
var newFilial = referenceWrapper.querySelector('.responsible_filial_' + countFilial).cloneNode(true);
newFilial.classList = 'responsible_filials responsible_filial_' + newFilialCount;
newFilial.querySelector('.reference-filial').id = 'reference_filial_' + newFilialCount;
newFilial.querySelector('.reference-filial').classList = 'reference-filial form-control';
newFilial.querySelector('.valid-reference_filial').innerHTML = '';
newFilial.querySelector('.responsible_user').innerHTML = '';
newFilial.querySelector('.reference-responsible').id = 'reference_responsible_' + newFilialCount;
newFilial.querySelector('.reference-period-first').id = 'reference_periodFirst_' + newFilialCount;
newFilial.querySelector('.reference-period-first').classList = 'reference-period-first form-control';
newFilial.querySelector('.reference-period-last').id = 'reference_periodLast_' + newFilialCount;
newFilial.querySelector('.reference-period-last').classList = 'reference-period-last form-control';
newFilial.querySelector('.reference-responsible').addEventListener('change', function() {
changeResponsible(newFilialCount, this.value);
})
responsibleFilial.parentNode.insertBefore(newFilial, responsibleFilial.nextSibling);
})
var crmFields = {};
helper.sendRequest(
[],
'https://sovamed.bitrix24.ru/rest/10998/3hrv38rzo3khchj3/crm.lead.fields.json',
'GET',
'json',
false,
'application/json'
).then(function(response) {
crmFields = response;
});
var submit = referenceWrapper.querySelector('button.submit');
submit.addEventListener('click', function() {
evnClick(referenceWrapper, crmFields);
})
let evnClick = function (wrapper, crmFields) {
var result = this.submit(wrapper);
var params = {
'fields' : {
'TITLE': 'Получение документов для налогового вычета',
'NAME': result.options.autorName,
'PHONE': [{
'VALUE': result.options.phone,
'VALUE_TYPE': 'WORK'
}],
'ASSIGNED_BY_ID' : 506,
'UF_CRM_1539951158': helper.getCityId(result.options.filials[0].filial),
'UF_CRM_1565783329': result.options.inn,
'UF_CRM_1658495790': '',
'UF_CRM_1565783428': result.options.filials[0].periodFirst + " - " + result.options.filials[0].periodLast,
'UF_CRM_1565783258': result.options.birthDate,
}
};
const normalizeFilialValue = (value) => {
if (typeof value !== 'string') return '';
return value
.replaceAll('\u00A0', ' ') // NBSP -> space
.replaceAll('.', '') // "г.Саратов" == "г. Саратов", "д. 33" == "д 33"
.replace(/\s+/g, ' ')
.replace(/\s*,\s*/g, ', ')
.trim()
.toLowerCase();
};
const filialValue = result.options.filials?.[0]?.filial ?? '';
const filialValueNormalized = normalizeFilialValue(filialValue);
// 1) точное совпадение после нормализации
crmFields.result.UF_CRM_1658495790.items.forEach(function (el) {
if (params.fields['UF_CRM_1658495790']) return;
if (filialValueNormalized && filialValueNormalized === normalizeFilialValue(el.VALUE)) {
params.fields['UF_CRM_1658495790'] = el.ID;
}
});
// 2) запасной вариант: если Bitrix хранит VALUE без доп. суффикса "(...)" и т.п.
if (!params.fields['UF_CRM_1658495790'] && filialValueNormalized) {
const filialValueNoParens = filialValueNormalized.replace(/\s*\([^)]*\)\s*/g, ' ').replace(/\s+/g, ' ').trim();
crmFields.result.UF_CRM_1658495790.items.forEach(function (el) {
if (params.fields['UF_CRM_1658495790']) return;
const bitrixValue = normalizeFilialValue(el.VALUE);
if (!bitrixValue) return;
if (bitrixValue === filialValueNoParens || filialValueNoParens.includes(bitrixValue) || bitrixValue.includes(filialValueNoParens)) {
params.fields['UF_CRM_1658495790'] = el.ID;
}
});
}
if (result.options.filials[0].responsible == 0) {
params.fields['UF_CRM_1565784083'] = 400 //[{"ID": "400","VALUE": "за другого пациента"}];
params.fields['UF_CRM_1654588779'] = result.options.filials[0].relation;
params.fields['UF_CRM_1565784170'] = result.options.filials[0].birthDate;
params.fields['UF_CRM_1565784142'] = result.options.filials[0].fio;
} else {
params.fields['UF_CRM_1565784083'] = 398 //[{"ID": "398","VALUE": "себя"}];
params.fields['UF_CRM_1654588779'] = 'за себя';
params.fields['UF_CRM_1565784170'] = result.options.birthDate;
params.fields['UF_CRM_1565784142'] = result.options.autorName;
}
const sendingSafe = (result.options.sending == 2 || result.options.sending === '2') ? 2 : 1;
if (sendingSafe == 1) {
params.fields['UF_CRM_1658499141'] = 2494 //[{"ID": "2494","VALUE": "на руки"}]
const filialSendingValue = result.options.filialSending ?? '';
const filialSendingValueNormalized = normalizeFilialValue(filialSendingValue);
// 1) точное совпадение после нормализации
crmFields.result.UF_CRM_1658497553.items.forEach(function (el) {
if (params.fields['UF_CRM_1658497553']) return;
if (filialSendingValueNormalized && filialSendingValueNormalized === normalizeFilialValue(el.VALUE)) {
params.fields['UF_CRM_1658497553'] = el.ID;
}
});
// 2) запасной вариант: совпадение без суффикса "(...)" и т.п.
if (!params.fields['UF_CRM_1658497553'] && filialSendingValueNormalized) {
const filialSendingValueNoParens = filialSendingValueNormalized
.replace(/\s*\([^)]*\)\s*/g, ' ')
.replace(/\s+/g, ' ')
.trim();
crmFields.result.UF_CRM_1658497553.items.forEach(function (el) {
if (params.fields['UF_CRM_1658497553']) return;
const bitrixValue = normalizeFilialValue(el.VALUE);
if (!bitrixValue) return;
if (bitrixValue === filialSendingValueNoParens || filialSendingValueNoParens.includes(bitrixValue) || bitrixValue.includes(filialSendingValueNoParens)) {
params.fields['UF_CRM_1658497553'] = el.ID;
}
});
}
} else if (sendingSafe == 2) {
params.fields['UF_CRM_1658499141'] = 4680 //[{"ID": "4680","VALUE": "отправка в налоговую инспекцию"}]
}
if (Object.keys(result.options.filials).length > 1) {
var comment = "";
for (var index = 0; index < Object.keys(result.options.filials).length; index++) {
if (index !== 0) {
comment += "Дополнительно:\n\t"
if (result.options.filials[index].responsible == 0) {
comment += 'Степень родства: ' + result.options.filials[index].relation + "\n\t";
comment += 'ФИО: ' + result.options.filials[index].fio + "\n\t";
comment += 'Дата рождения: ' + result.options.filials[index].birthDate + "\n\t";
} else {
comment += "За себя\n\t";
comment += 'ФИО: ' + result.options.autorName + "\n\t";
comment += 'Дата рождения: ' + result.options.birthDate + "\n\t";
}
comment += 'Филиал: ' + result.options.filials[index].filial + "\n\t";
comment += 'За период: ' + result.options.filials[index].periodFirst;
comment += ' - ' + result.options.filials[index].periodLast + "\n\t";
}
}
params.fields['UF_CRM_1545895397'] = comment;
}
if (result.invalid) {
return false;
}
loader.btnLoader(submit, true);
helper.sendRequest(
params,
'https://sovamed.bitrix24.ru/rest/10998/3hrv38rzo3khchj3/crm.lead.add.json',
'POST',
'json',
false,
'application/json'
).then(function(response) {
loader.btnLoader(submit, false);
if (referenceWrapper.dataset.ref == '/') {
helper.sendRequest({'reference' : 1, 'phone' : result.options.phone}, '/api/msg');
var successAlert = document.createElement('div');
successAlert.classList = 'alert alert-success alert-dismissible fade show';
successAlert.setAttribute('role', 'alert');
var divMsg = document.createElement('div');
divMsg.classList = 'alert-msg';
divMsg.innerHTML = '<p>Заявка успешно подана.</p>';
successAlert.append(divMsg);
var buttonClose = document.createElement('button');
buttonClose.classList = 'close';
buttonClose.dataset.dismiss ='alert';
buttonClose.setAttribute('aria-label', 'Close');
buttonClose.innerHTML = '<span aria-hidden="true">&times;</span>';
successAlert.append(buttonClose);
document.getElementById('alert-system').prepend(successAlert);
$(popup).modal('hide');
$('html, body').animate({scrollTop:0}, '300');
} else {
window.parent.postMessage({'message': 'hide.modal', 'phone' : result.options.phone}, atob(referenceWrapper.dataset.ref));
}
});
}.bind(this)
}
renderSending(referenceSending) {
var div = document.createElement('div');
div.classList = 'form-group mb-2';
var label = document.createElement('label');
label.innerHTML = 'Почтовый адрес:';
label.classList = 'mb-0';
label.setAttribute('for', 'reference_address')
div.append(label);
var input = document.createElement('input');
input.id = 'reference_address';
input.name = 'reference_address';
input.classList = 'form-control';
div.append(input);
var msg = document.createElement('div')
msg.classList = 'msg-valid valid-reference_address';
div.append(msg);
referenceSending.append(div);
var div = document.createElement('div');
div.classList = 'form-group mb-2';
var label = document.createElement('label');
label.innerHTML = 'Индекс:';
label.classList = 'mb-0';
label.setAttribute('for', 'reference_index')
div.append(label);
var input = document.createElement('input');
input.id = 'reference_index'
input.name = 'reference_index'
input.classList = 'form-control';
div.append(input);
var msg = document.createElement('div')
msg.classList = 'msg-valid valid-reference_index';
div.append(msg);
referenceSending.append(div);
}
renderResponsibleUser(responsibleUser, countFilial) {
var div = document.createElement('div');
div.classList = 'form-group mb-2';
var label = document.createElement('label');
label.innerHTML = 'ФИО пациента:';
label.classList = 'mb-0';
label.setAttribute('for', 'reference_patientName_' + countFilial)
div.append(label);
var input = document.createElement('input');
input.id = 'reference_patientName_' + countFilial
input.name = 'reference_patientName[' + countFilial + ']'
input.classList = 'form-control';
div.append(input);
var msg = document.createElement('div')
msg.classList = 'msg-valid valid-reference_patientName';
div.append(msg);
responsibleUser.append(div);
var div = document.createElement('div');
div.classList = 'form-group mb-2';
var label = document.createElement('label');
label.innerHTML = 'Дата рождения пациента:';
label.classList = 'mb-0';
label.setAttribute('for', 'reference_patientBirthDate_' + countFilial)
div.append(label);
var input = document.createElement('input');
input.id = 'reference_patientBirthDate_' + countFilial;
input.name = 'reference_patientBirthDate[' + countFilial + ']'
input.classList = 'form-control';
input.dataset.controller = 'datePicker';
input.setAttribute('range', false);
div.append(input);
responsibleUser.append(div);
var msg = document.createElement('div')
msg.classList = 'msg-valid valid-reference_patientBirthDate';
div.append(msg);
var div = document.createElement('div');
div.classList = 'form-group mb-2';
var label = document.createElement('label');
label.innerHTML = 'Степень родства:';
label.classList = 'mb-0';
label.setAttribute('for', 'reference_relation_' + countFilial)
div.append(label);
var select = document.createElement('select');
select.id = 'reference_relation_' + countFilial;
select.name = 'reference_relation_[' + countFilial + ']'
select.classList = 'form-control';
div.append(select);
var option = document.createElement('option');
option.innerHTML = 'супруг';
option.value = 'супруг';
select.append(option);
var option = document.createElement('option');
option.innerHTML = 'супруга';
option.value = 'супруга';
select.append(option);
var option = document.createElement('option');
option.innerHTML = 'мать';
option.value = 'мать';
select.append(option);
var option = document.createElement('option');
option.innerHTML = 'отец';
option.value = 'отeц';
select.append(option);
var option = document.createElement('option');
option.innerHTML = 'сын';
option.value = 'сын';
select.append(option);
var option = document.createElement('option');
option.innerHTML = 'дочь';
option.value = 'дочь';
select.append(option);
var msg = document.createElement('div')
msg.classList = 'msg-valid valid-reference_relation';
div.append(msg);
responsibleUser.append(div);
}
submit(wrapper) {
var valid, invalid = false;
var options = {};
options.autorName = wrapper.querySelector('#reference_autorName').value;
valid = validator.checkTextRu(
wrapper.querySelector('#reference_autorName'),
wrapper.querySelector(`.valid-reference_autorName`)
);
if (valid) {
invalid = valid
}
options.phone = wrapper.querySelector('#reference_phone').value;
valid = validator.checkPhone(
wrapper.querySelector('#reference_phone'),
wrapper.querySelector(`.valid-reference_phone`)
);
if (valid) {
invalid = valid
}
options.birthDate = wrapper.querySelector('#reference_birthDate').value;
valid = validator.checkDate(
wrapper.querySelector('#reference_birthDate'),
wrapper.querySelector(`.valid-reference_birthDate`)
);
if (valid) {
invalid = valid
}
options.inn = wrapper.querySelector('#reference_inn').value;
valid = validator.checkInn(
wrapper.querySelector('#reference_inn'),
wrapper.querySelector(`.valid-reference_inn`)
);
if (valid) {
invalid = valid
}
options.filials = {};
wrapper.querySelectorAll('.responsible_filials').forEach(function(el, index) {
options.filials[index] = {};
if (index == 0) {
options.filials[index]['filial'] = el.querySelector('#reference_filial').value;
valid = validator.checkNotEmpty(
el.querySelector('#reference_filial'),
el.querySelector('.valid-reference_filial')
);
if (valid) {
invalid = valid
}
options.filials[index]['periodFirst'] = el.querySelector('#reference_periodFirst').value;
options.filials[index]['periodLast'] = el.querySelector('#reference_periodLast').value;
if (valid) {
invalid = valid
}
var reference_responsible = '#reference_responsible';
} else {
options.filials[index]['filial'] = el.querySelector('#reference_filial_'+ index).value;
options.filials[index]['periodFirst'] = document.querySelector('#reference_periodFirst_'+ index).value
options.filials[index]['periodLast'] = document.querySelector('#reference_periodLast_'+ index).value
valid = validator.checkNotEmpty(
el.querySelector('#reference_filial_' + index),
el.querySelector('.valid-reference_filial')
);
if (valid) {
invalid = valid
}
var reference_responsible = '#reference_responsible_'+ index
}
options.filials[index]['responsible'] = el.querySelector(reference_responsible).value;
if (el.querySelector(reference_responsible).value == 0) {
options.filials[index]['fio'] = el.querySelector('#reference_patientName_'+ index).value;
valid = validator.checkTextRu(
el.querySelector('#reference_patientName_'+ index),
el.querySelector(`.valid-reference_patientName`)
);
if (valid) {
invalid = valid
}
options.filials[index]['birthDate'] = el.querySelector('#reference_patientBirthDate_'+ index).value;
valid = validator.checkDate(
el.querySelector('#reference_patientBirthDate_'+ index),
el.querySelector(`.valid-reference_patientBirthDate`)
);
if (valid) {
invalid = valid
}
options.filials[index]['relation'] = el.querySelector('#reference_relation_'+ index).value;
}
})
options.sending = wrapper.querySelector('#reference_sending')?.value ?? '1';
// Разрешённые варианты: 1 и 2. Всё остальное считаем "1".
const sendingInt = parseInt(options.sending, 10);
if (sendingInt !== 1 && sendingInt !== 2) {
options.sending = '1';
}
if (options.sending == 1 || options.sending === '1') {
options.filialSending = wrapper.querySelector('#reference_filialSending').value
valid = validator.checkNotEmpty(
wrapper.querySelector('#reference_filialSending'),
wrapper.querySelector('.valid-reference_filialSending')
);
if (valid) {
invalid = valid
}
}
return {'options': options, 'invalid': invalid};
}
}
@@ -0,0 +1,438 @@
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
const loader = require("./../components/loader.js");
const validator = require("./../components/validator.js");
const helper = require("./../components/helper.js");
export default class extends Controller {
connect() {
loader.loadSDK('registration')
var registerWrap = this.element;
var licenseLink = helper.getLicenseLink(Cookies.get('region'));
helper.renderCapcha(registerWrap.querySelector('.d-capcha-start'));
registerWrap.querySelectorAll('.license').forEach(function(el) {
/* политика */
var div = document.createElement('div');
div.classList = 'form-group';
var formCheck = document.createElement('div');
formCheck.classList = 'form-check';
div.append(formCheck);
var accept = document.createElement('input');
accept.classList = "form-check-input";
accept.id = "accept";
accept.checked = false;
accept.type = "checkbox";
formCheck.append(accept);
var license = helper.getLicenseLink(Cookies.get('region'));
var label = document.createElement('label');
label.setAttribute('for' , 'accept');
label.innerHTML = `ознакомлен(а) <a class="underline" href="${licenseLink}" target="_blank">с условиями политики в отношении обработки персональных данных</a>`;
formCheck.append(label);
var validAccept = document.createElement('div');
validAccept.classList = 'msg-valid valid-accept';
div.append(validAccept);
el.append(div)
/* согласие */
var formCheck = document.createElement('div');
formCheck.classList = 'form-check';
div.append(formCheck);
var acceptPerson = document.createElement('input');
acceptPerson.classList = "form-check-input";
acceptPerson.id = "acceptPerson";
acceptPerson.checked = false;
acceptPerson.type = "checkbox";
formCheck.append(acceptPerson);
var licensePerson = helper.getLicensePersonLink();
var labelPerson = document.createElement('label');
labelPerson.setAttribute('for' , 'acceptPerson');
labelPerson.innerHTML = `даю согласие <a class="underline" href="${licensePerson}" target="_blank">на обработку персональных данных</a>`;
formCheck.append(labelPerson);
var validAcceptPerson = document.createElement('div');
validAcceptPerson.classList = 'msg-valid valid-acceptPerson';
div.append(validAcceptPerson);
el.append(div)
});
}
btnBack() {
var registerWrap = this.element;
registerWrap.querySelector('.register-start').classList.remove('d-none');
registerWrap.querySelector('.register-init').classList.add('d-none');
registerWrap.querySelector('.register-complete').classList.add('d-none');
registerWrap.querySelector('.register-complete').dataset.rToken = null;
registerWrap.querySelector('.register-complete').dataset.pwdToken = null;
registerWrap.querySelector('.alert.msg').classList.add('d-none');
registerWrap.querySelector('.alert.msg').innerHTML = 'Поля, обозначенные звездочкой (<span class="text-danger">*</span>), обязательны для заполнения';
var capchaStart = helper.renderCapcha(registerWrap.querySelector('.d-capcha-start'));
setTimeout(() => {
window.smartCaptcha.reset(capchaStart.dataset.id)
}, 100);
}
btnStart() {
var captchaId = this.element.querySelector('#smart-captcha')?.dataset?.id;
var valid, invalid = false;
var registerWrap = this.element;
valid = validator.checkPhone(
registerWrap.querySelector('#phone'),
registerWrap.querySelector(`.valid-phone`)
);
if (valid) {
invalid = valid
}
valid = validator.checkSmartCaptcha(
window.smartCaptcha.getResponse(captchaId),
registerWrap.querySelector('.valid-captcha')
);
if (valid) {
invalid = valid
}
if (validator.checkAccept(registerWrap.querySelector('#accept'),registerWrap.querySelector('.valid-accept'))) {
invalid = true;
}
if (validator.checkAccept(registerWrap.querySelector('#acceptPerson'),registerWrap.querySelector('.valid-acceptPerson'))) {
invalid = true;
}
if (invalid) {
return false;
}
window.webSDK.recoveryInit({
'login': registerWrap.querySelector('#phone').value.replace(/[^\w\s!?]/g,''),
'captcha': window.smartCaptcha.getResponse(captchaId)
}).then(function (resolve) {
registerWrap.querySelector('.register-start').classList.add('d-none');
registerWrap.querySelector('.register-complete').classList.remove('d-none');
registerWrap.querySelector('.register-complete').dataset.pwdToken = resolve.data.pwdToken;
if (resolve.data.message.indexOf('почтовый ящик') != '-1') {
registerWrap.querySelector('.emailCode').classList.remove('d-none');
registerWrap.querySelector('.alertEmailView').innerHTML = resolve.data.message;
registerWrap.querySelector('.register-complete').dataset.type = 'email';
} else {
registerWrap.querySelector('.smsCode').classList.remove('d-none');
registerWrap.querySelector('.alertSmsCode').innerHTML = resolve.data.message;
registerWrap.querySelector('.register-complete').dataset.type = 'sms';
}
}).catch(function (e) {
if (e.data?.errors?.captcha) {
registerWrap.querySelector('.valid-captcha').innerText = e.data?.errors?.captcha?.[0];
window.smartCaptcha.reset(captchaId);
}
if (e.data?.message?.includes("не найден в базе данных")) {
registerWrap.querySelector('.register-start').classList.add('d-none');
registerWrap.querySelector('.register-init').classList.remove('d-none');
helper.renderCapcha(registerWrap.querySelector('.d-capcha-init'));
}
});
}
btnReg() {
var captchaId = this.element.querySelector('#smart-captcha')?.dataset?.id;
var valid, invalid = false;
var registerWrap = this.element;
registerWrap.querySelectorAll('.alert.alert-danger.alert-dismissible').forEach(function(e) {
e.remove();
});
var options = {
firstName: registerWrap.querySelector('#firstName').value,
lastName: registerWrap.querySelector('#lastName').value,
middleName: registerWrap.querySelector('#middleName').value
};
for (var key of Object.keys(options)) {
valid = validator.checkTextRu(
registerWrap.querySelector(`#${key}`),
registerWrap.querySelector(`.valid-${key}`)
);
if (valid) {
invalid = valid
}
}
options.email = registerWrap.querySelector('#email').value;
valid = validator.checkEmail(
registerWrap.querySelector('#email'),
registerWrap.querySelector(`.valid-email`)
);
if (valid) {
invalid = valid
}
options.phone = registerWrap.querySelector('#phone').value;
valid = validator.checkPhone(
registerWrap.querySelector('#phone'),
registerWrap.querySelector(`.valid-phone`)
);
if (valid) {
invalid = valid
}
valid = validator.checkSmartCaptcha(
window.smartCaptcha.getResponse(captchaId),
registerWrap.querySelector('.valid-captcha')
);
if (valid) {
invalid = valid
}
var validGender = false;
registerWrap.querySelectorAll('.gender').forEach(function (el) {
if (el.checked) {
registerWrap.querySelector('.valid-gender').innerHTML = '';
validGender = true;
options.gender = el.value;
}
});
if (!validGender) {
registerWrap.querySelector('.valid-gender').innerHTML = '<span class="text-danger">укажите Ваш пол</span>';
invalid = true;
}
registerWrap.querySelectorAll('.msg-valid').forEach(function (el) {
el.innerHTML = '';
});
window.webSDK.registerInit({
firstName: options.firstName,
lastName: options.lastName,
middleName: options.middleName,
birthDate: registerWrap.querySelector('#birthDate').value,
email: options.email,
phone: options.phone,
gender: options.gender,
captcha: window.smartCaptcha.getResponse(captchaId)
}).then(function(resolve) {
registerWrap.querySelector('.register-init').classList.add('d-none');
registerWrap.querySelector('.register-complete').classList.remove('d-none');
registerWrap.querySelector('.register-complete').dataset.rToken = resolve.data.rToken;
if (resolve.data && resolve.data.email == 'true') {
registerWrap.querySelector('.emailCode').classList.remove('d-none');
registerWrap.querySelector('.emailView').innerHTML = options.email;
} else {
registerWrap.querySelector('.smsCode').classList.remove('d-none');
registerWrap.querySelector('.smsView').innerHTML = options.phone;
}
}).catch(function(error) {
window.smartCaptcha.reset(captchaId);
helper.sendRequest({
data: {'error': error, method: 'registerInit'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
var registerAlert = document.getElementById('register-alert');
if (! registerAlert) {
var registerAlert = document.createElement('div');
registerAlert.classList = 'alert alert-danger alert-dismissible fade';
registerAlert.setAttribute('role', 'alert');
var divMsg = document.createElement('div');
divMsg.classList = 'alert-msg';
registerAlert.append(divMsg);
var buttonClose = document.createElement('button');
buttonClose.classList = 'close';
buttonClose.dataset.dismiss ='alert';
buttonClose.setAttribute('aria-label', 'Close');
buttonClose.innerHTML = '<span aria-hidden="true">&times;</span>';
registerAlert.append(buttonClose);
registerWrap.prepend(registerAlert);
}
if (error.data.message) {
registerAlert.classList = 'alert alert-danger alert-dismissible fade show';
registerAlert.querySelector('.alert-msg').innerHTML = error.data.message;
} else {
for (var prop in error.data) {
if (error.data[prop]) {
var el = registerWrap.querySelector('.valid-' + prop)
el.innerHTML = error.data[prop];
}
}
}
});
}
btnComplite() {
var registerWrap = this.element;
if (registerWrap.querySelector('.register-complete').dataset.pwdToken !== "null") {
var type = registerWrap.querySelector('.register-complete').dataset.type;
var code = registerWrap.querySelector('#emailCode');
if (type == 'sms') {
var code = registerWrap.querySelector('#smsCode');
}
this.recoveryComplite(code, type);
} else {
this.registerComplete();
}
}
registerComplete() {
var registerWrap = this.element;
window.webSDK.registerComplete({
rToken: registerWrap.querySelector('.register-complete').dataset.rToken,
emailCode: registerWrap.querySelector('#emailCode').value,
smsCode: registerWrap.querySelector('#smsCode').value,
password: registerWrap.querySelector('#password').value
}).then(function(response) {
registerWrap.querySelector('.alert.filter').classList.add('d-none');
var successAlert = document.createElement('div');
successAlert.classList = 'alert alert-success alert-dismissible fade show';
successAlert.setAttribute('role', 'alert');
var divMsg = document.createElement('div');
divMsg.classList = 'alert-msg';
divMsg.innerHTML = '<p>Регистрация завершена.</p>'
+ '<p>' + response.data.text + '</p>';
successAlert.append(divMsg);
var buttonClose = document.createElement('button');
buttonClose.classList = 'close';
buttonClose.dataset.dismiss ='alert';
buttonClose.setAttribute('aria-label', 'Close');
buttonClose.innerHTML = '<span aria-hidden="true">&times;</span>';
successAlert.append(buttonClose);
document.getElementById('alert-system').prepend(successAlert);
registerWrap.querySelector('.register-complete').classList.add('d-none');
}).catch(function(error) {
helper.sendRequest({
data: {'error': error, method: 'registerComplete'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
for (var prop in error.data) {
if (error.data[prop]) {
var classValid = prop.split('.')[1];
if (classValid) {
var el = registerWrap.querySelector('.valid-' + prop.split('.')[1]);
} else {
var el = registerWrap.querySelector('.valid-' + prop);
}
el.innerHTML = error.data[prop];
}
}
$('html, body').animate({scrollTop:0}, '300');
});
}
recoveryComplite(inputCode, type) {
var registerWrap = this.element;
var valid, invalid = false;
valid = validator.checkNotEmpty(
inputCode,
registerWrap.querySelector('.valid-' + type + 'Code')
);
if (valid) {
invalid = valid
}
valid = validator.checkNotEmpty(
registerWrap.querySelector('#password'),
registerWrap.querySelector('.valid-password')
);
if (valid) {
invalid = valid
}
if (invalid) {
return false;
}
window.webSDK.recoveryComplete({
'pwdToken': registerWrap.querySelector('.register-complete').dataset.pwdToken,
'password': registerWrap.querySelector('#password').value,
'code': inputCode.value
}).then(function (result) {
registerWrap.querySelector('.alert.msg').classList.add('d-none');
var successAlert = document.createElement('div');
successAlert.classList = 'alert alert-success alert-dismissible fade show';
successAlert.setAttribute('role', 'alert');
var divMsg = document.createElement('div');
divMsg.classList = 'alert-msg';
divMsg.innerHTML = result.data.message;
successAlert.append(divMsg);
var buttonClose = document.createElement('button');
buttonClose.classList = 'close';
buttonClose.dataset.dismiss ='alert';
buttonClose.setAttribute('aria-label', 'Close');
buttonClose.innerHTML = '<span aria-hidden="true">&times;</span>';
successAlert.append(buttonClose);
document.getElementById('alert-system').prepend(successAlert);
registerWrap.querySelector('.register-complete').classList.add('d-none');
$.ajax({
method: "POST",
crossDomain: false,
url: "/forget",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: {
token: popupBody.dataset.csrf,
uid: forget.data.uid,
password: forgetPasswd
}
});
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'recoveryComplete'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
var msg = registerWrap.querySelector('.msg');
msg.classList.add('alert-danger');
msg.classList.remove('filter');
if (e.data && e.data.error) {
msg.innerHTML = e.data.error
}
});
}
}
@@ -0,0 +1,377 @@
import { Controller } from 'stimulus';
import Inputmask from "inputmask";
const loader = require("./../components/loader.js");
const validator = require("./../components/validator.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="resetPassword" attribute will cause
* this controller to be executed. The name "resetPassword" comes from the filename:
* resetPassword_controller.js -> "resetPassword"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
loader.loadSDK('resetPassword')
let resetPasswordSmsCode = true;
var popup = document.getElementById('popup');
if (location.hash == '#recovery' && popup.dataset.recovery == 'true') {
popup.dataset.recovery = false;
renderForm(window.webSDK);
} else {
var element = this.element
element.addEventListener('click', function() {
renderForm(window.webSDK);
});
}
function renderForm(webSDK) {
var popup = document.getElementById('popup');
popup.querySelector('.modal-title').innerHTML = "Восстановление пароля";
var popupBody = popup.querySelector('#popup-body');
popupBody.innerHTML = "";
if (typeof $(popup).modal !== 'undefined') {
$(popup).modal('show');
}
var div = document.createElement('div');
div.classList = 'form-group';
if (resetPasswordSmsCode) {
var label = document.createElement('label');
label.setAttribute('for' , 'login-forget');
label.innerHTML = 'Телефон пользователя:';
div.append(label);
var input = document.createElement('input');
input.classList = "form-control";
input.id = "login-forget";
input.type = "phone";
input.autocomplete = "phone";
div.append(input);
var im = new Inputmask({mask: "7(899)999-99-99",definitions: {'8': {validator: "[9]"}}});
im.mask(input);
} else {
var label = document.createElement('label');
label.setAttribute('for' , 'login-forget');
label.innerHTML = 'E-mail пользователя:';
div.append(label);
var input = document.createElement('input');
input.classList = "form-control";
input.id = "login-forget";
input.autocomplete = "email";
input.type = "email";
div.append(input);
}
var validUsername = document.createElement('div');
validUsername.classList = "msg-valid valid-login-forget";
div.append(validUsername);
if (resetPasswordSmsCode) {
var p = document.createElement('p');
p.innerHTML = "На Ваш номер телефона будет отправлен код для восстановления пароля."
popupBody.append(p);
} else {
var p = document.createElement('p');
p.innerHTML = "На Вашу электронную почту будет отправлен код для восстановления пароля."
popupBody.append(p);
}
var msg = document.createElement('div');
msg.classList = 'd-none msg';
msg.innerHTML = '';
popupBody.append(div);
popupBody.append(msg);
var div = document.createElement('div');
div.classList = 'form-group';
var recaptcha = document.createElement('div');
recaptcha.id = "smart-captcha";
recaptcha.dataset.controller = "smartCaptcha";
div.append(recaptcha);
var validRecaptcha = document.createElement('div');
validRecaptcha.classList = "msg-valid valid-captcha";
div.append(validRecaptcha);
popupBody.append(div);
var button = document.createElement('button');
button.classList = "btn btn-primary";
button.innerHTML = "Восстановить"
button.addEventListener('click', function () {
loader.btnLoader(button, true);
resetPassword(webSDK, popup)
});
var footer = document.createElement('div');
footer.classList = 'modal-footer px-0';
footer.append(button);
popupBody.append(footer);
};
function resetPassword(webSDK, popup) {
var popupBody = popup.querySelector('#popup-body');
var valid, invalid = false;
if (resetPasswordSmsCode) {
valid = validator.checkPhone(
document.getElementById('login-forget'),
document.querySelector(`.valid-login-forget`)
);
var login = document.getElementById('login-forget').value.replace(/[^\w\s!?]/g,'');
} else {
valid = validator.checkEmail(
document.getElementById('login-forget'),
document.querySelector(`.valid-login-forget`)
);
var login = document.getElementById('login-forget').value;
}
if (valid) {
invalid = valid
}
valid = validator.checkSmartCaptcha(
window.smartCaptcha.getResponse(),
document.querySelector('.valid-captcha')
);
if (valid) {
invalid = valid
}
if (invalid) {
loader.btnLoader(popupBody.querySelector('button'), false);
return false;
}
$.ajax({
async : false,
method: "POST",
crossDomain: true,
url: helper.getHostname() + "/forget",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: {
token: popupBody.dataset.csrf,
login: login
},
success(response) {
window.webSDK.recoveryInit({
'login': login,
'captcha': window.smartCaptcha.getResponse()
}).then(function (resolve) {
renderFormConfirm(webSDK, popup, resolve, response);
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'recoveryInit'}
}, helper.getHostname() + '/api/log', "POST");
window.smartCaptcha.reset();
if (e.data?.errors?.captcha) {
document.querySelector('.valid-captcha').innerText = e.data?.errors?.captcha?.[0];
}
loader.btnLoader(popupBody.querySelector('button'), false);
if (e.data?.message) {
var msg = popupBody.querySelector('.msg');
msg.classList = 'alert alert-danger';
msg.innerHTML = e.data.message;
}
});
}
});
};
function renderFormConfirm(webSDK, popup, resolve, forget) {
var popupBody = popup.querySelector('#popup-body');
popupBody.innerHTML = "";
var message = document.createElement('p');
message.innerHTML = resolve.data.message;
popupBody.append(message);
var div = document.createElement('div');
div.classList = 'form-group';
var label = document.createElement('label');
label.setAttribute('for' , 'forget-code');
label.innerHTML = 'Код подтверждения:';
div.append(label);
var input = document.createElement('input');
input.classList = "form-control";
input.id = "forget-code";
input.autocomplete = "one-time-code";
input.autocorrect = "off";
input.spellcheck = "off";
input.type = "text";
div.append(input);
var divValidCode = document.createElement('div');
divValidCode.classList = "msg-valid valid-code";
div.append(divValidCode);
popupBody.append(div);
var div = document.createElement('div');
div.classList = 'form-group';
var label = document.createElement('label');
label.setAttribute('for' , 'forget-passwd');
label.innerHTML = 'Новый пароль:';
div.append(label);
var input = document.createElement('input');
input.classList = "form-control";
input.id = "forget-passwd";
input.autocomplete = "new-password";
input.type = "password";
div.append(input);
var divValidPass = document.createElement('div');
divValidPass.classList = "msg-valid valid-password";
divValidPass.innerHTML = "не менее 7 символов";
div.append(divValidPass);
popupBody.append(div);
var msg = document.createElement('div');
msg.classList = 'd-none alert alert-danger';
msg.innerHTML = '';
popupBody.append(msg);
var button = document.createElement('button');
button.classList = "btn btn-primary";
button.innerHTML = " Сохранить изменения";
button.addEventListener('click', function () {
popupBody.querySelectorAll('.msg-valid').forEach(function(el) {
el.innerHTML = '';
});
var invalid = false;
var forgetCode = document.getElementById('forget-code').value;
if (forgetCode === '') {
popupBody.querySelector('.valid-code')
.innerHTML = '<span class="text-danger">поле не может быть пустым</span>';
popupBody.querySelector('#forget-code').classList.add('is-invalid');
popupBody.querySelector('#forget-code').classList.remove('is-valid');
invalid = true;
} else {
popupBody.querySelector('#forget-code').classList.add('is-valid');
popupBody.querySelector('#forget-code').classList.remove('is-invalid');
}
var forgetPasswd = document.getElementById('forget-passwd').value;
if (forgetPasswd.length < 6 || /^[\u0400-\u04FF]+$/.test(forgetPasswd)) {
invalid = true;
if (/^[\u0400-\u04FF]+$/.test(forgetPasswd)) {
popupBody.querySelector('.valid-password')
.innerHTML = '<span class="text-danger">поле не должно содержать кириллицы</span>';
popupBody.querySelector('#forget-passwd').classList.add('is-invalid');
popupBody.querySelector('#forget-passwd').classList.remove('is-valid');
} else {
popupBody.querySelector('.valid-password')
.innerHTML = '<span class="text-danger">не менее 7 символов</span>';
popupBody.querySelector('#forget-passwd').classList.add('is-invalid');
popupBody.querySelector('#forget-passwd').classList.remove('is-valid');
}
} else {
popupBody.querySelector('#forget-passwd').classList.add('is-valid');
popupBody.querySelector('#forget-passwd').classList.remove('is-invalid');
}
if (invalid) {
return false;
}
window.webSDK.recoveryComplete({
'pwdToken': resolve.data.pwdToken,
'password': forgetPasswd,
'code': document.getElementById('forget-code').value
}).then(function (result) {
if (result.data.errors) {
if (result.data.errors.code) {
popupBody.querySelector('.valid-code').innerHTML = `<span class="text-danger">
${result.data.errors.code}</span>`;
}
return false;
}
popupBody.innerHTML = '';
var msg = document.createElement('div');
msg.classList = 'alert alert-success';
msg.innerHTML = result.data.message;
popupBody.append(msg);
$.ajax({
method: "POST",
crossDomain: true,
url: helper.getHostname() + "/forget",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: {
token: popupBody.dataset.csrf,
uid: forget.data.uid,
password: forgetPasswd
},
success(response) {
if (response.data.success == true) {
var parser = document.createElement('a');
parser.href = response.data.redirect;
window.location.replace(document.location.origin + parser.pathname + parser.search);
}
}
});
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'recoveryComplete'}
}, helper.getHostname() + '/api/log', "POST");
if (e.data && e.data.error) {
msg.innerHTML = e.data.error
msg.classList.remove('d-none');
}
});
});
var footer = document.createElement('div');
footer.classList = 'modal-footer';
footer.append(button);
popupBody.append(footer);
};
}
}
@@ -0,0 +1,28 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var btn = this.element;
$(window).scroll(function() {
if ($(window).scrollTop() > 300) {
btn.classList.remove('d-none')
} else {
btn.classList.add('d-none')
}
});
btn.addEventListener('click', function(e) {
$('html, body').animate({scrollTop:0}, '300');
});
}
}
@@ -0,0 +1,57 @@
import { Controller } from 'stimulus';
export default class extends Controller {
connect() {
}
cancelForm() {
const mainSearchInput = document.querySelector('[data-controller="searchNameInput"]');
if (mainSearchInput) {
mainSearchInput.value = '';
}
const showContent = document.querySelector('.show-content');
if (showContent) {
showContent.classList.add('d-none');
showContent.innerHTML = '';
}
}
searchForm() {
// Вызываем глобальную функцию из searchNameInput контроллера
if (typeof window.performSearch === 'function') {
window.performSearch();
} else {
// Fallback: делаем редирект вручную
const input = document.querySelector('[data-controller="searchNameInput"]');
const selectSearch = document.getElementById("select-search").value;
const searchValue = input ? input.value.trim() : '';
if (searchValue) {
const encodedValue = encodeURIComponent(searchValue);
// Извлекаем alias из текущего URL, если он есть
const currentPath = window.location.pathname;
const aliasMatch = currentPath.match(/\/specialists\/([^\/]+)/);
const alias = aliasMatch ? aliasMatch[1] : null;
let url;
if (selectSearch === 'name') {
const baseUrl = alias ? `/specialists/${alias}` : '/specialists';
url = `${baseUrl}?specialist_search%5Bname%5D=${encodedValue}`;
} else if (selectSearch === 'pl') {
url = `/stoimost-uslug?price_list_form%5Bschname%5D=${encodedValue}`;
} else if (selectSearch === 'department') {
const baseUrl = alias ? `/specialists/${alias}` : '/specialists';
url = `${baseUrl}?specialist_search%5Bdepartment%5D=${encodedValue}`;
}
if (url) {
window.location.href = url;
}
}
}
console.log('searchForm вызван');
}
}
@@ -0,0 +1,164 @@
import { Controller } from 'stimulus';
const helper = require("./../components/helper.js");
export default class extends Controller {
connect() {
let showContent = this.element.parentElement.querySelector('.show-content');
const input = this.element;
const searchConfig = {
'name': {
url: '/specialists',
paramName: 'specialist_search[name]',
encodedParam: 'specialist_search%5Bname%5D'
},
'pl': {
url: '/stoimost-uslug',
paramName: 'price_list_form[schname]',
encodedParam: 'price_list_form%5Bschname%5D'
},
'dep': {
url: '/specialists',
paramName: 'specialist_search[depname]',
encodedParam: 'specialist_search%5Bdepname%5D'
}
};
const performSearch = () => {
const selectSearch = document.getElementById("select-search").value;
const searchValue = input.value.trim();
if (!searchValue) return;
const config = searchConfig[selectSearch];
if (!config) return;
// Извлекаем alias из текущего URL, если он есть
const currentPath = window.location.pathname;
const aliasMatch = currentPath.match(/\/specialists\/([^\/]+)/);
const alias = aliasMatch ? aliasMatch[1] : null;
// Создаем URL с параметром поиска, сохраняя alias если он есть
const encodedValue = encodeURIComponent(searchValue);
let baseUrl = config.url;
if (alias && (selectSearch === 'name' || selectSearch === 'dep')) {
baseUrl = `/specialists/${alias}`;
}
const searchUrl = `${baseUrl}?${config.encodedParam}=${encodedValue}`;
console.log('Редирект на:', searchUrl);
window.location.href = searchUrl;
};
// Функция для автодополнения (при вводе 3+ символов)
const handleAutocomplete = (searchValue, selectSearch) => {
const onlineMode = location.pathname.includes('/online-specialists') ? 1 : 0;
if (searchValue.length >= 3 && selectSearch !== 'pl') {
let data = {
q: searchValue,
type: selectSearch,
onlineMode: onlineMode
};
showContent.innerText = '';
showContent.classList.add('d-none');
helper.sendRequest(data, "/api/search", "POST").then(function (response) {
showContent.innerHTML = '';
const ul = document.createElement('ul');
const { data: searchData } = response;
const listItemsHTML = searchData.map(el => {
const { alias, name, speciality } = el;
const config = searchConfig[selectSearch];
let url;
// Извлекаем alias из текущего URL, если он есть
const currentPath = window.location.pathname;
const currentAliasMatch = currentPath.match(/\/specialists\/([^\/]+)/);
const currentAlias = currentAliasMatch ? currentAliasMatch[1] : null;
if (selectSearch === 'name') {
url = `/specialist/${alias}?specialist_search[onlineMode]=${onlineMode}`;
} else if (selectSearch === 'pl') {
url = `/stoimost-uslug?${config.encodedParam}=${encodeURIComponent(name)}`;
} else if (selectSearch === 'dep') {
// Сохраняем текущий alias при поиске по отделению
const depUrl = currentAlias ? `/specialists/${currentAlias}` : '/specialists';
url = `${depUrl}?${config.encodedParam}=${encodeURIComponent(name)}`;
}
return `
<li>
<a href="${url}" class="search-result-link">
<span class="result-name">${name}</span>
${speciality ? `<span class="result-speciality">, ${speciality}</span>` : ''}
</a>
</li>
`;
}).join('');
ul.innerHTML = listItemsHTML;
showContent.append(ul);
showContent.classList.remove('d-none');
});
} else {
showContent.classList.add('d-none');
}
};
// Обработчик ввода в поле поиска
input.oninput = function(e) {
const selectSearch = document.getElementById("select-search").value;
const searchValue = e.target.value;
handleAutocomplete(searchValue, selectSearch);
};
// Обработчик нажатия Enter
input.addEventListener('keyup', function (evn) {
if (evn.keyCode == 13) { // Enter
evn.preventDefault();
performSearch();
}
});
// Делаем функцию доступной глобально для другого контроллера
window.performSearch = performSearch;
window.handleAutocomplete = handleAutocomplete;
// Инициализация значения из текущего параметра URL
this.initializeFromUrl();
}
// Метод для инициализации значения поля из параметров URL
initializeFromUrl() {
const input = this.element;
const urlParams = new URLSearchParams(window.location.search);
const selectSearch = document.getElementById("select-search").value;
const searchConfig = {
'name': ['specialist_search[name]', 'specialist_search%5Bname%5D'],
'pl': ['price_list_form[schname]', 'price_list_form%5Bschname%5D'],
'department': ['specialist_search[department]', 'specialist_search%5Bdepartment%5D']
};
const config = searchConfig[selectSearch];
if (config) {
// Пробуем получить значение из разных вариантов параметра
let searchValue = urlParams.get(config[0]) ||
urlParams.get(config[1]) ||
urlParams.get(decodeURIComponent(config[1]));
if (searchValue) {
input.value = searchValue;
// Если есть значение, показываем автодополнение
setTimeout(() => {
window.handleAutocomplete && window.handleAutocomplete(searchValue, selectSearch);
}, 100);
}
}
}
}
@@ -0,0 +1,73 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="searchOrderByInput" attribute will cause
* this controller to be executed. The name "searchOrderByInput" comes from the filename:
* searchOrderByInput_controller.js -> "searchOrderByInput"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var val = document.getElementById("specialist_search_order_by").value;
var items = this.element.querySelectorAll('span');
if (val) {
check(val, false);
}
items.forEach(function(el) {
el.addEventListener('click', function(evn) {
check(evn.target.id, true);
});
})
function check(index, redirect) {
console.log(index)
var array = index.split('.');
var id = array[0];
var sort = array[1];
items.forEach(function(item) {
var iconASC = item.querySelector('.fa-sort-amount-asc');
var iconDESC = item.querySelector('.fa-sort-amount-desc');
item.classList.remove('sort-line__item--active');
if (id == item.id) {
item.classList.add('sort-line__item--active');
if (sort == 'desc') {
item.classList.remove('asc');
}
if (item.classList.contains('asc')) {
iconASC.classList.remove('d-none');
iconDESC.classList.add('d-none');
item.classList.remove('asc');
document.getElementById("specialist_search_order_by").value = item.id + '.asc';
if (redirect) {
document.querySelector('.submit-filter').click();
}
} else {
iconDESC.classList.remove('d-none');
iconASC.classList.add('d-none');
item.classList.add('asc');
document.getElementById("specialist_search_order_by").value = item.id + '.desc';
if (redirect) {
document.querySelector('.submit-filter').click();
}
}
} else {
iconDESC.classList.add('d-none');
iconASC.classList.add('d-none');
item.classList.add('asc');
}
});
};
}
}
@@ -0,0 +1,377 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
export default class extends Controller {
connect() {
loader.loadSDK('securityCard').then(function(webSDK) {
webSDK.on('init', function() {
if (this.data.user.authenticated) {
runWebSDK(webSDK);
} else {
window.location.pathname = '/logout'
}
});
})
var securityCard = this.element;
var date = new Date();
var lastDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
let runWebSDK = function (webSDK) {
if (document.location.search == '?tab=allTest') {
securityCard.querySelector('.load').innerHTML = 'Загрузка данных';
securityTabs.querySelectorAll('a').forEach(function (el) {
if ('allTest' == el.dataset.allowTarget) {
el.classList.add('tab-item--active');
} else {
el.classList.remove('tab-item--active');
}
});
// allTest
treatPlaceList(webSDK, lastDate, securityCard, 'all');
} else {
treatPlaceList(webSDK, lastDate, securityCard, 'all');
}
}.bind(this)
var securityTabs = document.getElementById('security-tabs');
if (securityTabs) {
var tabsDecktop = securityTabs.querySelectorAll('a');
if (tabsDecktop.length > 0) {
tabsDecktop.forEach(function (el) {
el.addEventListener('click', function (evn) {
evn.target.classList = 'tab-item tab-item--active';
securityCard.querySelector('.section-wrap').innerHTML = '';
securityCard.querySelector('.load').innerHTML = 'Загрузка данных';
securityTabs.querySelectorAll('a').forEach(function (a) {
if (evn.target.dataset.allowTarget != a.dataset.allowTarget) {
a.classList.remove('tab-item--active');
}
});
if (evn.target.dataset.allowTarget == 'allTest') {
document.title = 'Результаты анализов';
document.getElementById('page-title').innerHTML = 'Результаты анализов';
} else {
document.title = 'Медицинская карта';
document.getElementById('page-title').innerHTML = 'Медицинская карта';
}
treatPlaceList(window.webSDK, lastDate, securityCard, evn.target.dataset.allowTarget);
});
});
} else {
securityTabs.addEventListener('change', function(evn) {
securityCard.querySelector('.section-wrap').innerHTML = '';
treatPlaceList(window.webSDK, lastDate, securityCard, evn.target.value);
});
}
}
function treatPlaceList(webSDK, lastDate, securityCard, allowTarget) {
var sectionWrap = securityCard.querySelector('.section-wrap');
var load = securityCard.querySelector('.load');
if (allowTarget == 'referrals') {
webSDK.loadReferralList({
start: 0,
length: 50
}).then(function (refferals) {
if (refferals.length == 0) {
securityCard.querySelector('.load').innerHTML = 'Записей не найдено';
}
refferals.forEach(function (item) {
var row = document.createElement('div');
row.classList = 'row';
var col6 = document.createElement('div');
col6.classList = 'col-md-6';
var dateTag = document.createElement('p');
dateTag.innerHTML = '<p><b><span class="month"></span>, <span class="date"></span></b></p><p class="refname"></p><p class="fromfname"></p>';
col6.append(dateTag);
row.append(col6);
var col6 = document.createElement('div');
col6.classList = 'col-md-6';
col6.innerHTML = '<p class="refcomment"></p><p>Специалист: <br><span class="fromdname"></span></p><p class="refstatusname"></p>';
row.append(col6);
var refferalsItem = document.createElement('div');
refferalsItem.classList = 'block-item p-2 mt-1';
refferalsItem.append(row);
refferalsItem.classList.remove('d-none');
refferalsItem.querySelector('.refname').innerHTML = item.refname;
refferalsItem.querySelector('.refcomment').innerHTML = item.refcomment;
refferalsItem.querySelector('.fromfname').innerHTML = item.fromfname;
refferalsItem.querySelector('.fromdname').innerHTML = item.fromdname;
refferalsItem.querySelector('.refstatusname').innerHTML = item.refstatusname;
var date = window.newDate(item.refdate);
refferalsItem.querySelector('.month').innerHTML = getWeekDay(date);
refferalsItem.querySelector('.date').innerHTML = window.dateFormat(date, 'd-m-Y')
sectionWrap.append(refferalsItem);
});
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'loadReferralList'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
});
} else {
webSDK.loadTreatPlaceList({
st: 20150101,
en: window.dateFormat(lastDate),
start: 0,
length: 100
}).then(function (resolve) {
console.log("loadTreatPlaceList")
if (resolve.data.length > 0) {
var count = 0;
load.classList.remove('d-none');
for (var i = 0; i < resolve.data.length; i++) {
if (allowTarget == 'allTest') {
if (analysis(resolve.data[i].protocolName)) {
count++;
sectionWrap.classList.remove('d-none');
addItem(resolve.data[i], sectionWrap, webSDK);
}
} else if (allowTarget == 'all') {
count = resolve.data.length
sectionWrap.classList.remove('d-none');
addItem(resolve.data[i], sectionWrap, webSDK);
}
}
load.classList.add('d-none');
if (count == 0) {
load.classList.remove('d-none');
}
} else {
securityCard.querySelector('.load').innerHTML = 'Записей не найдено';
load.classList.remove('d-none');
}
}).catch(function (e) {
helper.sendRequest({
data: {'error': e, method: 'loadTreatPlaceList'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
});
}
}
function analysis(protocolName) {
const regex = /анализ/gm;
let m;
var result = false;
while ((m = regex.exec(protocolName)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
m.some(function(match, groupIndex) {
result = true;
});
}
return result;
}
function addItem(item, wrap, webSDK) {
wrap.insertAdjacentHTML('beforeend', `
<div class="col-md-12 mt-3 px-0">
<div class="block-title">${getWeekDay(window.newDate(item.date))} ${window.dateFormat(window.newDate(item.date), 'd-m-Y')}</div>
<div class="block-content py-3 col-md-12">
<div class="row">
<div class="col-md-10 col-sm-12">
<b>${item.protocolName}</b>
<p class="pt-2">Специалист: <br> ${item.doctorName}</p>
</div>
<div class="col-md-2 col-sm-12">
<button type="button"
class="card-item__btn button ${helper.isMobile() ? 'w-100' : ''}"
data-protocol-id="${item.protocolId}"
data-treatcode="${item.treatcode}">
${helper.isMobile() ? 'Скачать' : 'Просмотр'}
</button>
</div>
<div class="col-12">
${item.attachments.length > 0 ? `
<div class="card-item__doc mt-2">
<p>Список изображений (файлов):</p>
${item.attachments.map(attachment => `
<div class="row">
<div class="col-md-8 d-none d-md-block">
${attachment.attachmentName}
</div>
<div class="col-md-2 col-sm-6">
<button type="button" class="button ${helper.isMobile() ? 'w-100' : ''}"
data-attachment-type="download"
data-attachment-id="${attachment.attachmentId}"
data-treatcode="${item.treatcode}"
data-protocol-id="${item.protocolId}">
Скачать
</button></br>
</div>
<div class="col-md-2 d-none d-md-block">
<button type="button" class="button ${helper.isMobile() ? 'w-100' : ''}"
data-attachment-type="raw"
data-attachment-id="${attachment.attachmentId}"
data-treatcode="${item.treatcode}"
data-protocol-id="${item.protocolId}">
Просмотр
</button></br>
</div>
</div>
`).join('')}
</div>
` : ''}
</div>
</div>
</div>
</div>
`);
const cardItem = wrap.lastElementChild;
if (item.attachments.length > 0) {
const attachmentLinks = cardItem.querySelectorAll('button[data-attachment-id]');
attachmentLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const popup = document.getElementById('popup');
const modalBody = popup.querySelector('.modal-body');
modalBody.dataset.attachmentType = this.dataset.attachmentType;
modalBody.innerHTML = `
<div class="text-center py-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Загрузка...</span>
</div>
<p class="mt-2">Загрузка файла...</p>
</div>
`;
webSDK.downloadTreatPlaceAttachment({
protocolId: this.dataset.protocolId,
treatcode: this.dataset.treatcode,
attachmentId: this.dataset.attachmentId,
download: this.dataset.attachmentType
}).then(function(blob) {
if (modalBody.dataset.attachmentType === 'download') {
return false;
}
modalBody.innerHTML = '';
const objectURL = URL.createObjectURL(blob.result);
if (blob.result.type === 'application/pdf' ||
blob.result.type === 'application/x-pdf') {
// Для PDF создаем iframe
const iframe = document.createElement('iframe');
iframe.src = objectURL;
iframe.style.width = "100%";
iframe.style.height = "500px";
iframe.style.border = "none";
iframe.title = "PDF документ";
iframe.type = 'application/pdf';
popup.querySelector('.modal-body').appendChild(iframe);
} else if (blob.result.type.startsWith('image/')) {
// Для изображений создаем img
const image = document.createElement('img');
image.src = objectURL;
image.style.width = "100%";
image.style.maxHeight = "80vh";
image.style.objectFit = "contain";
image.alt = "Изображение";
popup.querySelector('.modal-body').appendChild(image);
} else {
// Для других типов файлов - кнопка скачивания
const downloadLink = document.createElement('a');
downloadLink.href = objectURL;
downloadLink.download = 'document';
downloadLink.className = 'btn btn-primary';
downloadLink.textContent = 'Скачать файл';
downloadLink.style.margin = '20px auto';
downloadLink.style.display = 'block';
downloadLink.style.width = '200px';
popup.querySelector('.modal-body').appendChild(downloadLink);
// Также показываем информацию о типе файла
const info = document.createElement('p');
info.textContent = `Тип файла: ${blob.result.type}`;
info.style.textAlign = 'center';
popup.querySelector('.modal-body').appendChild(info);
}
$(popup).modal('show');
// Очистка памяти при закрытии модального окна
$(popup).on('hidden.bs.modal', function() {
URL.revokeObjectURL(objectURL);
$(popup).off('hidden.bs.modal');
});
}).catch(function (e) {
console.error('Error downloading file:', e);
helper.sendRequest({
data: {'error': e, method: 'TreatPlaceAttachment'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
popup.querySelector('.modal-body').innerHTML = `
<div class="alert alert-danger">
<h5>Ошибка загрузки файла</h5>
<p>${e.message || 'Неизвестная ошибка'}</p>
<button class="btn btn-secondary" onclick="$(popup).modal('hide')">Закрыть</button>
</div>
`;
$(popup).modal('show');
});
});
});
}
const btnInfo = cardItem.querySelector('.card-item__btn');
btnInfo.addEventListener('click', function () {
const popup = document.getElementById('popup');
popup.querySelector('.modal-body').innerHTML = '';
webSDK.loadTreatPlaceView({
protocolId: this.dataset.protocolId,
treatcode: this.dataset.treatcode,
container: popup.querySelector('.modal-body')
});
if (!helper.isMobile()) {
$(popup).modal('show');
}
});
}
}
}
@@ -0,0 +1,26 @@
import { Controller } from 'stimulus'
import selectpicker from 'bootstrap-select'
import 'bootstrap-select/dist/css/bootstrap-select.css'
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="selectpicker" attribute will cause
* this controller to be executed. The name "selectpicker" comes from the filename:
* selectpicker_controller.js -> "selectpicker"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var placeholder = 'ничего не выбрано'
if (this.element.dataset.placeholder) {
placeholder = this.element.dataset.placeholder;
}
jQuery(this.element).selectpicker({
noneSelectedText : placeholder
});
}
}
@@ -0,0 +1,32 @@
import { Controller } from 'stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.addEventListener('click', function () {
const popupWrap = document.getElementById('popup');
popupWrap.querySelector('.modal-title').textContent = 'Техническая поддержка';
popupWrap.querySelector('.modal-dialog').classList.remove('modal-lg');
const popupBody = popupWrap.querySelector('#popup-body');
popupBody.innerHTML = '';
const iframe = document.createElement('iframe');
iframe.src = 'https://sovaclinic.okdesk.ru/webform/issues?account_name=sovaclinic';
iframe.frameBorder = 0;
iframe.height = "450";
iframe.width = "100%";
popupBody.append(iframe);
$(popupWrap).modal('show');
})
}
}
+74
View File
@@ -0,0 +1,74 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="setting" attribute will cause
* this controller to be executed. The name "setting" comes from the filename:
* setting_controller.js -> "setting"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
loader.loadSDK('setting');
}
submit() {
var plainPassword = document.getElementById('setting_plainPassword');
var settingToken = document.getElementById('setting__token');
window.webSDK.clientModify({
'password': plainPassword.value
}).then(function(resolve) {
if (resolve.success) {
$.ajax({
method: "POST",
crossDomain: false,
url: "/setting",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: {
'setting': {
'_token': settingToken.value,
'plainPassword': plainPassword.value
}
},
success(response) {
if (response.data.success == true) {
var parser = document.createElement('a');
parser.href = response.data.redirect;
window.location.replace(document.location.origin + parser.pathname + parser.search);
}
}
});
}
}).catch(function (error) {
helper.sendRequest({
data: {'error': error, method: 'clientModify'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
console.log(error)
var msg = document.getElementById('msg');
var div = document.createElement('div');
div.classList = 'alert alert-danger';
msg.innerHTML = '';
msg.append(div);
if (error.data.password) {
var p = document.createElement('p');
p.innerHTML = error.data.password[0];
div.append(p);
} else if (error.data['password.password'][0]) {
var p = document.createElement('p');
p.innerHTML = error.data['password.password'][0];
div.append(p);
}
});
}
}
+513
View File
@@ -0,0 +1,513 @@
import { Controller } from 'stimulus';
import { sendReserve } from "./../components/record";
import Inputmask from "inputmask";
const validator = require('./../components/validator.js');
const helper = require('./../components/helper.js');
const loader = require("./../components/loader.js");
const Cookies = require('js-cookie');
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="signin" attribute will cause
* this controller to be executed. The name "signin" comes from the filename:
* signin_controller.js -> "signin"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
loader.loadSDK('signin').then(function (webSDK) {
webSDK.on('init', function() {
if (location.hash == '#recovery') {
const popup = document.getElementById('popup');
popup.dataset.controller = 'resetPassword';
popup.dataset.recovery = true;
$(popup).modal('show');
}
})
})
}
esia() {
const element = this.element
element.addEventListener('click', function() {
const currentUrl = window.location.href;
const redirectUrl = helper.addUrlParam(currentUrl, 'esia', 'true');
window.webSDK.loadLoginView({
authType: "esia",
redirectUrl: redirectUrl,
newWindow: false
});
});
}
login() {
function renderAuth(msg = false) {
var popup = document.getElementById('popup');
// Сохраняем данные записи перед очисткой popup (если они есть)
if (popup && popup.dataset.reserve === 'true') {
const reserveData = {
specialistid: popup.dataset.specialistid,
filialid: popup.dataset.filialid,
depnum: popup.dataset.depnum,
schedident: popup.dataset.schedident,
workDate: popup.dataset.workDate,
time: popup.dataset.time,
onlinemode: popup.dataset.onlinemode,
comment: popup.dataset.comment,
docname: popup.dataset.docname,
address: popup.dataset.address,
company: popup.dataset.company,
rnum: popup.dataset.rnum
};
// Сохраняем только если есть хотя бы одно поле
if (reserveData.specialistid || sessionStorage.getItem('reserveData')) {
sessionStorage.setItem('reserveData', JSON.stringify(reserveData));
sessionStorage.setItem('reserveFlag', 'true');
}
}
var popupBody = popup.querySelector('.modal-title');
popupBody.innerText = "Авторизация";
popupBody = popup.querySelector('#popup-body');
popupBody.innerHTML = '';
popupBody.dataset.controller = 'signin';
var validMessage = document.createElement('div');
validMessage.classList = "msg-valid valid-message alert alert-danger d-none";
if (msg) {
validMessage.innerHTML = msg;
validMessage.classList.remove('d-none');
}
popupBody.append(validMessage);
var username = document.createElement('input');
username.type = "text";
username.classList = "form-control border-radius";
username.required = "true";
username.autofocus = "off";
username.autocomplete = "off";
username.id = "username";
var groupPrepend = document.createElement('div');
groupPrepend.classList = 'input-group-prepend';
var select = document.createElement('select');
select.classList = "input-group-text";
var optionEmail = document.createElement('option');
optionEmail.value = "email";
optionEmail.innerText = "Email";
select.append(optionEmail);
var optionPhone = document.createElement('option');
optionPhone.value = "phone";
optionPhone.innerText = "Телефон";
select.append(optionPhone);
groupPrepend.append(select);
select.addEventListener('change', function() {
const selectedValue = this.value;
if (selectedValue === 'email') {
username?.inputmask.remove();
username.type = "email";
} else if (selectedValue === 'phone') {
username.type = "text";
Inputmask({ mask: '79999999999' }).mask(username);
}
});
var inputGroup = document.createElement('div');
inputGroup.classList = "input-group";
inputGroup.append(groupPrepend);
inputGroup.append(username);
var formGroup = document.createElement('div');
formGroup.classList = "form-group";
var validUsername = document.createElement('div');
validUsername.classList = "msg-valid valid-username";
formGroup.append(inputGroup);
formGroup.append(validUsername);
popupBody.append(formGroup);
var password = document.createElement('input');
password.placeholder = "Пароль";
password.type = "password";
password.classList = "form-control border-radius";
password.required = "true";
password.id = "password";
password.addEventListener('keydown', function(evn) {
if (evn.code == 'Enter') {
loader.btnLoader(btnSubmit, true);
submit(window.webSDK, username, password, popupBody);
}
});
var formGroup = document.createElement('div');
formGroup.classList = "form-group";
formGroup.dataset.controller = 'passwordShow';
formGroup.append(password);
var validPassword = document.createElement('div');
validPassword.classList = "msg-valid valid-password";
formGroup.append(validPassword);
popupBody.append(formGroup);
/* политика */
var div = document.createElement('div');
div.classList = 'form-group';
var formCheck = document.createElement('div');
formCheck.classList = 'form-check';
div.append(formCheck);
var accept = document.createElement('input');
accept.classList = "form-check-input";
accept.id = "accept";
accept.checked = false;
accept.type = "checkbox";
formCheck.append(accept);
var license = helper.getLicenseLink(Cookies.get('region'));
var label = document.createElement('label');
label.setAttribute('for' , 'accept');
label.innerHTML = `ознакомлен(а) <a class="underline" href="${license}" target="_blank">с условиями политики в отношении обработки персональных данных</a>`;
formCheck.append(label);
var validAccept = document.createElement('div');
validAccept.classList = 'msg-valid valid-accept';
div.append(validAccept);
popupBody.append(div)
/* согласие */
var formCheck = document.createElement('div');
formCheck.classList = 'form-check';
div.append(formCheck);
var acceptPerson = document.createElement('input');
acceptPerson.classList = "form-check-input";
acceptPerson.id = "acceptPerson";
acceptPerson.checked = false;
acceptPerson.type = "checkbox";
formCheck.append(acceptPerson);
var licensePerson = helper.getLicensePersonLink();
var labelPerson = document.createElement('label');
labelPerson.setAttribute('for' , 'acceptPerson');
labelPerson.innerHTML = `даю согласие <a class="underline" href="${licensePerson}" target="_blank">на обработку персональных данных</a>`;
formCheck.append(labelPerson);
var validAcceptPerson = document.createElement('div');
validAcceptPerson.classList = 'msg-valid valid-acceptPerson';
div.append(validAcceptPerson);
popupBody.append(div)
var btnSubmit = document.createElement('button');
btnSubmit.type = "button";
btnSubmit.innerHTML = "Войти";
btnSubmit.classList = "btn btn-outline-secondary submit";
btnSubmit.addEventListener('click', function() {
let invalid = false;
if (validator.checkAccept(accept, validAccept)) {
invalid = true;
}
if (validator.checkAccept(acceptPerson, validAcceptPerson)) {
invalid = true;
}
if (invalid == false) {
loader.btnLoader(btnSubmit, true);
submit(window.webSDK, username, password, popupBody);
}
});
var helpLink = document.createElement('a');
helpLink.classList = 'btn my-0';
helpLink.dataset.controller = 'serviceDesk';
helpLink.style = 'font-size: 21px;';
helpLink.innerHTML = `<i class="fa fa-info-circle" aria-hidden="true"></i>`;
var guLink = document.createElement('a');
guLink.classList = 'btn my-0';
guLink.dataset.action = 'signin#esia';
guLink.innerHTML = `<img src="${helper.getHostname()}/images/eisa.jpg" width="30" alt="EISA">`;
var forgetLink = document.createElement('button');
forgetLink.classList = 'btn';
forgetLink.dataset.controller = 'resetPassword';
forgetLink.innerHTML = 'Забыли пароль?';
var footer = document.createElement('div');
footer.classList = 'modal-footer px-0';
footer.append(helpLink);
footer.append(guLink);
footer.append(forgetLink);
footer.append(btnSubmit);
popupBody.append(footer);
}
renderAuth();
var popup = document.getElementById('popup');
if (popup && typeof $(popup).modal !== 'undefined') {
$(popup).modal('show');
}
function submit(webSDK, username, password, popupBody) {
popupBody.querySelectorAll('.msg-valid').forEach(function (e) {
e.classList.add('d-none');
e.innerHTML = '';
});
webSDK.loginClient({
login: username.value,
pass: password.value
}).then(function(user) {
if (user.result && user.result.checkdata && typeof user.result.checkdata.pToken !== 'undefined') {
changeTempPassword(user.result);
return false;
}
let data = {
user: user,
uid: user.id
}
if (window.location.pathname !== '/login') {
data = {
user: user,
uid: user.id,
redirectFrom: window.location.href
}
}
var popup = document.getElementById('popup');
if (popup.dataset.reserve === "true") {
data.redirectFrom = helper.getHostname() + '/case-history#doctor-success';
}
$.ajax({
method: "POST",
crossDomain: true,
url: "/api/authenticated",
contentType: "application/x-www-form-urlencoded",
dataType: "json",
data: data,
success(response) {
if (response.data.success == true) {
// Восстанавливаем данные записи из sessionStorage если они были сохранены
const reserveFlag = popup.dataset.reserve === "true" || sessionStorage.getItem('reserveFlag') === 'true';
if (reserveFlag) {
// Восстанавливаем данные из sessionStorage
const reserveDataStr = sessionStorage.getItem('reserveData');
if (reserveDataStr) {
try {
const reserveData = JSON.parse(reserveDataStr);
Object.keys(reserveData).forEach(key => {
if (reserveData[key] !== undefined && reserveData[key] !== null) {
popup.dataset[key] = reserveData[key];
}
});
console.log('Данные записи восстановлены из sessionStorage:', reserveData);
} catch (e) {
console.error('Ошибка при восстановлении данных из sessionStorage:', e);
}
}
// Устанавливаем флаг reserve если его нет
popup.dataset.reserve = 'true';
// Проверяем наличие всех необходимых полей перед вызовом sendReserve
const requiredFields = ['specialistid', 'filialid', 'depnum', 'schedident', 'workDate', 'time'];
const missingFields = requiredFields.filter(field => !popup.dataset[field]);
if (missingFields.length > 0) {
console.error('Отсутствуют необходимые поля для записи:', missingFields);
alert('Ошибка: не удалось восстановить данные для записи. Пожалуйста, попробуйте записаться снова.');
// Очищаем sessionStorage
sessionStorage.removeItem('reserveData');
sessionStorage.removeItem('reserveFlag');
// Делаем обычный редирект
var parser = document.createElement('a');
parser.href = response.data.redirect;
window.location.replace(helper.getHostname() + parser.pathname + parser.search);
return;
}
// Очищаем sessionStorage после успешного восстановления
sessionStorage.removeItem('reserveData');
sessionStorage.removeItem('reserveFlag');
}
if (window.bitrix === true) {
if (reserveFlag) {
// Для bitrix тоже нужно вызвать sendReserve для создания записи
// Сообщение покажет сам sendReserve после успешной записи
sendReserve(popup);
} else {
// Если не было флага reserve, показываем обычное сообщение
popup.querySelector('.modal-title').innerHTML = 'Запись на прием';
var message = '<p>Спасибо, Вы успешно записались на прием. </br>';
message += popup.dataset.comment + ', ';
message += popup.dataset.workDate + ' ' + popup.dataset.time + '</br></p>';
message += '<p>Вы всегда можете отменить или перенести запись в личном кабинете по ссылке: ';
message += '<a href="https://cabinet.sovamed.ru" >https://cabinet.sovamed.ru</a></p>';
popup.querySelector('#popup-body').innerHTML = message;
}
} else {
if (reserveFlag) {
// Если нужно создать запись, вызываем sendReserve, который сам сделает редирект
sendReserve(popup);
} else {
// Иначе делаем обычный редирект
var parser = document.createElement('a');
parser.href = response.data.redirect;
window.location.replace(helper.getHostname() + parser.pathname + parser.search);
}
}
}
}
});
}).catch(function(error) {
helper.sendRequest({
data: {'error': error, login: username.value, method: 'loginClient'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
var btnSubmit = popupBody.querySelector('button.submit');
loader.btnLoader(btnSubmit, false);
for (var prop in error.data) {
if (error.data[prop]) {
var el = popupBody.querySelector('.valid-' + prop)
el.classList.remove('d-none');
el.innerHTML = error.data[prop];
}
}
});
};
function changeTempPassword(response) {
var popup = document.getElementById('popup');
var popupBody = popup.querySelector('.modal-title')
.innerText = "Смена временного пароля";
var popupBody = popup.querySelector('#popup-body');
popupBody.innerHTML = '';
var validMessage = document.createElement('div');
validMessage.classList = "msg-valid valid-message alert alert-warning";
validMessage.innerHTML = response.checkdata.msg;
popupBody.append(validMessage);
var password = document.createElement('input');
password.placeholder = "Новый пароль";
password.type = "password";
password.classList = "form-control border-radius";
password.required = "true";
password.id = "password";
var formGroup = document.createElement('div');
formGroup.classList = "form-group";
formGroup.append(password);
var validPassword = document.createElement('div');
validPassword.classList = "msg-valid valid-password";
formGroup.append(validPassword);
popupBody.append(formGroup);
var confirm = document.createElement('input');
confirm.placeholder = "Подтверждение";
confirm.type = "password";
confirm.classList = "form-control border-radius";
confirm.required = "true";
confirm.id = "confirm";
var formGroup = document.createElement('div');
formGroup.classList = "form-group";
formGroup.append(confirm);
var validConfirm = document.createElement('div');
validConfirm.classList = "msg-valid valid-confirm";
formGroup.append(validConfirm);
popupBody.append(formGroup);
var btnSubmit = document.createElement('button');
btnSubmit.type = "button";
btnSubmit.innerHTML = "Сменить пароль";
btnSubmit.classList = "btn btn-outline-secondary submit";
btnSubmit.addEventListener('click', function() {
if (/^[\u0400-\u04FF]+$/.test(password.value)) {
popupBody.querySelector('.valid-password')
.innerHTML = '<span class="text-danger">Поле не должно содержать кириллицы</span>';
return false;
} else {
popupBody.querySelector('.valid-password').innerHTML = '';
}
if (password.value !== confirm.value) {
popupBody.querySelector('.valid-confirm')
.innerHTML = '<span class="text-danger">Подтверждение не совпадает с паролем</span>';
return false;
} else {
popupBody.querySelector('.valid-confirm').innerHTML = '';
}
loader.btnLoader(btnSubmit, true);
window.webSDK.changeTempPassword({
pwdToken: response.checkdata.pToken,
password: password.value,
confirm: confirm.value
}).then(function(resolve) {
renderAuth(resolve.data.success);
}).catch(function(e) {
helper.sendRequest({
data: {'error': e, method: 'changeTempPassword'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
var btnSubmit = popupBody.querySelector('button.submit');
loader.btnLoader(btnSubmit, false);
for (var prop in e.data.errors) {
if (e.data.errors[prop]) {
var el = popupBody.querySelector('.valid-' + prop.split('.')[1])
el.classList.remove('d-none');
el.innerHTML = e.data.errors[prop][0];
}
}
})
});
var footer = document.createElement('div');
footer.classList = 'modal-footer';
footer.append(btnSubmit);
popupBody.append(footer);
}
}
}
@@ -0,0 +1,64 @@
import { Controller } from 'stimulus';
import 'owl.carousel2/dist/assets/owl.carousel.css';
import 'owl.carousel2/dist/assets/owl.theme.default.css';
import 'owl.carousel2';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
static targets = ["showid"];
connect() {
var slideshow = this.element;
$(slideshow).owlCarousel({
nav: true,
margin: 15,
autoplay: false,
autoplayTimeout: 7000,
autoplayHoverPause: true,
navText : ['<span class="swiper-button-prev">&nbsp;</span>','<span class="swiper-button-next">&nbsp;</span>'],
responsive: {
0: {
items: 1,
dots: false,
},
600: {
items: 2,
dots: false,
},
1000: {
items: 2,
dots: false,
}
}
});
slideshow.classList.remove('hide');
slideshow.querySelectorAll('.show-msg').forEach(function (el) {
el.addEventListener('click', function (evn) {
var showId = evn.target.dataset.showId;
var crop = slideshow.querySelector(`#crop-${showId}`);
var full = slideshow.querySelector(`#full-${showId}`);
if (full.classList.contains('d-none')) {
crop.classList.add('d-none');
full.classList.remove('d-none');
evn.target.innerHTML = 'cвернуть';
} else {
crop.classList.remove('d-none');
full.classList.add('d-none');
evn.target.innerHTML = 'весь отзыв';
}
});
});
}
}
@@ -0,0 +1,69 @@
import { Controller } from 'stimulus';
const helper = require("./../components/helper.js");
const loader = require("./../components/loader.js");
export default class extends Controller {
connect() {
const btn = this.element;
if (window.smartCaptcha) {
const container = document.getElementById('smart-captcha');
const widgetId = window.smartCaptcha.render(container, {
sitekey: 'ysc1_EaQp6z8UPPQAIfHLm8mlrfFGee54huOrUEgGWgRpcf5c2225',
hl: 'ru',
});
container.dataset.id = widgetId;
window.smartCaptcha.subscribe( widgetId, 'success', function () {
btn.disabled = false;
});
}
if (btn && btn?.type === 'submit') {
btn.disabled = true;
btn.addEventListener('click', function(evn) {
evn.preventDefault();
loader.btnLoader(btn, true);
if ($('#' + btn.dataset.formId)[0].checkValidity()) {
helper.sendRequest({'smart-token' : window.smartCaptcha.getResponse()}, '/api/smart-captcha').then(function (response) {
if (response.status != 'ok') {
loader.btnLoader(btn, false);
window.smartCaptcha.reset();
} else {
$('#' + btn.dataset.formId).submit();
}
});
} else {
window.smartCaptcha.reset();
$('#' + btn.dataset.formId)[0].reportValidity();
loader.btnLoader(btn, false);
}
});
}
}
addYandexMetrica() {
const script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = `
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
`;
document.head.appendChild(script);
}
setYm() {
const ymNum = document.getElementsByName('ymNum')[0]?.value;
const ymId = document.getElementsByName('ymId')[0]?.value;
if (ymNum && ymId) {
this.addYandexMetrica();
window.ym(ymNum,'reachGoal', ymId);
}
}
}
@@ -0,0 +1,275 @@
import { Controller } from 'stimulus';
import Cookies from 'js-cookie';
import { renderFormAnonym, sendReserve, renderFormBitrix } from "./../components/record";
const helper = require("./../components/helper.js");
const record = require("./../components/record.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="specialistView" attribute will cause
* this controller to be executed. The name "specialistView" comes from the filename:
* detailDoctor_controller.js -> "specialistView"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
let currentDate = this.element.dataset.st;
let bodyModal = document.getElementById('detail-specialist');
var btnNext = bodyModal.querySelector('.btn-next');
var btnPrev = bodyModal.querySelector('.btn-prev');
btnNext.addEventListener('click', function(evn) {
if (this.dataset.currentdate) {
var date = this.dataset.currentdate;
} else {
var date = currentDate;
}
btnPrev.dataset.currentdate = new Date(date);
btnPrev.classList.remove('d-none');
bodyModal.querySelector('.popup-btns').classList.remove('justify-content-end');
bodyModal.querySelector('.popup-btns').classList.add('justify-content-between');
date = getNextWeek(date);
this.dataset.currentdate = new Date(date);
var departmentId = bodyModal.dataset.departmentid;
var specialistId = bodyModal.dataset.specialistid;
var filialId = bodyModal.dataset.filialid;
var onlineMode = bodyModal.dataset.onlinemode;
pullInterval(specialistId, departmentId, filialId, date, onlineMode);
});
btnPrev.addEventListener('click', function(evn) {
if (this.dataset.currentdate) {
var date = this.dataset.currentdate;
} else {
var date = currentDate;
}
var nDate = new Date(currentDate).toLocaleString('ru', {year: 'numeric',month: 'numeric',day: 'numeric'});
var cDate = new Date(date).toLocaleString('ru', {year: 'numeric',month: 'numeric',day: 'numeric'});
if (nDate == cDate) {
this.classList.add('d-none');
bodyModal.querySelector('.popup-btns').classList.add('justify-content-end');
bodyModal.querySelector('.popup-btns').classList.remove('justify-content-between');
}
btnNext.dataset.currentdate = new Date(date);
var departmentId = bodyModal.dataset.departmentid;
var specialistId = bodyModal.dataset.specialistid;
var filialId = bodyModal.dataset.filialid;
var onlineMode = bodyModal.dataset.onlinemode;
pullInterval(specialistId, departmentId, filialId, date, onlineMode);
this.dataset.currentdate = new Date(getPrevWeek(date));
});
this.element.querySelectorAll('.show-specialist-detail').forEach(function(btn) {
btn.addEventListener('click', function(evn) {
btnPrev.classList.add('d-none');
bodyModal.querySelector('.popup-btns').classList.remove('justify-content-between');
bodyModal.querySelector('.popup-btns').classList.add('justify-content-end');
var departmentId = bodyModal.dataset.departmentid = btn.dataset.departmentid;
var specialistId = bodyModal.dataset.specialistid = btn.dataset.specialistid;
bodyModal.dataset.company = btn.dataset.company;
var filialId = bodyModal.dataset.filialid = btn.dataset.filialid;
var onlineMode = bodyModal.dataset.onlinemode = btn.dataset.onlinemode;
pullInterval(specialistId, departmentId, filialId, currentDate, onlineMode);
pullDoctor(specialistId);
});
});
function pullDoctor(doctor) {
var modal = bodyModal.querySelector('.popup__content');
$.ajax({
dataType: "json",
method: "GET",
crossDomain: true,
url: "/api/doctor",
data: {
'sid': doctor,
},
beforeSend() {
modal.querySelector('.loading').classList.remove('d-none');
var aboutSpecialist = modal.querySelector('.about-specialist')
aboutSpecialist.classList.add('d-none');
aboutSpecialist.querySelector('.popup-staff__img').remove();
},
success(data) {
modal.querySelector('.loading').classList.add('d-none');
modal.querySelector('.about-specialist').classList.remove('d-none');
var content = modal.querySelector('.about-specialist');
var img = document.createElement('div');
img.src = data.data.img;
img.classList = 'img-vr popup-staff__img';
img.style.background = 'url(' + data.data.img + ') no-repeat';
img.style.backgroundSize = 'cover';
img.style.backgroundPosition = 'center -5px';
content.prepend(img);
content.querySelector('.popup-staff__name').innerHTML = data.data.name;
content.querySelector('.popup-staff__position').innerHTML = '';
if (data.data.speciality) {
content.querySelector('.popup-staff__position').innerHTML = data.data.speciality;
}
content.querySelector('.popup-staff__exp').innerHTML = '';
if (data.data.experience) {
content.querySelector('.popup-staff__exp').innerHTML = 'Стаж:' + data.data.experience;
}
}
});
}
function pullInterval(doctor, department, filial, date, onlineMode) {
let wrap = bodyModal.querySelector('.calendar-wrap');
let calendarBody = bodyModal.querySelector('.calendar-body');
$.ajax({
dataType: "json",
method: "GET",
crossDomain: true,
url: "/api/interval",
data: {
'update' : true,
'doctor': doctor,
'department': department,
'filial': filial,
'startInterval': getMonday(date),
'endInterval': getSunday(date),
'onlineMode': onlineMode
},
beforeSend() {
bodyModal.querySelector('.current-dates').innerHTML = getMonday(date) + ' - ' + getSunday(date);
wrap.innerHTML = "Идет загрузка...";
},
success(response) {
var isNotFree = true;
wrap.innerHTML = "";
response.data.intervalsData.forEach(function(el) {
if (el.isFree == true) {
var date = new Date(el.workDate).toLocaleString('ru', {
weekday: 'long',
month: 'long',
day: 'numeric'
});
var calBody = document.createElement('div');
calBody.classList = 'calendar-body popup-inteval__item';
var timeDiv = document.createElement('div');
timeDiv.classList = 'popup-inteval__date';
timeDiv.innerHTML = date + ' <i>' + el.startInterval + '—'+ el.endInterval + '</i>';
calBody.append(timeDiv);
var intervalTimeDiv = document.createElement('div');
intervalTimeDiv.classList = 'time-intervals';
var intervalDiv = document.createElement('div');
intervalDiv.classList = 'interval intervals-wrap';
intervalTimeDiv.append(intervalDiv);
for (let [key, item] of Object.entries(el.intervals)) {
if (item.isFree == true) {
isNotFree = false;
var spanInterval = document.createElement('span');
spanInterval.classList = 'time available';
spanInterval.innerText = item.startTime;
spanInterval.dataset.workDate = item.workDate;
spanInterval.dataset.schedident = item.schedident;
spanInterval.dataset.time = item.time;
spanInterval.dataset.onlinemode = item.onlineMode;
spanInterval.dataset.rnum = item.rNum;
spanInterval.dataset.specialistid = doctor;
spanInterval.dataset.filialid = filial;
spanInterval.dataset.department = department;
spanInterval.addEventListener('click', function (evn) {
var popupWrap = document.getElementById('popup');
evn.target.dataset.onlinemode = item.onlineMode;
if (record.renderFormRecord(response.data.userInfo, evn.target.dataset)) {
if (response.data.userInfo) {
evn.target.innerHTML = '<img width="20" src="/images/eclipse.gif">';
record.sendReserve(popupWrap)
} else {
$(popupWrap).modal('show');
}
}
})
intervalDiv.append(spanInterval);
}
}
if (!isNotFree) {
calBody.append(intervalDiv);
wrap.append(calBody);
}
}
});
if (isNotFree) {
wrap.innerHTML = "Всё занято. Выберите другую неделю.";
}
}
});
}
function getMonday(date) {
date = new Date(date);
return new Date(date.setDate(date.getDate() - date.getDay() + 1))
.toLocaleString('ru', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
});
}
function getSunday(date) {
date = new Date(date);
return new Date(date.setDate(date.getDate() - date.getDay() + 7))
.toLocaleString('ru', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
});
}
function getNextWeek(date) {
date = new Date(date);
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 7);
}
function getPrevWeek(date) {
date = new Date(date);
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - 7);
}
}
}
@@ -0,0 +1,23 @@
import { Controller } from 'stimulus';
import "swagger-ui-dist/swagger-ui.css"
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="default" attribute will cause
* this controller to be executed. The name "default" comes from the filename:
* default_controller.js -> "default"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var SwaggerUIBundle = require('swagger-ui-dist').SwaggerUIBundle;
var wrap = this.element;
SwaggerUIBundle({
url: "/api/swagger.json",
dom_id: '#swagger-ui'
});
}
}
+22
View File
@@ -0,0 +1,22 @@
import { Controller } from 'stimulus';
import Inputmask from "inputmask";
import { renderFormBitrix } from "./../components/record"
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="uslugi" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
var btn = this.element
btn.addEventListener('click', function () {
renderFormBitrix(this);
$('#popup').modal('show');
});
}
}
+118
View File
@@ -0,0 +1,118 @@
import { Controller } from 'stimulus';
const loader = require("./../components/loader.js");
const helper = require("./../components/helper.js");
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="widgets" attribute will cause
* this controller to be executed. The name "recaptcha" comes from the filename:
* recaptcha_controller.js -> "recaptcha"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
loader.loadSDK('widget').then(function(webSDK) {
webSDK.on('init', function() {
if (this.data.user.authenticated) {
runWebSDK();
}
});
})
let runWebSDK = function () {
this.securityCard();
this.finance();
}.bind(this)
}
finance() {
var financeWidget = document.getElementById('finance-widget');
window.webSDK.loadPaymentList({
start: 0,
length: 4
}).then(function (resolve) {
financeWidget.innerHTML = '';
if (resolve.length > 0) {
resolve.forEach(function(item) {
var div = document.createElement('div');
div.classList = 'payment-line';
var date = window.newDate(item.date);
var spanID = document.createElement('span');
spanID.classList = 'payment-line__id';
spanID.innerHTML = 'Счет № ' + item.id + ' от ' + window.dateFormat(date, 'd-m-Y');
div.append(spanID);
var spanPrice = document.createElement('span');
spanPrice.classList = 'payment-line__price';
spanPrice.innerHTML = item.amt + ' ₽';
div.append(spanPrice);
financeWidget.append(div);
});
} else {
var item = document.createElement('span');
item.innerHTML = 'Записей не найдено';
item.classList = 'line-item';
financeWidget.append(item);
}
}).catch(function (error) {
helper.sendRequest({
data: {'error': error, method: 'loadPaymentList'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
})
}
securityCard() {
var securityCardWidget = document.getElementById('security-card-widget');
var date = new Date();
var lastDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
if (window.webSDK.data.user.allows.caseHistory == true) {
window.webSDK.loadTreatPlaceList({
st: 20200101,
en: window.dateFormat(lastDate),
start: 0,
length: 4
}).then(function (resolve) {
securityCardWidget.innerHTML = '';
if (resolve.data.length > 0) {
resolve.data.forEach(function(el) {
var item = document.createElement('span');
item.innerHTML = el.protocolName.slice(0,37) + '...';
item.classList = 'line-item';
securityCardWidget.append(item);
});
} else {
var item = document.createElement('span');
item.innerHTML = 'Записей не найдено';
item.classList = 'line-item';
securityCardWidget.append(item);
}
}).catch(function (error) {
helper.sendRequest({
data: {'error': error, method: 'loadTreatPlaceList'}
}, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
securityCardWidget.innerHTML = '';
var item = document.createElement('span');
item.innerHTML = 'Записей не найдено';
item.classList = 'line-item';
securityCardWidget.append(item);
});
} else {
securityCardWidget.innerHTML = '';
var item = document.createElement('span');
item.innerHTML = 'Записей не найдено';
item.classList = 'line-item';
securityCardWidget.append(item);
}
}
}