v1.0.0
This commit is contained in:
189
web/lib/app.js
189
web/lib/app.js
@@ -18,42 +18,6 @@ async function appReload() {
|
||||
// listApartment = []
|
||||
}
|
||||
|
||||
const Rotation = async () => {
|
||||
const result = confirm(`Ви бажаєте провести ротацію територій між групами?`);
|
||||
|
||||
if (result) {
|
||||
let rotationButton = document.getElementById('rotationButton-title');
|
||||
rotationButton.innerText = "Зачекайте";
|
||||
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
|
||||
const URL = `${CONFIG.api}rotation`;
|
||||
await fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json, text/plain, */*",
|
||||
"Authorization": uuid
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
rotationButton.innerText = 'Ротація завершилась успішно!';
|
||||
|
||||
Territory.house.setHTML();
|
||||
Territory.homestead.setHTML();
|
||||
|
||||
setTimeout(() => {
|
||||
rotationButton.innerText = "Провести ротацію";
|
||||
}, 3000);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
rotationButton.innerText = "Помилка ротації!";
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Функция загрузки приложения
|
||||
window.addEventListener('load', async function () {
|
||||
console.log('[OS] ', detectOS());
|
||||
@@ -71,29 +35,14 @@ window.addEventListener('load', async function () {
|
||||
}
|
||||
}
|
||||
|
||||
let userInput = () => {
|
||||
let h = prompt("Введіть ваше посилання з UUID:");
|
||||
if (h) {
|
||||
h = h.replace("https://sheep-service.com/?uuid=", "");
|
||||
h = h.replace("https://sheep-service.com?uuid=", "");
|
||||
h = h.replace("https://sheep-service.com?/hash=", "");
|
||||
h = h.replace("https://sheep-service.com?hash=", "");
|
||||
|
||||
localStorage.setItem("uuid", h)
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.get('uuid')) {
|
||||
localStorage.setItem("uuid", urlParams.get('uuid'))
|
||||
}
|
||||
if (urlParams.get('hash')) {
|
||||
localStorage.setItem("uuid", urlParams.get('hash'))
|
||||
if (Router.getParams().uuid) {
|
||||
localStorage.setItem("uuid", Router.getParams().uuid)
|
||||
}
|
||||
|
||||
let uuid = localStorage.getItem("uuid") ? localStorage.getItem("uuid") : userInput();
|
||||
if (uuid) {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
if (!uuid) {
|
||||
Router.navigate(`/auth`).check().listen().delegateLinks();
|
||||
} else {
|
||||
const URL = `${CONFIG.api}auth`;
|
||||
USER = await fetch(URL, {
|
||||
method: 'GET',
|
||||
@@ -101,16 +50,126 @@ window.addEventListener('load', async function () {
|
||||
"Content-Type": "application/json, text/plain, */*",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
}).then(response => {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem("uuid");
|
||||
Router.navigate(`/auth`);
|
||||
}
|
||||
return response.json();
|
||||
});
|
||||
|
||||
console.log("USER Info: ", USER);
|
||||
|
||||
|
||||
if (USER.administrator.uuid || USER.moderator.uuid) document.getElementById("li-sheeps").style.display = "";
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_add_schedule)) document.getElementById("li-schedule").style.display = "";
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_manager_territory)) document.getElementById("li-territory").style.display = "";
|
||||
if (USER.administrator.uuid || USER.can_view_stand) document.getElementById("li-stand").style.display = "";
|
||||
}
|
||||
if (USER.possibilities.can_view_sheeps) document.getElementById("li-sheeps").style.display = "";
|
||||
if (USER.possibilities.can_view_schedule) document.getElementById("li-schedule").style.display = "";
|
||||
if (USER.possibilities.can_manager_territory) document.getElementById("li-territory").style.display = "";
|
||||
if (USER.possibilities.can_view_stand) document.getElementById("li-stand").style.display = "";
|
||||
|
||||
Router.check().listen();
|
||||
});
|
||||
if (USER.possibilities.can_view_sheeps) await Sheeps.sheeps_list.loadAPI();
|
||||
|
||||
editFontStyle();
|
||||
|
||||
Router.check().listen().delegateLinks();
|
||||
}
|
||||
});
|
||||
|
||||
function editFontStyle() {
|
||||
let fontSize = localStorage.getItem("fontSize")
|
||||
? localStorage.getItem("fontSize")
|
||||
: 'medium';
|
||||
|
||||
applyFontMode(fontSize);
|
||||
}
|
||||
|
||||
function applyFontMode(mode) {
|
||||
const options = {
|
||||
"small": {
|
||||
"--FontSize1": "10px",
|
||||
"--FontSize2": "11px",
|
||||
"--FontSize3": "12px",
|
||||
"--FontSize4": "13px",
|
||||
"--FontSize5": "14px"
|
||||
},
|
||||
"medium": {
|
||||
"--FontSize1": "12px",
|
||||
"--FontSize2": "13px",
|
||||
"--FontSize3": "14px",
|
||||
"--FontSize4": "15px",
|
||||
"--FontSize5": "16px"
|
||||
},
|
||||
"large": {
|
||||
"--FontSize1": "15px",
|
||||
"--FontSize2": "16px",
|
||||
"--FontSize3": "17px",
|
||||
"--FontSize4": "18px",
|
||||
"--FontSize5": "19px"
|
||||
}
|
||||
};
|
||||
|
||||
const root = document.documentElement;
|
||||
const config = options[mode];
|
||||
|
||||
if (!config) return;
|
||||
|
||||
Object.keys(config).forEach(key => {
|
||||
if (key.startsWith("--")) {
|
||||
root.style.setProperty(key, config[key]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Банер з прохання встановлення PWA
|
||||
let deferredPrompt;
|
||||
const isInStandaloneMode = () =>
|
||||
('standalone' in window.navigator && window.navigator.standalone === true);
|
||||
|
||||
if (detectOS() == 'iOS' && !isInStandaloneMode()) {
|
||||
setTimeout(() => {
|
||||
document.getElementById('blur-backdrop').classList.remove('pwa-hidden');
|
||||
document.getElementById('pwa-ios-overlay').classList.remove('pwa-hidden');
|
||||
document.body.classList.add('modal-open');
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
window.addEventListener("beforeinstallprompt", (e) => {
|
||||
e.preventDefault();
|
||||
deferredPrompt = e;
|
||||
|
||||
if (localStorage.getItem('modal') != "false") {
|
||||
document.getElementById("blur-backdrop").classList.remove("pwa-hidden");
|
||||
document.getElementById("pwa-install-overlay").classList.remove("pwa-hidden");
|
||||
document.body.classList.add("modal-open");
|
||||
}
|
||||
});
|
||||
document.getElementById("pwa-install-button").addEventListener("click", async () => {
|
||||
if (!deferredPrompt) return;
|
||||
|
||||
deferredPrompt.prompt();
|
||||
const { outcome } = await deferredPrompt.userChoice;
|
||||
console.log(`PWA install result: ${outcome}`);
|
||||
|
||||
closePopup();
|
||||
});
|
||||
document.getElementById("pwa-close-button").addEventListener("click", closePopup);
|
||||
document.getElementById('pwa-ios-close-button').addEventListener('click', closePopup);
|
||||
|
||||
function closePopup() {
|
||||
document.getElementById("pwa-install-overlay").classList.add("pwa-hidden");
|
||||
document.getElementById("blur-backdrop").classList.add("pwa-hidden");
|
||||
document.getElementById('pwa-ios-overlay').classList.add('pwa-hidden');
|
||||
document.body.classList.remove("modal-open");
|
||||
deferredPrompt = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('sw.js')
|
||||
.then(() => {
|
||||
console.log('Service Worker зарегистрирован');
|
||||
webPush.init();
|
||||
})
|
||||
.catch(err => console.error('Ошибка регистрации SW:', err));
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
clipboard = (text) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
.then(() => console.log("Текст скопійовано!"))
|
||||
.then(() => alert("Посилання скопійовано!"))
|
||||
.catch(err => console.error(err))
|
||||
}
|
||||
@@ -1,9 +1,34 @@
|
||||
let formattedDate = (unix_timestamp) => {
|
||||
if(!unix_timestamp) return
|
||||
|
||||
if (!unix_timestamp) return
|
||||
|
||||
let date = new Date(unix_timestamp);
|
||||
let year = date.getFullYear() >= 10 ? date.getFullYear() : "0" + date.getFullYear();
|
||||
let month = (date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1);
|
||||
let weekday = date.getDate() >= 10 ? date.getDate() : "0" + date.getDate();
|
||||
return weekday + '.' + month + '.' + year;
|
||||
}
|
||||
|
||||
let formattedDateTime = (unix_timestamp) => {
|
||||
let a
|
||||
if (unix_timestamp > 1000000000000) a = new Date(unix_timestamp);
|
||||
else a = new Date(unix_timestamp * 1000);
|
||||
let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
let year = a.getFullYear();
|
||||
let month = (a.getMonth() + 1) < 10 ? `0${(a.getMonth() + 1)}` : (a.getMonth() + 1);
|
||||
let date = a.getDate() < 10 ? `0${a.getDate()}` : a.getDate();
|
||||
let hour = a.getHours() < 10 ? `0${a.getHours()}` : a.getHours();
|
||||
let min = a.getMinutes() < 10 ? `0${a.getMinutes()}` : a.getMinutes();
|
||||
let sec = a.getSeconds() < 10 ? `0${a.getSeconds()}` : a.getSeconds();
|
||||
let time = date + '.' + month + '.' + year + ' ' + hour + ':' + min;
|
||||
return time;
|
||||
}
|
||||
|
||||
function getTimeInSeconds(time = Date.now()) {
|
||||
// Если время больше 10 знаков (это значит, что время в миллисекундах)
|
||||
if (time.toString().length < 10) {
|
||||
// Округляем до секунд, убирая последние 3 цифры (миллисекунды)
|
||||
time = Math.floor(time * 1000);
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
9
web/lib/components/setLeafletCursor.js
Normal file
9
web/lib/components/setLeafletCursor.js
Normal file
@@ -0,0 +1,9 @@
|
||||
function setLeafletCursor(cursor) {
|
||||
let styleTag = document.getElementById('leaflet-cursor-style');
|
||||
if (!styleTag) {
|
||||
styleTag = document.createElement('style');
|
||||
styleTag.id = 'leaflet-cursor-style';
|
||||
document.head.appendChild(styleTag);
|
||||
}
|
||||
styleTag.innerHTML = `.leaflet-interactive { cursor: ${cursor} !important; }`;
|
||||
}
|
||||
104
web/lib/components/webPush.js
Normal file
104
web/lib/components/webPush.js
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
const webPush = {
|
||||
async init() {
|
||||
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
|
||||
console.error('Push уведомления не поддерживаются');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Получаем публичный ключ VAPID с сервера
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const res = await fetch(`${CONFIG.api}push/key`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
const { publicKey } = await res.json();
|
||||
|
||||
// Преобразуем ключ
|
||||
function urlBase64ToUint8Array(base64String) {
|
||||
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
|
||||
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
|
||||
const raw = atob(base64);
|
||||
return Uint8Array.from([...raw].map(ch => ch.charCodeAt(0)));
|
||||
}
|
||||
|
||||
// Берем уже зарегистрированный Service Worker
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
|
||||
// Проверяем, есть ли уже подписка
|
||||
let subscription = await registration.pushManager.getSubscription();
|
||||
|
||||
if (!subscription) {
|
||||
|
||||
// Запрашиваем разрешение
|
||||
const permission = await Notification.requestPermission();
|
||||
if (permission !== 'granted') {
|
||||
console.warn('Пуш уведомления запрещены пользователем');
|
||||
return;
|
||||
}
|
||||
|
||||
// Подписка на push
|
||||
subscription = await registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(publicKey)
|
||||
});
|
||||
|
||||
// данные устройства
|
||||
const deviceInfo = {
|
||||
name: navigator.userAgent,
|
||||
model: navigator.platform || "unknown"
|
||||
};
|
||||
|
||||
// Отправка на сервер
|
||||
await fetch(`${CONFIG.api}push/subscribe`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({ subscription, device: deviceInfo })
|
||||
});
|
||||
|
||||
console.log('Push подписка готова:', subscription);
|
||||
|
||||
console.log('Создана новая подписка');
|
||||
} else {
|
||||
console.log('Подписка уже существует');
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('Ошибка инициализации push:', err);
|
||||
}
|
||||
},
|
||||
|
||||
async unsubscribe() {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
const subscription = await registration.pushManager.getSubscription();
|
||||
|
||||
if (subscription) {
|
||||
// удаляем подписку в браузере
|
||||
const success = await subscription.unsubscribe();
|
||||
|
||||
if (success) {
|
||||
console.log("Локальная подписка отменена");
|
||||
|
||||
// уведомляем сервер
|
||||
await fetch(`${CONFIG.api}push//unsubscribe`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({ endpoint: subscription.endpoint })
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log("Подписки нет");
|
||||
}
|
||||
}
|
||||
}
|
||||
17
web/lib/pages/auth/index.html
Normal file
17
web/lib/pages/auth/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<div id="page-auth">
|
||||
<form id="page-auth-form">
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
name="uuid"
|
||||
id="auth-forms-uuid"
|
||||
placeholder="UUID"
|
||||
required=""
|
||||
/>
|
||||
|
||||
<button type="submit">
|
||||
<span>Авторизуватися</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
47
web/lib/pages/auth/script.js
Normal file
47
web/lib/pages/auth/script.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const Auth = {
|
||||
init: async () => {
|
||||
let html = await fetch('/lib/pages/auth/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
document.getElementById("page-auth-form").addEventListener("submit", async function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
let uuid = document.getElementById("auth-forms-uuid").value;
|
||||
|
||||
uuid = uuid.replace("https://sheep-service.com/?uuid=", "");
|
||||
uuid = uuid.replace("https://sheep-service.com?uuid=", "");
|
||||
uuid = uuid.replace("https://sheep-service.com?/hash=", "");
|
||||
uuid = uuid.replace("https://sheep-service.com?hash=", "");
|
||||
|
||||
console.log(uuid);
|
||||
|
||||
const URL = `${CONFIG.api}auth`;
|
||||
USER = await fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json, text/plain, */*",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then(response => {
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem("uuid");
|
||||
Router.navigate(`/auth`);
|
||||
} else {
|
||||
localStorage.setItem("uuid", uuid);
|
||||
Router.navigate(`/`, false);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
});
|
||||
|
||||
console.log("USER Info: ", USER);
|
||||
|
||||
|
||||
if (USER.possibilities.can_view_sheeps) document.getElementById("li-sheeps").style.display = "";
|
||||
if (USER.possibilities.can_add_schedule) document.getElementById("li-schedule").style.display = "";
|
||||
if (USER.possibilities.can_manager_territory) document.getElementById("li-territory").style.display = "";
|
||||
if (USER.possibilities.can_view_stand) document.getElementById("li-stand").style.display = "";
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
58
web/lib/pages/auth/style.css
Normal file
58
web/lib/pages/auth/style.css
Normal file
@@ -0,0 +1,58 @@
|
||||
#page-auth {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-height: calc(100% + 70px);
|
||||
margin: 5px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#page-auth-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#page-auth-form>div {
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 160px;
|
||||
justify-content: center;
|
||||
width: 250px;
|
||||
padding: 10px 20px;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
transition: all .2s ease 0s;
|
||||
}
|
||||
|
||||
#page-auth-form>div>input {
|
||||
background: var(--ColorThemes0);
|
||||
font-size: var(--FontSize2);
|
||||
width: calc(100% - 10px);
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#page-auth-form>div>button {
|
||||
border-radius: 6px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
margin: 20px 0 0 0;
|
||||
}
|
||||
#page-auth-form>div>button>span {
|
||||
font-size: var(--FontSize2);
|
||||
font-weight: 400;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@@ -15,14 +15,6 @@
|
||||
background-size: 0.55rem auto;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
#header p {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -76,7 +68,7 @@
|
||||
summary p {
|
||||
padding: 0 10px;
|
||||
color: var(--PrimaryColorText);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 500;
|
||||
}
|
||||
summary svg {
|
||||
@@ -98,9 +90,16 @@
|
||||
padding: 1px;
|
||||
}
|
||||
}
|
||||
.apartments_list > div {
|
||||
.apartments_list > p {
|
||||
font-size: var(--FontSize5);
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card_info {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
border-radius: 8px;
|
||||
margin: 10px 10px 15px 10px;
|
||||
flex-direction: column;
|
||||
@@ -108,20 +107,24 @@
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
background: var(--ColorThemes2);
|
||||
}
|
||||
.apartments_list > div > .info {
|
||||
.card_info_homestead {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.card_info > .info {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.apartments_list > div > .info > span {
|
||||
.card_info > .info > span {
|
||||
min-width: 40px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
position: relative;
|
||||
margin: 5px;
|
||||
}
|
||||
.apartments_list > div > .info > select {
|
||||
.card_info > .info > select {
|
||||
color: #3d3d3d;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #eaebef;
|
||||
@@ -129,28 +132,38 @@
|
||||
background-color: var(--ColorThemes3);
|
||||
min-width: 110px;
|
||||
width: 100%;
|
||||
padding: 4px 20px 4px 4px;
|
||||
padding: 4px;
|
||||
height: 30px;
|
||||
}
|
||||
.apartments_list > div > .info > input {
|
||||
color: #3d3d3d;
|
||||
.card_info > .info > input,
|
||||
.card_info > .info > button {
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #eaebef;
|
||||
margin: 5px;
|
||||
background-color: var(--ColorThemes3);
|
||||
background-color: var(--ColorThemes0);
|
||||
border: 1px solid var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
width: 100%;
|
||||
max-width: 170px;
|
||||
min-width: 70px;
|
||||
padding: 0 4px;
|
||||
height: calc(30px - 2px);
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
}
|
||||
.apartments_list > div > textarea {
|
||||
.card_info > .info > button > svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
fill: var(--ColorThemes3);
|
||||
}
|
||||
.card_info > textarea {
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
margin: 5px;
|
||||
background-color: var(--ColorThemes0);
|
||||
border: 1px solid var(--ColorThemes1);
|
||||
@@ -163,13 +176,231 @@
|
||||
resize: vertical;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.card_info > textarea::placeholder {
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.card_info > textarea::-webkit-input-placeholder {
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#map_card {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: calc(100vh - 100px);
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="page-card">
|
||||
<div id="header">
|
||||
<p id="status"></p>
|
||||
<p id="hash"></p>
|
||||
<div class="list-controls" id="page-card-controls" style="display: none">
|
||||
<div id="page-card-sort">
|
||||
<button id="sort_1" onclick="Card.sort('2')" data-state="active">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 32.476562 5.9785156 A 1.50015 1.50015 0 0 0 31 7.5 L 31 37.878906 L 26.560547 33.439453 A 1.50015 1.50015 0 1 0 24.439453 35.560547 L 31.439453 42.560547 A 1.50015 1.50015 0 0 0 33.560547 42.560547 L 40.560547 35.560547 A 1.50015 1.50015 0 1 0 38.439453 33.439453 L 34 37.878906 L 34 7.5 A 1.50015 1.50015 0 0 0 32.476562 5.9785156 z M 14.375 8.0058594 C 14.257547 8.01575 14.139641 8.0379219 14.025391 8.0761719 L 11.025391 9.0761719 C 10.239391 9.3381719 9.8141719 10.188609 10.076172 10.974609 C 10.338172 11.760609 11.190609 12.188828 11.974609 11.923828 L 13 11.580078 L 13 20.5 C 13 21.329 13.671 22 14.5 22 C 15.329 22 16 21.329 16 20.5 L 16 9.5 C 16 9.018 15.767953 8.5652031 15.376953 8.2832031 C 15.082953 8.0717031 14.727359 7.9761875 14.375 8.0058594 z M 14 27 C 11.344 27 9.387625 28.682109 9.015625 31.287109 C 8.898625 32.107109 9.4671094 32.867375 10.287109 32.984375 C 11.106109 33.102375 11.867375 32.533891 11.984375 31.712891 C 12.096375 30.931891 12.537 30 14 30 C 15.103 30 16 30.897 16 32 C 16 33.103 15.103 34 14 34 C 11.592 34 9 35.721 9 39.5 C 9 40.329 9.672 41 10.5 41 L 17.5 41 C 18.329 41 19 40.329 19 39.5 C 19 38.671 18.329 38 17.5 38 L 12.308594 38 C 12.781594 37.093 13.664 37 14 37 C 16.757 37 19 34.757 19 32 C 19 29.243 16.757 27 14 27 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_2" onclick="Card.sort('3')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 31.478516 6 A 1.50015 1.50015 0 0 0 30.439453 6.4394531 L 23.439453 13.439453 A 1.50015 1.50015 0 1 0 25.560547 15.560547 L 30 11.121094 L 30 41.5 A 1.50015 1.50015 0 1 0 33 41.5 L 33 11.121094 L 37.439453 15.560547 A 1.50015 1.50015 0 1 0 39.560547 13.439453 L 32.560547 6.4394531 A 1.50015 1.50015 0 0 0 31.478516 6 z M 13.375 8.0058594 C 13.257547 8.01575 13.139641 8.0379219 13.025391 8.0761719 L 10.025391 9.0761719 C 9.2393906 9.3381719 8.8141719 10.188609 9.0761719 10.974609 C 9.3381719 11.760609 10.190609 12.188828 10.974609 11.923828 L 12 11.580078 L 12 20.5 C 12 21.329 12.671 22 13.5 22 C 14.329 22 15 21.329 15 20.5 L 15 9.5 C 15 9.018 14.767953 8.5652031 14.376953 8.2832031 C 14.082953 8.0717031 13.727359 7.9761875 13.375 8.0058594 z M 13 27 C 10.344 27 8.387625 28.682109 8.015625 31.287109 C 7.898625 32.107109 8.4671094 32.867375 9.2871094 32.984375 C 10.106109 33.102375 10.867375 32.533891 10.984375 31.712891 C 11.096375 30.931891 11.537 30 13 30 C 14.103 30 15 30.897 15 32 C 15 33.103 14.103 34 13 34 C 10.592 34 8 35.721 8 39.5 C 8 40.329 8.672 41 9.5 41 L 16.5 41 C 17.329 41 18 40.329 18 39.5 C 18 38.671 17.329 38 16.5 38 L 11.308594 38 C 11.781594 37.093 12.664 37 13 37 C 15.757 37 18 34.757 18 32 C 18 29.243 15.757 27 13 27 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_3" onclick="Card.sort('4')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
transform="rotate(180 32.5 24.5106)"
|
||||
id="svg_1"
|
||||
d="m32.47852,6a1.50015,1.50015 0 0 0 -1.03907,0.43945l-7,7a1.50015,1.50015 0 1 0 2.1211,2.1211l4.43945,-4.43946l0,30.37891a1.50015,1.50015 0 1 0 3,0l0,-30.37891l4.43945,4.43946a1.50015,1.50015 0 1 0 2.1211,-2.1211l-7,-7a1.50015,1.50015 0 0 0 -1.08203,-0.43945z"
|
||||
></path>
|
||||
<path
|
||||
d="m16,6c-5.511,0 -10,4.489 -10,10c0,5.511 4.489,10 10,10c5.511,0 10,-4.489 10,-10c0,-5.511 -4.489,-10 -10,-10zm0,2c4.43012,0 8,3.56988 8,8c0,4.43012 -3.56988,8 -8,8c-4.43012,0 -8,-3.56988 -8,-8c0,-4.43012 3.56988,-8 8,-8zm-1,2l0,6.41406l4.29297,4.29297l1.41406,-1.41406l-3.70703,-3.70703l0,-5.58594l-2,0z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_4" onclick="Card.sort('1')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
id="svg_1"
|
||||
d="m32.47852,6a1.50015,1.50015 0 0 0 -1.03907,0.43945l-7,7a1.50015,1.50015 0 1 0 2.1211,2.1211l4.43945,-4.43946l0,30.37891a1.50015,1.50015 0 1 0 3,0l0,-30.37891l4.43945,4.43946a1.50015,1.50015 0 1 0 2.1211,-2.1211l-7,-7a1.50015,1.50015 0 0 0 -1.08203,-0.43945z"
|
||||
></path>
|
||||
<path
|
||||
d="m16,22.85262c-5.511,0 -10,4.489 -10,10c0,5.511 4.489,10 10,10c5.511,0 10,-4.489 10,-10c0,-5.511 -4.489,-10 -10,-10zm0,2c4.43012,0 8,3.56988 8,8c0,4.43012 -3.56988,8 -8,8c-4.43012,0 -8,-3.56988 -8,-8c0,-4.43012 3.56988,-8 8,-8zm-1,2l0,6.41406l4.29297,4.29297l1.41406,-1.41406l-3.70703,-3.70703l0,-5.58594l-2,0z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="page-card-status">
|
||||
<div id="cloud_1" data-state="active" title="Йде синхронізація...">
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
version="1.1"
|
||||
>
|
||||
<g>
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)" opacity="1">
|
||||
<g transform="translate(24 29)">
|
||||
<g transform="rotate(0)">
|
||||
<g transform="scale(1 1)">
|
||||
<g transform="translate(-24 -29)">
|
||||
<g opacity="1">
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 18.772, 33.991)"
|
||||
opacity="1"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
>
|
||||
<path
|
||||
d="M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
>
|
||||
<animate
|
||||
calcMode="spline"
|
||||
repeatCount="indefinite"
|
||||
attributeName="d"
|
||||
dur="1.166667"
|
||||
begin="0.000000"
|
||||
keyTimes="0; 0.107143; 0.178571; 0.821429; 0.892857; 1"
|
||||
keySplines="0 0 1 1; 0.333000 0.000000 0.667000 1.000000; 0.167000 0.167000 0.833000 0.833000; 0.333000 0.000000 0.667000 1.000000; 0.000000 0.000000 0.000000 0.000000"
|
||||
values="M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055; M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055; M -1.771,-2.28 C -1.771,-2.28 -1.761,-2.279 -1.761,-2.279 -1.761,-2.279 -1.78,-2.283 -1.78,-2.283; M -1.768,-2.281 C -1.768,-2.281 -1.758,-2.28 -1.758,-2.28 -1.758,-2.28 -1.778,-2.284 -1.778,-2.284; M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055; M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055"
|
||||
></animate>
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 24.037, 34)"
|
||||
opacity="1"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
>
|
||||
<path
|
||||
d="M 7.036,-2.5 C 6.006,0.413 3.228,2.5 -0.036,2.5 -3.227,2.5 -5.953,0.507 -7.036,-2.303"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
></path>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 29.227, 24.009)"
|
||||
opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
>
|
||||
<path
|
||||
d="M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
>
|
||||
<animate
|
||||
calcMode="spline"
|
||||
repeatCount="indefinite"
|
||||
attributeName="d"
|
||||
dur="1.166667"
|
||||
begin="0.000000"
|
||||
keyTimes="0; 0.107143; 0.178571; 0.821429; 0.892857; 1"
|
||||
keySplines="0 0 1 1; 0.333000 0.000000 0.667000 1.000000; 0.167000 0.167000 0.833000 0.833000; 0.333000 0.000000 0.667000 1.000000; 0.000000 0.000000 0.000000 0.000000"
|
||||
values="M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055; M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055; M 1.775,2.301 C 1.775,2.301 1.775,2.298 1.775,2.298 1.775,2.298 1.777,2.29 1.777,2.29; M 1.767,2.292 C 1.767,2.292 1.767,2.289 1.767,2.289 1.767,2.289 1.768,2.281 1.768,2.281; M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055; M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055"
|
||||
></animate>
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 23.963, 24)"
|
||||
opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
>
|
||||
<path
|
||||
d="M -7.036,2.5 C -6.006,-0.413 -3.229,-2.5 0.036,-2.5 3.228,-2.5 5.953,-0.507 7.036,2.303"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<animateTransform
|
||||
calcMode="spline"
|
||||
repeatCount="indefinite"
|
||||
attributeName="transform"
|
||||
dur="1.166667"
|
||||
begin="0.000000"
|
||||
type="rotate"
|
||||
keyTimes="0; 0.107143; 0.821429; 0.892857; 1"
|
||||
keySplines="0 0 1 1; 0.333000 0.000000 0.667000 1.000000; 0.333000 0.000000 0.667000 1.000000; 0.000000 0.000000 0.000000 0.000000"
|
||||
values="0; 0; 380; 360; 360"
|
||||
></animateTransform>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)" opacity="1">
|
||||
<g
|
||||
fill-opacity="1"
|
||||
transform="matrix(1, 0, 0, 1, 24, 22.5)"
|
||||
opacity="1"
|
||||
fill="var(--ColorThemes3)"
|
||||
>
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccccccccccccccccccc"
|
||||
d="M 15,-2.5 C 15,-2.5 14.42,-2.5 14.42,-2.5 13.67,-9.79 7.49,-15.5 0,-15.5 -7.49,-15.5 -13.67,-9.79 -14.42,-2.5 -14.42,-2.5 -15,-2.5 -15,-2.5 -19.96,-2.5 -24,1.54 -24,6.5 -24,11.46 -19.96,15.5 -15,15.5 -15,15.5 -12.17,15.5 -12.17,15.5 -12.38,14.91 -12.48,14.26 -12.42,13.59 -12.42,13.59 -12.32,12.5 -12.32,12.5 -12.32,12.5 -15,12.5 -15,12.5 -18.31,12.5 -21,9.81 -21,6.5 -21,3.19 -18.31,0.5 -15,0.5 -15,0.5 -13,0.5 -13,0.5 -12.17,0.5 -11.5,-0.17 -11.5,-1 -11.5,-7.34 -6.34,-12.5 0,-12.5 6.34,-12.5 11.5,-7.34 11.5,-1 11.5,-0.17 12.17,0.5 13,0.5 13,0.5 15,0.5 15,0.5 18.31,0.5 21,3.19 21,6.5 21,9.81 18.31,12.5 15,12.5 15,12.5 10.38,12.5 10.38,12.5 9.73,13.64 8.89,14.66 7.92,15.5 7.92,15.5 15,15.5 15,15.5 19.96,15.5 24,11.46 24,6.5 24,1.54 19.96,-2.5 15,-2.5 Z"
|
||||
style=""
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="cloud_2" data-state="" title="Синхронізовано">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 7 C 16.51 7 10.330078 12.71 9.5800781 20 L 9 20 C 4.04 20 0 24.04 0 29 C 0 33.96 4.04 38 9 38 L 16.640625 38 L 13.640625 35 L 9 35 C 5.69 35 3 32.31 3 29 C 3 25.69 5.69 23 9 23 L 11 23 C 11.83 23 12.5 22.33 12.5 21.5 C 12.5 15.16 17.66 10 24 10 C 30.34 10 35.5 15.16 35.5 21.5 C 35.5 22.33 36.17 23 37 23 L 39 23 C 42.31 23 45 25.69 45 29 C 45 32.31 42.31 35 39 35 L 29.839844 35 L 26.539062 38 L 39 38 C 43.96 38 48 33.96 48 29 C 48 24.04 43.96 20 39 20 L 38.419922 20 C 37.669922 12.71 31.49 7 24 7 z M 32.542969 24.986328 A 1.50015 1.50015 0 0 0 31.490234 25.390625 L 21.548828 34.427734 L 16.560547 29.439453 A 1.50015 1.50015 0 1 0 14.439453 31.560547 L 20.439453 37.560547 A 1.50015 1.50015 0 0 0 22.509766 37.609375 L 33.509766 27.609375 A 1.50015 1.50015 0 0 0 32.542969 24.986328 z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="cloud_3" data-state="" title="Помилка синхронізації">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 8 C 16.51 8 10.330078 13.71 9.5800781 21 L 9 21 C 4.04 21 0 25.04 0 30 C 0 34.96 4.04 39 9 39 L 19.099609 39 C 18.899609 38 18.999922 36.95 19.419922 36 L 9 36 C 5.69 36 3 33.31 3 30 C 3 26.69 5.69 24 9 24 L 11 24 C 11.83 24 12.5 23.33 12.5 22.5 C 12.5 16.16 17.66 11 24 11 C 30.34 11 35.5 16.16 35.5 22.5 C 35.5 23.33 36.17 24 37 24 L 39 24 C 42.31 24 45 26.69 45 30 C 45 33.31 42.31 36 39 36 L 28.580078 36 C 29.000078 36.95 29.100391 38 28.900391 39 L 39 39 C 43.96 39 48 34.96 48 30 C 48 25.04 43.96 21 39 21 L 38.419922 21 C 37.669922 13.71 31.49 8 24 8 z M 23.976562 20.978516 A 1.50015 1.50015 0 0 0 22.5 22.5 L 22.5 31.5 A 1.50015 1.50015 0 1 0 25.5 31.5 L 25.5 22.5 A 1.50015 1.50015 0 0 0 23.976562 20.978516 z M 24 36 A 2 2 0 0 0 24 40 A 2 2 0 0 0 24 36 z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="list"></div>
|
||||
<div id="map_card"></div>
|
||||
</div>
|
||||
|
||||
<div id="card-new-date" style="display: none; opacity: 0">
|
||||
<div class="mess">
|
||||
<button id="card-new-date-button">Оновити дату</button>
|
||||
<input type="datetime-local" id="card-new-date-input" placeholder="Дата" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,358 +1,641 @@
|
||||
let socket, username;
|
||||
|
||||
let listEntrances = []
|
||||
let listApartment = []
|
||||
|
||||
let holdTimer;
|
||||
let startTime;
|
||||
let map_card;
|
||||
|
||||
const Card = {
|
||||
init: async (type, id) => {
|
||||
let html = await fetch('/lib/pages/card/index.html').then((response) => response.text());
|
||||
// Глобальні змінні стану
|
||||
id: null,
|
||||
socket: null,
|
||||
reconnectTimeout: null,
|
||||
reconnectAttempts: 0,
|
||||
username: null,
|
||||
listEntrances: [],
|
||||
listApartment: [],
|
||||
listBuilding: [],
|
||||
|
||||
// Кольори статусів квартир
|
||||
color_status: [
|
||||
["var(--ColorThemes2)", "var(--ColorThemes3)"],
|
||||
["#fbf1e0", "#ff8300"],
|
||||
["#fce3e2", "#ff0000"],
|
||||
["#d7ddec", "#2919bd"],
|
||||
["#d5e9dd", "#11a568"],
|
||||
["#d7ebfa", "#3fb4fc"],
|
||||
["#e8dbf5", "#b381eb"]
|
||||
],
|
||||
|
||||
// Ініціалізація сторінки
|
||||
async init(type, Id) {
|
||||
// Завантажуємо HTML
|
||||
const html = await fetch('/lib/pages/card/index.html').then(r => r.text());
|
||||
app.innerHTML = html;
|
||||
Card.id = Id;
|
||||
|
||||
house = id;
|
||||
// Закриваємо старий WebSocket
|
||||
if (this.socket) this.socket.close(1000, "Перезапуск з'єднання");
|
||||
this.cloud.start(makeid(6));
|
||||
|
||||
if (socket) socket.close(1000, "Перезапуск соединения");
|
||||
// Якщо це сторінка будинку, отримуємо під’їзди та стартуємо WebSocket
|
||||
if (type === "house") {
|
||||
const controls = document.getElementById('page-card-controls');
|
||||
controls.style.display = "flex";
|
||||
|
||||
if (type == "house") {
|
||||
getEntrances();
|
||||
start(makeid(6));
|
||||
// Застосовуємо режим сортування
|
||||
this.sort(localStorage.getItem('sort_mode'), false);
|
||||
this.getEntrances({ update: false });
|
||||
} else if (type === "homestead") {
|
||||
this.getHomestead.map({});
|
||||
}
|
||||
|
||||
document.addEventListener("mousedown", handleStart);
|
||||
document.addEventListener("touchstart", handleStart);
|
||||
document.addEventListener("mouseup", handleCancel);
|
||||
document.addEventListener("mouseleave", handleCancel);
|
||||
document.addEventListener("touchend", handleCancel);
|
||||
document.addEventListener("touchcancel", handleCancel);
|
||||
|
||||
function handleStart(event) {
|
||||
const button = event.target.closest(".hold-button");
|
||||
if (!button) return;
|
||||
|
||||
// event.preventDefault();
|
||||
startTime = Date.now();
|
||||
|
||||
holdTimer = setTimeout(() => {
|
||||
console.log("Долгое нажатие на", button.name);
|
||||
let number_id = button.name.split("-");
|
||||
mess(Number(number_id[0]), Number(number_id[1]));
|
||||
}, 1000);
|
||||
// Додаємо обробник закриття попапу
|
||||
const popup = document.getElementById('card-new-date');
|
||||
if (!popup.dataset.listenerAdded) {
|
||||
popup.addEventListener('click', (e) => {
|
||||
if (!popup.querySelector('.mess').contains(e.target)) {
|
||||
this.dateEditor.close();
|
||||
}
|
||||
});
|
||||
popup.dataset.listenerAdded = 'true';
|
||||
}
|
||||
},
|
||||
|
||||
function handleCancel() {
|
||||
const holdDuration = Date.now() - startTime; // Считаем, сколько длилось нажатие
|
||||
// Робота з WebSocket
|
||||
cloud: {
|
||||
start(name) {
|
||||
if (!name) return;
|
||||
Card.username = name;
|
||||
|
||||
if (holdDuration < 1000) {
|
||||
clearTimeout(holdTimer); // Если нажали менее 1 секунды, сбрасываем таймер
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const ws = new WebSocket(`${CONFIG.wss}?uuid=${uuid}`);
|
||||
Card.socket = ws;
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("[WebSocket] З'єднання встановлено");
|
||||
Card.cloud.setStatus('ok');
|
||||
ws.send(JSON.stringify({
|
||||
event: 'connection',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
uuid,
|
||||
username: name,
|
||||
data: {}
|
||||
}));
|
||||
Card.reconnectAttempts = 0;
|
||||
clearTimeout(Card.reconnectTimeout);
|
||||
};
|
||||
|
||||
ws.onmessage = (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.event === 'connection' && data.username !== Card.username) {
|
||||
console.log(`Новий користувач: ${data.username}`);
|
||||
}
|
||||
if (data.event === 'message') {
|
||||
Card.cloud.update(data);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
console.warn("[WebSocket] З'єднання розірвано");
|
||||
Card.cloud.setStatus('err');
|
||||
Card.reconnectAttempts++;
|
||||
if (Card.reconnectAttempts <= 5) {
|
||||
Card.reconnectTimeout = setTimeout(() => {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}, 1000);
|
||||
} else {
|
||||
if (confirm("З'єднання розірвано! Перепідключитись?")) {
|
||||
Card.reconnectAttempts = 0;
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = (err) => {
|
||||
console.error("[WebSocket] Помилка", err);
|
||||
Card.cloud.setStatus('err');
|
||||
};
|
||||
},
|
||||
|
||||
setStatus(mode) {
|
||||
const ids = ['cloud_1', 'cloud_2', 'cloud_3'];
|
||||
ids.forEach((id, idx) => {
|
||||
const el = document.getElementById(id);
|
||||
el.setAttribute('data-state', ['sync', 'ok', 'err'].indexOf(mode) === idx ? 'active' : '');
|
||||
});
|
||||
},
|
||||
|
||||
update(msg) {
|
||||
if (msg.type !== "apartment" && msg.type !== "building") return;
|
||||
|
||||
const [bg, color] = Card.color_status[msg.data.status];
|
||||
|
||||
const id = msg.data.id;
|
||||
const el = document.getElementById(`status_${id}`);
|
||||
const redDot = document.getElementById(`redDot_${id}`);
|
||||
|
||||
if (msg.type === "building") {
|
||||
redDot.style = `background:${bg};border:2px solid ${color}`;
|
||||
const apt = Card.listBuilding.find(e => e.id === id);
|
||||
|
||||
if (!apt) return;
|
||||
|
||||
apt.status = msg.data.status;
|
||||
apt.description = msg.data.description;
|
||||
apt.updated_at = msg.data.updated_at;
|
||||
} else if (msg.type === "apartment") {
|
||||
if (!el) return;
|
||||
|
||||
document.getElementById(`card_${id}`).style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
el.value = msg.data.status;
|
||||
el.style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
document.getElementById(`description_${id}`).value = msg.data.description;
|
||||
document.getElementById(`date_text_${id}`).innerText = formattedDateTime(msg.data.updated_at);
|
||||
}
|
||||
},
|
||||
|
||||
messApartment({ number, id, update, time }) {
|
||||
const apt = Card.listApartment[number]?.find(e => e.id === id);
|
||||
if (!apt) return;
|
||||
|
||||
const statusEl = document.getElementById(`status_${id}`);
|
||||
const descEl = document.getElementById(`description_${id}`);
|
||||
|
||||
let date = () => {
|
||||
if (!update && !time) {
|
||||
return apt.updated_at;
|
||||
} else if (update && !time) {
|
||||
return getTimeInSeconds();
|
||||
} else if (update && time) {
|
||||
return getTimeInSeconds(time);
|
||||
}
|
||||
}
|
||||
|
||||
apt.status = Number(statusEl.value);
|
||||
apt.description = descEl.value;
|
||||
apt.updated_at = date();
|
||||
|
||||
const [bg, color] = Card.color_status[apt.status];
|
||||
statusEl.style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
const message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
username: Card.username,
|
||||
type: "apartment",
|
||||
data: {
|
||||
...apt,
|
||||
sheep_id: USER.id
|
||||
}
|
||||
};
|
||||
|
||||
if (Card.socket?.readyState === WebSocket.OPEN) {
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
} else {
|
||||
if (confirm("З'єднання розірвано! Перепідключитись?")) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
messBuildings({ id, update, time }) {
|
||||
const apt = Card.listBuilding.find(e => e.id === id);
|
||||
if (!apt) return;
|
||||
|
||||
const statusEl = document.getElementById(`status_${id}`);
|
||||
const descEl = document.getElementById(`description_${id}`);
|
||||
|
||||
let date = () => {
|
||||
if (!update && !time) {
|
||||
return apt.updated_at;
|
||||
} else if (update && !time) {
|
||||
return getTimeInSeconds();
|
||||
} else if (update && time) {
|
||||
return getTimeInSeconds(time);
|
||||
}
|
||||
}
|
||||
|
||||
apt.status = Number(statusEl.value);
|
||||
apt.description = descEl.value;
|
||||
apt.updated_at = date();
|
||||
|
||||
const [bg, color] = Card.color_status[apt.status];
|
||||
statusEl.style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
const message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
username: Card.username,
|
||||
type: "building",
|
||||
data: {
|
||||
...apt,
|
||||
sheep_id: USER.id
|
||||
}
|
||||
};
|
||||
|
||||
if (Card.socket?.readyState === WebSocket.OPEN) {
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
} else {
|
||||
if (confirm("З'єднання розірвано! Перепідключитись?")) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// let color_status = [
|
||||
// "#000000",
|
||||
// "#C16917",
|
||||
// "#b10202",
|
||||
// "#3d3d3d",
|
||||
// "#11734b",
|
||||
// "#6cc5fc",
|
||||
// "#5a3286"
|
||||
// ];
|
||||
|
||||
// let color_status = [
|
||||
// ["#ffffff", "#000000"],
|
||||
// ["#e7af32", "#ffffff"],
|
||||
// ["#fc2a2a", "#ffffff"],
|
||||
// ["#3d3d3d", "#ffffff"],
|
||||
// ["#11a568", "#ffffff"],
|
||||
// ["#6cc5fc", "#ffffff"],
|
||||
// ["#b381eb", "#ffffff"]
|
||||
// ];
|
||||
|
||||
let color_status = [
|
||||
["var(--ColorThemes2)", "var(--ColorThemes3)"],
|
||||
["#fbf1e0", "#ff8300"],
|
||||
["#fce3e2", "#ff0000"],
|
||||
["#d7ddec", "#2919bd"],
|
||||
["#d5e9dd", "#11a568"],
|
||||
["#d7ebfa", "#3fb4fc"],
|
||||
["#e8dbf5", "#b381eb"]
|
||||
];
|
||||
|
||||
function start(name) {
|
||||
if (!name) return;
|
||||
|
||||
|
||||
document.getElementById("hash").innerText = `HASH: ${name}`
|
||||
username = name;
|
||||
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
socket = new WebSocket(`${CONFIG.wss}?uuid=${uuid}`);
|
||||
|
||||
socket.onopen = function (e) {
|
||||
console.log("[WebSocket | open] Соединение установлено");
|
||||
document.getElementById("status").innerText = "WebSocket | open";
|
||||
|
||||
const message = {
|
||||
event: 'connection',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
uuid: uuid,
|
||||
username: name,
|
||||
data: {
|
||||
id: 1,
|
||||
entrance_id: 1,
|
||||
apartment_number: 1,
|
||||
title: "1",
|
||||
group_number: 1,
|
||||
status: 1,
|
||||
description: "",
|
||||
created_at: 1727541827,
|
||||
updated_at: 1727541827
|
||||
// Отримання під’їздів
|
||||
async getEntrances({ house_id = Card.id, update = false }) {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const res = await fetch(`${CONFIG.api}/house/${house_id}/entrances`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
this.listEntrances = data;
|
||||
|
||||
const container = document.getElementById('list');
|
||||
if (!update) container.innerHTML = "";
|
||||
|
||||
if (update) {
|
||||
for (const { id, entrance_number } of data) {
|
||||
this.getApartment({ id, number: entrance_number, update: true });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
socket.send(JSON.stringify(message))
|
||||
};
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
socket.onmessage = function (event) {
|
||||
let data = JSON.parse(event.data)
|
||||
const canManage = USER.mode === 2 || (USER.mode === 1 && USER.possibilities.can_manager_territory);
|
||||
|
||||
if (data.event == 'connection') {
|
||||
if (data.username == username) return
|
||||
for (const element of data) {
|
||||
const { id, entrance_number, title, history, working } = element;
|
||||
const isMy = ((history.name === "Групова" && history.group_id == USER.group_id) || history.name === USER.name);
|
||||
|
||||
console.log(`Добавлен новый пользователь по имени ${data.username}`);
|
||||
} else if (data.event == 'message') {
|
||||
update(data);
|
||||
const show = (isMy && working) ? "open" : canManage ? "close" : null;
|
||||
if (!show) continue;
|
||||
|
||||
if (data.username == username) return
|
||||
const icon = isMy && working
|
||||
? `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M 12 1 C 9.1277778 1 6.7189086 3.0461453 6.1230469 5.7871094 L 8.078125 6.2128906 C 8.4822632 4.3538547 10.072222 3 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>`
|
||||
: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M 12 1 C 8.6761905 1 6 3.6761905 6 7 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 8 8 L 8 7 C 8 4.7238095 9.7238095 3 12 3 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>`;
|
||||
|
||||
console.log(`${data.username} пишет: `, data.data);
|
||||
const details = document.createElement('details');
|
||||
if (show === "open") details.setAttribute('open', '');
|
||||
details.innerHTML = `
|
||||
<summary><p>${title}</p>${icon}</summary>
|
||||
<div id="apartments_${id}" class="apartments_list"></div>
|
||||
`;
|
||||
fragment.appendChild(details);
|
||||
|
||||
this.getApartment({ id, number: entrance_number, update: false });
|
||||
}
|
||||
};
|
||||
|
||||
socket.onclose = function (event) {
|
||||
if (event.wasClean) {
|
||||
document.getElementById("status").innerText = "WebSocket | close"
|
||||
console.log(`[WebSocket | close] Соединение закрыто чисто, код=${event.code} причина=${event.reason}`);
|
||||
container.appendChild(fragment);
|
||||
},
|
||||
|
||||
async getApartment({ id, number, update }) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const res = await fetch(`${CONFIG.api}/apartment/${id}`, {
|
||||
headers: { "Authorization": uuid }
|
||||
});
|
||||
const data = await res.json();
|
||||
this.listApartment[number] = data;
|
||||
|
||||
const sort_mode = localStorage.getItem('sort_mode') ?? "1";
|
||||
const sorters = {
|
||||
"1": (a, b) => a.apartment_number - b.apartment_number,
|
||||
"2": (a, b) => b.apartment_number - a.apartment_number,
|
||||
"3": (a, b) => a.updated_at - b.updated_at,
|
||||
"4": (a, b) => b.updated_at - a.updated_at,
|
||||
};
|
||||
data.sort(sorters[sort_mode] || sorters["1"]);
|
||||
|
||||
const container = document.getElementById(`apartments_${id}`);
|
||||
if (!update) container.innerHTML = "";
|
||||
|
||||
const statusOptions = (selected) => {
|
||||
const labels = ["", "Відмова (Не цікавить)", "Не заходити (Груба відмова)", "Нема домофона", "Повторна відвідина", "Немає вдома", "Свідки Єгови"];
|
||||
return labels.map((txt, i) => `<option value="${i}" ${i === selected ? "selected" : ""}>${txt}</option>`).join("");
|
||||
};
|
||||
|
||||
if (update) {
|
||||
for (const apt of data) {
|
||||
const [bg, color] = this.color_status[apt.status];
|
||||
const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
const dateEl = document.getElementById(`date_${apt.id}`);
|
||||
const cardEl = document.getElementById(`card_${apt.id}`);
|
||||
const statusEl = document.getElementById(`status_${apt.id}`);
|
||||
const dateTextEl = document.getElementById(`date_text_${apt.id}`);
|
||||
const descEl = document.getElementById(`description_${apt.id}`);
|
||||
|
||||
if (cardEl) cardEl.style = style;
|
||||
if (statusEl) {
|
||||
statusEl.value = apt.status;
|
||||
statusEl.style = style;
|
||||
}
|
||||
if (dateEl) dateEl.setAttribute('onclick', `Card.dateEditor.open({id: ${apt.id}, number: ${number}, updated_at: ${apt.updated_at}})`);
|
||||
if (dateTextEl) dateTextEl.innerText = formattedDateTime(apt.updated_at);
|
||||
if (descEl) descEl.innerText = apt.description ?? "";
|
||||
}
|
||||
} else {
|
||||
document.getElementById("status").innerText = "WebSocket | close"
|
||||
console.log('[WebSocket | close] Соединение прервано');
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// setTimeout(function() {
|
||||
// start(username);
|
||||
// }, 1000);
|
||||
if (data.length == 0) {
|
||||
const p = document.createElement('p');
|
||||
|
||||
const result = confirm(`З'єднання розірвано! Перепідключитись?`);
|
||||
if (result) {
|
||||
getEntrances();
|
||||
start(username);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
socket.onerror = function (error) {
|
||||
console.log(`[WebSocket | error]`);
|
||||
document.getElementById("status").innerText = "WebSocket | error"
|
||||
};
|
||||
}
|
||||
|
||||
function mess(entrance_number, id, date_type) {
|
||||
let sort_mode = localStorage.getItem('sort_mode') ?? true;
|
||||
console.log(id, listApartment[entrance_number]);
|
||||
|
||||
const pos = listApartment[entrance_number].map(e => e.id).indexOf(id);
|
||||
let apartment = listApartment[entrance_number][pos];
|
||||
|
||||
console.log(pos, apartment);
|
||||
|
||||
|
||||
let status = document.getElementById(`status_${id}`);
|
||||
let description = document.getElementById(`description_${id}`);
|
||||
let date = new Date(document.getElementById(`date_${id}`).value);
|
||||
const timestamp = date.getTime();
|
||||
|
||||
apartment.description = description.value;
|
||||
apartment.status = Number(status.value);
|
||||
apartment.updated_at = date_type ? getTimeInSeconds(timestamp) : getTimeInSeconds(),
|
||||
|
||||
|
||||
status.style.backgroundColor = color_status[status.value][0];
|
||||
status.style.color = color_status[status.value][1];
|
||||
status.style.border = `1px solid ${color_status[status.value][1]}`;
|
||||
|
||||
let user_hash = localStorage.getItem('hash');
|
||||
|
||||
let message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
hash: user_hash,
|
||||
username: username,
|
||||
data: {
|
||||
id: apartment.id,
|
||||
entrance_id: apartment.entrance_id,
|
||||
apartment_number: apartment.apartment_number,
|
||||
title: apartment.title,
|
||||
group_number: apartment.group_number,
|
||||
status: apartment.status,
|
||||
description: apartment.description,
|
||||
updated_at: apartment.updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
socket.send(JSON.stringify(message));
|
||||
|
||||
if (!date_type && sort_mode != 'false') sort(apartment.id, apartment.entrance_id);
|
||||
}
|
||||
|
||||
function update(message) {
|
||||
if (!document.getElementById(`status_${message.data.id}`)) return;
|
||||
|
||||
let now = new Date(message.data.updated_at);
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
|
||||
document.getElementById(`card_${message.data.id}`).style.backgroundColor = color_status[message.data.status][0];
|
||||
document.getElementById(`card_${message.data.id}`).style.color = color_status[message.data.status][1];
|
||||
document.getElementById(`card_${message.data.id}`).style.border = `1px solid ${color_status[message.data.status][1]}`;
|
||||
|
||||
document.getElementById(`status_${message.data.id}`).style.backgroundColor = color_status[message.data.status][0];
|
||||
document.getElementById(`status_${message.data.id}`).style.color = color_status[message.data.status][1];
|
||||
document.getElementById(`status_${message.data.id}`).style.border = `1px solid ${color_status[message.data.status][1]}`;
|
||||
|
||||
|
||||
|
||||
document.getElementById(`status_${message.data.id}`).value = message.data.status;
|
||||
document.getElementById(`description_${message.data.id}`).value = message.data.description;
|
||||
document.getElementById(`date_${message.data.id}`).value = now.toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
function getEntrances(house_id = house) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/house/${house_id}/entrances`;
|
||||
fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
listEntrances = data;
|
||||
|
||||
document.getElementById('list').innerHTML = "";
|
||||
|
||||
for (let i = 0; i < listEntrances.length; i++) {
|
||||
const element = listEntrances[i];
|
||||
|
||||
let status = () => {
|
||||
if ((element.history.name == "Групова" || element.history.name == USER.name) && element.working) return "open";
|
||||
else if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_manager_territory)) return "close";
|
||||
|
||||
return "style='display: none;'"
|
||||
}
|
||||
|
||||
let statusIcon = () => {
|
||||
if ((element.history.name == "Групова" || element.history.name == USER.name) && element.working) return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M 12 1 C 9.1277778 1 6.7189086 3.0461453 6.1230469 5.7871094 L 8.078125 6.2128906 C 8.4822632 4.3538547 10.072222 3 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>'
|
||||
else return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 12 1 C 8.6761905 1 6 3.6761905 6 7 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 8 8 L 8 7 C 8 4.7238095 9.7238095 3 12 3 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>'
|
||||
}
|
||||
|
||||
document.getElementById('list').innerHTML += `
|
||||
<details ${status()}>
|
||||
<summary>
|
||||
<p>${element.title}</p>
|
||||
${statusIcon()}
|
||||
</summary>
|
||||
<div id="apartments_${element.id}" class="apartments_list">
|
||||
|
||||
</div>
|
||||
</details>
|
||||
p.innerHTML = `
|
||||
Інформація про цей під'їзд відсутня. Надайте інформацію відповідальному за території.
|
||||
`;
|
||||
getApartment(element.id, element.entrance_number);
|
||||
|
||||
console.log(element);
|
||||
return container.appendChild(p);
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
for (const apt of data) {
|
||||
const [bg, color] = this.color_status[apt.status];
|
||||
const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
function getApartment(entrance_id, entrance_number) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartment/${entrance_id}`;
|
||||
fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
listApartment[entrance_number] = data;
|
||||
const div = document.createElement('div');
|
||||
|
||||
data.sort((a, b) => a.apartment_number - b.apartment_number);
|
||||
div.className = `card_info`;
|
||||
div.id = `card_${apt.id}`;
|
||||
div.style = style;
|
||||
|
||||
data.sort((a, b) => a.updated_at - b.updated_at);
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const element = data[i];
|
||||
|
||||
let now = new Date(element.updated_at);
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
now = now.toISOString().slice(0, 16)
|
||||
|
||||
let disabled = () => {
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_manager_territory)) return '';
|
||||
else if (element.status == 2) return "disabled";
|
||||
}
|
||||
|
||||
document.getElementById(`apartments_${entrance_id}`).innerHTML += `
|
||||
<div id="card_${element.id}" style="border: 1px solid ${color_status[element.status][1]};background: ${color_status[element.status][0]};color: ${color_status[element.status][1]};">
|
||||
<div class="info">
|
||||
<span>кв.${element.title}</span>
|
||||
<select id="status_${element.id}" onchange="mess(${entrance_number}, ${element.id})" style="background-color: ${color_status[element.status][0]}; color: ${color_status[element.status][1]}; border: 1px solid ${color_status[element.status][1]};" ${disabled()}>
|
||||
<option value="0" ${element.status == 0 ? "selected" : ""}></option>
|
||||
<option value="1" ${element.status == 1 ? "selected" : ""}>Відмова</option>
|
||||
<option value="2" ${element.status == 2 ? "selected" : ""}>Не заходити (Груба відмова)</option>
|
||||
<option value="3" ${element.status == 3 ? "selected" : ""}>Нема домофона</option>
|
||||
<option value="4" ${element.status == 4 ? "selected" : ""}>Повторна відвідина</option>
|
||||
<option value="5" ${element.status == 5 ? "selected" : ""}>Немає вдома</option>
|
||||
<option value="6" ${element.status == 6 ? "selected" : ""}>Свідки Єгови</option>
|
||||
</select>
|
||||
<input onchange="mess(${entrance_number}, ${element.id}, true)" name="${entrance_number}-${element.id}" class="hold-button" type="datetime-local" id="date_${element.id}" placeholder="Дата" value="${element.updated_at ? now : ""}" ${disabled()} style="max-width: 170px;">
|
||||
</div>
|
||||
<textarea onchange="mess(${entrance_number}, ${element.id}, true)" id="description_${element.id}" placeholder="Нотатки..." ${disabled()}}>${element.description ?? ""}</textarea>
|
||||
div.innerHTML = `
|
||||
<div class="info">
|
||||
<span>кв.${apt.title}</span>
|
||||
<select id="status_${apt.id}" onchange="Card.cloud.messApartment({number:${number},id:${apt.id},update:true})" style="${style}">
|
||||
${statusOptions(apt.status)}
|
||||
</select>
|
||||
<button id="date_${apt.id}" onclick="Card.dateEditor.open({id:${apt.id},number:${number},updated_at:${apt.updated_at}})">
|
||||
<p id="date_text_${apt.id}">${formattedDateTime(apt.updated_at)}</p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
<textarea id="description_${apt.id}" onchange="Card.cloud.messApartment({number:${number},id:${apt.id}})" placeholder="Коротка нотатка.">${apt.description || ""}</textarea>
|
||||
`;
|
||||
|
||||
fragment.appendChild(div);
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
container.appendChild(fragment);
|
||||
}
|
||||
},
|
||||
|
||||
function sort(id, entrance_id) {
|
||||
let child = document.getElementById(`card_${id}`);
|
||||
getHomestead: {
|
||||
markers: {},
|
||||
|
||||
document.getElementById(`apartments_${entrance_id}`).removeChild(child);
|
||||
async loadAPI({ url }) {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
|
||||
document.getElementById(`apartments_${entrance_id}`).append(child);
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
|
||||
child.style.border = "1px solid var(--PrimaryColor)";
|
||||
}
|
||||
return await response.json();
|
||||
},
|
||||
|
||||
function getTimeInSeconds(time = Date.now()) {
|
||||
// Если время больше 10 знаков (это значит, что время в миллисекундах)
|
||||
if (time.toString().length < 10) {
|
||||
// Округляем до секунд, убирая последние 3 цифры (миллисекунды)
|
||||
time = Math.floor(time * 1000);
|
||||
async map({ homestead_id = Card.id }) {
|
||||
let data = await this.loadAPI({ url: `${CONFIG.api}homestead/${homestead_id}` });
|
||||
|
||||
console.log(data);
|
||||
|
||||
|
||||
let lat = data.geo?.lat ?? data.points?.[0]?.[0]?.[0]?.lat ?? 49.5629016;
|
||||
let lng = data.geo?.lng ?? data.points?.[0]?.[0]?.[0]?.lng ?? 25.6145625;
|
||||
let zoom = 15;
|
||||
|
||||
if (map_card && map_card.remove) {
|
||||
map_card.stopLocate();
|
||||
map_card.remove();
|
||||
}
|
||||
|
||||
const mapElement = document.getElementById('map_card');
|
||||
mapElement.style.display = "flex";
|
||||
if (!mapElement) return;
|
||||
|
||||
let googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
|
||||
});
|
||||
|
||||
let osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
});
|
||||
|
||||
let mytile = L.tileLayer('https://sheep-service.com/map/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
tms: true
|
||||
});
|
||||
|
||||
map_card = L.map(mapElement, {
|
||||
renderer: L.canvas(),
|
||||
center: [lat, lng],
|
||||
zoom,
|
||||
zoomControl: false,
|
||||
layers: [
|
||||
googleHybrid,
|
||||
osm,
|
||||
mytile
|
||||
]
|
||||
});
|
||||
|
||||
// слежение в реальном времени
|
||||
map_card.locate({ setView: false, watch: true, enableHighAccuracy: true });
|
||||
map_card.on('locationfound', (e) => {
|
||||
if (!map_card._userMarker) {
|
||||
map_card._userMarker = L.marker(e.latlng).addTo(map_card)
|
||||
.bindPopup("Ви тут!");
|
||||
} else {
|
||||
map_card._userMarker.setLatLng(e.latlng);
|
||||
}
|
||||
});
|
||||
|
||||
let baseMaps = {
|
||||
"Google Hybrid": googleHybrid,
|
||||
"OpenStreetMap": osm,
|
||||
"Sheep Service Map": mytile,
|
||||
};
|
||||
|
||||
let layerControl = L.control.layers(baseMaps, [], { position: 'bottomright' }).addTo(map_card);
|
||||
|
||||
map_card.pm.setLang("ua");
|
||||
|
||||
const polygonOptions = {
|
||||
color: "#f2bd53",
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '20,15',
|
||||
dashOffset: '20',
|
||||
};
|
||||
|
||||
L.polygon(data.points, polygonOptions).addTo(map_card);
|
||||
|
||||
map_card.setZoom(data.zoom);
|
||||
|
||||
// map_card.getZoom()
|
||||
|
||||
// console.log(data.zoom);
|
||||
|
||||
|
||||
Card.listBuilding = await this.loadAPI({ url: `${CONFIG.api}building/${homestead_id}` });
|
||||
|
||||
const statusOptions = (selected) => {
|
||||
const labels = ["", "Відмова (Не цікавить)", "Не заходити (Груба відмова)", "Нема домофона", "Повторна відвідина", "Немає вдома", "Свідки Єгови"];
|
||||
return labels.map((txt, i) => `<option value="${i}" ${i === selected ? "selected" : ""}>${txt}</option>`).join("");
|
||||
};
|
||||
|
||||
|
||||
// for (let i = 0; i < Card.listBuilding.length; i++) {
|
||||
// const element = Card.listBuilding[i];
|
||||
// const [bg, color] = Card.color_status[element.status];
|
||||
// const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
// const div = document.createElement('div');
|
||||
|
||||
// const redDot = L.divIcon({
|
||||
// className: "leaflet_drop",
|
||||
// html: `<div id="redDot_${element.id}" style='background:${bg};border:2px solid ${color}'></div>`,
|
||||
// iconSize: [16, 16],
|
||||
// iconAnchor: [8, 8]
|
||||
// });
|
||||
|
||||
// div.className = `card_info card_info_homestead`;
|
||||
// div.id = `card_${element.id}`;
|
||||
// div.style = style;
|
||||
|
||||
// div.innerHTML = `
|
||||
// <div class="info">
|
||||
// <select id="status_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id},update:true})" style="${style}">
|
||||
// ${statusOptions(element.status)}
|
||||
// </select>
|
||||
// <button id="date_${element.id}" onclick="Card.dateEditor.open({id:${element.id},updated_at:${element.updated_at}})">
|
||||
// <p id="date_text_${element.id}">${formattedDateTime(element.updated_at)}</p>
|
||||
// <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"></path></svg>
|
||||
// </button>
|
||||
// </div>
|
||||
// <textarea id="description_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id}})" placeholder="Коротка нотатка.">${element.description || ""}</textarea>
|
||||
// `;
|
||||
|
||||
// L.marker(element.geo, { icon: redDot }).addTo(map_card)
|
||||
// .bindPopup(div);
|
||||
// }
|
||||
|
||||
for (let i = 0; i < Card.listBuilding.length; i++) {
|
||||
const element = Card.listBuilding[i];
|
||||
const [bg, color] = Card.color_status[element.status];
|
||||
|
||||
const redDot = L.divIcon({
|
||||
className: "leaflet_drop",
|
||||
html: `<div id="redDot_${element.id}" style='background:${bg};border:2px solid ${color}'></div>`,
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8]
|
||||
});
|
||||
|
||||
// создаём маркер
|
||||
const marker = L.marker(element.geo, { icon: redDot }).addTo(map_card);
|
||||
|
||||
marker.bindPopup("");
|
||||
|
||||
// при открытии popup генерим div заново
|
||||
marker.on("popupopen", () => {
|
||||
const el = Card.listBuilding.find(e => e.id === element.id);
|
||||
const [bg, color] = Card.color_status[el.status];
|
||||
const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "card_info card_info_homestead";
|
||||
div.id = `card_${el.id}`;
|
||||
div.style = style;
|
||||
|
||||
let date = new Date(el.updated_at);
|
||||
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
||||
|
||||
div.innerHTML = `
|
||||
<div class="info">
|
||||
<select id="status_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id},update:true})" style="${style}">
|
||||
${statusOptions(element.status)}
|
||||
</select>
|
||||
<input type="datetime-local" id="date_${element.id}" placeholder="Дата" onchange="Card.cloud.messBuildings({id:${element.id}})" value="${date.toISOString().slice(0, 16)}">
|
||||
</div>
|
||||
<textarea id="description_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id}})" placeholder="Коротка нотатка.">${element.description || ""}</textarea>
|
||||
`;
|
||||
|
||||
marker.setPopupContent(div);
|
||||
});
|
||||
|
||||
Card.getHomestead.markers[element.id] = marker; // сохраним ссылку на маркер
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Сортування
|
||||
sort(mode, load) {
|
||||
const idx = Math.max(1, Math.min(4, Number(mode) || 1));
|
||||
['sort_1', 'sort_2', 'sort_3', 'sort_4'].forEach((id, i) => {
|
||||
document.getElementById(id)?.setAttribute('data-state', i + 1 === idx ? 'active' : '');
|
||||
});
|
||||
localStorage.setItem('sort_mode', idx);
|
||||
if (!load) this.getEntrances({ update: false });
|
||||
},
|
||||
|
||||
// Редактор дати
|
||||
dateEditor: {
|
||||
open({ id, number, updated_at }) {
|
||||
const block = document.getElementById('card-new-date');
|
||||
const input = document.getElementById('card-new-date-input');
|
||||
const button = document.getElementById('card-new-date-button');
|
||||
|
||||
// Приводимо дату до ISO без зсуву часового поясу
|
||||
let date = new Date(updated_at == 0 ? Date.now() : updated_at);
|
||||
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
||||
input.value = date.toISOString().slice(0, 16)
|
||||
|
||||
// Призначаємо обробники
|
||||
input.setAttribute("onchange", `Card.dateEditor.edit({ id: ${id}, number: ${number} })`)
|
||||
button.setAttribute("onclick", `Card.dateEditor.edit({ id: ${id}, number: ${number}, type: 'now'})`)
|
||||
|
||||
|
||||
// Показуємо блок
|
||||
block.style.display = "";
|
||||
requestAnimationFrame(() => block.style.opacity = "1");
|
||||
},
|
||||
close() {
|
||||
// Робимо плавне зникнення
|
||||
const block = document.getElementById('card-new-date');
|
||||
block.style.opacity = "0";
|
||||
|
||||
const onTransitionEnd = () => {
|
||||
block.style.display = "none";
|
||||
block.removeEventListener("transitionend", onTransitionEnd);
|
||||
};
|
||||
block.addEventListener("transitionend", onTransitionEnd);
|
||||
},
|
||||
edit({ id, number, type }) {
|
||||
let input = document.getElementById('card-new-date-input').value;
|
||||
|
||||
if (type == "now") {
|
||||
Card.cloud.messApartment({ number: number, id: id, update: true });
|
||||
} else {
|
||||
if (input) {
|
||||
const ts = new Date(input).getTime();
|
||||
Card.cloud.messApartment({ number, id, update: true, time: ts });
|
||||
} else {
|
||||
Card.cloud.messApartment({ number: number, id: id });
|
||||
}
|
||||
}
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
452
web/lib/pages/card/script_old.js
Normal file
452
web/lib/pages/card/script_old.js
Normal file
@@ -0,0 +1,452 @@
|
||||
|
||||
const Card = {
|
||||
socket: null,
|
||||
reconnectTimeout: null,
|
||||
reconnectNumber: 0,
|
||||
username: null,
|
||||
listEntrances: [],
|
||||
listApartment: [],
|
||||
color_status: [
|
||||
["var(--ColorThemes2)", "var(--ColorThemes3)"],
|
||||
["#fbf1e0", "#ff8300"],
|
||||
["#fce3e2", "#ff0000"],
|
||||
["#d7ddec", "#2919bd"],
|
||||
["#d5e9dd", "#11a568"],
|
||||
["#d7ebfa", "#3fb4fc"],
|
||||
["#e8dbf5", "#b381eb"]
|
||||
],
|
||||
init: async (type, id) => {
|
||||
let html = await fetch('/lib/pages/card/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
house = id;
|
||||
|
||||
if (Card.socket) Card.socket.close(1000, "Перезапуск соединения");
|
||||
|
||||
Card.sort(localStorage.getItem('sort_mode'), false)
|
||||
|
||||
if (type == "house") {
|
||||
Card.getEntrances({ update: false });
|
||||
Card.cloud.start(makeid(6));
|
||||
}
|
||||
|
||||
|
||||
// Закриття вікно popup при натисканні за його межі
|
||||
const block_card = document.getElementById('card-new-date');
|
||||
const mess = block_card.querySelector('.mess');
|
||||
if (!block_card.dataset.listenerAdded) {
|
||||
block_card.addEventListener('click', function (event) {
|
||||
if (!mess.contains(event.target)) {
|
||||
Card.dateEditor.close();
|
||||
}
|
||||
});
|
||||
block_card.dataset.listenerAdded = 'true';
|
||||
}
|
||||
},
|
||||
cloud: {
|
||||
status: (mode) => {
|
||||
|
||||
let cloud_1 = document.getElementById('cloud_1');
|
||||
let cloud_2 = document.getElementById('cloud_2');
|
||||
let cloud_3 = document.getElementById('cloud_3');
|
||||
|
||||
switch (mode) {
|
||||
case 'sync':
|
||||
cloud_1.setAttribute('data-state', 'active');
|
||||
cloud_2.setAttribute('data-state', '');
|
||||
cloud_3.setAttribute('data-state', '');
|
||||
break;
|
||||
case 'ok':
|
||||
cloud_1.setAttribute('data-state', '');
|
||||
cloud_2.setAttribute('data-state', 'active');
|
||||
cloud_3.setAttribute('data-state', '');
|
||||
break;
|
||||
case 'err':
|
||||
cloud_1.setAttribute('data-state', '');
|
||||
cloud_2.setAttribute('data-state', '');
|
||||
cloud_3.setAttribute('data-state', 'active');
|
||||
break;
|
||||
}
|
||||
},
|
||||
start: (name) => {
|
||||
if (!name) return;
|
||||
|
||||
Card.username = name;
|
||||
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
Card.socket = new WebSocket(`${CONFIG.wss}?uuid=${uuid}`);
|
||||
|
||||
Card.socket.onopen = function (e) {
|
||||
console.log("[WebSocket | open] З'єднання встановлено");
|
||||
Card.cloud.status('ok');
|
||||
|
||||
const message = {
|
||||
event: 'connection',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
uuid: uuid,
|
||||
username: name,
|
||||
data: {
|
||||
id: 1,
|
||||
entrance_id: 1,
|
||||
apartment_number: 1,
|
||||
title: "1",
|
||||
group_number: 1,
|
||||
status: 1,
|
||||
description: "",
|
||||
created_at: 1727541827,
|
||||
updated_at: 1727541827
|
||||
}
|
||||
}
|
||||
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
|
||||
Card.reconnectNumber = 0;
|
||||
clearTimeout(Card.reconnectTimeout);
|
||||
};
|
||||
|
||||
Card.socket.onmessage = function (event) {
|
||||
let data = JSON.parse(event.data)
|
||||
|
||||
if (data.event == 'connection') {
|
||||
if (data.username == Card.username) return
|
||||
|
||||
console.log(`Доданий новий користувач на ім'я ${data.username}`);
|
||||
} else if (data.event == 'message') {
|
||||
Card.cloud.update(data);
|
||||
|
||||
if (data.username == Card.username) return
|
||||
|
||||
console.log(`${data.username} пише: `, data.data);
|
||||
}
|
||||
};
|
||||
|
||||
Card.socket.onclose = function (event) {
|
||||
if (event.wasClean) {
|
||||
console.log(`[WebSocket | close] З'єднання закрито чисто, код =${event.code} причина=${event.reason}`);
|
||||
Card.cloud.status('err');
|
||||
} else {
|
||||
console.log(`[WebSocket | close] З'єднання перервано`);
|
||||
Card.cloud.status('err');
|
||||
|
||||
Card.reconnectTimeout = setTimeout(function () {
|
||||
Card.reconnectNumber++;
|
||||
if (Card.reconnectNumber > 5) {
|
||||
Card.reconnectNumber = 0;
|
||||
clearTimeout(Card.reconnectTimeout);
|
||||
|
||||
const result = confirm(`З'єднання розірвано! Перепідключитись?`);
|
||||
if (result) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
} else {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
Card.socket.onerror = function (error) {
|
||||
console.log(`[WebSocket | error]`);
|
||||
Card.cloud.status('err');
|
||||
};
|
||||
},
|
||||
mess: ({ number, id, update, time }) => {
|
||||
const pos = Card.listApartment[number].map(e => e.id).indexOf(id);
|
||||
let apartment = Card.listApartment[number][pos];
|
||||
|
||||
|
||||
let status = document.getElementById(`status_${id}`);
|
||||
let description = document.getElementById(`description_${id}`);
|
||||
|
||||
let date = () => {
|
||||
if (!update && !time) {
|
||||
return apartment.updated_at;
|
||||
} else if (update && !time) {
|
||||
return getTimeInSeconds();
|
||||
} else if (update && time) {
|
||||
return getTimeInSeconds(time);
|
||||
}
|
||||
}
|
||||
|
||||
apartment.description = description.value;
|
||||
apartment.status = Number(status.value);
|
||||
apartment.updated_at = date();
|
||||
|
||||
status.style.backgroundColor = Card.color_status[status.value][0];
|
||||
status.style.color = Card.color_status[status.value][1];
|
||||
status.style.border = `1px solid ${Card.color_status[status.value][1]}`;
|
||||
|
||||
let message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
|
||||
username: Card.username,
|
||||
data: {
|
||||
id: apartment.id,
|
||||
entrance_id: apartment.entrance_id,
|
||||
apartment_number: apartment.apartment_number,
|
||||
title: apartment.title,
|
||||
group_number: apartment.group_number,
|
||||
status: apartment.status,
|
||||
description: apartment.description,
|
||||
updated_at: apartment.updated_at,
|
||||
sheep_id: USER.id
|
||||
}
|
||||
}
|
||||
|
||||
if (Card.socket && Card.socket.readyState === WebSocket.OPEN) {
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
} else {
|
||||
console.warn("WebSocket не підключено. Повідомлення не надіслано.");
|
||||
const result = confirm(`З'єднання розірвано! Перепідключитись?`);
|
||||
if (result) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.start(Card.username);
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
let sort_mode = localStorage.getItem('sort_mode') ?? '1';
|
||||
|
||||
if (sort_mode == '3') {
|
||||
let child = document.getElementById(`card_${apartment.id}`);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).removeChild(child);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).append(child);
|
||||
child.style.border = "1px solid var(--PrimaryColor)";
|
||||
} else if (sort_mode == '4') {
|
||||
let child = document.getElementById(`card_${apartment.id}`);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).removeChild(child);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).prepend(child);
|
||||
child.style.border = "1px solid var(--PrimaryColor)";
|
||||
}
|
||||
}
|
||||
},
|
||||
update: (message) => {
|
||||
if (!document.getElementById(`status_${message.data.id}`)) return;
|
||||
|
||||
document.getElementById(`card_${message.data.id}`).style.backgroundColor = Card.color_status[message.data.status][0];
|
||||
document.getElementById(`card_${message.data.id}`).style.color = Card.color_status[message.data.status][1];
|
||||
document.getElementById(`card_${message.data.id}`).style.border = `1px solid ${Card.color_status[message.data.status][1]}`;
|
||||
|
||||
document.getElementById(`status_${message.data.id}`).style.backgroundColor = Card.color_status[message.data.status][0];
|
||||
document.getElementById(`status_${message.data.id}`).style.color = Card.color_status[message.data.status][1];
|
||||
document.getElementById(`status_${message.data.id}`).style.border = `1px solid ${Card.color_status[message.data.status][1]}`;
|
||||
|
||||
|
||||
|
||||
document.getElementById(`status_${message.data.id}`).value = message.data.status;
|
||||
document.getElementById(`description_${message.data.id}`).value = message.data.description;
|
||||
document.getElementById(`date_text_${message.data.id}`).innerText = formattedDateTime(message.data.updated_at);
|
||||
}
|
||||
},
|
||||
getEntrances: ({ house_id = house, update = false }) => {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/house/${house_id}/entrances`;
|
||||
fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
Card.listEntrances = data;
|
||||
|
||||
const element_list = document.getElementById('list');
|
||||
|
||||
if (update) {
|
||||
for (let i = 0; i < Card.listEntrances.length; i++) {
|
||||
const element = Card.listEntrances[i];
|
||||
Card.getApartment({ id: element.id, number: element.entrance_number, update: update });
|
||||
}
|
||||
} else {
|
||||
element_list.innerHTML = "";
|
||||
for (let i = 0; i < Card.listEntrances.length; i++) {
|
||||
const element = Card.listEntrances[i];
|
||||
|
||||
let status = () => {
|
||||
if ((element.history.name == "Групова" || element.history.name == USER.name) && element.working) return "open";
|
||||
else if (USER.mode == 2 || (USER.mode == 1 && USER.possibilities.can_manager_territory)) return "close";
|
||||
else return "style='display: none;'"
|
||||
}
|
||||
|
||||
let statusIcon = () => {
|
||||
if ((element.history.name == "Групова" || element.history.name == USER.name) && element.working) return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M 12 1 C 9.1277778 1 6.7189086 3.0461453 6.1230469 5.7871094 L 8.078125 6.2128906 C 8.4822632 4.3538547 10.072222 3 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>'
|
||||
else return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 12 1 C 8.6761905 1 6 3.6761905 6 7 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 8 8 L 8 7 C 8 4.7238095 9.7238095 3 12 3 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>'
|
||||
}
|
||||
|
||||
element_list.innerHTML += `
|
||||
<details ${status()}>
|
||||
<summary>
|
||||
<p>${element.title}</p>
|
||||
${statusIcon()}
|
||||
</summary>
|
||||
<div id="apartments_${element.id}" class="apartments_list">
|
||||
|
||||
</div>
|
||||
</details>
|
||||
`;
|
||||
Card.getApartment({ id: element.id, number: element.entrance_number, update: false });
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
getApartment: ({ id, number, update }) => {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartment/${id}`;
|
||||
fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
Card.listApartment[number] = data;
|
||||
|
||||
if (update) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const element = data[i];
|
||||
|
||||
let now = new Date(element.updated_at);
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
now = now.toISOString().slice(0, 16)
|
||||
|
||||
document.getElementById(`card_${element.id}`).setAttribute('style', `border: 1px solid ${Card.color_status[element.status][1]};background: ${Card.color_status[element.status][0]};color: ${Card.color_status[element.status][1]};`);
|
||||
document.getElementById(`status_${element.id}`).value = element.status;
|
||||
document.getElementById(`status_${element.id}`).setAttribute('style', `background-color: ${Card.color_status[element.status][0]}; color: ${Card.color_status[element.status][1]}; border: 1px solid ${Card.color_status[element.status][1]};`);
|
||||
document.getElementById(`date_${element.id}`).setAttribute('onclick', `Card.dateEditor.open({id: ${element.id}, number: ${number}, updated_at: ${element.updated_at}})`);
|
||||
document.getElementById(`date_text_${element.id}`).innerText = element.updated_at ? formattedDateTime(element.updated_at) : "0.0.0000 00:00";
|
||||
document.getElementById(`description_${element.id}`).innerText = element.description ?? "";
|
||||
}
|
||||
} else {
|
||||
let sort_mode = localStorage.getItem('sort_mode') ?? 1;
|
||||
|
||||
if (sort_mode == "1")
|
||||
data.sort((a, b) => a.apartment_number - b.apartment_number);
|
||||
else if (sort_mode == "2")
|
||||
data.sort((a, b) => b.apartment_number - a.apartment_number);
|
||||
else if (sort_mode == "3")
|
||||
data.sort((a, b) => a.updated_at - b.updated_at);
|
||||
else if (sort_mode == "4")
|
||||
data.sort((a, b) => b.updated_at - a.updated_at);
|
||||
else
|
||||
data.sort((a, b) => a.apartment_number - b.apartment_number);
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const element = data[i];
|
||||
|
||||
let now = new Date(element.updated_at);
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
now = now.toISOString().slice(0, 16)
|
||||
|
||||
let disabled = () => {
|
||||
if (USER.possibilities.can_manager_territory) return '';
|
||||
else if (element.status == 2) return "disabled";
|
||||
}
|
||||
|
||||
document.getElementById(`apartments_${id}`).innerHTML += `
|
||||
<div id="card_${element.id}" style="border: 1px solid ${Card.color_status[element.status][1]};background: ${Card.color_status[element.status][0]};color: ${Card.color_status[element.status][1]};">
|
||||
<div class="info">
|
||||
<span>кв.${element.title}</span>
|
||||
<select id="status_${element.id}" onchange="Card.cloud.mess({ number: ${number}, id: ${element.id}, update: true})" style="background-color: ${Card.color_status[element.status][0]}; color: ${Card.color_status[element.status][1]}; border: 1px solid ${Card.color_status[element.status][1]};" ${disabled()}>
|
||||
<option value="0" ${element.status == 0 ? "selected" : ""}></option>
|
||||
<option value="1" ${element.status == 1 ? "selected" : ""}>Не цікавить</option>
|
||||
<option value="2" ${element.status == 2 ? "selected" : ""}>Не заходити (Груба відмова)</option>
|
||||
<option value="3" ${element.status == 3 ? "selected" : ""}>Нема домофона</option>
|
||||
<option value="4" ${element.status == 4 ? "selected" : ""}>Повторна відвідина</option>
|
||||
<option value="5" ${element.status == 5 ? "selected" : ""}>Немає вдома</option>
|
||||
<option value="6" ${element.status == 6 ? "selected" : ""}>Свідки Єгови</option>
|
||||
</select>
|
||||
<button placeholder="Дата" id="date_${element.id}" onclick="Card.dateEditor.open({id: ${element.id}, number: ${number}, updated_at: ${element.updated_at}})" ${disabled()}>
|
||||
<p id="date_text_${element.id}">${element.updated_at ? formattedDateTime(element.updated_at) : "0.0.0000 00:00"}</p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
|
||||
<path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<textarea onchange="Card.cloud.mess({ number: ${number}, id: ${element.id}})" id="description_${element.id}" placeholder="Нотатки..." ${disabled()}}>${element.description ?? ""}</textarea>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
sort: (mode, load) => {
|
||||
const sortIds = ['sort_1', 'sort_2', 'sort_3', 'sort_4'];
|
||||
|
||||
sortIds.forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.setAttribute('data-state', '');
|
||||
});
|
||||
|
||||
let index = parseInt(mode, 10);
|
||||
if (isNaN(index) || index < 1 || index > 4) index = 1;
|
||||
|
||||
const activeEl = document.getElementById(`sort_${index}`);
|
||||
if (activeEl) activeEl.setAttribute('data-state', 'active');
|
||||
|
||||
localStorage.setItem('sort_mode', index.toString());
|
||||
|
||||
if (!load) Card.getEntrances({ update: false });
|
||||
},
|
||||
dateEditor: {
|
||||
open: ({ id, number, updated_at }) => {
|
||||
const block = document.getElementById('card-new-date');
|
||||
const card_new_date_input = document.getElementById('card-new-date-input');
|
||||
const card_new_date_button = document.getElementById('card-new-date-button');
|
||||
|
||||
let now = new Date(updated_at);
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
now = now.toISOString().slice(0, 16)
|
||||
|
||||
card_new_date_input.value = now;
|
||||
card_new_date_input.setAttribute("onchange", `Card.dateEditor.edit({ id: ${id}, number: ${number} })`)
|
||||
card_new_date_button.setAttribute("onclick", `Card.dateEditor.edit({ id: ${id}, number: ${number}, type: 'now'})`)
|
||||
|
||||
block.style.display = "";
|
||||
setTimeout(() => {
|
||||
block.style.opacity = "1";
|
||||
}, 100)
|
||||
|
||||
},
|
||||
close: () => {
|
||||
const block = document.getElementById('card-new-date');
|
||||
|
||||
block.style.opacity = "0";
|
||||
setTimeout(() => {
|
||||
block.style.display = "none";
|
||||
}, 200)
|
||||
},
|
||||
edit: ({ id, number, type }) => {
|
||||
const card_new_date_input = document.getElementById('card-new-date-input');
|
||||
|
||||
if (type == "now") {
|
||||
Card.cloud.mess({ number: number, id: id, update: true });
|
||||
} else {
|
||||
if (card_new_date_input.value) {
|
||||
let date = new Date(card_new_date_input.value);
|
||||
const timestamp = date.getTime();
|
||||
Card.cloud.mess({ number: number, id: id, update: true, time: timestamp });
|
||||
} else {
|
||||
Card.cloud.mess({ number: number, id: id });
|
||||
}
|
||||
}
|
||||
|
||||
Card.dateEditor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,150 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
|
||||
.page-card>.list-controls {
|
||||
padding: 10px;
|
||||
margin: 0px 0 10px 0;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#page-card-sort {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-card-sort button {
|
||||
display: none;
|
||||
font-size: 18px;
|
||||
background: 0;
|
||||
cursor: pointer;
|
||||
min-width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin-right: 10px;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: calc(var(--border-radius) - 5px - 2px);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
}
|
||||
|
||||
#page-card-sort button[data-state="active"] {
|
||||
background: var(--PrimaryColor);
|
||||
}
|
||||
|
||||
#page-card-sort button:hover {
|
||||
background: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#page-card-sort button>svg {
|
||||
width: 22px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#page-card-sort button:hover svg {
|
||||
fill: var(--ColorThemes1);
|
||||
}
|
||||
|
||||
#page-card-sort button:hover {
|
||||
display: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#page-card-sort button[data-state="active"] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-card-status {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-card-status>div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-card-status>div[data-state="active"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
#page-card-status>div>svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: var(--ColorThemes3);
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
|
||||
#card-new-date {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background: rgb(31 31 33 / 41%);
|
||||
transition: all .2s ease 0s;
|
||||
}
|
||||
|
||||
#card-new-date>.mess {
|
||||
display: flex;
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
background: var(--ColorThemes0);
|
||||
box-shadow: 0px 2px 3px rgb(0 0 0 / 5%), 0px 5px 15px rgb(0 0 0 / 5%), 0px 4px 8px rgb(0 0 0 / 5%), 0px 0px 1px rgb(0 0 0 / 5%);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -50px;
|
||||
margin-left: -160px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
padding: 10px;
|
||||
border-radius: 15px;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
#card-new-date>.mess>button {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background-color: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
cursor: pointer;
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#card-new-date>.mess>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes2);
|
||||
color: var(--ColorThemes3);
|
||||
cursor: pointer;
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
@@ -1,115 +1,110 @@
|
||||
<div class="page-constructor">
|
||||
<details id="details-info" open>
|
||||
<summary>
|
||||
<div id="part-1" class="part_block">
|
||||
<h1>
|
||||
<span>Крок 1.</span> Інформація про будинок, територію, точки на карті
|
||||
</summary>
|
||||
<form id="info-form">
|
||||
<div id="details-info-type">
|
||||
<div class="tabs">
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-house"
|
||||
value="house"
|
||||
name="info-type"
|
||||
checked
|
||||
/>
|
||||
<label class="tab" for="info-type-house">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 6 A 1.50015 1.50015 0 0 0 13 7.5 L 13 25 L 7.5 25 A 1.50015 1.50015 0 0 0 6 26.5 L 6 42.5 A 1.50015 1.50015 0 1 0 9 42.5 L 9 28 L 14.253906 28 A 1.50015 1.50015 0 0 0 14.740234 28 L 19 28 L 19 42.5 A 1.50015 1.50015 0 1 0 22 42.5 L 22 26.746094 A 1.50015 1.50015 0 0 0 22 26.259766 L 22 22 L 33.253906 22 A 1.50015 1.50015 0 0 0 33.740234 22 L 39 22 L 39 42.5 A 1.50015 1.50015 0 1 0 42 42.5 L 42 20.5 A 1.50015 1.50015 0 0 0 40.5 19 L 35 19 L 35 7.5 A 1.50015 1.50015 0 0 0 33.5 6 L 14.5 6 z M 16 9 L 32 9 L 32 19 L 20.5 19 A 1.50015 1.50015 0 0 0 19 20.5 L 19 25 L 16 25 L 16 9 z M 20 12 C 19.448 12 19 12.448 19 13 L 19 15 C 19 15.552 19.448 16 20 16 L 22 16 C 22.552 16 23 15.552 23 15 L 23 13 C 23 12.448 22.552 12 22 12 L 20 12 z M 26 12 C 25.448 12 25 12.448 25 13 L 25 15 C 25 15.552 25.448 16 26 16 L 28 16 C 28.552 16 29 15.552 29 15 L 29 13 C 29 12.448 28.552 12 28 12 L 26 12 z M 26 25 C 25.448 25 25 25.448 25 26 L 25 28 C 25 28.552 25.448 29 26 29 L 28 29 C 28.552 29 29 28.552 29 28 L 29 26 C 29 25.448 28.552 25 28 25 L 26 25 z M 33 25 C 32.448 25 32 25.448 32 26 L 32 28 C 32 28.552 32.448 29 33 29 L 35 29 C 35.552 29 36 28.552 36 28 L 36 26 C 36 25.448 35.552 25 35 25 L 33 25 z M 13 31 C 12.448 31 12 31.448 12 32 L 12 34 C 12 34.552 12.448 35 13 35 L 15 35 C 15.552 35 16 34.552 16 34 L 16 32 C 16 31.448 15.552 31 15 31 L 13 31 z M 26 31 C 25.448 31 25 31.448 25 32 L 25 34 C 25 34.552 25.448 35 26 35 L 28 35 C 28.552 35 29 34.552 29 34 L 29 32 C 29 31.448 28.552 31 28 31 L 26 31 z M 33 31 C 32.448 31 32 31.448 32 32 L 32 34 C 32 34.552 32.448 35 33 35 L 35 35 C 35.552 35 36 34.552 36 34 L 36 32 C 36 31.448 35.552 31 35 31 L 33 31 z M 13 37 C 12.448 37 12 37.448 12 38 L 12 40 C 12 40.552 12.448 41 13 41 L 15 41 C 15.552 41 16 40.552 16 40 L 16 38 C 16 37.448 15.552 37 15 37 L 13 37 z M 26 37 C 25.448 37 25 37.448 25 38 L 25 40 C 25 40.552 25.448 41 26 41 L 28 41 C 28.552 41 29 40.552 29 40 L 29 38 C 29 37.448 28.552 37 28 37 L 26 37 z M 33 37 C 32.448 37 32 37.448 32 38 L 32 40 C 32 40.552 32.448 41 33 41 L 35 41 C 35.552 41 36 40.552 36 40 L 36 38 C 36 37.448 35.552 37 35 37 L 33 37 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Багатоквартирний будинок</span>
|
||||
</label>
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-homestead"
|
||||
value="homestead"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-homestead">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 5.015625 C 22.851301 5.015625 21.70304 5.3892757 20.753906 6.1367188 A 1.50015 1.50015 0 0 0 20.751953 6.1367188 L 8.859375 15.509766 C 7.0558128 16.931133 6 19.102989 6 21.400391 L 6 39.488281 C 6 41.403236 7.5850452 42.988281 9.5 42.988281 L 38.5 42.988281 C 40.414955 42.988281 42 41.403236 42 39.488281 L 42 21.400391 C 42 19.102989 40.944187 16.931133 39.140625 15.509766 L 39 15.396484 L 39 7.5 A 1.50015 1.50015 0 0 0 37.5 6 L 32.5 6 A 1.50015 1.50015 0 0 0 31 7.5 L 31 9.09375 L 27.246094 6.1367188 C 26.29696 5.3892758 25.148699 5.015625 24 5.015625 z M 24 8.0078125 C 24.489801 8.0078125 24.979759 8.1705836 25.390625 8.4941406 L 31.572266 13.363281 A 1.50015 1.50015 0 0 0 34 12.185547 L 34 9 L 36 9 L 36 16.125 A 1.50015 1.50015 0 0 0 36.572266 17.302734 L 37.285156 17.865234 C 38.369594 18.719867 39 20.019792 39 21.400391 L 39 39.488281 C 39 39.783326 38.795045 39.988281 38.5 39.988281 L 9.5 39.988281 C 9.2049548 39.988281 9 39.783326 9 39.488281 L 9 21.400391 C 9 20.019792 9.6304058 18.719867 10.714844 17.865234 L 22.609375 8.4941406 C 23.020241 8.1705836 23.510199 8.0078125 24 8.0078125 z M 14.5 23.988281 A 1.50015 1.50015 0 0 0 13 25.488281 L 13 33.488281 A 1.50015 1.50015 0 0 0 14.5 34.988281 L 20.5 34.988281 A 1.50015 1.50015 0 0 0 22 33.488281 L 22 25.488281 A 1.50015 1.50015 0 0 0 20.5 23.988281 L 14.5 23.988281 z M 27.5 23.988281 A 1.50015 1.50015 0 0 0 26 25.488281 L 26 33.488281 A 1.50015 1.50015 0 0 0 27.5 34.988281 L 33.5 34.988281 A 1.50015 1.50015 0 0 0 35 33.488281 L 35 25.488281 A 1.50015 1.50015 0 0 0 33.5 23.988281 L 27.5 23.988281 z M 16 26.988281 L 19 26.988281 L 19 31.988281 L 16 31.988281 L 16 26.988281 z M 29 26.988281 L 32 26.988281 L 32 31.988281 L 29 31.988281 L 29 26.988281 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Житловий район</span>
|
||||
</label>
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-points"
|
||||
value="points"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-points">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 4 C 16.285455 4 10 10.285455 10 18 C 10 21.46372 11.272608 24.643548 13.359375 27.085938 L 13.359375 27.087891 L 13.361328 27.087891 C 13.361328 27.087891 19.149094 33.866566 21.298828 35.917969 C 22.798087 37.348278 25.199464 37.347492 26.699219 35.917969 C 29.129083 33.600994 34.636721 27.090553 34.640625 27.085938 L 34.642578 27.082031 C 36.728766 24.639939 38 21.462159 38 18 C 38 10.285455 31.714545 4 24 4 z M 24 7 C 30.093455 7 35 11.906545 35 18 C 35 20.73228 34.005417 23.211194 32.359375 25.136719 L 32.359375 25.138672 L 32.357422 25.138672 C 32.357422 25.138672 26.632181 31.83589 24.628906 33.746094 C 24.258577 34.099392 23.73947 34.099392 23.369141 33.746094 C 21.715477 32.16807 15.643092 25.141834 15.638672 25.136719 L 15.636719 25.132812 C 13.99327 23.20762 13 20.730712 13 18 C 13 11.906545 17.906545 7 24 7 z M 24 12 C 22.125 12 20.528815 12.757133 19.503906 13.910156 C 18.478997 15.063179 18 16.541667 18 18 C 18 19.458333 18.478997 20.936821 19.503906 22.089844 C 20.528815 23.242867 22.125 24 24 24 C 25.875 24 27.471185 23.242867 28.496094 22.089844 C 29.521003 20.936821 30 19.458333 30 18 C 30 16.541667 29.521003 15.063179 28.496094 13.910156 C 27.471185 12.757133 25.875 12 24 12 z M 24 15 C 25.124999 15 25.778816 15.367867 26.253906 15.902344 C 26.728997 16.436821 27 17.208333 27 18 C 27 18.791667 26.728997 19.563179 26.253906 20.097656 C 25.778816 20.632133 25.124999 21 24 21 C 22.875001 21 22.221184 20.632133 21.746094 20.097656 C 21.271003 19.563179 21 18.791667 21 18 C 21 17.208333 21.271003 16.436821 21.746094 15.902344 C 22.221184 15.367867 22.875001 15 24 15 z M 12.771484 29.441406 C 8.2264844 30.754406 5 32.953 5 36 C 5 41.252 14.558 44 24 44 C 33.442 44 43 41.252 43 36 C 43 32.954 39.775422 30.757359 35.232422 29.443359 C 34.654422 30.099359 33.863187 30.993844 32.992188 31.964844 C 37.418188 33.005844 40 34.691 40 36 C 40 38.039 33.767 41 24 41 C 14.233 41 8 38.039 8 36 C 8 34.69 10.586531 33.001938 15.019531 31.960938 C 14.152531 30.995938 13.355484 30.100406 12.771484 29.441406 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Точки на карті</span>
|
||||
</label>
|
||||
<span class="glider"></span>
|
||||
</div>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
<div id="details-info-address" class="details-info-input">
|
||||
<label for="info-address-title">Назва вулиці</label>
|
||||
<div id="info-type">
|
||||
<div class="tabs">
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-house"
|
||||
value="house"
|
||||
name="info-type"
|
||||
checked
|
||||
/>
|
||||
<label class="tab" for="info-type-house">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 6 A 1.50015 1.50015 0 0 0 13 7.5 L 13 25 L 7.5 25 A 1.50015 1.50015 0 0 0 6 26.5 L 6 42.5 A 1.50015 1.50015 0 1 0 9 42.5 L 9 28 L 14.253906 28 A 1.50015 1.50015 0 0 0 14.740234 28 L 19 28 L 19 42.5 A 1.50015 1.50015 0 1 0 22 42.5 L 22 26.746094 A 1.50015 1.50015 0 0 0 22 26.259766 L 22 22 L 33.253906 22 A 1.50015 1.50015 0 0 0 33.740234 22 L 39 22 L 39 42.5 A 1.50015 1.50015 0 1 0 42 42.5 L 42 20.5 A 1.50015 1.50015 0 0 0 40.5 19 L 35 19 L 35 7.5 A 1.50015 1.50015 0 0 0 33.5 6 L 14.5 6 z M 16 9 L 32 9 L 32 19 L 20.5 19 A 1.50015 1.50015 0 0 0 19 20.5 L 19 25 L 16 25 L 16 9 z M 20 12 C 19.448 12 19 12.448 19 13 L 19 15 C 19 15.552 19.448 16 20 16 L 22 16 C 22.552 16 23 15.552 23 15 L 23 13 C 23 12.448 22.552 12 22 12 L 20 12 z M 26 12 C 25.448 12 25 12.448 25 13 L 25 15 C 25 15.552 25.448 16 26 16 L 28 16 C 28.552 16 29 15.552 29 15 L 29 13 C 29 12.448 28.552 12 28 12 L 26 12 z M 26 25 C 25.448 25 25 25.448 25 26 L 25 28 C 25 28.552 25.448 29 26 29 L 28 29 C 28.552 29 29 28.552 29 28 L 29 26 C 29 25.448 28.552 25 28 25 L 26 25 z M 33 25 C 32.448 25 32 25.448 32 26 L 32 28 C 32 28.552 32.448 29 33 29 L 35 29 C 35.552 29 36 28.552 36 28 L 36 26 C 36 25.448 35.552 25 35 25 L 33 25 z M 13 31 C 12.448 31 12 31.448 12 32 L 12 34 C 12 34.552 12.448 35 13 35 L 15 35 C 15.552 35 16 34.552 16 34 L 16 32 C 16 31.448 15.552 31 15 31 L 13 31 z M 26 31 C 25.448 31 25 31.448 25 32 L 25 34 C 25 34.552 25.448 35 26 35 L 28 35 C 28.552 35 29 34.552 29 34 L 29 32 C 29 31.448 28.552 31 28 31 L 26 31 z M 33 31 C 32.448 31 32 31.448 32 32 L 32 34 C 32 34.552 32.448 35 33 35 L 35 35 C 35.552 35 36 34.552 36 34 L 36 32 C 36 31.448 35.552 31 35 31 L 33 31 z M 13 37 C 12.448 37 12 37.448 12 38 L 12 40 C 12 40.552 12.448 41 13 41 L 15 41 C 15.552 41 16 40.552 16 40 L 16 38 C 16 37.448 15.552 37 15 37 L 13 37 z M 26 37 C 25.448 37 25 37.448 25 38 L 25 40 C 25 40.552 25.448 41 26 41 L 28 41 C 28.552 41 29 40.552 29 40 L 29 38 C 29 37.448 28.552 37 28 37 L 26 37 z M 33 37 C 32.448 37 32 37.448 32 38 L 32 40 C 32 40.552 32.448 41 33 41 L 35 41 C 35.552 41 36 40.552 36 40 L 36 38 C 36 37.448 35.552 37 35 37 L 33 37 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Багатоквартирний будинок</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-homestead"
|
||||
value="homestead"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-homestead">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 5.015625 C 22.851301 5.015625 21.70304 5.3892757 20.753906 6.1367188 A 1.50015 1.50015 0 0 0 20.751953 6.1367188 L 8.859375 15.509766 C 7.0558128 16.931133 6 19.102989 6 21.400391 L 6 39.488281 C 6 41.403236 7.5850452 42.988281 9.5 42.988281 L 38.5 42.988281 C 40.414955 42.988281 42 41.403236 42 39.488281 L 42 21.400391 C 42 19.102989 40.944187 16.931133 39.140625 15.509766 L 39 15.396484 L 39 7.5 A 1.50015 1.50015 0 0 0 37.5 6 L 32.5 6 A 1.50015 1.50015 0 0 0 31 7.5 L 31 9.09375 L 27.246094 6.1367188 C 26.29696 5.3892758 25.148699 5.015625 24 5.015625 z M 24 8.0078125 C 24.489801 8.0078125 24.979759 8.1705836 25.390625 8.4941406 L 31.572266 13.363281 A 1.50015 1.50015 0 0 0 34 12.185547 L 34 9 L 36 9 L 36 16.125 A 1.50015 1.50015 0 0 0 36.572266 17.302734 L 37.285156 17.865234 C 38.369594 18.719867 39 20.019792 39 21.400391 L 39 39.488281 C 39 39.783326 38.795045 39.988281 38.5 39.988281 L 9.5 39.988281 C 9.2049548 39.988281 9 39.783326 9 39.488281 L 9 21.400391 C 9 20.019792 9.6304058 18.719867 10.714844 17.865234 L 22.609375 8.4941406 C 23.020241 8.1705836 23.510199 8.0078125 24 8.0078125 z M 14.5 23.988281 A 1.50015 1.50015 0 0 0 13 25.488281 L 13 33.488281 A 1.50015 1.50015 0 0 0 14.5 34.988281 L 20.5 34.988281 A 1.50015 1.50015 0 0 0 22 33.488281 L 22 25.488281 A 1.50015 1.50015 0 0 0 20.5 23.988281 L 14.5 23.988281 z M 27.5 23.988281 A 1.50015 1.50015 0 0 0 26 25.488281 L 26 33.488281 A 1.50015 1.50015 0 0 0 27.5 34.988281 L 33.5 34.988281 A 1.50015 1.50015 0 0 0 35 33.488281 L 35 25.488281 A 1.50015 1.50015 0 0 0 33.5 23.988281 L 27.5 23.988281 z M 16 26.988281 L 19 26.988281 L 19 31.988281 L 16 31.988281 L 16 26.988281 z M 29 26.988281 L 32 26.988281 L 32 31.988281 L 29 31.988281 L 29 26.988281 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Житловий район</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-points"
|
||||
value="points"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-points">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 4 C 16.285455 4 10 10.285455 10 18 C 10 21.46372 11.272608 24.643548 13.359375 27.085938 L 13.359375 27.087891 L 13.361328 27.087891 C 13.361328 27.087891 19.149094 33.866566 21.298828 35.917969 C 22.798087 37.348278 25.199464 37.347492 26.699219 35.917969 C 29.129083 33.600994 34.636721 27.090553 34.640625 27.085938 L 34.642578 27.082031 C 36.728766 24.639939 38 21.462159 38 18 C 38 10.285455 31.714545 4 24 4 z M 24 7 C 30.093455 7 35 11.906545 35 18 C 35 20.73228 34.005417 23.211194 32.359375 25.136719 L 32.359375 25.138672 L 32.357422 25.138672 C 32.357422 25.138672 26.632181 31.83589 24.628906 33.746094 C 24.258577 34.099392 23.73947 34.099392 23.369141 33.746094 C 21.715477 32.16807 15.643092 25.141834 15.638672 25.136719 L 15.636719 25.132812 C 13.99327 23.20762 13 20.730712 13 18 C 13 11.906545 17.906545 7 24 7 z M 24 12 C 22.125 12 20.528815 12.757133 19.503906 13.910156 C 18.478997 15.063179 18 16.541667 18 18 C 18 19.458333 18.478997 20.936821 19.503906 22.089844 C 20.528815 23.242867 22.125 24 24 24 C 25.875 24 27.471185 23.242867 28.496094 22.089844 C 29.521003 20.936821 30 19.458333 30 18 C 30 16.541667 29.521003 15.063179 28.496094 13.910156 C 27.471185 12.757133 25.875 12 24 12 z M 24 15 C 25.124999 15 25.778816 15.367867 26.253906 15.902344 C 26.728997 16.436821 27 17.208333 27 18 C 27 18.791667 26.728997 19.563179 26.253906 20.097656 C 25.778816 20.632133 25.124999 21 24 21 C 22.875001 21 22.221184 20.632133 21.746094 20.097656 C 21.271003 19.563179 21 18.791667 21 18 C 21 17.208333 21.271003 16.436821 21.746094 15.902344 C 22.221184 15.367867 22.875001 15 24 15 z M 12.771484 29.441406 C 8.2264844 30.754406 5 32.953 5 36 C 5 41.252 14.558 44 24 44 C 33.442 44 43 41.252 43 36 C 43 32.954 39.775422 30.757359 35.232422 29.443359 C 34.654422 30.099359 33.863187 30.993844 32.992188 31.964844 C 37.418188 33.005844 40 34.691 40 36 C 40 38.039 33.767 41 24 41 C 14.233 41 8 38.039 8 36 C 8 34.69 10.586531 33.001938 15.019531 31.960938 C 14.152531 30.995938 13.355484 30.100406 12.771484 29.441406 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Точки на карті</span>
|
||||
</label>
|
||||
<span class="glider"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="info-form">
|
||||
<div>
|
||||
<label for="info-title">Назва вулиці</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-address-title"
|
||||
id="info-title"
|
||||
name="address"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-number" class="details-info-input">
|
||||
<label for="info-number-title">Номер будинку</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-number-title"
|
||||
name="number"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
<div>
|
||||
<label for="info-number">Номер будинку / частини</label>
|
||||
<input type="text" id="info-number" name="number" required value="" />
|
||||
</div>
|
||||
|
||||
<div id="details-info-settlement" class="details-info-input">
|
||||
<label for="info-settlement-title">Місто</label>
|
||||
<div>
|
||||
<label for="info-settlement">Місто</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-settlement-title"
|
||||
id="info-settlement"
|
||||
name="settlement"
|
||||
required
|
||||
value="Тернопіль"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-group" class="details-info-input">
|
||||
<label for="info-group-title">Теократична група</label>
|
||||
<input
|
||||
type="number"
|
||||
id="info-group-title"
|
||||
name="group"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" id="part-1-button">Далі</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="details-info-osm" class="details-info-input">
|
||||
<div id="part-2" class="part_block" style="display: none">
|
||||
<h1 id="part-2-title"><span>Крок 2.</span> Створення будинку / ділянки</h1>
|
||||
|
||||
<div class="osm-info">
|
||||
<div>
|
||||
<label for="info-settlement-title">OSM iD</label>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="info-osm-title"
|
||||
name="osm"
|
||||
placeholder="123, 345, 678"
|
||||
required
|
||||
value=""
|
||||
onchange="Constructor.osm.autoPoligon(this.value)"
|
||||
/>
|
||||
<a href="https://www.openstreetmap.org/#map=19/49.561725/25.604458" target="_blank" title="Де знайти OSM iD ?"
|
||||
><svg
|
||||
<a
|
||||
href="https://www.openstreetmap.org/#map=19/49.561725/25.604458"
|
||||
target="_blank"
|
||||
title="Де знайти OSM iD ?"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
width="100px"
|
||||
@@ -117,76 +112,25 @@
|
||||
>
|
||||
<path
|
||||
d="M 24 4 C 12.972066 4 4 12.972074 4 24 C 4 35.027926 12.972066 44 24 44 C 35.027934 44 44 35.027926 44 24 C 44 12.972074 35.027934 4 24 4 z M 24 7 C 33.406615 7 41 14.593391 41 24 C 41 33.406609 33.406615 41 24 41 C 14.593385 41 7 33.406609 7 24 C 7 14.593391 14.593385 7 24 7 z M 24 14 A 2 2 0 0 0 24 18 A 2 2 0 0 0 24 14 z M 23.976562 20.978516 A 1.50015 1.50015 0 0 0 22.5 22.5 L 22.5 33.5 A 1.50015 1.50015 0 1 0 25.5 33.5 L 25.5 22.5 A 1.50015 1.50015 0 0 0 23.976562 20.978516 z"
|
||||
/></svg
|
||||
></a>
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<span>або</span>
|
||||
<button onclick="Constructor.osm.newPoligon()">Обрати на карті</button>
|
||||
</div>
|
||||
|
||||
<button id="info-form-button" type="submit">Далі</button>
|
||||
</form>
|
||||
</details>
|
||||
<div class="block-map">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<details id="details-map" disabled>
|
||||
<summary id="details-map-title">
|
||||
<span>Крок 2.</span> Створення підїздів
|
||||
</summary>
|
||||
<form id="map-form">
|
||||
<div class="editor-buttons" id="details-map-buttons-entranse">
|
||||
<button type="button" onclick="Constructor.editor.drawEntranse()">
|
||||
Створити новий під'їзд
|
||||
</button>
|
||||
<div>
|
||||
<button type="button" id="ruler" onclick="Constructor.editor.drawRectangle()">
|
||||
Лінійка
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="ruler_divide"
|
||||
onclick="Constructor.editor.ruler()"
|
||||
style="display: none"
|
||||
>
|
||||
Поділити
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" id="part-2-button">Далі</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="editor-buttons"
|
||||
id="details-map-buttons-homestead"
|
||||
style="display: none"
|
||||
>
|
||||
<div>
|
||||
<button type="button" id="ruler" onclick="Constructor.editor.drawRectangle()">
|
||||
Лінійка
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="ruler_divide"
|
||||
onclick="Constructor.editor.ruler()"
|
||||
style="display: none"
|
||||
>
|
||||
Поділити
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="part-3" class="part_block" style="display: none">
|
||||
<h1 id="part-3-title"><span>Крок 3.</span> Створення квартир</h1>
|
||||
|
||||
<div id="list-entranse" style="display: none"></div>
|
||||
<div id="list-homestead" style="display: none"></div>
|
||||
|
||||
<div class="block-map">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
<button id="map-form-button" type="submit">Далі</button>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<details id="details-area" disabled>
|
||||
<summary><span>Крок 3.</span> Конструктор квартир <input type="number" value="1" id="next-apartment-title" onchange="Constructor.apartments.editNum(this)" title="Авто-номер наступної квартири"></summary>
|
||||
|
||||
<form id="area-form">
|
||||
<div id="list-area"></div>
|
||||
|
||||
<button id="area-form-button" type="submit">Зберегти</button>
|
||||
</form>
|
||||
</details>
|
||||
<button type="button" id="part-3-button">Зберегти</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,21 +6,11 @@
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
.page-constructor form>button {
|
||||
border-radius: 6px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
margin: 20px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.page-constructor details {
|
||||
#part-1,
|
||||
#part-2,
|
||||
#part-3 {
|
||||
border-radius: 10px;
|
||||
width: 100%;
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
@@ -29,62 +19,35 @@
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
.page-constructor>details[disabled] summary,
|
||||
.page-constructor>details.disabled summary {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.page-constructor>details summary::-webkit-details-marker,
|
||||
.page-constructor>details summary::marker {
|
||||
display: none;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.page-constructor summary {
|
||||
width: calc(100% - 40px);
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 16px;
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-constructor summary span {
|
||||
#part-1>h1,
|
||||
#part-2>h1,
|
||||
#part-3>h1 {
|
||||
width: calc(100% - 40px);
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#part-1>h1>span,
|
||||
#part-2>h1>span,
|
||||
#part-3>h1>span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.page-constructor summary input {
|
||||
font-weight: 500;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
margin: 13px;
|
||||
font-size: 12px;
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.page-constructor #info-form,
|
||||
.page-constructor #map-form,
|
||||
.page-constructor #area-form {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
#details-info-type {
|
||||
#part-1>#info-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs {
|
||||
#part-1>#info-type>.tabs {
|
||||
display: flex;
|
||||
position: relative;
|
||||
background-color: var(--ColorThemes0);
|
||||
@@ -94,11 +57,12 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[type="radio"] {
|
||||
|
||||
#part-1>#info-type>.tabs>input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab {
|
||||
#part-1>#info-type>.tabs>.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -113,23 +77,23 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab>svg {
|
||||
#part-1>#info-type>.tabs>.tab>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab>span {
|
||||
#part-1>#info-type>.tabs>.tab>span {
|
||||
margin-left: 6px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[type="radio"]:checked+label {
|
||||
#part-1>#info-type>.tabs>input[type="radio"]:checked+label {
|
||||
color: var(--PrimaryColorText);
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.glider {
|
||||
#part-1>#info-type>.tabs>.glider {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
@@ -141,47 +105,47 @@
|
||||
}
|
||||
|
||||
@media (min-width: 601px) {
|
||||
#details-info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
transform: translateX(200%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
#details-info-type>.tabs {
|
||||
#part-1>#info-type>.tabs {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab {
|
||||
#part-1>#info-type>.tabs>.tab {
|
||||
width: calc(100% - 8px);
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.glider {
|
||||
#part-1>#info-type>.tabs>.glider {
|
||||
width: calc(100% - 8px);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
transform: translateY(200%);
|
||||
}
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input {
|
||||
#part-1>form>div {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin: 20px 0;
|
||||
@@ -189,17 +153,16 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input label {
|
||||
#part-1>form>div>label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input input {
|
||||
#part-1>form>div>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
@@ -207,52 +170,163 @@
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
.page-constructor #details-info-osm div {
|
||||
#part-1>form>button,
|
||||
#part-2>button,
|
||||
#part-3>button {
|
||||
border-radius: 6px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
margin: 20px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#part-2>.osm-info {
|
||||
padding-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#part-2>.osm-info>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-constructor #details-info-osm input {
|
||||
#part-2>.osm-info>div {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#part-2>.osm-info>div>label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#part-2>.osm-info>div>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#part-2>.osm-info>div>div>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input a {
|
||||
#part-2>.osm-info>div>div>a {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input a>svg {
|
||||
#part-2>.osm-info>div>div>a>svg {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
fill: var(--ColorThemes3)
|
||||
fill: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
.page-constructor #list-area {
|
||||
margin-top: 15px;
|
||||
#part-2>.osm-info>span {
|
||||
font-size: var(--FontSize5);
|
||||
margin: 10px;
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#part-2>.osm-info>button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
transition: 0.15s ease-in;
|
||||
color: var(--PrimaryColorText);
|
||||
background: var(--PrimaryColor);
|
||||
border-radius: 6px;
|
||||
flex-direction: row;
|
||||
z-index: 2;
|
||||
font-size: var(--FontSize3);
|
||||
}
|
||||
|
||||
#part-2>.block-map {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
#part-2>#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#part-3>input {
|
||||
font-weight: 500;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
margin: 13px;
|
||||
font-size: var(--FontSize1);
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
#part-3>#house {
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.page-constructor #list-area h3 {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
margin: 10px;
|
||||
padding: 7px;
|
||||
color: var(--ColorThemes0);
|
||||
background: var(--ColorThemes3);
|
||||
border-radius: 4px;
|
||||
#part-3>#house>button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 34px;
|
||||
min-width: 34px;
|
||||
height: calc(100% - 10px);
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
margin: 0 10px;
|
||||
border-radius: 6px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.block-area {
|
||||
#part-3>#house>button>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
#part-3>#house>.entrance {
|
||||
min-height: 200px;
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
border-style: dashed;
|
||||
@@ -260,8 +334,20 @@
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.addFloors,
|
||||
.addApartment {
|
||||
#part-3>#house>.entrance>.entrance-info>input {
|
||||
text-align: center;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
margin: 10px;
|
||||
padding: 7px;
|
||||
color: var(--ColorThemes0);
|
||||
background: var(--ColorThemes3);
|
||||
border-radius: 4px;
|
||||
width: calc(100% - 14px - 20px);
|
||||
}
|
||||
|
||||
#part-3>#house>.entrance>.entrance-info>button,
|
||||
#part-3>#house>.entrance>.floor>.floor-info>button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 34px;
|
||||
@@ -276,15 +362,15 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.addFloors>svg,
|
||||
.addApartment>svg {
|
||||
#part-3>#house>.entrance>.entrance-info>button>svg,
|
||||
#part-3>#house>.entrance>.floor>.floor-info>button>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.block-apartments-floors {
|
||||
#part-3>#house>.entrance>.floor {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: calc(100% - 22px);
|
||||
@@ -293,7 +379,7 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.block-apartments-floors h2 {
|
||||
#part-3>#house>.entrance>.floor>.floor-info>h2 {
|
||||
position: absolute;
|
||||
width: 65px;
|
||||
right: -1px;
|
||||
@@ -302,12 +388,12 @@
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes2);
|
||||
border-radius: 0 4px 0 4px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
padding: 2px 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.block-apartments-number {
|
||||
#part-3>#house>.entrance>.floor>.apartment {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
@@ -320,17 +406,17 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.block-apartments-number input {
|
||||
#part-3>#house>.entrance>.floor>.apartment>input {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
background: 0;
|
||||
}
|
||||
|
||||
.block-apartments-number button {
|
||||
#part-3>#house>.entrance>.floor>.apartment>button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@@ -338,7 +424,7 @@
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
@@ -347,148 +433,46 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.block-apartments-number button>svg {
|
||||
#part-3>#house>.entrance>.floor>.apartment>button>svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#part-3>.info {}
|
||||
|
||||
.block-map {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
#part-3>.info>p {
|
||||
font-size: var(--FontSize2);
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.8;
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
#part-3>.info>button {
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.entranse_number {
|
||||
left: -10px !important;
|
||||
top: -10px !important;
|
||||
}
|
||||
|
||||
.markerEntranse {
|
||||
background: hsl(0deg 0% 52.12% / 90%);
|
||||
font-size: 24px;
|
||||
border: 2px solid #676767;
|
||||
border-radius: 2px;
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
min-width: 30px;
|
||||
min-height: 30px;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.editor-buttons {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.editor-buttons>button {
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
margin: 5px 0;
|
||||
border: 0;
|
||||
color: var(--PrimaryColorText);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--PrimaryColor);
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.editor-buttons>div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
height: 30px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.editor-buttons>div>button {
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes1);
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-radius: 6px;
|
||||
width: fit-content;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse,
|
||||
.page-constructor #list-homestead {
|
||||
width: 100%;
|
||||
min-height: 86px;
|
||||
display: flex;
|
||||
display: flex
|
||||
;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: initial;
|
||||
overflow-y: auto;
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
background: 0;
|
||||
border-radius: 6px;
|
||||
border-style: dashed;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse>.house,
|
||||
.page-constructor #list-homestead>.house {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: var(--ColorThemes1);
|
||||
border: 2px solid var(--PrimaryColor);
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.page-constructor #list-entranse>.house>input,
|
||||
.page-constructor #list-homestead>.house>input {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
background: 0;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse>.house>button,
|
||||
.page-constructor #list-homestead>.house>button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
#part-3>.info>button>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: 16px;
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
fill: var(--ColorThemes0);
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse>.house>button>svg,
|
||||
.page-constructor #list-homestead>.house>button>svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--PrimaryColorText);
|
||||
#part-3>.info>button>span {
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes0);
|
||||
}
|
||||
181
web/lib/pages/constructor_old/index.html
Normal file
181
web/lib/pages/constructor_old/index.html
Normal file
@@ -0,0 +1,181 @@
|
||||
<div class="page-constructor">
|
||||
<details id="details-info" open>
|
||||
<summary>
|
||||
<span>Крок 1.</span> Інформація про будинок, територію, точки на карті
|
||||
</summary>
|
||||
<form id="info-form">
|
||||
<div id="details-info-type">
|
||||
<div class="tabs">
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-house"
|
||||
value="house"
|
||||
name="info-type"
|
||||
checked
|
||||
/>
|
||||
<label class="tab" for="info-type-house">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 6 A 1.50015 1.50015 0 0 0 13 7.5 L 13 25 L 7.5 25 A 1.50015 1.50015 0 0 0 6 26.5 L 6 42.5 A 1.50015 1.50015 0 1 0 9 42.5 L 9 28 L 14.253906 28 A 1.50015 1.50015 0 0 0 14.740234 28 L 19 28 L 19 42.5 A 1.50015 1.50015 0 1 0 22 42.5 L 22 26.746094 A 1.50015 1.50015 0 0 0 22 26.259766 L 22 22 L 33.253906 22 A 1.50015 1.50015 0 0 0 33.740234 22 L 39 22 L 39 42.5 A 1.50015 1.50015 0 1 0 42 42.5 L 42 20.5 A 1.50015 1.50015 0 0 0 40.5 19 L 35 19 L 35 7.5 A 1.50015 1.50015 0 0 0 33.5 6 L 14.5 6 z M 16 9 L 32 9 L 32 19 L 20.5 19 A 1.50015 1.50015 0 0 0 19 20.5 L 19 25 L 16 25 L 16 9 z M 20 12 C 19.448 12 19 12.448 19 13 L 19 15 C 19 15.552 19.448 16 20 16 L 22 16 C 22.552 16 23 15.552 23 15 L 23 13 C 23 12.448 22.552 12 22 12 L 20 12 z M 26 12 C 25.448 12 25 12.448 25 13 L 25 15 C 25 15.552 25.448 16 26 16 L 28 16 C 28.552 16 29 15.552 29 15 L 29 13 C 29 12.448 28.552 12 28 12 L 26 12 z M 26 25 C 25.448 25 25 25.448 25 26 L 25 28 C 25 28.552 25.448 29 26 29 L 28 29 C 28.552 29 29 28.552 29 28 L 29 26 C 29 25.448 28.552 25 28 25 L 26 25 z M 33 25 C 32.448 25 32 25.448 32 26 L 32 28 C 32 28.552 32.448 29 33 29 L 35 29 C 35.552 29 36 28.552 36 28 L 36 26 C 36 25.448 35.552 25 35 25 L 33 25 z M 13 31 C 12.448 31 12 31.448 12 32 L 12 34 C 12 34.552 12.448 35 13 35 L 15 35 C 15.552 35 16 34.552 16 34 L 16 32 C 16 31.448 15.552 31 15 31 L 13 31 z M 26 31 C 25.448 31 25 31.448 25 32 L 25 34 C 25 34.552 25.448 35 26 35 L 28 35 C 28.552 35 29 34.552 29 34 L 29 32 C 29 31.448 28.552 31 28 31 L 26 31 z M 33 31 C 32.448 31 32 31.448 32 32 L 32 34 C 32 34.552 32.448 35 33 35 L 35 35 C 35.552 35 36 34.552 36 34 L 36 32 C 36 31.448 35.552 31 35 31 L 33 31 z M 13 37 C 12.448 37 12 37.448 12 38 L 12 40 C 12 40.552 12.448 41 13 41 L 15 41 C 15.552 41 16 40.552 16 40 L 16 38 C 16 37.448 15.552 37 15 37 L 13 37 z M 26 37 C 25.448 37 25 37.448 25 38 L 25 40 C 25 40.552 25.448 41 26 41 L 28 41 C 28.552 41 29 40.552 29 40 L 29 38 C 29 37.448 28.552 37 28 37 L 26 37 z M 33 37 C 32.448 37 32 37.448 32 38 L 32 40 C 32 40.552 32.448 41 33 41 L 35 41 C 35.552 41 36 40.552 36 40 L 36 38 C 36 37.448 35.552 37 35 37 L 33 37 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Багатоквартирний будинок</span>
|
||||
</label>
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-homestead"
|
||||
value="homestead"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-homestead">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 5.015625 C 22.851301 5.015625 21.70304 5.3892757 20.753906 6.1367188 A 1.50015 1.50015 0 0 0 20.751953 6.1367188 L 8.859375 15.509766 C 7.0558128 16.931133 6 19.102989 6 21.400391 L 6 39.488281 C 6 41.403236 7.5850452 42.988281 9.5 42.988281 L 38.5 42.988281 C 40.414955 42.988281 42 41.403236 42 39.488281 L 42 21.400391 C 42 19.102989 40.944187 16.931133 39.140625 15.509766 L 39 15.396484 L 39 7.5 A 1.50015 1.50015 0 0 0 37.5 6 L 32.5 6 A 1.50015 1.50015 0 0 0 31 7.5 L 31 9.09375 L 27.246094 6.1367188 C 26.29696 5.3892758 25.148699 5.015625 24 5.015625 z M 24 8.0078125 C 24.489801 8.0078125 24.979759 8.1705836 25.390625 8.4941406 L 31.572266 13.363281 A 1.50015 1.50015 0 0 0 34 12.185547 L 34 9 L 36 9 L 36 16.125 A 1.50015 1.50015 0 0 0 36.572266 17.302734 L 37.285156 17.865234 C 38.369594 18.719867 39 20.019792 39 21.400391 L 39 39.488281 C 39 39.783326 38.795045 39.988281 38.5 39.988281 L 9.5 39.988281 C 9.2049548 39.988281 9 39.783326 9 39.488281 L 9 21.400391 C 9 20.019792 9.6304058 18.719867 10.714844 17.865234 L 22.609375 8.4941406 C 23.020241 8.1705836 23.510199 8.0078125 24 8.0078125 z M 14.5 23.988281 A 1.50015 1.50015 0 0 0 13 25.488281 L 13 33.488281 A 1.50015 1.50015 0 0 0 14.5 34.988281 L 20.5 34.988281 A 1.50015 1.50015 0 0 0 22 33.488281 L 22 25.488281 A 1.50015 1.50015 0 0 0 20.5 23.988281 L 14.5 23.988281 z M 27.5 23.988281 A 1.50015 1.50015 0 0 0 26 25.488281 L 26 33.488281 A 1.50015 1.50015 0 0 0 27.5 34.988281 L 33.5 34.988281 A 1.50015 1.50015 0 0 0 35 33.488281 L 35 25.488281 A 1.50015 1.50015 0 0 0 33.5 23.988281 L 27.5 23.988281 z M 16 26.988281 L 19 26.988281 L 19 31.988281 L 16 31.988281 L 16 26.988281 z M 29 26.988281 L 32 26.988281 L 32 31.988281 L 29 31.988281 L 29 26.988281 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Житловий район</span>
|
||||
</label>
|
||||
<input
|
||||
type="radio"
|
||||
id="info-type-points"
|
||||
value="points"
|
||||
name="info-type"
|
||||
/>
|
||||
<label class="tab" for="info-type-points">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 4 C 16.285455 4 10 10.285455 10 18 C 10 21.46372 11.272608 24.643548 13.359375 27.085938 L 13.359375 27.087891 L 13.361328 27.087891 C 13.361328 27.087891 19.149094 33.866566 21.298828 35.917969 C 22.798087 37.348278 25.199464 37.347492 26.699219 35.917969 C 29.129083 33.600994 34.636721 27.090553 34.640625 27.085938 L 34.642578 27.082031 C 36.728766 24.639939 38 21.462159 38 18 C 38 10.285455 31.714545 4 24 4 z M 24 7 C 30.093455 7 35 11.906545 35 18 C 35 20.73228 34.005417 23.211194 32.359375 25.136719 L 32.359375 25.138672 L 32.357422 25.138672 C 32.357422 25.138672 26.632181 31.83589 24.628906 33.746094 C 24.258577 34.099392 23.73947 34.099392 23.369141 33.746094 C 21.715477 32.16807 15.643092 25.141834 15.638672 25.136719 L 15.636719 25.132812 C 13.99327 23.20762 13 20.730712 13 18 C 13 11.906545 17.906545 7 24 7 z M 24 12 C 22.125 12 20.528815 12.757133 19.503906 13.910156 C 18.478997 15.063179 18 16.541667 18 18 C 18 19.458333 18.478997 20.936821 19.503906 22.089844 C 20.528815 23.242867 22.125 24 24 24 C 25.875 24 27.471185 23.242867 28.496094 22.089844 C 29.521003 20.936821 30 19.458333 30 18 C 30 16.541667 29.521003 15.063179 28.496094 13.910156 C 27.471185 12.757133 25.875 12 24 12 z M 24 15 C 25.124999 15 25.778816 15.367867 26.253906 15.902344 C 26.728997 16.436821 27 17.208333 27 18 C 27 18.791667 26.728997 19.563179 26.253906 20.097656 C 25.778816 20.632133 25.124999 21 24 21 C 22.875001 21 22.221184 20.632133 21.746094 20.097656 C 21.271003 19.563179 21 18.791667 21 18 C 21 17.208333 21.271003 16.436821 21.746094 15.902344 C 22.221184 15.367867 22.875001 15 24 15 z M 12.771484 29.441406 C 8.2264844 30.754406 5 32.953 5 36 C 5 41.252 14.558 44 24 44 C 33.442 44 43 41.252 43 36 C 43 32.954 39.775422 30.757359 35.232422 29.443359 C 34.654422 30.099359 33.863187 30.993844 32.992188 31.964844 C 37.418188 33.005844 40 34.691 40 36 C 40 38.039 33.767 41 24 41 C 14.233 41 8 38.039 8 36 C 8 34.69 10.586531 33.001938 15.019531 31.960938 C 14.152531 30.995938 13.355484 30.100406 12.771484 29.441406 z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Точки на карті</span>
|
||||
</label>
|
||||
<span class="glider"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="details-info-address" class="details-info-input">
|
||||
<label for="info-address-title">Назва вулиці</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-address-title"
|
||||
name="address"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-number" class="details-info-input">
|
||||
<label for="info-number-title">Номер будинку</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-number-title"
|
||||
name="number"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-settlement" class="details-info-input">
|
||||
<label for="info-settlement-title">Місто</label>
|
||||
<input
|
||||
type="text"
|
||||
id="info-settlement-title"
|
||||
name="settlement"
|
||||
required
|
||||
value="Тернопіль"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-osm" class="details-info-input">
|
||||
<label for="info-settlement-title">OSM iD</label>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="info-osm-title"
|
||||
name="osm"
|
||||
placeholder="123, 345, 678"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
<a href="https://www.openstreetmap.org/#map=19/49.561725/25.604458" target="_blank" title="Де знайти OSM iD ?"
|
||||
><svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
width="100px"
|
||||
height="100px"
|
||||
>
|
||||
<path
|
||||
d="M 24 4 C 12.972066 4 4 12.972074 4 24 C 4 35.027926 12.972066 44 24 44 C 35.027934 44 44 35.027926 44 24 C 44 12.972074 35.027934 4 24 4 z M 24 7 C 33.406615 7 41 14.593391 41 24 C 41 33.406609 33.406615 41 24 41 C 14.593385 41 7 33.406609 7 24 C 7 14.593391 14.593385 7 24 7 z M 24 14 A 2 2 0 0 0 24 18 A 2 2 0 0 0 24 14 z M 23.976562 20.978516 A 1.50015 1.50015 0 0 0 22.5 22.5 L 22.5 33.5 A 1.50015 1.50015 0 1 0 25.5 33.5 L 25.5 22.5 A 1.50015 1.50015 0 0 0 23.976562 20.978516 z"
|
||||
/></svg
|
||||
></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="info-form-button" type="submit">Далі</button>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<details id="details-map" disabled>
|
||||
<summary id="details-map-title">
|
||||
<span>Крок 2.</span> Створення підїздів
|
||||
</summary>
|
||||
<form id="map-form">
|
||||
<div class="editor-buttons" id="details-map-buttons-entranse">
|
||||
<button type="button" onclick="Constructor.editor.drawEntranse()">
|
||||
Створити новий під'їзд
|
||||
</button>
|
||||
<div>
|
||||
<button type="button" id="ruler" onclick="Constructor.editor.drawRectangle()">
|
||||
Лінійка
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="ruler_divide"
|
||||
onclick="Constructor.editor.ruler()"
|
||||
style="display: none"
|
||||
>
|
||||
Поділити
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="editor-buttons"
|
||||
id="details-map-buttons-homestead"
|
||||
style="display: none"
|
||||
>
|
||||
<div>
|
||||
<button type="button" id="ruler" onclick="Constructor.editor.drawRectangle()">
|
||||
Лінійка
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="ruler_divide"
|
||||
onclick="Constructor.editor.ruler()"
|
||||
style="display: none"
|
||||
>
|
||||
Поділити
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="list-entranse" style="display: none"></div>
|
||||
<div id="list-homestead" style="display: none"></div>
|
||||
|
||||
<div class="block-map">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
<button id="map-form-button" type="submit">Далі</button>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<details id="details-area" disabled>
|
||||
<summary><span>Крок 3.</span> Конструктор квартир <input type="number" value="1" id="next-apartment-title" onchange="Constructor.apartments.editNum(this)" title="Авто-номер наступної квартири"></summary>
|
||||
|
||||
<form id="area-form">
|
||||
<div id="list-area"></div>
|
||||
|
||||
<button id="area-form-button" type="submit">Зберегти</button>
|
||||
</form>
|
||||
</details>
|
||||
</div>
|
||||
731
web/lib/pages/constructor_old/script.js
Normal file
731
web/lib/pages/constructor_old/script.js
Normal file
@@ -0,0 +1,731 @@
|
||||
let map, houseGroup, entransePolygonsGroup, entranseNumPolygonsGroup, splitPolygonsGroup, RectangleGroup;
|
||||
let numApartments = 1;
|
||||
let mode = '';
|
||||
|
||||
|
||||
const Constructor = {
|
||||
info: {
|
||||
type: null,
|
||||
title: null,
|
||||
number: null,
|
||||
points: [],
|
||||
points_number: [],
|
||||
point_icons: [],
|
||||
geo: [],
|
||||
osm_id: [],
|
||||
settlement: [],
|
||||
description: null,
|
||||
entrance: [],
|
||||
apartments: {},
|
||||
zoom: null
|
||||
},
|
||||
init: async () => {
|
||||
let html = await fetch('/lib/pages/constructor/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
map = "";
|
||||
map = "";
|
||||
houseGroup = "";
|
||||
entransePolygonsGroup = "";
|
||||
entranseNumPolygonsGroup = "";
|
||||
splitPolygonsGroup = "";
|
||||
RectangleGroup = "";
|
||||
numApartments = 1;
|
||||
|
||||
Constructor.apartments.init();
|
||||
|
||||
document.querySelectorAll('input[name="info-type"]').forEach(radio => {
|
||||
radio.addEventListener('change', event => {
|
||||
console.log(`Выбран: ${event.target.value}`);
|
||||
Constructor.info.type = event.target.value;
|
||||
|
||||
let detailsInfo_number = document.getElementById('details-info-number');
|
||||
let detailsInfo_osm = document.getElementById('details-info-osm');
|
||||
let detailsInfo_number_title = document.getElementById('info-number-title');
|
||||
let detailsInfo_osm_title = document.getElementById('info-osm-title');
|
||||
|
||||
let detailsMap_title = document.getElementById('details-map-title');
|
||||
let detailsMap_buttons_entranse = document.getElementById('details-map-buttons-entranse');
|
||||
let detailsMap_buttons_homestead = document.getElementById('details-map-buttons-homestead');
|
||||
let detailsMap_button = document.getElementById('map-form-button');
|
||||
|
||||
|
||||
let detailsArea = document.getElementById('details-area');
|
||||
|
||||
switch (event.target.value) {
|
||||
case 'points':
|
||||
detailsInfo_number.style.display = "none";
|
||||
detailsInfo_osm.style.display = "none";
|
||||
detailsInfo_number_title.removeAttribute("required");
|
||||
detailsInfo_osm_title.removeAttribute("required");
|
||||
|
||||
detailsMap_title.innerHTML = "<span>Крок 2.</span> Створення точок на карті"
|
||||
detailsMap_buttons_entranse.style.display = "none";
|
||||
detailsMap_buttons_homestead.style.display = "none";
|
||||
detailsMap_button.innerText = "Зберегти";
|
||||
|
||||
detailsArea.style.display = "none";
|
||||
break;
|
||||
|
||||
case 'homestead':
|
||||
detailsInfo_number.style.display = "";
|
||||
detailsInfo_osm.style.display = "";
|
||||
detailsInfo_number_title.setAttribute("required", "");
|
||||
detailsInfo_osm_title.setAttribute("required", "");
|
||||
|
||||
detailsMap_title.innerHTML = "<span>Крок 2.</span> Створення житлових територій"
|
||||
detailsMap_buttons_entranse.style.display = "none";
|
||||
detailsMap_buttons_homestead.style.display = "";
|
||||
detailsMap_button.innerText = "Зберегти";
|
||||
|
||||
detailsArea.style.display = "none";
|
||||
break;
|
||||
|
||||
default:
|
||||
detailsInfo_number.style.display = "";
|
||||
detailsInfo_osm.style.display = "";
|
||||
detailsInfo_number_title.setAttribute("required", "");
|
||||
detailsInfo_osm_title.setAttribute("required", "");
|
||||
|
||||
detailsMap_title.innerHTML = "<span>Крок 2.</span> Створення підʼїздів"
|
||||
detailsMap_buttons_entranse.style.display = "";
|
||||
detailsMap_buttons_homestead.style.display = "none";
|
||||
detailsMap_button.innerText = "Далі";
|
||||
|
||||
detailsArea.style.display = "";
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById("info-form").addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
let details_map = document.getElementById("details-map");
|
||||
details_map.removeAttribute("disabled");
|
||||
details_map.open = true;
|
||||
|
||||
const infoForm = document.getElementById("info-form");
|
||||
let osm = () => {
|
||||
const a = document.getElementById("info-osm-title").value;
|
||||
const b = a.replace(/\s+/g, "").split(',')
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
Constructor.info.type = infoForm.querySelector('input[name="info-type"]:checked').value;
|
||||
Constructor.info.title = document.getElementById("info-address-title").value;
|
||||
Constructor.info.number = document.getElementById("info-number-title").value;
|
||||
Constructor.info.settlement = document.getElementById("info-settlement-title").value;
|
||||
Constructor.info.osm_id = osm();
|
||||
|
||||
Constructor.osm.init();
|
||||
|
||||
Constructor.osm.setMap();
|
||||
})
|
||||
|
||||
document.getElementById("map-form").addEventListener("submit", async function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
let details_area = document.getElementById("details-area");
|
||||
details_area.removeAttribute("disabled");
|
||||
details_area.open = true;
|
||||
|
||||
switch (Constructor.info.type) {
|
||||
case 'points':
|
||||
|
||||
break;
|
||||
|
||||
case 'homestead':
|
||||
await Constructor.api.setPack();
|
||||
break;
|
||||
|
||||
default:
|
||||
let details_area = document.getElementById("details-area");
|
||||
details_area.removeAttribute("disabled");
|
||||
details_area.open = true;
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
document.getElementById("area-form").addEventListener("submit", async function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
await Constructor.api.setPack();
|
||||
})
|
||||
},
|
||||
apartments: {
|
||||
init: () => {
|
||||
let listArea = document.getElementById('list-area');
|
||||
listArea.innerHTML = ``;
|
||||
|
||||
for (const key in Constructor.info.apartments) {
|
||||
const element = Constructor.info.apartments[key];
|
||||
const pos = Constructor.info.entrance.map(e => e.editor_id).indexOf(key);
|
||||
console.log(element);
|
||||
|
||||
let listArea = document.getElementById('list-area');
|
||||
listArea.innerHTML += `
|
||||
<div class="block-area" id="block-area-${key}">
|
||||
<h3>${Constructor.info.entrance[pos].title}</h3>
|
||||
<button class="addFloors" title="Додати поверх" type="button" onclick="Constructor.apartments.addFloors('${key}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>
|
||||
|
||||
<div id="area-${key}"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
element.sort((a, b) => a.floors_number - b.floors_number);
|
||||
|
||||
let uniqueFloors = [...new Set(element.map(obj => obj.floors_number))];
|
||||
|
||||
for (let i = 0; i < uniqueFloors.length; i++) {
|
||||
let num = uniqueFloors[i];
|
||||
|
||||
let areaBlock = document.getElementById(`area-${key}`);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.className = "block-apartments-floors";
|
||||
div.id = `floors-${key}-${num}`
|
||||
div.innerHTML = `
|
||||
<button class="addApartment" id="buttonApartment-${key}-${num}" title="Додати квартиру" type="button" onclick="Constructor.apartments.addApartment('${key}', '${num}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>
|
||||
`;
|
||||
|
||||
areaBlock.prepend(div);
|
||||
}
|
||||
|
||||
element.sort((a, b) => b.title - a.title);
|
||||
|
||||
for (let i = 0; i < element.length; i++) {
|
||||
const apartment = element[i];
|
||||
let num = apartment.floors_number;
|
||||
|
||||
let floorsBlock = document.getElementById(`floors-${key}-${apartment.floors_number}`);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.className = "block-apartments-number";
|
||||
div.id = `block-apartments-${key}-${apartment.editor_id}`
|
||||
div.innerHTML = `
|
||||
<input type="text" value="${apartment.title}" id="apartament-${key}-${apartment.editor_id}" onchange="Constructor.apartments.editApartment('${key}','${apartment.editor_id}')">
|
||||
<button type="button" onclick="Constructor.apartments.deleteApartment('${key}','${apartment.editor_id}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
`;
|
||||
|
||||
floorsBlock.prepend(div);
|
||||
}
|
||||
|
||||
element.sort((a, b) => b.floors_number - a.floors_number);
|
||||
}
|
||||
},
|
||||
editNum: (element) => {
|
||||
numApartments = Number(element.value);
|
||||
},
|
||||
addFloors: (area) => {
|
||||
let areaBlock = document.getElementById(`area-${area}`);
|
||||
|
||||
let uniqueFloors = [...new Set(Constructor.info.apartments[area].map(obj => obj.floors_number))];
|
||||
let new_floors = uniqueFloors.length + 1;
|
||||
let new_id = makeid(5);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.className = "block-apartments-floors";
|
||||
div.id = `floors-${area}-${new_floors}`
|
||||
div.innerHTML = `
|
||||
<h2>Поверх ${new_floors}</h2>
|
||||
<div class="block-apartments-number" id="block-apartments-${area}-${new_id}">
|
||||
<input type="text" value="${numApartments}" id="apartament-${area}-${new_id}" onchange="Constructor.apartments.editApartment('${area}', '${new_id}')">
|
||||
<button type="button" onclick="Constructor.apartments.deleteApartment('${area}', '${new_id}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
<button class="addApartment" id="buttonApartment-${area}-${new_floors}" title="Додати квартиру" type="button" onclick="Constructor.apartments.addApartment('${area}', '${new_floors}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>
|
||||
`
|
||||
|
||||
areaBlock.prepend(div);
|
||||
|
||||
Constructor.info.apartments[area].push({
|
||||
editor_id: new_id,
|
||||
entrance_id: null,
|
||||
apartment_number: Constructor.info.apartments[area].length,
|
||||
title: numApartments,
|
||||
floors_number: new_floors
|
||||
});
|
||||
|
||||
numApartments++;
|
||||
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
|
||||
},
|
||||
addApartment: (area, floors) => {
|
||||
let new_id = makeid(5);
|
||||
|
||||
Constructor.info.apartments[area].push({
|
||||
editor_id: new_id,
|
||||
entrance_id: null,
|
||||
apartment_number: Constructor.info.apartments[area].length,
|
||||
title: numApartments,
|
||||
floors_number: Number(floors)
|
||||
})
|
||||
|
||||
let floorsBlock = document.getElementById(`floors-${area}-${floors}`);
|
||||
document.getElementById(`buttonApartment-${area}-${floors}`).remove();
|
||||
|
||||
floorsBlock.innerHTML += `
|
||||
<div class="block-apartments-number" id="block-apartments-${area}-${new_id}">
|
||||
<input type="text" value="${numApartments}" id="apartament-${area}-${new_id}" onchange="Constructor.apartments.editApartment('${area}', '${new_id}')">
|
||||
<button type="button" onclick="Constructor.apartments.deleteApartment('${area}', '${new_id}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
floorsBlock.innerHTML += `<button class="addApartment" id="buttonApartment-${area}-${floors}" title="Додати квартиру" type="button" onclick="Constructor.apartments.addApartment('${area}', '${floors}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>`
|
||||
|
||||
numApartments++;
|
||||
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
},
|
||||
editApartment: (area, apartament) => {
|
||||
let input = document.getElementById(`apartament-${area}-${apartament}`);
|
||||
input.setAttribute("value", input.value);
|
||||
|
||||
const pos = Constructor.info.apartments[area].map(e => e.editor_id).indexOf(apartament);
|
||||
|
||||
info.apartments[area][pos].title = input.value;
|
||||
},
|
||||
deleteApartment: (area, apartament) => {
|
||||
document.getElementById(`block-apartments-${area}-${apartament}`).remove();
|
||||
const pos = Constructor.info.apartments[area].map(e => e.editor_id).indexOf(apartament);
|
||||
Constructor.info.apartments[area].splice(pos, 1);
|
||||
|
||||
numApartments--;
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
}
|
||||
},
|
||||
osm: {
|
||||
init: () => {
|
||||
let center = { lat: 49.5629016, lng: 25.6145625 };
|
||||
let zoom = 19;
|
||||
|
||||
let googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
|
||||
});
|
||||
|
||||
let osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
minZoom: 15
|
||||
});
|
||||
|
||||
let mytile = L.tileLayer('https://sheep-service.com/map/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
tms: true
|
||||
});
|
||||
|
||||
if (!map) {
|
||||
|
||||
houseGroup = new L.FeatureGroup();
|
||||
splitPolygonsGroup = new L.FeatureGroup();
|
||||
RectangleGroup = new L.FeatureGroup();
|
||||
entransePolygonsGroup = new L.FeatureGroup();
|
||||
entranseNumPolygonsGroup = new L.FeatureGroup();
|
||||
|
||||
map = L.map('map', {
|
||||
renderer: L.canvas(),
|
||||
center,
|
||||
zoom,
|
||||
layers: [
|
||||
googleHybrid,
|
||||
osm,
|
||||
mytile,
|
||||
houseGroup,
|
||||
entransePolygonsGroup,
|
||||
entranseNumPolygonsGroup,
|
||||
splitPolygonsGroup,
|
||||
RectangleGroup,
|
||||
],
|
||||
zoomControl: false
|
||||
});
|
||||
|
||||
|
||||
let baseMaps = {
|
||||
"Google Hybrid": googleHybrid,
|
||||
"OpenStreetMap": osm,
|
||||
"Territory Map": mytile
|
||||
};
|
||||
let overlayMaps = {
|
||||
"Будинки": houseGroup,
|
||||
"Під'їзди": entransePolygonsGroup,
|
||||
"Номера під'їздів": entranseNumPolygonsGroup,
|
||||
"Слой редактирования": splitPolygonsGroup,
|
||||
"Слой линейки": RectangleGroup,
|
||||
};
|
||||
|
||||
L.control.layers(baseMaps, overlayMaps, { position: 'bottomright' }).addTo(map);
|
||||
|
||||
map.pm.setLang("ua");
|
||||
|
||||
map.pm.addControls({
|
||||
position: 'bottomright',
|
||||
drawCircleMarker: false,
|
||||
drawPolyline: false,
|
||||
drawPolygon: false,
|
||||
drawRectangle: false,
|
||||
drawCircle: false,
|
||||
drawText: false,
|
||||
drawMarker: false,
|
||||
cutPolygon: false,
|
||||
tooltips: false
|
||||
});
|
||||
map.pm.toggleControls()
|
||||
|
||||
map.pm.setGlobalOptions({
|
||||
layerGroup: splitPolygonsGroup
|
||||
})
|
||||
}
|
||||
|
||||
Constructor.editor.init();
|
||||
},
|
||||
getOSM: async (wayId) => {
|
||||
const overpassUrl = `https://overpass-api.de/api/interpreter?data=[out:json];way(${wayId});(._;>;);out;`;
|
||||
|
||||
return await fetch(overpassUrl)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const nodes = new Map();
|
||||
|
||||
data.elements.forEach(el => {
|
||||
if (el.type === "node") {
|
||||
nodes.set(el.id, { lat: el.lat, lng: el.lon });
|
||||
}
|
||||
});
|
||||
|
||||
const way = data.elements.find(el => el.type === "way");
|
||||
if (way) {
|
||||
const coordinates = way.nodes.map(nodeId => nodes.get(nodeId));
|
||||
console.log("Координаты точек:", coordinates);
|
||||
|
||||
return [coordinates];
|
||||
} else {
|
||||
console.log("Way не найден!");
|
||||
}
|
||||
})
|
||||
.catch(error => console.error("Ошибка запроса:", error));
|
||||
},
|
||||
setMap: async () => {
|
||||
houseGroup.clearLayers();
|
||||
|
||||
if (!Constructor.info.osm_id) {
|
||||
let osm = () => {
|
||||
const a = document.getElementById("info-osm-title").value;
|
||||
const b = a.replace(/\s+/g, "").split(',')
|
||||
|
||||
return b;
|
||||
}
|
||||
Constructor.info.osm_id = osm();
|
||||
}
|
||||
|
||||
for (let i = 0; i < Constructor.info.osm_id.length; i++) {
|
||||
const element = await Constructor.osm.getOSM(Constructor.info.osm_id[i]);
|
||||
let coords = [];
|
||||
element[0].forEach((feature) => coords.push([feature.lat, feature.lng]));
|
||||
|
||||
let centerPoint = turf.centerOfMass(turf.polygon([coords]));
|
||||
|
||||
|
||||
if (Constructor.info.type == "homestead") {
|
||||
map.setView([centerPoint.geometry.coordinates[0], centerPoint.geometry.coordinates[1]], 17);
|
||||
|
||||
L.polygon(element, {
|
||||
color: "#f2bd53",
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '20, 15',
|
||||
dashOffset: '20',
|
||||
}).addTo(houseGroup);
|
||||
} else if (Constructor.info.type == "house") {
|
||||
map.setView([centerPoint.geometry.coordinates[0], centerPoint.geometry.coordinates[1]], 18);
|
||||
|
||||
Constructor.info.points.push(element);
|
||||
Constructor.info.points_number.push(element[0][0]);
|
||||
|
||||
L.polygon(element, {
|
||||
color: "#585858",
|
||||
fillColor: "#f2bd53",
|
||||
fillOpacity: 0.8,
|
||||
tm_id: `house_${i}`
|
||||
}).addTo(houseGroup);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(Constructor.info);
|
||||
|
||||
}
|
||||
},
|
||||
api: {
|
||||
setPack: async () => {
|
||||
let area_form_button = document.getElementById('area-form-button');
|
||||
area_form_button.innerText = "Зачекайте...";
|
||||
|
||||
Constructor.info.geo = await map.getCenter();
|
||||
Constructor.info.zoom = await map.getZoom();
|
||||
|
||||
console.log(Constructor.info);
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}constructor`;
|
||||
await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify(Constructor.info)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.status == 200) {
|
||||
console.log({ 'setPack': 'ok' });
|
||||
area_form_button.innerText = "Запис додано";
|
||||
|
||||
return response.json()
|
||||
} else {
|
||||
console.log('err');
|
||||
area_form_button.innerText = "Помилка запису";
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
|
||||
Territory.house.list = [];
|
||||
Territory.homestead.list = [];
|
||||
Router.navigate(`/territory/manager/${Constructor.info.type}/${data.id}`);
|
||||
|
||||
setTimeout(() => {
|
||||
area_form_button.innerText = "Зберегти";
|
||||
}, 3000);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
area_form_button.innerText = "Помилка запису";
|
||||
})
|
||||
}
|
||||
},
|
||||
editor: {
|
||||
init: () => {
|
||||
map.on('pm:create', function (event) {
|
||||
let layer = event.layer;
|
||||
|
||||
let newCoords = layer.getLatLngs()[0].map(function (coords) {
|
||||
return [coords.lng, coords.lat];
|
||||
});
|
||||
newCoords.push(newCoords[0]);
|
||||
let turfNew = turf.polygon([newCoords]);
|
||||
|
||||
if (mode == 'entranse') {
|
||||
console.log(L.PM.Utils.findLayers(houseGroup));
|
||||
for (let i = 0; i < L.PM.Utils.findLayers(houseGroup).length; i++) {
|
||||
const polygon = L.PM.Utils.findLayers(houseGroup)[i]._latlngs;
|
||||
|
||||
let polygonCoords = polygon[0].map(function (coords) {
|
||||
return [coords.lng, coords.lat];
|
||||
});
|
||||
polygonCoords.push(polygonCoords[0]); // Замикаємо полігон
|
||||
let turfPolygon = turf.polygon([polygonCoords]);
|
||||
|
||||
// Пошук точки перехрестя
|
||||
let intersections = turf.intersect(turfNew, turfPolygon);
|
||||
|
||||
if (intersections) {
|
||||
let points = [];
|
||||
let coords = [];
|
||||
|
||||
intersections.geometry.coordinates[0].forEach(function (feature) {
|
||||
coords.push([feature[1], feature[0]])
|
||||
points.push({ lat: feature[1], lng: feature[0] })
|
||||
});
|
||||
|
||||
let centerPoint = turf.centerOfMass(turf.polygon([coords]));
|
||||
|
||||
let points_number = { lat: centerPoint.geometry.coordinates[0], lng: centerPoint.geometry.coordinates[1] }
|
||||
|
||||
let newID = makeid(6);
|
||||
|
||||
Constructor.info.entrance.push({
|
||||
editor_id: newID,
|
||||
house_id: null,
|
||||
entrance_number: Constructor.info.entrance.length,
|
||||
title: `Під'їзд ${Constructor.info.entrance.length + 1}`,
|
||||
points: points,
|
||||
points_number: points_number,
|
||||
floors_quantity: null,
|
||||
apartments_quantity: null,
|
||||
created_at: null
|
||||
})
|
||||
|
||||
Constructor.info.apartments[newID] = [];
|
||||
Constructor.apartments.init();
|
||||
|
||||
let listEntranse = document.getElementById('list-entranse');
|
||||
listEntranse.style.display = "";
|
||||
listEntranse.innerHTML += `
|
||||
<div class="house" style="align-items: center;" id="Entranse_${newID}">
|
||||
<input type="number" value="${Constructor.info.entrance.length}" id="Entranse_input_${newID}" onchange="Constructor.editor.editEntranse('${newID}')">
|
||||
<button type="button" onclick="Constructor.editor.dellEntranse('${newID}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
L.polygon(coords, { color: 'red' }).addTo(entransePolygonsGroup);
|
||||
|
||||
let myIcon = L.divIcon({ className: 'entranse_number', html: `<div class="markerEntranse">${Constructor.info.entrance.length}</div>` });
|
||||
L.marker(centerPoint.geometry.coordinates, { icon: myIcon }).addTo(entranseNumPolygonsGroup);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
drawEntranse: () => {
|
||||
mode = 'entranse';
|
||||
|
||||
map.pm.setGlobalOptions({
|
||||
layerGroup: splitPolygonsGroup
|
||||
})
|
||||
map.pm.setPathOptions({
|
||||
color: '#f2bd53',
|
||||
fillColor: '#f2bd53',
|
||||
fillOpacity: 0.5,
|
||||
radius: 500
|
||||
});
|
||||
|
||||
if (map.pm.globalDragModeEnabled()) {
|
||||
map.pm.disableDraw();
|
||||
} else {
|
||||
map.pm.enableDraw("Polygon", {
|
||||
snappable: true,
|
||||
snapDistance: 20,
|
||||
tooltips: false,
|
||||
templineStyle: { color: '#f2bd53' },
|
||||
hintlineStyle: { color: '#f2bd53', dashArray: [5, 5] }
|
||||
});
|
||||
}
|
||||
},
|
||||
drawRectangle: () => {
|
||||
mode = 'rectangle';
|
||||
|
||||
document.getElementById('ruler_divide').style.display = 'block'
|
||||
document.getElementById('ruler').style.width = "calc(50% - 5px)"
|
||||
document.getElementById('ruler_divide').style.width = "calc(50% - 5px)"
|
||||
document.getElementById('ruler').innerHTML = 'Лінійка'
|
||||
|
||||
map.pm.toggleControls()
|
||||
RectangleGroup.clearLayers();
|
||||
RectangleGroup.addTo(map);
|
||||
|
||||
map.pm.setGlobalOptions({
|
||||
layerGroup: RectangleGroup
|
||||
})
|
||||
map.pm.setPathOptions({
|
||||
color: '#b645ef',
|
||||
fillColor: '#b645ef',
|
||||
fillOpacity: 0.5,
|
||||
radius: 500
|
||||
});
|
||||
|
||||
if (map.pm.globalDragModeEnabled()) {
|
||||
map.pm.disableDraw();
|
||||
} else {
|
||||
map.pm.enableDraw("Rectangle", {
|
||||
snappable: true,
|
||||
snapDistance: 20,
|
||||
tooltips: false,
|
||||
templineStyle: { color: '#b645ef' },
|
||||
hintlineStyle: { color: '#b645ef', dashArray: [5, 5] }
|
||||
});
|
||||
}
|
||||
},
|
||||
ruler: (n) => {
|
||||
n = prompt('На сколько поделить линейку ?', 2);
|
||||
const polygon = L.PM.Utils.findLayers(RectangleGroup)[0]._latlngs;
|
||||
let newCoords = polygon[0].map(function (coords) {
|
||||
return [coords.lng, coords.lat];
|
||||
});
|
||||
newCoords.push(newCoords[0]);
|
||||
let turfNew = turf.polygon([newCoords]);
|
||||
|
||||
console.log(turfNew);
|
||||
|
||||
|
||||
var line = turf.polygonToLine(turfNew);
|
||||
console.log(line.geometry.coordinates);
|
||||
|
||||
coords = line.geometry.coordinates;
|
||||
|
||||
for (let i = 1; i < n; i++) {
|
||||
let a1 = (((coords[2][1] - coords[1][1]) / n) * i + coords[1][1])
|
||||
let b1 = (((coords[2][0] - coords[1][0]) / n) * i + coords[1][0])
|
||||
let a2 = (((coords[3][1] - coords[0][1]) / n) * i + coords[0][1])
|
||||
let b2 = (((coords[3][0] - coords[0][0]) / n) * i + coords[0][0])
|
||||
|
||||
let c1 = (((coords[1][1] - coords[0][1]) / n) * i + coords[0][1])
|
||||
let d1 = (((coords[1][0] - coords[0][0]) / n) * i + coords[0][0])
|
||||
let c2 = (((coords[2][1] - coords[3][1]) / n) * i + coords[3][1])
|
||||
let d2 = (((coords[2][0] - coords[3][0]) / n) * i + coords[3][0])
|
||||
|
||||
L.circleMarker([a1, b1], { radius: 2, color: 'red' }).addTo(RectangleGroup);
|
||||
L.circleMarker([a2, b2], { radius: 2, color: 'red' }).addTo(RectangleGroup);
|
||||
L.circleMarker([c1, d1], { radius: 2, color: 'red' }).addTo(RectangleGroup);
|
||||
L.circleMarker([c2, d2], { radius: 2, color: 'red' }).addTo(RectangleGroup);
|
||||
}
|
||||
|
||||
coords.forEach(function (feature) {
|
||||
L.circleMarker([feature[1], feature[0]], { radius: 2, color: 'red' }).addTo(RectangleGroup);
|
||||
});
|
||||
},
|
||||
dellEntranse: (id) => {
|
||||
delete Constructor.info.apartments[id];
|
||||
|
||||
const pos = Constructor.info.entrance.map(e => e.editor_id).indexOf(id);
|
||||
console.log(pos);
|
||||
|
||||
|
||||
Constructor.info.entrance.splice(pos, 1);
|
||||
console.log(id);
|
||||
|
||||
document.getElementById(`Entranse_${id}`).remove();
|
||||
|
||||
let Entranse = Object.keys(entransePolygonsGroup._layers);
|
||||
let numsEntranse = Object.keys(entranseNumPolygonsGroup._layers);
|
||||
console.log(Entranse, Entranse[pos]);
|
||||
console.log(numsEntranse, numsEntranse[pos]);
|
||||
|
||||
entransePolygonsGroup.removeLayer(entransePolygonsGroup._layers[Entranse[pos]]);
|
||||
entranseNumPolygonsGroup.removeLayer(entranseNumPolygonsGroup._layers[numsEntranse[pos]]);
|
||||
|
||||
Constructor.apartments.init();
|
||||
},
|
||||
editEntranse: (id) => {
|
||||
const input = document.getElementById(`Entranse_input_${id}`);
|
||||
|
||||
const pos = Constructor.info.entrance.map(e => e.editor_id).indexOf(id);
|
||||
|
||||
Constructor.info.entrance[pos].entrance_number = Number(input.value) - 1;
|
||||
Constructor.info.entrance[pos].title = `Під'їзд ${input.value}`;
|
||||
|
||||
let numsEntranse = Object.keys(entranseNumPolygonsGroup._layers);
|
||||
let newIcon = L.divIcon({ className: 'entranse_number', html: `<div class="markerEntranse">${input.value}</div>` });
|
||||
entranseNumPolygonsGroup._layers[numsEntranse[pos]].setIcon(newIcon);
|
||||
|
||||
input.setAttribute("value", input.value);
|
||||
|
||||
Constructor.apartments.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
495
web/lib/pages/constructor_old/style.css
Normal file
495
web/lib/pages/constructor_old/style.css
Normal file
@@ -0,0 +1,495 @@
|
||||
.page-constructor {
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
.page-constructor form>button {
|
||||
border-radius: 6px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
margin: 20px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.page-constructor details {
|
||||
border-radius: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
margin-bottom: 20px;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
.page-constructor>details[disabled] summary,
|
||||
.page-constructor>details.disabled summary {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.page-constructor>details summary::-webkit-details-marker,
|
||||
.page-constructor>details summary::marker {
|
||||
display: none;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.page-constructor summary {
|
||||
width: calc(100% - 40px);
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-constructor summary span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.page-constructor summary input {
|
||||
font-weight: 500;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
margin: 13px;
|
||||
font-size: var(--FontSize1);
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.page-constructor #info-form,
|
||||
.page-constructor #map-form,
|
||||
.page-constructor #area-form {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
#details-info-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs {
|
||||
display: flex;
|
||||
position: relative;
|
||||
background-color: var(--ColorThemes0);
|
||||
padding: 4px;
|
||||
border-radius: 6px;
|
||||
width: calc(100% - 8px);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
width: calc(100% / 3);
|
||||
cursor: pointer;
|
||||
padding: 0 15px;
|
||||
transition: 0.15s ease-in;
|
||||
color: var(--ColorThemes3);
|
||||
fill: var(--ColorThemes3);
|
||||
flex-direction: row;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab>span {
|
||||
margin-left: 6px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[type="radio"]:checked+label {
|
||||
color: var(--PrimaryColorText);
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.glider {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
width: calc((100% - 8px) / 3);
|
||||
background-color: var(--PrimaryColor);
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
@media (min-width: 601px) {
|
||||
#details-info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
transform: translateX(200%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
#details-info-type>.tabs {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.tab {
|
||||
width: calc(100% - 8px);
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>.glider {
|
||||
width: calc(100% - 8px);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-house"]:checked~.glider {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
#details-info-type>.tabs>input[id="info-type-points"]:checked~.glider {
|
||||
transform: translateY(200%);
|
||||
}
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin: 20px 0;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
.page-constructor #details-info-osm div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-constructor #details-info-osm input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input a {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.page-constructor .details-info-input a>svg {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
fill: var(--ColorThemes3)
|
||||
}
|
||||
|
||||
.page-constructor #list-area {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.page-constructor #list-area h3 {
|
||||
text-align: center;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
margin: 10px;
|
||||
padding: 7px;
|
||||
color: var(--ColorThemes0);
|
||||
background: var(--ColorThemes3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.block-area {
|
||||
min-height: 200px;
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
border-style: dashed;
|
||||
border-radius: 6px;
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.addFloors,
|
||||
.addApartment {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
margin: 25px;
|
||||
border-radius: 50%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.addFloors>svg,
|
||||
.addApartment>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.block-apartments-floors {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: calc(100% - 22px);
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.block-apartments-floors h2 {
|
||||
position: absolute;
|
||||
width: 65px;
|
||||
right: -1px;
|
||||
top: -1px;
|
||||
margin: 0;
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes2);
|
||||
border-radius: 0 4px 0 4px;
|
||||
font-size: var(--FontSize1);
|
||||
padding: 2px 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.block-apartments-number {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: var(--ColorThemes1);
|
||||
border: 2px solid var(--PrimaryColor);
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.block-apartments-number input {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
background: 0;
|
||||
}
|
||||
|
||||
.block-apartments-number button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: var(--FontSize5);
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.block-apartments-number button>svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
|
||||
.block-map {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.entranse_number {
|
||||
left: -10px !important;
|
||||
top: -10px !important;
|
||||
}
|
||||
|
||||
.markerEntranse {
|
||||
background: hsl(0deg 0% 52.12% / 90%);
|
||||
font-size: 24px;
|
||||
border: 2px solid #676767;
|
||||
border-radius: 2px;
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
min-width: 30px;
|
||||
min-height: 30px;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.editor-buttons {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.editor-buttons>button {
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
margin: 5px 0;
|
||||
border: 0;
|
||||
color: var(--PrimaryColorText);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--PrimaryColor);
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
font-weight: 400;
|
||||
font-size: var(--FontSize1);
|
||||
}
|
||||
|
||||
.editor-buttons>div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
height: 30px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.editor-buttons>div>button {
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes1);
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-radius: 6px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
font-size: var(--FontSize1);
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse,
|
||||
.page-constructor #list-homestead {
|
||||
width: 100%;
|
||||
min-height: 86px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: initial;
|
||||
overflow-y: auto;
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
background: 0;
|
||||
border-radius: 6px;
|
||||
border-style: dashed;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse>.house,
|
||||
.page-constructor #list-homestead>.house {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: var(--ColorThemes1);
|
||||
border: 2px solid var(--PrimaryColor);
|
||||
margin: 10px;
|
||||
border-radius: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
.page-constructor #list-entranse>.house>input,
|
||||
.page-constructor #list-homestead>.house>input {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
background: 0;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse>.house>button,
|
||||
.page-constructor #list-homestead>.house>button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: var(--FontSize5);
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-constructor #list-entranse>.house>button>svg,
|
||||
.page-constructor #list-homestead>.house>button>svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
@@ -36,101 +36,51 @@
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-group" class="details-info-input">
|
||||
<label for="info-group-title">Теократична група</label>
|
||||
<input
|
||||
type="number"
|
||||
id="info-group-title"
|
||||
name="group"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="details-info-osm" class="details-info-input">
|
||||
<label for="info-settlement-title">OSM iD</label>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="info-osm-title"
|
||||
name="osm"
|
||||
placeholder="123, 345, 678"
|
||||
required
|
||||
value=""
|
||||
/>
|
||||
<a href="https://www.openstreetmap.org/#map=19/49.561725/25.604458" target="_blank" title="Де знайти OSM iD ?"
|
||||
><svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
width="100px"
|
||||
height="100px"
|
||||
>
|
||||
<path
|
||||
d="M 24 4 C 12.972066 4 4 12.972074 4 24 C 4 35.027926 12.972066 44 24 44 C 35.027934 44 44 35.027926 44 24 C 44 12.972074 35.027934 4 24 4 z M 24 7 C 33.406615 7 41 14.593391 41 24 C 41 33.406609 33.406615 41 24 41 C 14.593385 41 7 33.406609 7 24 C 7 14.593391 14.593385 7 24 7 z M 24 14 A 2 2 0 0 0 24 18 A 2 2 0 0 0 24 14 z M 23.976562 20.978516 A 1.50015 1.50015 0 0 0 22.5 22.5 L 22.5 33.5 A 1.50015 1.50015 0 1 0 25.5 33.5 L 25.5 22.5 A 1.50015 1.50015 0 0 0 23.976562 20.978516 z"
|
||||
/></svg
|
||||
></a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<details id="details-map" open>
|
||||
<summary id="details-map-title">
|
||||
<span>Крок 2.</span> Перегляд
|
||||
</summary>
|
||||
<summary id="details-map-title"><span>Крок 2.</span> Перегляд</summary>
|
||||
<form id="map-form">
|
||||
<!-- <div class="editor-buttons" id="details-map-buttons-entranse">
|
||||
<button type="button" onclick="Editor.editor.drawEntranse()">
|
||||
Створити новий під'їзд
|
||||
</button>
|
||||
<div>
|
||||
<button type="button" id="ruler" onclick="Editor.editor.drawRectangle()">
|
||||
Лінійка
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="ruler_divide"
|
||||
onclick="Editor.editor.ruler()"
|
||||
style="display: none"
|
||||
>
|
||||
Поділити
|
||||
</button>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div
|
||||
class="editor-buttons"
|
||||
id="details-map-buttons-homestead"
|
||||
style="display: none"
|
||||
>
|
||||
<!-- <div>
|
||||
<button type="button" id="ruler" onclick="Editor.editor.drawRectangle()">
|
||||
Лінійка
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="ruler_divide"
|
||||
onclick="Editor.editor.ruler()"
|
||||
style="display: none"
|
||||
>
|
||||
Поділити
|
||||
</button>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div id="list-entranse" style="display: none"></div>
|
||||
<div id="list-homestead" style="display: none"></div>
|
||||
|
||||
<div class="block-map">
|
||||
<button
|
||||
type="button"
|
||||
onclick="Editor.homestead.editing_mode()"
|
||||
id="homestead-editing"
|
||||
style="display: none;"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
|
||||
<path
|
||||
d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
<button id="map-form-button" type="submit" style="display: none;">Далі</button>
|
||||
<button id="map-form-button" type="submit" style="display: none">
|
||||
Далі
|
||||
</button>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<details id="details-area" open style="display: none;">
|
||||
<summary><span>Крок 3.</span> Конструктор квартир <input type="number" value="1" id="next-apartment-title" onchange="Editor.apartments.editNum(this)" title="Авто-номер наступної квартири"></summary>
|
||||
<details id="details-area" open style="display: none">
|
||||
<summary>
|
||||
<span>Крок 3.</span> Конструктор квартир
|
||||
<input
|
||||
type="number"
|
||||
value="1"
|
||||
id="next-apartment-title"
|
||||
onchange="Editor.apartments.editNum(this)"
|
||||
title="Авто-номер наступної квартири"
|
||||
/>
|
||||
</summary>
|
||||
|
||||
<form id="area-form">
|
||||
<div id="list-area"></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const Editor = {
|
||||
init: async (type, id) => {
|
||||
async init(type, id) {
|
||||
let html = await fetch('/lib/pages/editor/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
@@ -12,14 +12,9 @@ const Editor = {
|
||||
numApartments = 1;
|
||||
|
||||
Editor.info.setHTML(type, id);
|
||||
|
||||
// document.getElementById("area-form").addEventListener("submit", async function (event) {
|
||||
// event.preventDefault();
|
||||
|
||||
// await Editor.api.setPack();
|
||||
// })
|
||||
},
|
||||
loadAPI: async function (URL) {
|
||||
|
||||
async loadAPI(URL) {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
return await fetch(URL, {
|
||||
method: 'GET',
|
||||
@@ -29,71 +24,66 @@ const Editor = {
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
},
|
||||
|
||||
info: {
|
||||
list: {
|
||||
type: null,
|
||||
group_id: null,
|
||||
title: null,
|
||||
number: null,
|
||||
points: [],
|
||||
points_number: [],
|
||||
point_icons: [],
|
||||
geo: [],
|
||||
osm_id: [],
|
||||
settlement: [],
|
||||
description: null,
|
||||
entrance: [],
|
||||
apartments: {}
|
||||
type: null, title: null, number: null,
|
||||
points: [], points_number: [], point_icons: [],
|
||||
geo: [], osm_id: [], settlement: [], description: null,
|
||||
entrance: [], apartments: {}
|
||||
},
|
||||
setHTML: async (type, id) => {
|
||||
let detailsInfo_address_title = document.getElementById('info-address-title');
|
||||
let detailsInfo_number_title = document.getElementById('info-number-title');
|
||||
let detailsInfo_settlement_title = document.getElementById('info-settlement-title');
|
||||
let detailsInfo_group_title = document.getElementById('info-group-title');
|
||||
let detailsInfo_osm_title = document.getElementById('info-osm-title');
|
||||
|
||||
Editor.info.list = await Editor.loadAPI(`${CONFIG.api}${type}/${id}`);
|
||||
async setHTML(type, id) {
|
||||
const els = {
|
||||
title: document.getElementById('info-address-title'),
|
||||
number: document.getElementById('info-number-title'),
|
||||
settlement: document.getElementById('info-settlement-title')
|
||||
};
|
||||
|
||||
this.list = await Editor.loadAPI(`${CONFIG.api}${type}/${id}`);
|
||||
Editor.info.list.type = type;
|
||||
Editor.info.list.entrance = [];
|
||||
Editor.info.list.apartments = {};
|
||||
|
||||
console.log(Editor.info.list);
|
||||
detailsInfo_address_title.value = Editor.info.list.title;
|
||||
detailsInfo_number_title.value = Editor.info.list.number;
|
||||
detailsInfo_settlement_title.value = Editor.info.list.settlement;
|
||||
detailsInfo_group_title.value = Editor.info.list.group_id;
|
||||
detailsInfo_osm_title.value = Editor.info.list.osm_id.join(", ");
|
||||
|
||||
els.title.value = this.list.title;
|
||||
els.number.value = this.list.number;
|
||||
els.settlement.value = this.list.settlement;
|
||||
|
||||
Editor.osm.init();
|
||||
Editor.info.setMap();
|
||||
|
||||
this.setMap();
|
||||
|
||||
if (type == "house") {
|
||||
Editor.entrances.setHTML(id);
|
||||
document.getElementById('details-area').style.display = "";
|
||||
} else if (type == "homestead") {
|
||||
Editor.homestead.init(id);
|
||||
}
|
||||
},
|
||||
setMap: async () => {
|
||||
|
||||
setMap() {
|
||||
houseGroup.clearLayers();
|
||||
|
||||
for (let i = 0; i < Editor.info.list.points.length; i++) {
|
||||
const element = Editor.info.list.points[i];
|
||||
|
||||
if (Editor.info.list.type == "homestead") {
|
||||
map.setView([Editor.info.list.geo.lat, Editor.info.list.geo.lng], 17);
|
||||
map.setView([this.list.geo.lat, this.list.geo.lng], this.list.zoom);
|
||||
|
||||
L.polygon(element, {
|
||||
color: colorGroup(Editor.info.list.group_id),
|
||||
color: "#f2bd53",
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '20, 15',
|
||||
dashArray: '20,15',
|
||||
dashOffset: '20',
|
||||
}).addTo(houseGroup);
|
||||
} else if (Editor.info.list.type == "house") {
|
||||
map.setView([Editor.info.list.geo.lat, Editor.info.list.geo.lng], 18);
|
||||
map.setView([this.list.geo.lat, this.list.geo.lng], this.list.zoom);
|
||||
|
||||
L.polygon(element, {
|
||||
color: "#585858",
|
||||
fillColor: colorGroup(Editor.info.list.group_id),
|
||||
fillColor: "#f2bd53",
|
||||
fillOpacity: 0.8,
|
||||
tm_id: `house_${i}`
|
||||
}).addTo(houseGroup);
|
||||
@@ -101,290 +91,18 @@ const Editor = {
|
||||
}
|
||||
}
|
||||
},
|
||||
entrances: {
|
||||
list: [],
|
||||
setHTML: async (id) => {
|
||||
Editor.entrances.list = await Editor.loadAPI(`${CONFIG.api}house/${id}/entrances`);
|
||||
|
||||
console.log(Editor.entrances.list);
|
||||
Editor.entrances.setMap()
|
||||
},
|
||||
setMap: async () => {
|
||||
entransePolygonsGroup.clearLayers();
|
||||
entranseNumPolygonsGroup.clearLayers();
|
||||
|
||||
for (let i = 0; i < Editor.entrances.list.length; i++) {
|
||||
const element = Editor.entrances.list[i];
|
||||
console.log(element);
|
||||
|
||||
let listEntranse = document.getElementById('list-entranse');
|
||||
listEntranse.style.display = "";
|
||||
listEntranse.innerHTML += `
|
||||
<div class="house" style="align-items: center;" id="Entranse_${element.id}">
|
||||
<p>${element.entrance_number + 1}</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
let listArea = document.getElementById('list-area');
|
||||
listArea.innerHTML += `
|
||||
<div class="block-area" id="block-area-${element.id}">
|
||||
<h3>${element.title}</h3>
|
||||
<button class="addFloors" title="Додати поверх" type="button" onclick="Editor.apartments.addFloors('${element.id}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>
|
||||
|
||||
<div id="area-${element.id}"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Editor.apartments.setHTML(element.id);
|
||||
|
||||
L.polygon(element.points, { color: 'red' }).addTo(entransePolygonsGroup);
|
||||
|
||||
let myIcon = L.divIcon({ className: 'entranse_number', html: `<div class="markerEntranse">${element.entrance_number + 1}</div>` });
|
||||
L.marker(element.points_number, { icon: myIcon }).addTo(entranseNumPolygonsGroup);
|
||||
}
|
||||
}
|
||||
},
|
||||
apartments: {
|
||||
list: [],
|
||||
setHTML: async (id) => {
|
||||
Editor.apartments.list[`${id}`] = await Editor.loadAPI(`${CONFIG.api}apartments/${id}`);
|
||||
|
||||
const uniqueFloors = [...new Set(Editor.apartments.list[`${id}`].map(item => item.floors_number))];
|
||||
for (let i = 0; i < uniqueFloors.length; i++) {
|
||||
let num = uniqueFloors[i];
|
||||
|
||||
let area = document.getElementById(`area-${id}`);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.className = "block-apartments-floors";
|
||||
div.id = `floors-${id}-${num}`
|
||||
div.innerHTML = `
|
||||
<h2>Поверх ${num}</h2>
|
||||
<button class="addApartment" id="buttonApartment-${id}-${num}" title="Додати квартиру" type="button" onclick="Editor.apartments.addApartment('${id}', '${num}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>
|
||||
`;
|
||||
|
||||
area.prepend(div);
|
||||
}
|
||||
|
||||
Editor.apartments.list[`${id}`].sort((a, b) => b.title - a.title);
|
||||
|
||||
for (let i = 0; i < Editor.apartments.list[`${id}`].length; i++) {
|
||||
const apartment = Editor.apartments.list[`${id}`][i];
|
||||
let num = apartment.floors_number;
|
||||
|
||||
let floorsBlock = document.getElementById(`floors-${id}-${num}`);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.className = "block-apartments-number";
|
||||
div.id = `block-apartments-${id}-${apartment.id}`
|
||||
div.innerHTML = `
|
||||
<input type="text" value="${apartment.title}" id="apartament-${id}-${apartment.id}" onchange="Editor.apartments.editApartment('${id}','${apartment.id}')">
|
||||
<button type="button" onclick="Editor.apartments.deleteApartment('${id}','${apartment.id}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
`;
|
||||
floorsBlock.prepend(div);
|
||||
|
||||
numApartments++;
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
}
|
||||
},
|
||||
editNum: (element) => {
|
||||
numApartments = Number(element.value);
|
||||
},
|
||||
addFloors: async (area) => {
|
||||
let areaBlock = document.getElementById(`area-${area}`);
|
||||
let uniqueFloors = [...new Set(Editor.apartments.list[area].map(obj => obj.floors_number))];
|
||||
let new_floors = uniqueFloors.length + 1;
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
apartment_number: Editor.apartments.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: Number(new_floors)
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.className = "block-apartments-floors";
|
||||
div.id = `floors-${area}-${new_floors}`
|
||||
div.innerHTML = `
|
||||
<h2>Поверх ${new_floors}</h2>
|
||||
<div class="block-apartments-number" id="block-apartments-${area}-${data.id}">
|
||||
<input type="text" value="${numApartments}" id="apartament-${area}-${data.id}" onchange="Editor.apartments.editApartment('${area}', '${data.id}')">
|
||||
<button type="button" onclick="Editor.apartments.deleteApartment('${area}', '${data.id}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
<button class="addApartment" id="buttonApartment-${area}-${new_floors}" title="Додати квартиру" type="button" onclick="Editor.apartments.addApartment('${area}', '${new_floors}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>
|
||||
`
|
||||
|
||||
areaBlock.prepend(div);
|
||||
|
||||
console.log(Editor.apartments.list[area]);
|
||||
|
||||
|
||||
Editor.apartments.list[area].push({
|
||||
id: data.id,
|
||||
entrance_id: Number(area),
|
||||
apartment_number: Editor.apartments.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: Number(new_floors)
|
||||
});
|
||||
|
||||
numApartments++;
|
||||
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
},
|
||||
addApartment: async (area, floors) => {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
apartment_number: Editor.apartments.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: Number(floors)
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
|
||||
Editor.apartments.list[area].push({
|
||||
id: data.id,
|
||||
entrance_id: Number(area),
|
||||
apartment_number: Editor.apartments.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: Number(floors)
|
||||
});
|
||||
|
||||
let floorsBlock = document.getElementById(`floors-${area}-${floors}`);
|
||||
document.getElementById(`buttonApartment-${area}-${floors}`).remove();
|
||||
|
||||
floorsBlock.innerHTML += `
|
||||
<div class="block-apartments-number" id="block-apartments-${area}-${data.id}">
|
||||
<input type="text" value="${numApartments}" id="apartament-${area}-${data.id}" onchange="Editor.apartments.editApartment('${area}', '${data.id}')">
|
||||
<button type="button" onclick="Editor.apartments.deleteApartment('${area}', '${data.id}')">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
floorsBlock.innerHTML += `<button class="addApartment" id="buttonApartment-${area}-${floors}" title="Додати квартиру" type="button" onclick="Editor.apartments.addApartment('${area}', '${floors}')"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg></button>`
|
||||
|
||||
numApartments++;
|
||||
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
},
|
||||
editApartment: async (area, apartament) => {
|
||||
let input = document.getElementById(`apartament-${area}-${apartament}`);
|
||||
input.setAttribute("value", input.value);
|
||||
|
||||
const pos = Editor.apartments.list[area].map(e => e.id).indexOf(Number(apartament));
|
||||
Editor.apartments.list[area][pos].title = input.value;
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
await fetch(URL, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: Editor.apartments.list[area][pos].title,
|
||||
status: Editor.apartments.list[area][pos].status,
|
||||
description: Editor.apartments.list[area][pos].description,
|
||||
id: Editor.apartments.list[area][pos].id
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
},
|
||||
deleteApartment: async (area, apartament) => {
|
||||
const pos = Editor.apartments.list[area].map(e => e.id).indexOf(Number(apartament));
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
await fetch(URL, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: Editor.apartments.list[area][pos].id
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
console.log(data);
|
||||
document.getElementById(`block-apartments-${area}-${apartament}`).remove();
|
||||
Editor.apartments.list[area].splice(pos, 1);
|
||||
|
||||
numApartments--;
|
||||
let next_apartment_title = document.getElementById('next-apartment-title');
|
||||
next_apartment_title.value = numApartments;
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
},
|
||||
osm: {
|
||||
init: () => {
|
||||
let center = { lat: 49.5629016, lng: 25.6145625 };
|
||||
let zoom = 19;
|
||||
|
||||
let googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
init() {
|
||||
const googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
|
||||
});
|
||||
|
||||
let osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
minZoom: 15
|
||||
});
|
||||
|
||||
let mytile = L.tileLayer('https://tm.rozenrod.com/webp/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
tms: true
|
||||
const osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
|
||||
const mytile = L.tileLayer('https://sheep-service.com/map/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20, minZoom: 15, tms: true
|
||||
});
|
||||
|
||||
if (!map) {
|
||||
|
||||
houseGroup = new L.FeatureGroup();
|
||||
splitPolygonsGroup = new L.FeatureGroup();
|
||||
RectangleGroup = new L.FeatureGroup();
|
||||
@@ -392,40 +110,26 @@ const Editor = {
|
||||
entranseNumPolygonsGroup = new L.FeatureGroup();
|
||||
|
||||
map = L.map('map', {
|
||||
renderer: L.canvas(),
|
||||
center,
|
||||
zoom,
|
||||
layers: [
|
||||
googleHybrid,
|
||||
osm,
|
||||
mytile,
|
||||
houseGroup,
|
||||
entransePolygonsGroup,
|
||||
entranseNumPolygonsGroup,
|
||||
splitPolygonsGroup,
|
||||
RectangleGroup,
|
||||
],
|
||||
renderer: L.canvas(), zoom: 17,
|
||||
layers: [googleHybrid, osm, mytile, houseGroup,
|
||||
entransePolygonsGroup, entranseNumPolygonsGroup,
|
||||
splitPolygonsGroup, RectangleGroup],
|
||||
zoomControl: false
|
||||
});
|
||||
|
||||
|
||||
let baseMaps = {
|
||||
"Google Hybrid": googleHybrid,
|
||||
"OpenStreetMap": osm,
|
||||
"Territory Map": mytile
|
||||
};
|
||||
let overlayMaps = {
|
||||
"Будинки": houseGroup,
|
||||
"Під'їзди": entransePolygonsGroup,
|
||||
"Номера під'їздів": entranseNumPolygonsGroup,
|
||||
"Слой редактирования": splitPolygonsGroup,
|
||||
"Слой линейки": RectangleGroup,
|
||||
};
|
||||
|
||||
L.control.layers(baseMaps, overlayMaps, { position: 'bottomright' }).addTo(map);
|
||||
L.control.layers(
|
||||
{ "Google Hybrid": googleHybrid, "OpenStreetMap": osm, "Territory Map": mytile },
|
||||
{
|
||||
"Будинки": houseGroup,
|
||||
"Під'їзди": entransePolygonsGroup,
|
||||
"Номера під'їздів": entranseNumPolygonsGroup,
|
||||
"Слой редагування": splitPolygonsGroup,
|
||||
"Слой лінійки": RectangleGroup
|
||||
},
|
||||
{ position: 'bottomright' }
|
||||
).addTo(map);
|
||||
|
||||
map.pm.setLang("ua");
|
||||
|
||||
map.pm.addControls({
|
||||
position: 'bottomright',
|
||||
drawCircleMarker: false,
|
||||
@@ -438,12 +142,495 @@ const Editor = {
|
||||
cutPolygon: false,
|
||||
tooltips: false
|
||||
});
|
||||
map.pm.toggleControls()
|
||||
|
||||
map.pm.setGlobalOptions({
|
||||
layerGroup: splitPolygonsGroup
|
||||
})
|
||||
map.pm.toggleControls();
|
||||
map.pm.setGlobalOptions({ layerGroup: splitPolygonsGroup });
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
entrances: {
|
||||
list: [],
|
||||
|
||||
async setHTML(id) {
|
||||
this.list = await Editor.loadAPI(`${CONFIG.api}house/${id}/entrances`);
|
||||
|
||||
entransePolygonsGroup.clearLayers();
|
||||
entranseNumPolygonsGroup.clearLayers();
|
||||
|
||||
const listArea = document.getElementById('list-area');
|
||||
if (!listArea) return;
|
||||
|
||||
listArea.innerHTML = "";
|
||||
|
||||
for (const element of this.list) {
|
||||
// Блок area
|
||||
const divArea = document.createElement('div');
|
||||
divArea.className = "block-area";
|
||||
divArea.id = `block-area-${element.id}`;
|
||||
|
||||
const h3 = document.createElement('h3');
|
||||
h3.textContent = element.title;
|
||||
|
||||
const addBtn = document.createElement('button');
|
||||
addBtn.className = "addFloors";
|
||||
addBtn.type = "button";
|
||||
addBtn.title = "Додати поверх";
|
||||
addBtn.dataset.entranceId = element.id;
|
||||
addBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
addBtn.setAttribute(`onclick`, `Editor.apartments.addFloors("${element.id}")`);
|
||||
|
||||
const innerArea = document.createElement('div');
|
||||
innerArea.id = `area-${element.id}`;
|
||||
|
||||
divArea.append(h3, addBtn, innerArea);
|
||||
listArea.appendChild(divArea);
|
||||
|
||||
// Завантажуємо квартири для ентрансів
|
||||
Editor.apartments.setHTML(element.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
apartments: {
|
||||
list: {},
|
||||
|
||||
async setHTML(id) {
|
||||
this.list[id] = await Editor.loadAPI(`${CONFIG.api}apartments/${id}`);
|
||||
const area = document.getElementById(`area-${id}`);
|
||||
if (!area) return;
|
||||
|
||||
// Унікальні поверхи
|
||||
const uniqueFloors = [...new Set(this.list[id].map(a => a.floors_number))].sort((a, b) => a - b);
|
||||
|
||||
// Створюємо блоки поверхів
|
||||
for (const num of uniqueFloors) {
|
||||
const div = document.createElement('div');
|
||||
div.className = "block-apartments-floors";
|
||||
div.id = `floors-${id}-${num}`;
|
||||
|
||||
const h2 = document.createElement('h2');
|
||||
h2.textContent = `Поверх ${num}`;
|
||||
div.appendChild(h2);
|
||||
|
||||
const addBtn = document.createElement('button');
|
||||
addBtn.className = "addApartment";
|
||||
addBtn.id = `buttonApartment-${id}-${num}`;
|
||||
addBtn.type = "button";
|
||||
addBtn.title = "Додати квартиру";
|
||||
addBtn.dataset.area = id;
|
||||
addBtn.dataset.floors = num;
|
||||
addBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
addBtn.setAttribute(`onclick`, `Editor.apartments.addApartment("${id}", "${num}")`);
|
||||
|
||||
|
||||
div.appendChild(addBtn);
|
||||
area.prepend(div);
|
||||
}
|
||||
|
||||
// Сортуємо квартири за назвою
|
||||
this.list[id].sort((a, b) => b.title - a.title);
|
||||
|
||||
// Створюємо блоки квартир
|
||||
for (const apartment of this.list[id]) {
|
||||
const floorsBlock = document.getElementById(`floors-${id}-${apartment.floors_number}`);
|
||||
if (!floorsBlock) continue;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.className = "block-apartments-number";
|
||||
div.id = `block-apartments-${id}-${apartment.id}`;
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.type = "text";
|
||||
input.value = apartment.title;
|
||||
input.id = `apartament-${id}-${apartment.id}`;
|
||||
input.dataset.area = id;
|
||||
input.dataset.apartment = apartment.id;
|
||||
input.setAttribute(`onclick`, `Editor.apartments.editApartment("${id}", "${apartment.id}")`);
|
||||
|
||||
const delBtn = document.createElement('button');
|
||||
delBtn.type = "button";
|
||||
delBtn.dataset.area = id;
|
||||
delBtn.dataset.apartment = apartment.id;
|
||||
delBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
delBtn.setAttribute(`onclick`, `Editor.apartments.deleteApartment("${id}", "${apartment.id}")`);
|
||||
|
||||
div.append(input, delBtn);
|
||||
floorsBlock.prepend(div);
|
||||
|
||||
numApartments++;
|
||||
}
|
||||
|
||||
const nextApartmentTitle = document.getElementById('next-apartment-title');
|
||||
if (nextApartmentTitle) nextApartmentTitle.value = numApartments;
|
||||
},
|
||||
|
||||
async addFloors(area) {
|
||||
const areaBlock = document.getElementById(`area-${area}`);
|
||||
const uniqueFloors = [...new Set(this.list[area].map(obj => obj.floors_number))];
|
||||
const newFloors = uniqueFloors.length + 1;
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
apartment_number: this.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: newFloors
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
// Створюємо блок поверху
|
||||
const div = document.createElement('div');
|
||||
div.className = "block-apartments-floors";
|
||||
div.id = `floors-${area}-${newFloors}`;
|
||||
|
||||
// Заголовок поверху
|
||||
const h2 = document.createElement('h2');
|
||||
h2.textContent = `Поверх ${newFloors}`;
|
||||
div.appendChild(h2);
|
||||
|
||||
// Блок квартири
|
||||
const apartmentBlock = document.createElement('div');
|
||||
apartmentBlock.className = "block-apartments-number";
|
||||
apartmentBlock.id = `block-apartments-${area}-${data.id}`;
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.type = "text";
|
||||
input.value = numApartments;
|
||||
input.id = `apartament-${area}-${data.id}`;
|
||||
input.onchange = () => Editor.apartments.editApartment(area, data.id);
|
||||
|
||||
const delBtn = document.createElement('button');
|
||||
delBtn.type = "button";
|
||||
delBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
delBtn.onclick = () => Editor.apartments.deleteApartment(area, data.id);
|
||||
|
||||
apartmentBlock.append(input, delBtn);
|
||||
div.appendChild(apartmentBlock);
|
||||
|
||||
// Кнопка додати квартиру
|
||||
const addBtn = document.createElement('button');
|
||||
addBtn.className = "addApartment";
|
||||
addBtn.id = `buttonApartment-${area}-${newFloors}`;
|
||||
addBtn.title = "Додати квартиру";
|
||||
addBtn.type = "button";
|
||||
addBtn.onclick = () => Editor.apartments.addApartment(area, newFloors);
|
||||
addBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
div.appendChild(addBtn);
|
||||
|
||||
areaBlock.prepend(div);
|
||||
|
||||
// Оновлюємо список квартир
|
||||
this.list[area].push({
|
||||
id: data.id,
|
||||
entrance_id: Number(area),
|
||||
apartment_number: this.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: newFloors
|
||||
});
|
||||
|
||||
numApartments++;
|
||||
const nextApartmentTitle = document.getElementById('next-apartment-title');
|
||||
if (nextApartmentTitle) nextApartmentTitle.value = numApartments;
|
||||
|
||||
} catch (err) {
|
||||
console.error("Помилка при додаванні поверху:", err);
|
||||
}
|
||||
},
|
||||
|
||||
async addApartment(area, floors) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
apartment_number: this.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: Number(floors)
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
// Оновлюємо список квартир
|
||||
this.list[area].push({
|
||||
id: data.id,
|
||||
entrance_id: Number(area),
|
||||
apartment_number: this.list[area].length,
|
||||
title: numApartments.toString(),
|
||||
floors_number: Number(floors)
|
||||
});
|
||||
|
||||
const floorsBlock = document.getElementById(`floors-${area}-${floors}`);
|
||||
|
||||
// Видаляємо стару кнопку додати квартиру
|
||||
const oldButton = document.getElementById(`buttonApartment-${area}-${floors}`);
|
||||
if (oldButton) oldButton.remove();
|
||||
|
||||
// Створюємо блок нової квартири
|
||||
const apartmentDiv = document.createElement('div');
|
||||
apartmentDiv.className = "block-apartments-number";
|
||||
apartmentDiv.id = `block-apartments-${area}-${data.id}`;
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.type = "text";
|
||||
input.value = numApartments;
|
||||
input.id = `apartament-${area}-${data.id}`;
|
||||
input.onchange = () => Editor.apartments.editApartment(area, data.id);
|
||||
|
||||
const delBtn = document.createElement('button');
|
||||
delBtn.type = "button";
|
||||
delBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
delBtn.onclick = () => Editor.apartments.deleteApartment(area, data.id);
|
||||
|
||||
apartmentDiv.append(input, delBtn);
|
||||
floorsBlock.appendChild(apartmentDiv);
|
||||
|
||||
// Додаємо кнопку "додати квартиру" знову
|
||||
const addBtn = document.createElement('button');
|
||||
addBtn.className = "addApartment";
|
||||
addBtn.id = `buttonApartment-${area}-${floors}`;
|
||||
addBtn.title = "Додати квартиру";
|
||||
addBtn.type = "button";
|
||||
addBtn.onclick = () => Editor.apartments.addApartment(area, floors);
|
||||
addBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"></path></svg>`;
|
||||
floorsBlock.appendChild(addBtn);
|
||||
|
||||
numApartments++;
|
||||
const nextApartmentTitle = document.getElementById('next-apartment-title');
|
||||
if (nextApartmentTitle) nextApartmentTitle.value = numApartments;
|
||||
|
||||
} catch (err) {
|
||||
console.error("Помилка при додаванні квартири:", err);
|
||||
}
|
||||
},
|
||||
|
||||
async editApartment(area, apartment) {
|
||||
const input = document.getElementById(`apartament-${area}-${apartment}`);
|
||||
if (!input) return;
|
||||
|
||||
const newTitle = input.value;
|
||||
|
||||
// Оновлюємо локальний список квартир
|
||||
const pos = this.list[area].findIndex(e => e.id === Number(apartment));
|
||||
if (pos === -1) return;
|
||||
|
||||
this.list[area][pos].title = newTitle;
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: this.list[area][pos].id,
|
||||
title: this.list[area][pos].title,
|
||||
status: this.list[area][pos].status,
|
||||
description: this.list[area][pos].description
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
} catch (err) {
|
||||
console.error("Помилка при редагуванні квартири:", err);
|
||||
}
|
||||
},
|
||||
|
||||
async deleteApartment(area, apartment) {
|
||||
const pos = this.list[area].findIndex(e => e.id === Number(apartment));
|
||||
if (pos === -1) return;
|
||||
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartments/${area}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({ id: this.list[area][pos].id })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
// Видаляємо елемент з DOM
|
||||
const apartmentBlock = document.getElementById(`block-apartments-${area}-${apartment}`);
|
||||
if (apartmentBlock) apartmentBlock.remove();
|
||||
|
||||
// Оновлюємо локальний список
|
||||
this.list[area].splice(pos, 1);
|
||||
|
||||
// Оновлюємо номер наступної квартири
|
||||
numApartments = Math.max(0, numApartments - 1);
|
||||
const nextApartmentTitle = document.getElementById('next-apartment-title');
|
||||
if (nextApartmentTitle) nextApartmentTitle.value = numApartments;
|
||||
|
||||
} catch (err) {
|
||||
console.error("Помилка при видаленні квартири:", err);
|
||||
}
|
||||
},
|
||||
|
||||
editNum(el) { numApartments = Number(el.value) },
|
||||
},
|
||||
|
||||
homestead: {
|
||||
id: null, list: [], editing: false,
|
||||
|
||||
async init(id) {
|
||||
this.editing = false;
|
||||
this.id = id;
|
||||
setLeafletCursor('pointer');
|
||||
|
||||
document.getElementById('homestead-editing').style.display = "";
|
||||
|
||||
// Завантаження даних будівлі
|
||||
this.list = await Editor.loadAPI(`${CONFIG.api}building/${id}`);
|
||||
|
||||
// Обробник кліку на карту
|
||||
houseGroup.on('click', e => {
|
||||
if (e.layer instanceof L.Marker || !this.editing) return;
|
||||
|
||||
const { lat, lng } = e.latlng;
|
||||
console.log(`Координати: ${lat.toFixed(5)}, ${lng.toFixed(5)}`);
|
||||
|
||||
setLeafletCursor('progress');
|
||||
this.editing.editing = false;
|
||||
|
||||
this.addBuilding({ geo: e.latlng, title: this.list.length + 1 });
|
||||
this.list.push({});
|
||||
});
|
||||
|
||||
// Встановлюємо вид карти
|
||||
const viewLatLng = Editor.info.list.geo?.lat
|
||||
? [Editor.info.list.geo.lat, Editor.info.list.geo.lng]
|
||||
: [Editor.info.list.points[0][0][0].lat, Editor.info.list.points[0][0][0].lng];
|
||||
map.setView(viewLatLng, Editor.info.list.zoom);
|
||||
|
||||
|
||||
for (const element of this.list) {
|
||||
// Додаємо маркер на карту
|
||||
const redDot = L.divIcon({
|
||||
className: "leaflet_drop",
|
||||
html: `<div id="redDot_${element.id}"></div>`,
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8]
|
||||
});
|
||||
|
||||
L.marker(element.geo, { icon: redDot })
|
||||
.addTo(houseGroup)
|
||||
.bindPopup(`
|
||||
Точка: ${element.id}<br>
|
||||
Координати: ${element.geo.lat.toFixed(5)}, ${element.geo.lng.toFixed(5)}<br>
|
||||
<button class="map_dell" onclick="Editor.homestead.delleteBuilding({id: ${element.id}})" type="button">Видалити</button>
|
||||
`);
|
||||
}
|
||||
},
|
||||
|
||||
async addBuilding({ geo, title }) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}building/${this.id}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({ title, geo })
|
||||
});
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
// Додаємо маркер на карту
|
||||
const redDot = L.divIcon({
|
||||
className: "leaflet_drop",
|
||||
html: `<div id="redDot_${data.id}"></div>`,
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8]
|
||||
});
|
||||
|
||||
const marker = L.marker(geo, { icon: redDot }).addTo(houseGroup);
|
||||
marker.bindPopup(`
|
||||
Точка: ${data.id}<br>
|
||||
Координати: ${geo.lat.toFixed(5)}, ${geo.lng.toFixed(5)}<br>
|
||||
<button class="map_dell" onclick="Editor.homestead.delleteBuilding({id: ${data.id}})" type="button">Видалити</button>
|
||||
`);
|
||||
|
||||
setLeafletCursor('crosshair');
|
||||
this.editing = true;
|
||||
|
||||
} catch (err) {
|
||||
console.error("Помилка при додаванні будівлі:", err);
|
||||
}
|
||||
},
|
||||
|
||||
async delleteBuilding({ id }) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}building/${id}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
// Видаляємо елемент списку та маркер
|
||||
const el = document.getElementById(`redDot_${id}`);
|
||||
if (el) el.remove();
|
||||
|
||||
const block = document.getElementById(`Building_${id}`);
|
||||
if (block) block.remove();
|
||||
|
||||
houseGroup.eachLayer(layer => {
|
||||
if (layer instanceof L.Marker && layer.getPopup()?.getContent().includes(`Точка: ${id}`)) {
|
||||
houseGroup.removeLayer(layer);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error("Помилка при видаленні будівлі:", err);
|
||||
}
|
||||
},
|
||||
|
||||
editing_mode() {
|
||||
const btn = document.getElementById('homestead-editing');
|
||||
this.editing = !this.editing;
|
||||
setLeafletCursor(this.editing ? 'crosshair' : 'pointer');
|
||||
btn.innerHTML = this.editing
|
||||
? `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"> <path d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z" ></path> </svg>`
|
||||
: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"> <path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z" ></path> </svg>`;
|
||||
if (this.editing) alert("Натискаючи на карту будуть створюватись нові точки (будинки)");
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
margin: 20px 0;
|
||||
text-transform: uppercase;
|
||||
@@ -48,7 +48,7 @@
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
@@ -65,7 +65,7 @@
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
margin: 13px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
@@ -120,7 +120,7 @@
|
||||
|
||||
#details-info-type>.tabs>.tab>span {
|
||||
margin-left: 6px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
|
||||
@@ -207,6 +207,7 @@
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
.page-editor #details-info-osm div {
|
||||
@@ -243,7 +244,7 @@
|
||||
|
||||
.page-editor #list-area h3 {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
margin: 10px;
|
||||
padding: 7px;
|
||||
@@ -302,7 +303,7 @@
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes2);
|
||||
border-radius: 0 4px 0 4px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
padding: 2px 4px;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -323,7 +324,7 @@
|
||||
.block-apartments-number input {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
@@ -338,7 +339,7 @@
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
@@ -360,6 +361,38 @@
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
#homestead-editing {
|
||||
position: absolute;
|
||||
height: 40px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: var(--FontSize5);
|
||||
margin: 10px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 500;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
width: 40px;
|
||||
z-index: 999;
|
||||
right: 0;
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
#homestead-editing>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#map {
|
||||
@@ -405,7 +438,7 @@
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
}
|
||||
|
||||
.editor-buttons>div {
|
||||
@@ -424,7 +457,7 @@
|
||||
border-radius: 6px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
}
|
||||
|
||||
.page-editor #list-entranse,
|
||||
@@ -441,6 +474,7 @@
|
||||
border-radius: 6px;
|
||||
border-style: dashed;
|
||||
margin: 10px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-editor #list-entranse>.house,
|
||||
@@ -449,6 +483,8 @@
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
min-width: 60px;
|
||||
min-height: 60px;
|
||||
background: var(--ColorThemes1);
|
||||
border: 2px solid var(--PrimaryColor);
|
||||
margin: 10px;
|
||||
@@ -464,7 +500,7 @@
|
||||
.page-editor #list-homestead>.house>p {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
@@ -483,7 +519,7 @@
|
||||
height: 20px;
|
||||
border-radius: 0 4px 0 4px;
|
||||
background: var(--PrimaryColor);
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
margin: -2px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
<div class="page-home">
|
||||
<details id="details-personal-territory" open>
|
||||
<details id="details-personal-territory" open style="display: none;">
|
||||
<summary>
|
||||
<span>Території для опрацювання</span>
|
||||
</summary>
|
||||
|
||||
<div id="home-personal-territory-list"></div>
|
||||
</details>
|
||||
|
||||
<details id="details-group-territory" open style="display: none;">
|
||||
<summary>
|
||||
<span>Групові території</span>
|
||||
</summary>
|
||||
|
||||
<div id="home-group-territory-list"></div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
@@ -3,93 +3,142 @@ const Home = {
|
||||
let html = await fetch('/lib/pages/home/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
Home.house.setHTML();
|
||||
Home.homestead.setHTML();
|
||||
if (USER.possibilities.can_view_territory) {
|
||||
Home.personal.house.setHTML();
|
||||
Home.personal.homestead.setHTML();
|
||||
|
||||
Home.group.house.setHTML();
|
||||
Home.group.homestead.setHTML();
|
||||
}
|
||||
},
|
||||
house: {
|
||||
loadAPI: async function () {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
personal: {
|
||||
house: {
|
||||
list: [],
|
||||
loadAPI: async () => {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const URL = `${CONFIG.api}houses/list?mode=sheep`;
|
||||
const res = await fetch(URL, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
Home.personal.house.list = await res.json();
|
||||
return Home.personal.house.list;
|
||||
},
|
||||
setHTML: async () => {
|
||||
const list = Home.personal.house.list.length > 0
|
||||
? Home.personal.house.list
|
||||
: await Home.personal.house.loadAPI();
|
||||
|
||||
const URL = `${CONFIG.api}houses/list?mode=sheep`;
|
||||
return await fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
},
|
||||
setHTML: async function () {
|
||||
let list = await Home.house.loadAPI();
|
||||
if (USER.possibilities.can_view_territory && list.length)
|
||||
document.getElementById('details-personal-territory').style.display = "";
|
||||
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
Home.renderCards(list, "house", "personal");
|
||||
}
|
||||
},
|
||||
homestead: {
|
||||
list: [],
|
||||
loadAPI: async () => {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const URL = `${CONFIG.api}homestead/list?mode=sheep`;
|
||||
const res = await fetch(URL, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
Home.personal.homestead.list = await res.json();
|
||||
return Home.personal.homestead.list;
|
||||
},
|
||||
setHTML: async () => {
|
||||
const list = Home.personal.homestead.list.length > 0
|
||||
? Home.personal.homestead.list
|
||||
: await Home.personal.homestead.loadAPI();
|
||||
|
||||
console.log(list);
|
||||
let block_house = document.getElementById('home-personal-territory-list')
|
||||
if (USER.possibilities.can_view_territory && list.length)
|
||||
document.getElementById('details-personal-territory').style.display = "";
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const element = list[i];
|
||||
|
||||
block_house.innerHTML += `
|
||||
<div class="card">
|
||||
<i style="background-image: url(https://sheep-service.com/cards/house/T${element.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="group" style="background: ${colorGroup(element.group_id)}">
|
||||
<span>Група №${element.group_id}</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>
|
||||
<p>${element.title} ${element.number}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/territory/card/house/${element.id}" data-route></a>
|
||||
</div>
|
||||
`;
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
Home.renderCards(list, "homestead", "personal");
|
||||
}
|
||||
}
|
||||
},
|
||||
homestead: {
|
||||
loadAPI: async function () {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
group: {
|
||||
house: {
|
||||
list: [],
|
||||
loadAPI: async () => {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const URL = `${CONFIG.api}house/list?mode=group`;
|
||||
const res = await fetch(URL, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
Home.group.house.list = await res.json();
|
||||
return Home.group.house.list;
|
||||
},
|
||||
setHTML: async () => {
|
||||
const list = Home.group.house.list.length > 0
|
||||
? Home.group.house.list
|
||||
: await Home.group.house.loadAPI();
|
||||
|
||||
const URL = `${CONFIG.api}homestead/list?mode=sheep`;
|
||||
return await fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
},
|
||||
setHTML: async function () {
|
||||
let list = await Home.homestead.loadAPI();
|
||||
if (USER.possibilities.can_view_territory && list.length)
|
||||
document.getElementById('details-group-territory').style.display = "";
|
||||
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
Home.renderCards(list, "house", "group");
|
||||
}
|
||||
},
|
||||
homestead: {
|
||||
list: [],
|
||||
loadAPI: async () => {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const URL = `${CONFIG.api}homestead/list?mode=group`;
|
||||
const res = await fetch(URL, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
Home.group.homestead.list = await res.json();
|
||||
return Home.group.homestead.list;
|
||||
},
|
||||
setHTML: async () => {
|
||||
const list = Home.group.homestead.list.length > 0
|
||||
? Home.group.homestead.list
|
||||
: await Home.group.homestead.loadAPI();
|
||||
|
||||
console.log(list);
|
||||
let block_homestead = document.getElementById('home-personal-territory-list')
|
||||
if (USER.possibilities.can_view_territory && list.length)
|
||||
document.getElementById('details-group-territory').style.display = "";
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const element = list[i];
|
||||
|
||||
block_homestead.innerHTML += `
|
||||
<div class="card">
|
||||
<i style="background-image: url(https://sheep-service.com/cards/homestead/H${element.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="group" style="background: ${colorGroup(element.group_id)}">
|
||||
<span>Група №${element.group_id}</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>
|
||||
<p>${element.title} ${element.number}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/territory/card/homestead/${element.id}" data-route></a>
|
||||
</div>
|
||||
`;
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
Home.renderCards(list, "homestead", "group");
|
||||
}
|
||||
}
|
||||
},
|
||||
renderCards: (list, type, block) => {
|
||||
const container = document.getElementById(`home-${block}-territory-list`);
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
for (const el of list) {
|
||||
const card = document.createElement("div");
|
||||
card.className = "card";
|
||||
|
||||
card.innerHTML = `
|
||||
<i style="background-image: url(https://sheep-service.com/cards/${type}/${type === "house" ? "T" : "H"}${el.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="info">
|
||||
<div><p>${el.title} ${el.number}</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/territory/card/${type}/${el.id}" data-route></a>
|
||||
`;
|
||||
fragment.appendChild(card);
|
||||
}
|
||||
|
||||
container.appendChild(fragment);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
@@ -47,7 +47,8 @@
|
||||
}
|
||||
|
||||
|
||||
.page-home #home-personal-territory-list {
|
||||
.page-home #home-personal-territory-list,
|
||||
.page-home #home-group-territory-list {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
@@ -112,7 +113,7 @@
|
||||
/* background-repeat: round; */
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(https://tm.rozenrod.com/web/img/bg.webp);
|
||||
background-color: var(--PrimaryColor);
|
||||
}
|
||||
.page-home .card>a {
|
||||
position: absolute;
|
||||
@@ -132,60 +133,41 @@
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.page-home .group {
|
||||
width: calc(100% - 20px);
|
||||
max-height: 50px;
|
||||
border-radius: 7px;
|
||||
padding: 10px 0;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
background: var(--PrimaryColor);
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.page-home .group>span {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.page-home .info {
|
||||
width: calc(100% - 20px);
|
||||
margin-bottom: 10px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.page-home .info>div {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
background: var(--ColorThemes0);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: 7px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.page-home .info>div>span {
|
||||
color: var(--ColorThemes3);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 300;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.page-home .info>div>p {
|
||||
color: var(--ColorThemes3);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
padding: 10px;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<div class="page-options">
|
||||
<div class="option checkbox">
|
||||
<input
|
||||
class="custom-checkbox"
|
||||
id="page-options-notifications"
|
||||
type="checkbox"
|
||||
onchange="Options.optionPush.edit(this.checked)"
|
||||
/>
|
||||
<label for="page-options-notifications"> Повідомлення: </label>
|
||||
</div>
|
||||
|
||||
<div class="option inputs">
|
||||
<label for="page-options-fontSize">Розмір шрифту:</label>
|
||||
<select id="page-options-fontSize" onchange="Options.optionFont.edit(this.value)">
|
||||
<option value="small">Маленький</option>
|
||||
<option value="medium">Середній</option>
|
||||
<option value="large">Великий</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,51 @@
|
||||
const Options = {
|
||||
init: async () => {
|
||||
let html = await fetch('/lib/pages/options/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
app.innerHTML = html;
|
||||
|
||||
await Options.optionPush.init();
|
||||
Options.optionFont.init();
|
||||
},
|
||||
optionPush: {
|
||||
init: async () => {
|
||||
const element = document.getElementById("page-options-notifications");
|
||||
const permission = await Notification.requestPermission();
|
||||
|
||||
if (!('serviceWorker' in navigator) || !('PushManager' in window) || permission !== 'granted') {
|
||||
element.disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
let subscription = await registration.pushManager.getSubscription();
|
||||
|
||||
if (subscription) {
|
||||
element.checked = true;
|
||||
} else {
|
||||
element.checked = false;
|
||||
}
|
||||
},
|
||||
edit: (state) => {
|
||||
if (state) {
|
||||
webPush.init();
|
||||
} else {
|
||||
webPush.unsubscribe();
|
||||
}
|
||||
}
|
||||
},
|
||||
optionFont: {
|
||||
init: () => {
|
||||
const element = document.getElementById("page-options-fontSize");
|
||||
|
||||
let fontSize = localStorage.getItem("fontSize")
|
||||
? localStorage.getItem("fontSize")
|
||||
: 'medium';
|
||||
|
||||
element.value = fontSize;
|
||||
},
|
||||
edit: (mode) => {
|
||||
localStorage.setItem("fontSize", mode);
|
||||
applyFontMode(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
.page-options {
|
||||
position: relative;
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
.page-options>.option {
|
||||
text-align: left;
|
||||
font-weight: 400;
|
||||
padding: 20px;
|
||||
margin: 0 0 15px;
|
||||
border-radius: 15px;
|
||||
font-size: var(--FontSize5);
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.page-options>.option>label {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin: 5px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-options>.option>select {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
.page-options>.option>.custom-checkbox+label {
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
margin: 5px 0;
|
||||
}
|
||||
0
web/lib/pages/schedule/index.html
Normal file
0
web/lib/pages/schedule/index.html
Normal file
8
web/lib/pages/schedule/script.js
Normal file
8
web/lib/pages/schedule/script.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const Schedule = {
|
||||
init: async () => {
|
||||
let html = await fetch('/lib/pages/schedule/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
0
web/lib/pages/schedule/style.css
Normal file
0
web/lib/pages/schedule/style.css
Normal file
@@ -2,6 +2,25 @@
|
||||
<div id="block-sheeps-list">
|
||||
<div class="header">
|
||||
<h1>Всі вісники</h1>
|
||||
|
||||
<div>
|
||||
<button title="Пошук" id="block-sheeps-list-search-buttom">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72">
|
||||
<path
|
||||
d="M 31 11 C 19.973 11 11 19.973 11 31 C 11 42.027 19.973 51 31 51 C 34.974166 51 38.672385 49.821569 41.789062 47.814453 L 54.726562 60.751953 C 56.390563 62.415953 59.088953 62.415953 60.751953 60.751953 C 62.415953 59.087953 62.415953 56.390563 60.751953 54.726562 L 47.814453 41.789062 C 49.821569 38.672385 51 34.974166 51 31 C 51 19.973 42.027 11 31 11 z M 31 19 C 37.616 19 43 24.384 43 31 C 43 37.616 37.616 43 31 43 C 24.384 43 19 37.616 19 31 C 19 24.384 24.384 19 31 19 z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
${butt_add}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search" id="block-sheeps-list-search" data-state="closed">
|
||||
<input
|
||||
type="text"
|
||||
id="block-sheeps-list-search-name"
|
||||
placeholder="Імʼя вісника"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="card-profile"></div>
|
||||
@@ -32,7 +51,7 @@
|
||||
<div class="header">
|
||||
<h1>Інформація про вісника</h1>
|
||||
|
||||
<button onclick="Sheeps.editor.close()">
|
||||
<button onclick="Sheeps.editor.close()" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26">
|
||||
<path
|
||||
d="M 6.65625 4 C 6.367188 4 6.105469 4.113281 5.90625 4.3125 L 4.3125 5.90625 C 3.914063 6.304688 3.914063 7 4.3125 7.5 L 9.8125 13 L 4.3125 18.5 C 3.914063 19 3.914063 19.695313 4.3125 20.09375 L 5.90625 21.6875 C 6.40625 22.085938 7.101563 22.085938 7.5 21.6875 L 13 16.1875 L 18.5 21.6875 C 19 22.085938 19.695313 22.085938 20.09375 21.6875 L 21.6875 20.09375 C 22.085938 19.59375 22.085938 18.898438 21.6875 18.5 L 16.1875 13 L 21.6875 7.5 C 22.085938 7 22.085938 6.304688 21.6875 5.90625 L 20.09375 4.3125 C 19.59375 3.914063 18.898438 3.914063 18.5 4.3125 L 13 9.8125 L 7.5 4.3125 C 7.25 4.113281 6.945313 4 6.65625 4 Z"
|
||||
@@ -42,7 +61,7 @@
|
||||
</div>
|
||||
<i id="sheep-editor-icon"></i>
|
||||
<div class="editor-blocks-inputs" id="editor-blocks-inputs-uuid">
|
||||
<label>UUID</label>
|
||||
<label>UUID <span>Натисніть, щоб скопіювати</span></label>
|
||||
<input
|
||||
id="sheep-editor-uuid"
|
||||
type="text"
|
||||
@@ -81,9 +100,9 @@
|
||||
<div class="editor-blocks-inputs">
|
||||
<label for="sheep-editor-mode">Права</label>
|
||||
<select id="sheep-editor-mode" name="mode">
|
||||
<option value="sheep" selected>Користувач</option>
|
||||
<option value="moderator">Модератор</option>
|
||||
<option value="administrator">Адміністратор</option>
|
||||
<option value="0" selected>Користувач</option>
|
||||
<option value="1">Модератор</option>
|
||||
<option value="2">Адміністратор</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -103,6 +122,15 @@
|
||||
>
|
||||
<p for="editor-access">Дозволи модератора</p>
|
||||
<div>
|
||||
<div class="checkbox">
|
||||
<input
|
||||
name="can_view_sheeps"
|
||||
class="custom-checkbox"
|
||||
id="sheep-editor-can_view_sheeps"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label for="sheep-editor-can_view_sheeps"> View Sheeps </label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<input
|
||||
name="can_add_sheeps"
|
||||
@@ -199,7 +227,91 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="sheep-editor-button" style="display: none">Зберегти</button>
|
||||
<button id="sheep-editor-button" style="display: none" type="submit">
|
||||
Зберегти
|
||||
</button>
|
||||
|
||||
<details id="editor-blocks-territory" style="display: none;">
|
||||
<summary>Території вісника</summary>
|
||||
|
||||
<div>
|
||||
<div id="title">
|
||||
<h1>вул. Бродівська 50Б (Під'їзд 1)</h1>
|
||||
|
||||
<a
|
||||
href="/territory/card/house/57"
|
||||
title="Редактор квартир"
|
||||
data-route=""
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 12.5 6 C 8.9280619 6 6 8.9280619 6 12.5 L 6 35.5 C 6 39.071938 8.9280619 42 12.5 42 L 35.5 42 C 39.071938 42 42 39.071938 42 35.5 L 42 12.5 C 42 8.9280619 39.071938 6 35.5 6 L 12.5 6 z M 12.5 9 L 14 9 L 14 15 L 9 15 L 9 12.5 C 9 10.549938 10.549938 9 12.5 9 z M 17 9 L 35.5 9 C 37.450062 9 39 10.549938 39 12.5 L 39 15 L 17 15 L 17 9 z M 9 18 L 14 18 L 14 23 L 9 23 L 9 18 z M 17 18 L 39 18 L 39 23 L 17 23 L 17 18 z M 9 26 L 14 26 L 14 31 L 9 31 L 9 26 z M 17 26 L 39 26 L 39 31 L 17 31 L 17 26 z M 9 34 L 14 34 L 14 39 L 12.5 39 C 10.549938 39 9 37.450062 9 35.5 L 9 34 z M 17 34 L 39 34 L 39 35.5 C 39 37.450062 37.450062 39 35.5 39 L 17 39 L 17 34 z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територія видана:</h1>
|
||||
<h2>02.07.2025</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Варто забрати:</h1>
|
||||
<h2>01.11.2025</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div id="title">
|
||||
<h1>вул. Бродівська 50Б (Під'їзд 1)</h1>
|
||||
|
||||
<a
|
||||
href="/territory/card/house/57"
|
||||
title="Редактор квартир"
|
||||
data-route=""
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 12.5 6 C 8.9280619 6 6 8.9280619 6 12.5 L 6 35.5 C 6 39.071938 8.9280619 42 12.5 42 L 35.5 42 C 39.071938 42 42 39.071938 42 35.5 L 42 12.5 C 42 8.9280619 39.071938 6 35.5 6 L 12.5 6 z M 12.5 9 L 14 9 L 14 15 L 9 15 L 9 12.5 C 9 10.549938 10.549938 9 12.5 9 z M 17 9 L 35.5 9 C 37.450062 9 39 10.549938 39 12.5 L 39 15 L 17 15 L 17 9 z M 9 18 L 14 18 L 14 23 L 9 23 L 9 18 z M 17 18 L 39 18 L 39 23 L 17 23 L 17 18 z M 9 26 L 14 26 L 14 31 L 9 31 L 9 26 z M 17 26 L 39 26 L 39 31 L 17 31 L 17 26 z M 9 34 L 14 34 L 14 39 L 12.5 39 C 10.549938 39 9 37.450062 9 35.5 L 9 34 z M 17 34 L 39 34 L 39 35.5 C 39 37.450062 37.450062 39 35.5 39 L 17 39 L 17 34 z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територія видана:</h1>
|
||||
<h2>02.07.2025</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Варто забрати:</h1>
|
||||
<h2>01.11.2025</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div id="title">
|
||||
<h1>вул. Бродівська 50Б (Під'їзд 1)</h1>
|
||||
|
||||
<a
|
||||
href="/territory/card/house/57"
|
||||
title="Редактор квартир"
|
||||
data-route=""
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 12.5 6 C 8.9280619 6 6 8.9280619 6 12.5 L 6 35.5 C 6 39.071938 8.9280619 42 12.5 42 L 35.5 42 C 39.071938 42 42 39.071938 42 35.5 L 42 12.5 C 42 8.9280619 39.071938 6 35.5 6 L 12.5 6 z M 12.5 9 L 14 9 L 14 15 L 9 15 L 9 12.5 C 9 10.549938 10.549938 9 12.5 9 z M 17 9 L 35.5 9 C 37.450062 9 39 10.549938 39 12.5 L 39 15 L 17 15 L 17 9 z M 9 18 L 14 18 L 14 23 L 9 23 L 9 18 z M 17 18 L 39 18 L 39 23 L 17 23 L 17 18 z M 9 26 L 14 26 L 14 31 L 9 31 L 9 26 z M 17 26 L 39 26 L 39 31 L 17 31 L 17 26 z M 9 34 L 14 34 L 14 39 L 12.5 39 C 10.549938 39 9 37.450062 9 35.5 L 9 34 z M 17 34 L 39 34 L 39 35.5 C 39 37.450062 37.450062 39 35.5 39 L 17 39 L 17 34 z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територія видана:</h1>
|
||||
<h2>02.07.2025</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Варто забрати:</h1>
|
||||
<h2>01.11.2025</h2>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
||||
#block-sheep-info {
|
||||
width: 100%;
|
||||
margin: 0 10px 15px;
|
||||
border-radius: 15px;
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -39,45 +39,102 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: var(--PrimaryColor);
|
||||
margin: 10px;
|
||||
border-radius: 10px;
|
||||
margin: 10px 10px 0px 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.header>h1 {
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
color: var(--PrimaryColorText);
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.header>button {
|
||||
#block-sheeps-list>.header>div {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.header>div>button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
margin-right: 5px;
|
||||
border-radius: 8px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 3px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.header>button>svg {
|
||||
#block-sheeps-list>.header>div>button>svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#block-sheeps-list>.header>div>#block-sheeps-button-add>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--ColorThemes3);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
|
||||
#block-sheeps-list>.search {
|
||||
width: calc(100% - 30px);
|
||||
background-color: var(--PrimaryColor);
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
margin: -12px 10px 20px 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 5px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
transition: max-height 0.3s ease, opacity 0.3s ease, margin 0.3s ease, padding 0.3s ease;
|
||||
}
|
||||
|
||||
|
||||
#block-sheeps-list>.search[data-state="open"] {
|
||||
max-height: 60px;
|
||||
padding: 22px 5px 5px 5px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.search>input {
|
||||
width: calc(100% - 10px);
|
||||
padding: 0 5px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background: var(--ColorThemes3);
|
||||
color: var(--ColorThemes0);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
#block-sheeps-list>.search>input::placeholder {
|
||||
color: var(--ColorThemes0);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.search>input::-webkit-input-placeholder {
|
||||
color: var(--ColorThemes0);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.card-profile {
|
||||
width: calc(100% - 30px);
|
||||
min-height: 100px;
|
||||
background-color: var(--ColorThemes2);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
margin: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -105,13 +162,13 @@
|
||||
}
|
||||
|
||||
#block-sheeps-list>.card-profile>.info>.text>h1 {
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
color: var(--ColorThemes3);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#block-sheeps-list>.card-profile>.info>.text>h2 {
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
color: var(--ColorThemes3);
|
||||
font-weight: 400;
|
||||
opacity: 0.8;
|
||||
@@ -128,12 +185,12 @@
|
||||
|
||||
#block-sheeps-list>.card-profile>.info>.access>b {
|
||||
padding: 2px 5px;
|
||||
border-radius: 5px;
|
||||
border-radius: calc(var(--border-radius) - 10px);
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
margin-right: 5px;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
font-size: var(--FontSize2);
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -190,11 +247,11 @@
|
||||
justify-content: space-between;
|
||||
background: var(--ColorThemes3);
|
||||
margin: 0 0 10px 0;
|
||||
border-radius: 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.header>h1 {
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes0);
|
||||
margin-left: 10px;
|
||||
@@ -207,7 +264,7 @@
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
margin-right: 5px;
|
||||
border-radius: 8px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 3px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
@@ -237,27 +294,33 @@
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-inputs label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
flex-direction: row;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-inputs label>span {
|
||||
opacity: 0.5;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-inputs input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-inputs select {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
@@ -267,9 +330,9 @@
|
||||
display: flex;
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
@@ -289,14 +352,14 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-checkbox>div {
|
||||
background: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
width: calc(100% - 15px);
|
||||
padding: 0 5px 0 10px;
|
||||
}
|
||||
@@ -304,7 +367,7 @@
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-checkbox>div>.checkbox {
|
||||
margin: 10px 0;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.editor-blocks-checkbox>div>.checkbox>.custom-checkbox+label {
|
||||
@@ -314,17 +377,18 @@
|
||||
user-select: none;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>button {
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
margin: 20px 0 0 0;
|
||||
margin: 10px 0 0 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@@ -332,7 +396,7 @@
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
margin: 0 10px 15px;
|
||||
border-radius: 15px;
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -366,11 +430,11 @@
|
||||
justify-content: space-between;
|
||||
background: var(--ColorThemes3);
|
||||
margin: 0 0 10px 0;
|
||||
border-radius: 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
}
|
||||
|
||||
#block-sheep-addeds>#sheep-addeds>.header>h1 {
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes0);
|
||||
margin-left: 10px;
|
||||
@@ -383,7 +447,7 @@
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
margin-right: 5px;
|
||||
border-radius: 8px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 3px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
@@ -414,7 +478,7 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
@@ -423,34 +487,147 @@
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize2);
|
||||
}
|
||||
|
||||
#block-sheep-addeds>#sheep-addeds>.addeds-blocks-inputs select {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#block-sheep-addeds>#sheep-addeds>button {
|
||||
border-radius: 6px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
background: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
margin: 20px 0 0 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
||||
#editor-blocks-territory {
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
margin-top: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
#editor-blocks-territory summary {
|
||||
width: calc(100% - 40px);
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div {
|
||||
width: calc(100% - 40px);
|
||||
color: var(--ColorThemes3) #f3f3f3;
|
||||
background-color: var(--ColorThemes2);
|
||||
border: 1px solid var(--PrimaryColor);
|
||||
box-shadow: var(--shadow-l1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
min-height: 100px;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border-radius: calc(var(--border-radius) - 5px - 6px);
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>#title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
margin-bottom: 10px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>#title>h1 {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: 6px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>#title>a {
|
||||
color: var(--ColorThemes0);
|
||||
border-radius: 6px;
|
||||
font-weight: 400;
|
||||
opacity: 1;
|
||||
min-height: 30px;
|
||||
min-width: 30px;
|
||||
padding: 0;
|
||||
margin: 0 0 0 10px;
|
||||
background: var(--PrimaryColor);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>#title>a>svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>div {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>div>h1 {
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#editor-blocks-territory>div>div>h2,
|
||||
#editor-blocks-territory>div>div>a,
|
||||
#editor-blocks-territory>div>div>p {
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 300;
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.8;
|
||||
margin: 0 7px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (min-width: 1001px),
|
||||
(min-height: 541px) {
|
||||
|
||||
@@ -470,6 +647,7 @@
|
||||
display: none;
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
||||
#block-sheep-info>#sheep-editor>.header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,282 @@
|
||||
<div class="page-stand">
|
||||
<label for="dateSelect">Виберіть дату:</label>
|
||||
<select id="dateSelect"></select>
|
||||
<!-- <label for="dateSelect">Виберіть дату:</label>
|
||||
<select id="dateSelect"></select> -->
|
||||
|
||||
<details id="stand-info">
|
||||
<summary>Інформація про стенд</summary>
|
||||
<div>
|
||||
<span>Розташування:</span>
|
||||
<p id="stand-info-title">Тест</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>Геолокація:</span>
|
||||
<p id="stand-info-geo"></p>
|
||||
</div>
|
||||
<img id="stand-info-image" src="" />
|
||||
</details>
|
||||
|
||||
<div id="stand-schedule">
|
||||
<!-- <div class="block-day" id="day-0">
|
||||
<h3>08.08.2025 • Пʼятниця</h3>
|
||||
<div>
|
||||
<span id="time">09:00-10:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">10:00-11:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">11:00-12:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">12:00-13:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">14:00-15:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">15:00-16:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">16:00-17:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">17:00-18:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-day" id="day-1">
|
||||
<h3>11.08.2025 • Понеділок</h3>
|
||||
<div>
|
||||
<span id="time">09:00-10:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">10:00-11:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">11:00-12:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">12:00-13:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">14:00-15:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">15:00-16:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">16:00-17:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span id="time">17:00-18:00</span>
|
||||
<select id="name_1">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_2">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
<select id="name_3">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const Stand = {
|
||||
schedule: [],
|
||||
init: async () => {
|
||||
let html = await fetch('/lib/pages/stand/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
@@ -33,6 +34,90 @@ const Stand = {
|
||||
});
|
||||
}
|
||||
|
||||
generateAvailableDates();
|
||||
// generateAvailableDates();
|
||||
Stand.generator();
|
||||
},
|
||||
generator: () => {
|
||||
let block_schedule = document.getElementById('stand-schedule');
|
||||
|
||||
let html = "";
|
||||
|
||||
let stand = {
|
||||
id: 1,
|
||||
title: "Універсам",
|
||||
geo: { lat: 0, lng: 0 },
|
||||
hour_start: 9,
|
||||
hour_end: 14,
|
||||
quantity_sheep: 4,
|
||||
week_days: [0, 2, 4, 6],
|
||||
processing_time: 0.5,
|
||||
updated_at: null
|
||||
}
|
||||
|
||||
Stand.schedule = [];
|
||||
|
||||
// Кількість годин служіння
|
||||
let stand_length = (stand.hour_end - stand.hour_start) / stand.processing_time;
|
||||
|
||||
for (let z = 0; z < stand.week_days.length; z++) {
|
||||
Stand.schedule.push([]);
|
||||
|
||||
let date = new Date();
|
||||
date.setDate(date.getDate() + stand.week_days[z]);
|
||||
let dayName = date.toLocaleDateString('uk-UA', { weekday: 'long' });
|
||||
|
||||
html += `
|
||||
<div class="block-day" id="day-${z}">
|
||||
<h3>${date.toLocaleDateString()} • ${dayName}</h3>
|
||||
`;
|
||||
|
||||
let stand_date = 1 + stand.week_days[z];
|
||||
|
||||
for (let i = 0; i < stand_length; i++) {
|
||||
let time_now = stand.hour_start + (stand.processing_time * i);
|
||||
let timeFormat = (a) => a > 9 ? a : `0${a}`;
|
||||
|
||||
function formatTime(hours) {
|
||||
let h = Math.floor(hours);
|
||||
let m = (hours % 1 === 0.5) ? "30" : "00";
|
||||
let hh = h.toString().padStart(2, "0");
|
||||
return `${hh}:${m}`;
|
||||
}
|
||||
|
||||
html += `
|
||||
<div id="hour-${z}-${i}">
|
||||
<span class="time">${formatTime(time_now)}-${formatTime(time_now + stand.processing_time)}</span>
|
||||
`;
|
||||
|
||||
for (let q = 0; q < stand.quantity_sheep; q++) {
|
||||
html += `
|
||||
<select id="name">
|
||||
<option value=""></option>
|
||||
<option value="Test">Test</option>
|
||||
</select>
|
||||
`;
|
||||
|
||||
Stand.schedule[z].push({
|
||||
id: (i + z) * stand.quantity_sheep + q,
|
||||
hour: stand.hour_start + (stand.processing_time * i),
|
||||
number_sheep: q,
|
||||
date: stand_date,
|
||||
sheep_id: null,
|
||||
stand_id: stand.id,
|
||||
updated_at: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
html += `</div>`; // закриваємо hour
|
||||
}
|
||||
|
||||
html += `</div>`; // закриваємо day
|
||||
}
|
||||
|
||||
document.getElementById('stand-info-title').innerText = stand.title;
|
||||
document.getElementById('stand-info-geo').innerHTML = '';
|
||||
document.getElementById('stand-info-image').setAttribute('src', '');
|
||||
|
||||
block_schedule.innerHTML = html;
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,147 @@
|
||||
width: calc(100% - 40px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
.page-stand select {
|
||||
.page-stand details {
|
||||
border-radius: var(--border-radius);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
margin-bottom: 20px;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
}
|
||||
|
||||
.page-stand summary {
|
||||
width: calc(100% - 40px);
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#stand-info div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
color: var(--ColorThemes3);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#stand-info div span {
|
||||
opacity: 0.8;
|
||||
font-weight: 400;
|
||||
font-size: var(--FontSize2);
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#stand-info div p {
|
||||
font-weight: 300;
|
||||
font-size: var(--FontSize4);
|
||||
}
|
||||
|
||||
#stand-info img {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: calc(100% - 20px);
|
||||
border-radius: calc(var(--border-radius) - 8px);
|
||||
margin: 10px;
|
||||
height: auto;
|
||||
aspect-ratio: 16 / 9;
|
||||
background-color: #f2e5c9;
|
||||
}
|
||||
|
||||
#stand-info img::before {
|
||||
content: "Приклад розташування";
|
||||
display: block;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#stand-schedule {
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 40px - 50px);
|
||||
height: fit-content;
|
||||
margin: 0 10px 15px;
|
||||
border-radius: var(--border-radius);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
transition: all .2sease 0s;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: calc(100% - 20px);
|
||||
margin: 10px;
|
||||
padding: 10px 0;
|
||||
border: 1px solid var(--PrimaryColor);
|
||||
background-color: var(--ColorThemes2);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
min-height: 100px;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day h3 {
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
padding: 10px;
|
||||
text-transform: capitalize;
|
||||
width: calc(100% - 20px);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 5px 0;
|
||||
margin: 0 10px;
|
||||
align-items: center;
|
||||
min-width: calc(100% - 20px);
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day div span {
|
||||
min-width: 85px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day div select {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
margin: 0 5px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes1);
|
||||
background-color: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
margin: 10px 0;
|
||||
box-shadow: var(--shadow-l1);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day div:nth-child(2n) {
|
||||
background: var(--ColorThemes0);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
#stand-schedule>.block-day div:nth-child(2n) select {
|
||||
background-color: var(--ColorThemes2);
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
<div class="page-territory">
|
||||
<div class="buttons-list">
|
||||
<button onclick="Rotation()" id="rotationButton" style="display: none;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M16.5 25.5c-.52.893-1.476 1.5-2.584 1.5-1.657 0-3-1.343-3-3s1.343-3 3-3c1.108 0 2.064.607 2.584 1.5H23v-11C23 8.468 20.533 6 17.5 6h-6C8.467 6 6 8.468 6 11.5v25c0 3.032 2.467 5.5 5.5 5.5h6c3.033 0 5.5-2.468 5.5-5.5v-11H16.5zM36.5 6h-6C27.467 6 25 8.468 25 11.5v11h7.879l-1.439-1.439c-.586-.586-.586-1.535 0-2.121s1.535-.586 2.121 0l4 4c.586.586.586 1.535 0 2.121l-4 4C33.268 29.354 32.884 29.5 32.5 29.5s-.768-.146-1.061-.439c-.586-.586-.586-1.535 0-2.121l1.439-1.439H25v11c0 3.032 2.467 5.5 5.5 5.5h6c3.033 0 5.5-2.468 5.5-5.5v-25C42 8.468 39.533 6 36.5 6z"
|
||||
/>
|
||||
</svg>
|
||||
<span id="rotationButton-title">Провести ротацію</span>
|
||||
</button>
|
||||
|
||||
<a href="/constructor" data-route id="constructorButton" style="display: none;">
|
||||
<div class="buttons-list" id="buttons-list">
|
||||
<a
|
||||
href="/constructor"
|
||||
data-route
|
||||
id="constructorButton"
|
||||
style="display: none"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 4 C 12.015 4 10 6.015 10 8.5 L 10 39.5 C 10 41.985 12.015 44 14.5 44 L 22.042969 44 C 22.079969 43.749 22.138516 43.502672 22.228516 43.263672 L 22.283203 43.285156 C 22.353203 42.961156 23.236422 40.161109 23.982422 37.787109 C 24.272422 36.865109 24.779891 36.029703 25.462891 35.345703 L 33.904297 27 L 27.5 27 C 26.672 27 26 26.328 26 25.5 L 26 16 L 38 16 L 38 23.054688 C 38.72 22.587688 39.4975 22.254422 40.3125 22.107422 C 40.5365 22.067422 40.769 22.062922 41 22.044922 L 41 14.5 C 41 13.672 40.328 13 39.5 13 L 34 13 L 34 8.5 C 34 6.015 31.985 4 29.5 4 L 14.5 4 z M 30.5 18 A 1.50015 1.50015 0 1 0 30.5 21 L 33.5 21 A 1.50015 1.50015 0 1 0 33.5 18 L 30.5 18 z M 41.498047 24 C 41.224047 24.001 40.946969 24.025172 40.667969 24.076172 C 39.783969 24.235172 38.939563 24.696156 38.226562 25.410156 L 26.427734 37.208984 C 26.070734 37.565984 25.807969 38.011141 25.667969 38.494141 L 24.097656 43.974609 C 24.025656 44.164609 23.993 44.365406 24 44.566406 C 24.013 44.929406 24.155594 45.288406 24.433594 45.566406 C 24.710594 45.843406 25.067688 45.986 25.429688 46 C 25.630688 46.007 25.834391 45.975344 26.025391 45.902344 L 31.505859 44.332031 C 31.988859 44.192031 32.431062 43.930266 32.789062 43.572266 L 44.589844 31.773438 C 45.303844 31.060437 45.764828 30.216031 45.923828 29.332031 C 45.973828 29.053031 45.997047 28.775953 45.998047 28.501953 C 46.001047 27.307953 45.540687 26.179312 44.679688 25.320312 C 43.820687 24.460313 42.692047 23.998 41.498047 24 z M 22 35 C 22.828 35 23.5 35.672 23.5 36.5 C 23.5 37.328 22.828 38 22 38 C 21.172 38 20.5 37.328 20.5 36.5 C 20.5 35.672 21.172 35 22 35 z"
|
||||
@@ -19,11 +15,86 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="list-controls"></div>
|
||||
<div class="list-controls">
|
||||
<div id="page-territory-sort">
|
||||
<button id="sort_1" onclick="Territory.sort('2')" data-state="active">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 32.476562 5.9785156 A 1.50015 1.50015 0 0 0 31 7.5 L 31 37.878906 L 26.560547 33.439453 A 1.50015 1.50015 0 1 0 24.439453 35.560547 L 31.439453 42.560547 A 1.50015 1.50015 0 0 0 33.560547 42.560547 L 40.560547 35.560547 A 1.50015 1.50015 0 1 0 38.439453 33.439453 L 34 37.878906 L 34 7.5 A 1.50015 1.50015 0 0 0 32.476562 5.9785156 z M 14.375 8.0058594 C 14.257547 8.01575 14.139641 8.0379219 14.025391 8.0761719 L 11.025391 9.0761719 C 10.239391 9.3381719 9.8141719 10.188609 10.076172 10.974609 C 10.338172 11.760609 11.190609 12.188828 11.974609 11.923828 L 13 11.580078 L 13 20.5 C 13 21.329 13.671 22 14.5 22 C 15.329 22 16 21.329 16 20.5 L 16 9.5 C 16 9.018 15.767953 8.5652031 15.376953 8.2832031 C 15.082953 8.0717031 14.727359 7.9761875 14.375 8.0058594 z M 14 27 C 11.344 27 9.387625 28.682109 9.015625 31.287109 C 8.898625 32.107109 9.4671094 32.867375 10.287109 32.984375 C 11.106109 33.102375 11.867375 32.533891 11.984375 31.712891 C 12.096375 30.931891 12.537 30 14 30 C 15.103 30 16 30.897 16 32 C 16 33.103 15.103 34 14 34 C 11.592 34 9 35.721 9 39.5 C 9 40.329 9.672 41 10.5 41 L 17.5 41 C 18.329 41 19 40.329 19 39.5 C 19 38.671 18.329 38 17.5 38 L 12.308594 38 C 12.781594 37.093 13.664 37 14 37 C 16.757 37 19 34.757 19 32 C 19 29.243 16.757 27 14 27 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_2" onclick="Territory.sort('3')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 31.478516 6 A 1.50015 1.50015 0 0 0 30.439453 6.4394531 L 23.439453 13.439453 A 1.50015 1.50015 0 1 0 25.560547 15.560547 L 30 11.121094 L 30 41.5 A 1.50015 1.50015 0 1 0 33 41.5 L 33 11.121094 L 37.439453 15.560547 A 1.50015 1.50015 0 1 0 39.560547 13.439453 L 32.560547 6.4394531 A 1.50015 1.50015 0 0 0 31.478516 6 z M 13.375 8.0058594 C 13.257547 8.01575 13.139641 8.0379219 13.025391 8.0761719 L 10.025391 9.0761719 C 9.2393906 9.3381719 8.8141719 10.188609 9.0761719 10.974609 C 9.3381719 11.760609 10.190609 12.188828 10.974609 11.923828 L 12 11.580078 L 12 20.5 C 12 21.329 12.671 22 13.5 22 C 14.329 22 15 21.329 15 20.5 L 15 9.5 C 15 9.018 14.767953 8.5652031 14.376953 8.2832031 C 14.082953 8.0717031 13.727359 7.9761875 13.375 8.0058594 z M 13 27 C 10.344 27 8.387625 28.682109 8.015625 31.287109 C 7.898625 32.107109 8.4671094 32.867375 9.2871094 32.984375 C 10.106109 33.102375 10.867375 32.533891 10.984375 31.712891 C 11.096375 30.931891 11.537 30 13 30 C 14.103 30 15 30.897 15 32 C 15 33.103 14.103 34 13 34 C 10.592 34 8 35.721 8 39.5 C 8 40.329 8.672 41 9.5 41 L 16.5 41 C 17.329 41 18 40.329 18 39.5 C 18 38.671 17.329 38 16.5 38 L 11.308594 38 C 11.781594 37.093 12.664 37 13 37 C 15.757 37 18 34.757 18 32 C 18 29.243 15.757 27 13 27 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_3" onclick="Territory.sort('4')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
transform="rotate(180 32.5 24.5106)"
|
||||
id="svg_1"
|
||||
d="m32.47852,6a1.50015,1.50015 0 0 0 -1.03907,0.43945l-7,7a1.50015,1.50015 0 1 0 2.1211,2.1211l4.43945,-4.43946l0,30.37891a1.50015,1.50015 0 1 0 3,0l0,-30.37891l4.43945,4.43946a1.50015,1.50015 0 1 0 2.1211,-2.1211l-7,-7a1.50015,1.50015 0 0 0 -1.08203,-0.43945z"
|
||||
></path>
|
||||
<path
|
||||
d="m16,6c-5.511,0 -10,4.489 -10,10c0,5.511 4.489,10 10,10c5.511,0 10,-4.489 10,-10c0,-5.511 -4.489,-10 -10,-10zm0,2c4.43012,0 8,3.56988 8,8c0,4.43012 -3.56988,8 -8,8c-4.43012,0 -8,-3.56988 -8,-8c0,-4.43012 3.56988,-8 8,-8zm-1,2l0,6.41406l4.29297,4.29297l1.41406,-1.41406l-3.70703,-3.70703l0,-5.58594l-2,0z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_4" onclick="Territory.sort('1')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
id="svg_1"
|
||||
d="m32.47852,6a1.50015,1.50015 0 0 0 -1.03907,0.43945l-7,7a1.50015,1.50015 0 1 0 2.1211,2.1211l4.43945,-4.43946l0,30.37891a1.50015,1.50015 0 1 0 3,0l0,-30.37891l4.43945,4.43946a1.50015,1.50015 0 1 0 2.1211,-2.1211l-7,-7a1.50015,1.50015 0 0 0 -1.08203,-0.43945z"
|
||||
></path>
|
||||
<path
|
||||
d="m16,22.85262c-5.511,0 -10,4.489 -10,10c0,5.511 4.489,10 10,10c5.511,0 10,-4.489 10,-10c0,-5.511 -4.489,-10 -10,-10zm0,2c4.43012,0 8,3.56988 8,8c0,4.43012 -3.56988,8 -8,8c-4.43012,0 -8,-3.56988 -8,-8c0,-4.43012 3.56988,-8 8,-8zm-1,2l0,6.41406l4.29297,4.29297l1.41406,-1.41406l-3.70703,-3.70703l0,-5.58594l-2,0z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<select
|
||||
id="list-controls-filter-status"
|
||||
name="status"
|
||||
onchange="Territory.filter()"
|
||||
>
|
||||
<option value="0" selected>Всі території</option>
|
||||
<option value="1">Зайняті території</option>
|
||||
<option value="2">Вільні території</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<details open>
|
||||
<summary>
|
||||
<span>Багатоквартирні будинки</span>
|
||||
<div>
|
||||
<button
|
||||
id="territory_entrances_true"
|
||||
onclick="Territory.house.territoryType('true')"
|
||||
data-state=""
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 4 C 11.480226 4 9 6.4802259 9 9.5 L 9 41.5 C 9 42.863594 10.136406 44 11.5 44 L 19.5 44 C 20.863594 44 22 42.863594 22 41.5 L 22 37.5 C 22 37.204955 22.204955 37 22.5 37 L 25.5 37 C 25.795045 37 26 37.204955 26 37.5 L 26 41.5 C 26 42.863594 27.136406 44 28.5 44 L 36.5 44 C 37.863594 44 39 42.863594 39 41.5 L 39 9.5 C 39 6.4802259 36.519774 4 33.5 4 L 14.5 4 z M 14.5 7 L 33.5 7 C 34.898226 7 36 8.1017741 36 9.5 L 36 41 L 29 41 L 29 37.5 C 29 35.585045 27.414955 34 25.5 34 L 22.5 34 C 20.585045 34 19 35.585045 19 37.5 L 19 41 L 12 41 L 12 9.5 C 12 8.1017741 13.101774 7 14.5 7 z M 16.5 10 A 1.50015 1.50015 0 1 0 16.5 13 L 17.5 13 A 1.50015 1.50015 0 1 0 17.5 10 L 16.5 10 z M 23.5 10 A 1.50015 1.50015 0 1 0 23.5 13 L 24.5 13 A 1.50015 1.50015 0 1 0 24.5 10 L 23.5 10 z M 30.5 10 A 1.50015 1.50015 0 1 0 30.5 13 L 31.5 13 A 1.50015 1.50015 0 1 0 31.5 10 L 30.5 10 z M 16.5 16 A 1.50015 1.50015 0 1 0 16.5 19 L 17.5 19 A 1.50015 1.50015 0 1 0 17.5 16 L 16.5 16 z M 23.5 16 A 1.50015 1.50015 0 1 0 23.5 19 L 24.5 19 A 1.50015 1.50015 0 1 0 24.5 16 L 23.5 16 z M 30.5 16 A 1.50015 1.50015 0 1 0 30.5 19 L 31.5 19 A 1.50015 1.50015 0 1 0 31.5 16 L 30.5 16 z M 16.5 22 A 1.50015 1.50015 0 1 0 16.5 25 L 17.5 25 A 1.50015 1.50015 0 1 0 17.5 22 L 16.5 22 z M 23.5 22 A 1.50015 1.50015 0 1 0 23.5 25 L 24.5 25 A 1.50015 1.50015 0 1 0 24.5 22 L 23.5 22 z M 30.5 22 A 1.50015 1.50015 0 1 0 30.5 25 L 31.5 25 A 1.50015 1.50015 0 1 0 31.5 22 L 30.5 22 z M 16.5 28 A 1.50015 1.50015 0 1 0 16.5 31 L 17.5 31 A 1.50015 1.50015 0 1 0 17.5 28 L 16.5 28 z M 23.5 28 A 1.50015 1.50015 0 1 0 23.5 31 L 24.5 31 A 1.50015 1.50015 0 1 0 24.5 28 L 23.5 28 z M 30.5 28 A 1.50015 1.50015 0 1 0 30.5 31 L 31.5 31 A 1.50015 1.50015 0 1 0 31.5 28 L 30.5 28 z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
id="territory_entrances_false"
|
||||
onclick="Territory.house.territoryType('false')"
|
||||
data-state=""
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 14.5 6 A 1.50015 1.50015 0 0 0 13 7.5 L 13 25 L 7.5 25 A 1.50015 1.50015 0 0 0 6 26.5 L 6 42.5 A 1.50015 1.50015 0 1 0 9 42.5 L 9 28 L 14.253906 28 A 1.50015 1.50015 0 0 0 14.740234 28 L 19 28 L 19 42.5 A 1.50015 1.50015 0 1 0 22 42.5 L 22 26.746094 A 1.50015 1.50015 0 0 0 22 26.259766 L 22 22 L 33.253906 22 A 1.50015 1.50015 0 0 0 33.740234 22 L 39 22 L 39 42.5 A 1.50015 1.50015 0 1 0 42 42.5 L 42 20.5 A 1.50015 1.50015 0 0 0 40.5 19 L 35 19 L 35 7.5 A 1.50015 1.50015 0 0 0 33.5 6 L 14.5 6 z M 16 9 L 32 9 L 32 19 L 20.5 19 A 1.50015 1.50015 0 0 0 19 20.5 L 19 25 L 16 25 L 16 9 z M 20 12 C 19.448 12 19 12.448 19 13 L 19 15 C 19 15.552 19.448 16 20 16 L 22 16 C 22.552 16 23 15.552 23 15 L 23 13 C 23 12.448 22.552 12 22 12 L 20 12 z M 26 12 C 25.448 12 25 12.448 25 13 L 25 15 C 25 15.552 25.448 16 26 16 L 28 16 C 28.552 16 29 15.552 29 15 L 29 13 C 29 12.448 28.552 12 28 12 L 26 12 z M 26 25 C 25.448 25 25 25.448 25 26 L 25 28 C 25 28.552 25.448 29 26 29 L 28 29 C 28.552 29 29 28.552 29 28 L 29 26 C 29 25.448 28.552 25 28 25 L 26 25 z M 33 25 C 32.448 25 32 25.448 32 26 L 32 28 C 32 28.552 32.448 29 33 29 L 35 29 C 35.552 29 36 28.552 36 28 L 36 26 C 36 25.448 35.552 25 35 25 L 33 25 z M 13 31 C 12.448 31 12 31.448 12 32 L 12 34 C 12 34.552 12.448 35 13 35 L 15 35 C 15.552 35 16 34.552 16 34 L 16 32 C 16 31.448 15.552 31 15 31 L 13 31 z M 26 31 C 25.448 31 25 31.448 25 32 L 25 34 C 25 34.552 25.448 35 26 35 L 28 35 C 28.552 35 29 34.552 29 34 L 29 32 C 29 31.448 28.552 31 28 31 L 26 31 z M 33 31 C 32.448 31 32 31.448 32 32 L 32 34 C 32 34.552 32.448 35 33 35 L 35 35 C 35.552 35 36 34.552 36 34 L 36 32 C 36 31.448 35.552 31 35 31 L 33 31 z M 13 37 C 12.448 37 12 37.448 12 38 L 12 40 C 12 40.552 12.448 41 13 41 L 15 41 C 15.552 41 16 40.552 16 40 L 16 38 C 16 37.448 15.552 37 15 37 L 13 37 z M 26 37 C 25.448 37 25 37.448 25 38 L 25 40 C 25 40.552 25.448 41 26 41 L 28 41 C 28.552 41 29 40.552 29 40 L 29 38 C 29 37.448 28.552 37 28 37 L 26 37 z M 33 37 C 32.448 37 32 37.448 32 38 L 32 40 C 32 40.552 32.448 41 33 41 L 35 41 C 35.552 41 36 40.552 36 40 L 36 38 C 36 37.448 35.552 37 35 37 L 33 37 z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</summary>
|
||||
|
||||
<div id="list-house"></div>
|
||||
|
||||
@@ -3,128 +3,250 @@ const Territory = {
|
||||
let html = await fetch('/lib/pages/territory/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
if (USER.administrator.uuid) document.getElementById('rotationButton').style.display = "";
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_add_territory)) document.getElementById("constructorButton").style.display = "";
|
||||
let selectStatus = document.getElementById('list-controls-filter-status');
|
||||
let filterStatus = localStorage.getItem("filterStatus") ? Number(localStorage.getItem("filterStatus")) : 0;
|
||||
selectStatus.value = filterStatus;
|
||||
|
||||
if (USER.mode == 2) {
|
||||
document.getElementById("buttons-list").style.display = "flex";
|
||||
}
|
||||
if (USER.possibilities.can_add_territory) {
|
||||
document.getElementById("buttons-list").style.display = "flex";
|
||||
document.getElementById("constructorButton").style.display = "";
|
||||
}
|
||||
|
||||
// Застосовуємо режим сортування
|
||||
Territory.sort(localStorage.getItem('territory_sort_mode'));
|
||||
|
||||
|
||||
if (localStorage.getItem('territory_entrances') == 'true') {
|
||||
document.getElementById('territory_entrances_true').setAttribute('data-state', '')
|
||||
document.getElementById('territory_entrances_false').setAttribute('data-state', 'active')
|
||||
} else {
|
||||
document.getElementById('territory_entrances_true').setAttribute('data-state', 'active')
|
||||
document.getElementById('territory_entrances_false').setAttribute('data-state', '')
|
||||
}
|
||||
},
|
||||
|
||||
// Сортування
|
||||
sort(mode) {
|
||||
const idx = Math.max(1, Math.min(4, Number(mode) || 1));
|
||||
['sort_1', 'sort_2', 'sort_3', 'sort_4'].forEach((id, i) => {
|
||||
document.getElementById(id)?.setAttribute('data-state', i + 1 === idx ? 'active' : '');
|
||||
});
|
||||
localStorage.setItem('territory_sort_mode', idx);
|
||||
|
||||
Territory.house.setHTML();
|
||||
Territory.homestead.setHTML();
|
||||
},
|
||||
house: {
|
||||
loadAPI: async function () {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
|
||||
const URL = `${CONFIG.api}houses/list`;
|
||||
return await fetch(URL, {
|
||||
house: {
|
||||
list: [],
|
||||
loadAPI: async function (url) {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
});
|
||||
Territory.house.list = await response.json();
|
||||
return Territory.house.list;
|
||||
},
|
||||
setHTML: async function () {
|
||||
let list = await Territory.house.loadAPI();
|
||||
const block_house = document.getElementById('list-house');
|
||||
const territory_entrances = localStorage.getItem('territory_entrances') === 'true';
|
||||
const sort_mode = localStorage.getItem('territory_sort_mode') ?? "1";
|
||||
const filterStatus = Number(localStorage.getItem("filterStatus") ?? 0);
|
||||
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
const url = `${CONFIG.api}houses/list${territory_entrances ? '/entrances' : ''}`;
|
||||
let list = this.list.length > 0 ? this.list : await this.loadAPI(url);
|
||||
|
||||
console.log(list);
|
||||
let block_house = document.getElementById('list-house')
|
||||
block_house.innerHTML = "";
|
||||
const compare = {
|
||||
"1": (a, b) => this.compareAB(a, b, territory_entrances, 'asc'),
|
||||
"2": (a, b) => this.compareAB(a, b, territory_entrances, 'desc'),
|
||||
"3": (a, b) => a.history?.date?.start - b.history?.date?.start,
|
||||
"4": (a, b) => b.history?.date?.start - a.history?.date?.start,
|
||||
}[sort_mode] ?? ((a, b) => a.id - b.id);
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const element = list[i];
|
||||
list.sort(compare);
|
||||
|
||||
let progress = ((element.entrance.working / element.entrance.quantity) * 100);
|
||||
let html = "";
|
||||
for (const element of list) {
|
||||
const qty = element.entrance?.quantity ?? 0;
|
||||
const work = element.entrance?.working ?? 0;
|
||||
|
||||
let pageURL = () => {
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_manager_territory)) return `/territory/manager/house/${element.id}`;
|
||||
else return `/territory/card/house/${element.id}`
|
||||
const statusMatch =
|
||||
filterStatus === 0 ||
|
||||
(filterStatus === 1 && qty === work && !territory_entrances) ||
|
||||
(filterStatus === 1 && element.working === true) ||
|
||||
(filterStatus === 2 && qty !== work && !territory_entrances) ||
|
||||
(filterStatus === 2 && element.working === false);
|
||||
|
||||
if (statusMatch) {
|
||||
html += this.renderCard({ element, territory_entrances });
|
||||
}
|
||||
}
|
||||
|
||||
block_house.innerHTML += `
|
||||
block_house.innerHTML = html;
|
||||
},
|
||||
compareAB: (a, b, entrances, order = 'asc') => {
|
||||
const dir = order === 'asc' ? 1 : -1;
|
||||
const ah = entrances ? a.house : a;
|
||||
const bh = entrances ? b.house : b;
|
||||
|
||||
const tA = ah.title?.toLowerCase() ?? '';
|
||||
const tB = bh.title?.toLowerCase() ?? '';
|
||||
if (tA < tB) return -1 * dir;
|
||||
if (tA > tB) return 1 * dir;
|
||||
|
||||
const nA = ah.number?.toLowerCase() ?? '';
|
||||
const nB = bh.number?.toLowerCase() ?? '';
|
||||
if (nA < nB) return -1 * dir;
|
||||
if (nA > nB) return 1 * dir;
|
||||
|
||||
return 0;
|
||||
},
|
||||
renderCard: ({ element, territory_entrances }) => {
|
||||
if (territory_entrances) {
|
||||
const working = element.working;
|
||||
const bg = working ? `background: ${colorGroup(element.history.group_id)} color: #fff;` : "";
|
||||
|
||||
const person = working
|
||||
? `<span>Територію опрацьовує:</span> <p>${element.history.name === 'Групова' ? 'Група ' + element.history.group_id : element.history.name}</p>`
|
||||
: `<span>Територія не опрацьовується</span>`;
|
||||
|
||||
return `
|
||||
<div class="card">
|
||||
<i style="background-image: url(https://sheep-service.com/cards/house/T${element.house.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="info">
|
||||
<div>
|
||||
<p>${element.house.title} ${element.house.number} (${element.title})</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sheep" style="${bg}">
|
||||
${person}
|
||||
</div>
|
||||
</div>
|
||||
<a href="/territory/manager/house/${element.house.id}" data-route></a>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
const qty = element.entrance.quantity;
|
||||
const work = element.entrance.working;
|
||||
const progress = ((work / qty) * 100).toFixed(1);
|
||||
return `
|
||||
<div class="card">
|
||||
<i style="background-image: url(https://sheep-service.com/cards/house/T${element.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="group" style="background: ${colorGroup(element.group_id)}">
|
||||
<span>Група №${element.group_id}</span>
|
||||
<div class="info">
|
||||
<div>
|
||||
<p>${element.title} ${element.number}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>
|
||||
<div class="progress" style="width: ${progress}%"></div>
|
||||
<span>Вільні під'їзди:</span>
|
||||
<p>${element.entrance.quantity - element.entrance.working} / ${element.entrance.quantity}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>${element.title} ${element.number}</p>
|
||||
<p>${qty - work} / ${qty}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="${pageURL()}" data-route></a>
|
||||
<a href="/territory/manager/house/${element.id}" data-route></a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
},
|
||||
territoryType: (type) => {
|
||||
localStorage.setItem('territory_entrances', type);
|
||||
document.getElementById('territory_entrances_true').setAttribute('data-state', type === 'false' ? 'active' : '');
|
||||
document.getElementById('territory_entrances_false').setAttribute('data-state', type === 'true' ? 'active' : '');
|
||||
Territory.house.list = [];
|
||||
Territory.house.setHTML();
|
||||
}
|
||||
},
|
||||
homestead: {
|
||||
list: [],
|
||||
loadAPI: async function () {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const URL = `${CONFIG.api}homestead/list`;
|
||||
return await fetch(URL, {
|
||||
|
||||
const response = await fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
});
|
||||
|
||||
this.list = await response.json();
|
||||
return this.list;
|
||||
},
|
||||
setHTML: async function () {
|
||||
let list = await Territory.homestead.loadAPI();
|
||||
const block = document.getElementById('list-homestead');
|
||||
const sortMode = localStorage.getItem('territory_sort_mode') ?? "1";
|
||||
const filterStatus = Number(localStorage.getItem("filterStatus") ?? 0);
|
||||
|
||||
list.sort((a, b) => b.id - a.id);
|
||||
let list = this.list.length > 0 ? this.list : await this.loadAPI();
|
||||
|
||||
console.log(list);
|
||||
let block_homestead = document.getElementById('list-homestead')
|
||||
block_homestead.innerHTML = "";
|
||||
const compare = {
|
||||
"1": (a, b) => a.id - b.id,
|
||||
"2": (a, b) => b.id - a.id,
|
||||
"3": (a, b) => (a.history?.date?.start ?? 0) - (b.history?.date?.start ?? 0),
|
||||
"4": (a, b) => (b.history?.date?.start ?? 0) - (a.history?.date?.start ?? 0),
|
||||
}[sortMode] ?? ((a, b) => a.id - b.id);
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const element = list[i];
|
||||
list.sort(compare);
|
||||
|
||||
let block_history = () => {
|
||||
if (element.working) {
|
||||
return `
|
||||
let html = "";
|
||||
|
||||
for (const element of list) {
|
||||
const statusMatch =
|
||||
filterStatus === 0 ||
|
||||
(filterStatus === 1 && element.working) ||
|
||||
(filterStatus === 2 && !element.working);
|
||||
|
||||
if (statusMatch) {
|
||||
html += this.renderCard(element);
|
||||
}
|
||||
}
|
||||
|
||||
block.innerHTML = html;
|
||||
},
|
||||
renderCard: (element) => {
|
||||
const working = element.working;
|
||||
const bg = working ? `background: ${colorGroup(element.history.group_id)} color: #fff;` : "";
|
||||
const person = working
|
||||
? `<span>Територію опрацьовує:</span> <p>${element.history.name === 'Групова' ? 'Група ' + element.history.group_id : element.history.name}</p>`
|
||||
: `<span>Територія не опрацьовується</span>`;
|
||||
|
||||
return `
|
||||
<div class="card">
|
||||
<i style="background-image: url(https://sheep-service.com/cards/homestead/H${element.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="info">
|
||||
<div>
|
||||
<div class="progress" style="width: 100%"></div>
|
||||
<p>${element.history.name}</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
let pageURL = () => {
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_manager_territory)) return `/territory/manager/homestead/${element.id}`;
|
||||
else return `/territory/card/homestead/${element.id}`
|
||||
}
|
||||
|
||||
block_homestead.innerHTML += `
|
||||
<div class="card">
|
||||
<i style="background-image: url(https://sheep-service.com/cards/homestead/H${element.id}.webp);"></i>
|
||||
<div class="contents">
|
||||
<div class="group" style="background: ${colorGroup(element.group_id)}">
|
||||
<span>Група №${element.group_id}</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
${block_history()}
|
||||
<div>
|
||||
<p>${element.title} ${element.number}</p>
|
||||
</div>
|
||||
<p>${element.title} ${element.number}</p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="${pageURL()}" data-route></a>
|
||||
<div class="sheep" style="${bg}">
|
||||
${person}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
<a href="/territory/manager/homestead/${element.id}" data-route></a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
},
|
||||
filter: () => {
|
||||
let selectStatus = document.getElementById('list-controls-filter-status').value;
|
||||
|
||||
localStorage.setItem("filterStatus", selectStatus);
|
||||
|
||||
|
||||
Territory.house.setHTML();
|
||||
Territory.homestead.setHTML();
|
||||
}
|
||||
}
|
||||
@@ -8,20 +8,20 @@
|
||||
|
||||
.page-territory>.buttons-list {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 40px;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: 15px;
|
||||
border-radius: var(--border-radius);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-territory>.buttons-list>button,
|
||||
.page-territory>.buttons-list>a {
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
padding: 0 10px;
|
||||
margin-right: 20px;
|
||||
min-width: fit-content;
|
||||
@@ -35,7 +35,7 @@
|
||||
.page-territory>.buttons-list>button>span,
|
||||
.page-territory>.buttons-list>a>span {
|
||||
color: var(--PrimaryColorText);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@@ -47,13 +47,87 @@
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.page-territory>.list-controls {
|
||||
padding: 10px;
|
||||
margin: 0px 0 10px 0;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.page-territory>.list-controls select {
|
||||
min-width: 140px;
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes2);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
box-shadow: var(--shadow-l1);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: var(--FontSize1);
|
||||
cursor: pointer;
|
||||
padding: 0 5px;
|
||||
margin-right: 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 2px);
|
||||
}
|
||||
|
||||
|
||||
#page-territory-sort {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-territory-sort button {
|
||||
display: none;
|
||||
font-size: 18px;
|
||||
background: 0;
|
||||
cursor: pointer;
|
||||
min-width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin-right: 10px;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: calc(var(--border-radius) - 5px - 2px);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
}
|
||||
|
||||
#page-territory-sort button[data-state="active"] {
|
||||
background: var(--PrimaryColor);
|
||||
}
|
||||
|
||||
#page-territory-sort button:hover {
|
||||
background: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#page-territory-sort button>svg {
|
||||
width: 22px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#page-territory-sort button:hover svg {
|
||||
fill: var(--ColorThemes1);
|
||||
}
|
||||
|
||||
#page-territory-sort button:hover {
|
||||
display: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#page-territory-sort button[data-state="active"] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.page-territory details {
|
||||
border-radius: 15px;
|
||||
border-radius: var(--border-radius);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 10px;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
@@ -78,16 +152,53 @@
|
||||
cursor: pointer;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 300;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.page-territory summary span {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.page-territory summary>div>button {
|
||||
display: none;
|
||||
font-size: 18px;
|
||||
background: 0;
|
||||
cursor: pointer;
|
||||
min-width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.page-territory summary>div>button[data-state="active"] {
|
||||
background: var(--PrimaryColor);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.page-territory summary>div>button:hover {
|
||||
background: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
.page-territory summary>div>button>svg {
|
||||
width: 22px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
.page-territory summary>div>button:hover svg {
|
||||
fill: var(--ColorThemes1);
|
||||
}
|
||||
|
||||
.page-territory #list-house,
|
||||
.page-territory #list-homestead {
|
||||
width: 100%;
|
||||
@@ -110,7 +221,7 @@
|
||||
margin: 0px 10px 20px 10px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
border-radius: calc(var(--border-radius) - 5px);
|
||||
}
|
||||
|
||||
@media (max-width: 2300px) {
|
||||
@@ -159,7 +270,7 @@
|
||||
/* background-repeat: round; */
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: url(https://tm.rozenrod.com/web/img/bg.webp);
|
||||
background-color: var(--PrimaryColor);
|
||||
}
|
||||
|
||||
.page-territory .card>a {
|
||||
@@ -180,45 +291,25 @@
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.page-territory .group {
|
||||
width: calc(100% - 20px);
|
||||
max-height: 50px;
|
||||
border-radius: 7px;
|
||||
padding: 10px 0;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
background: var(--PrimaryColor);
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.page-territory .group>span {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.page-territory .info {
|
||||
width: calc(100% - 20px);
|
||||
margin-bottom: 10px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.page-territory .info>div {
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
background: var(--ColorThemes0);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: 7px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -233,15 +324,42 @@
|
||||
|
||||
.page-territory .info>div>span {
|
||||
color: var(--ColorThemes3);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 300;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.page-territory .info>div>p {
|
||||
color: var(--ColorThemes3);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
padding: 10px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.page-territory .sheep {
|
||||
margin: 10px;
|
||||
max-height: 50px;
|
||||
border-radius: calc(var(--border-radius) - 5px - 4px);
|
||||
padding: 10px 0;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
background: var(--PrimaryColor);
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.page-territory .sheep>span {
|
||||
color: var(--PrimaryColorText);
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.page-territory .sheep>p {
|
||||
color: var(--PrimaryColorText);
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
margin-top: 5px;
|
||||
}
|
||||
@@ -5,25 +5,53 @@
|
||||
|
||||
<div id="map_territory_manager"></div>
|
||||
|
||||
<div class="menu-picture">
|
||||
<a id="menu-picture-error" title="Зображення не знайдено!">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" style="fill: #c14d4d;">
|
||||
<div class="menu">
|
||||
<a
|
||||
id="menu-picture-error"
|
||||
class="menu-picture-"
|
||||
title="Зображення не знайдено!"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 30 30"
|
||||
style="fill: #c14d4d"
|
||||
>
|
||||
<path
|
||||
d="M 3.7070312 2.2929688 L 2.2929688 3.7070312 L 26.292969 27.707031 L 27.707031 26.292969 L 26.375 24.960938 C 27.299776 24.784872 28 23.976233 28 23 L 28 7 C 28 5.895 27.105 5 26 5 L 6.4140625 5 L 3.7070312 2.2929688 z M 2.1367188 6.2851562 C 2.0517188 6.5071563 2 6.747 2 7 L 2 23 C 2 24.105 2.895 25 4 25 L 20.851562 25 L 17.851562 22 L 5 22 L 5 15 L 7.2890625 12.710938 C 7.5140625 12.485938 7.7747812 12.317219 8.0507812 12.199219 L 2.1367188 6.2851562 z M 23 8 C 24.105 8 25 8.895 25 10 C 25 11.105 24.105 12 23 12 C 21.895 12 21 11.105 21 10 C 21 8.895 21.895 8 23 8 z M 19 14.001953 C 19.61925 14.001953 20.238437 14.238437 20.710938 14.710938 L 25 19 L 25 22 L 23.414062 22 L 16.707031 15.292969 L 17.289062 14.710938 C 17.761563 14.238437 18.38075 14.001953 19 14.001953 z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a id="menu-picture-ok" style="display: none;" title="Зображення знайдено" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" style="fill: #8BC34A;">
|
||||
<a
|
||||
id="menu-picture-ok"
|
||||
class="menu-picture"
|
||||
style="display: none"
|
||||
title="Зображення знайдено"
|
||||
target="_blank"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 30 30"
|
||||
style="fill: #8bc34a"
|
||||
>
|
||||
<path
|
||||
d="M 4 5 C 2.895 5 2 5.895 2 7 L 2 23 C 2 24.105 2.895 25 4 25 L 26 25 C 27.105 25 28 24.105 28 23 L 28 7 C 28 5.895 27.105 5 26 5 L 4 5 z M 23 8 C 24.105 8 25 8.895 25 10 C 25 11.105 24.105 12 23 12 C 21.895 12 21 11.105 21 10 C 21 8.895 21.895 8 23 8 z M 9 13.001953 C 9.61925 13.001953 10.238437 13.238437 10.710938 13.710938 L 13.972656 16.972656 L 15 18 L 16.15625 19.15625 C 16.57825 19.57825 17.259641 19.574344 17.681641 19.152344 C 18.104641 18.730344 18.104641 18.044094 17.681641 17.621094 L 16.529297 16.470703 L 17.289062 15.710938 C 18.234063 14.765937 19.765937 14.765937 20.710938 15.710938 L 25 20 L 25 22 L 5 22 L 5 16 L 7.2890625 13.710938 C 7.7615625 13.238437 8.38075 13.001953 9 13.001953 z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<button title="Створити нове зображення" onclick="Territory_Manager.getScreen()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"> <path d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"/></svg>
|
||||
</button>
|
||||
<a
|
||||
id="editor_button"
|
||||
class="menu-edit"
|
||||
style="display: none"
|
||||
data-route
|
||||
title="Змінити територію"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">
|
||||
<path
|
||||
d="M 22.828125 3 C 22.316375 3 21.804562 3.1954375 21.414062 3.5859375 L 19 6 L 24 11 L 26.414062 8.5859375 C 27.195062 7.8049375 27.195062 6.5388125 26.414062 5.7578125 L 24.242188 3.5859375 C 23.851688 3.1954375 23.339875 3 22.828125 3 z M 17 8 L 5.2597656 19.740234 C 5.2597656 19.740234 6.1775313 19.658 6.5195312 20 C 6.8615312 20.342 6.58 22.58 7 23 C 7.42 23.42 9.6438906 23.124359 9.9628906 23.443359 C 10.281891 23.762359 10.259766 24.740234 10.259766 24.740234 L 22 13 L 17 8 z M 4 23 L 3.0566406 25.671875 A 1 1 0 0 0 3 26 A 1 1 0 0 0 4 27 A 1 1 0 0 0 4.328125 26.943359 A 1 1 0 0 0 4.3378906 26.939453 L 4.3632812 26.931641 A 1 1 0 0 0 4.3691406 26.927734 L 7 26 L 5.5 24.5 L 4 23 z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,9 +75,9 @@
|
||||
name="info-description"
|
||||
id="info-description"
|
||||
placeholder="Примітка"
|
||||
onchange="Territory_Manager.info.update()"
|
||||
></textarea>
|
||||
</div>
|
||||
<a id="editor_button" style="display: none" data-route>Змінити територію</a>
|
||||
</div>
|
||||
|
||||
<div id="territory-entrance"></div>
|
||||
@@ -57,10 +85,22 @@
|
||||
|
||||
<div id="territory-new" style="display: none; opacity: 0">
|
||||
<div class="mess">
|
||||
<span>Налаштування</span>
|
||||
<select id="new-worker-name" name="new-worker-name" required="">
|
||||
<select id="new-worker-group" name="new-worker-name">
|
||||
<option value="" selected="" disabled="">Оберіть...</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
<option value="6">6</option>
|
||||
<option value="7">7</option>
|
||||
</select>
|
||||
<input
|
||||
id="new-worker-name"
|
||||
type="text"
|
||||
name="new-worker-name"
|
||||
list="list_sheeps"
|
||||
/>
|
||||
<div>
|
||||
<button onclick="Territory_Manager.mess.close()">Закрити</button>
|
||||
<button
|
||||
@@ -73,3 +113,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<datalist id="list_sheeps"></datalist>
|
||||
|
||||
@@ -15,7 +15,7 @@ const Territory_Manager = {
|
||||
}
|
||||
|
||||
let editor_button = document.getElementById('editor_button');
|
||||
if (USER.administrator.uuid || (USER.moderator.uuid && USER.moderator.can_add_territory)){
|
||||
if (USER.possibilities.can_add_territory) {
|
||||
editor_button.style.display = "";
|
||||
editor_button.setAttribute("href", `/territory/editor/${type}/${id}`)
|
||||
}
|
||||
@@ -26,481 +26,464 @@ const Territory_Manager = {
|
||||
for (let i = 0; i < sheeps_list.length; i++) {
|
||||
const element = sheeps_list[i];
|
||||
|
||||
if (Territory_Manager.info.list.group_id == element.group_id) {
|
||||
document.getElementById('new-worker-name').innerHTML += `
|
||||
<option value="${element.name}">${element.name}</option>
|
||||
`;
|
||||
}
|
||||
document.getElementById('list_sheeps').innerHTML += `
|
||||
<option value="${element.name}">${element.name}</option>
|
||||
`;
|
||||
}
|
||||
|
||||
const card = document.getElementById('territory-new');
|
||||
const mess = card.querySelector('.mess');
|
||||
|
||||
if (!card.dataset.listenerAdded) {
|
||||
card.addEventListener('click', function (event) {
|
||||
if (!mess.contains(event.target)) {
|
||||
Territory_Manager.mess.close();
|
||||
}
|
||||
});
|
||||
card.dataset.listenerAdded = 'true';
|
||||
}
|
||||
},
|
||||
info: {
|
||||
list: {},
|
||||
loadAPI: async (url) => {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
Territory_Manager.info.list = await fetch(url, {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
});
|
||||
|
||||
Territory_Manager.info.list = await response.json();
|
||||
return Territory_Manager.info.list;
|
||||
},
|
||||
|
||||
setHTML: async (type, id) => {
|
||||
if (type == "house") {
|
||||
let url = `${CONFIG.api}house/${id}`;
|
||||
let data = await Territory_Manager.info.loadAPI(url);
|
||||
const url = `${CONFIG.api}${type}/${id}`;
|
||||
const data = await Territory_Manager.info.loadAPI(url);
|
||||
Territory_Manager.map(type, data);
|
||||
|
||||
Territory_Manager.map(type, data);
|
||||
const info_picture = document.getElementById('info-picture');
|
||||
const info_title = document.getElementById('info-title');
|
||||
const info_number = document.getElementById('info-number');
|
||||
const info_settlement = document.getElementById('info-settlement');
|
||||
const info_description = document.getElementById('info-description');
|
||||
|
||||
let info_picture = document.getElementById('info-picture');
|
||||
let info_title = document.getElementById('info-title');
|
||||
let info_number = document.getElementById('info-number');
|
||||
let info_settlement = document.getElementById('info-settlement');
|
||||
let info_description = document.getElementById('info-description');
|
||||
|
||||
info_picture.addEventListener("click", (event) => {
|
||||
let state = info_picture.getAttribute('data-state')
|
||||
if (state == 'active') info_picture.setAttribute('data-state', '')
|
||||
else info_picture.setAttribute('data-state', 'active')
|
||||
if (!info_picture.dataset.listener) {
|
||||
info_picture.addEventListener("click", () => {
|
||||
const state = info_picture.getAttribute('data-state');
|
||||
info_picture.setAttribute('data-state', state === 'active' ? '' : 'active');
|
||||
});
|
||||
|
||||
info_picture.setAttribute("src", ``);
|
||||
info_title.innerText = data.title;
|
||||
info_number.innerText = data.number;
|
||||
info_settlement.innerText = data.settlement;
|
||||
info_description.value = data.description;
|
||||
} else if (type == "homestead") {
|
||||
let url = `${CONFIG.api}homestead/${id}`;
|
||||
let data = await Territory_Manager.info.loadAPI(url);
|
||||
|
||||
Territory_Manager.map(type, data);
|
||||
|
||||
let info_picture = document.getElementById('info-picture');
|
||||
let info_title = document.getElementById('info-title');
|
||||
let info_number = document.getElementById('info-number');
|
||||
let info_settlement = document.getElementById('info-settlement');
|
||||
let info_description = document.getElementById('info-description');
|
||||
|
||||
info_picture.addEventListener("click", (event) => {
|
||||
let state = info_picture.getAttribute('data-state')
|
||||
if (state == 'active') info_picture.setAttribute('data-state', '')
|
||||
else info_picture.setAttribute('data-state', 'active')
|
||||
});
|
||||
|
||||
info_picture.setAttribute("src", ``);
|
||||
info_title.innerText = data.title;
|
||||
info_number.innerText = data.number;
|
||||
info_settlement.innerText = data.settlement;
|
||||
info_description.value = data.description;
|
||||
info_picture.dataset.listener = "true";
|
||||
}
|
||||
|
||||
urlImage = `https://sheep-service.com/cards/${type}/${type == "house" ? "T" : "H"}${id}.webp`;
|
||||
const checkImage = await fetch(urlImage);
|
||||
|
||||
if(checkImage.ok) {
|
||||
document.getElementById('menu-picture-error').style.display = 'none';
|
||||
document.getElementById('menu-picture-ok').style.display = '';
|
||||
document.getElementById('menu-picture-ok').setAttribute("href", urlImage);
|
||||
} else {
|
||||
info_picture.setAttribute("src", "");
|
||||
info_title.textContent = data.title;
|
||||
info_number.textContent = data.number;
|
||||
info_settlement.textContent = data.settlement;
|
||||
info_description.value = data.description;
|
||||
|
||||
const urlImage = `https://sheep-service.com/cards/${type}/${type === "house" ? "T" : "H"}${id}.webp`;
|
||||
try {
|
||||
const checkImage = await fetch(urlImage, { method: 'GET' });
|
||||
const showOk = checkImage.ok;
|
||||
|
||||
document.getElementById('menu-picture-ok').style.display = showOk ? '' : 'none';
|
||||
document.getElementById('menu-picture-error').style.display = showOk ? 'none' : '';
|
||||
if (showOk) {
|
||||
document.getElementById('menu-picture-ok').setAttribute("href", urlImage);
|
||||
}
|
||||
} catch (err) {
|
||||
document.getElementById('menu-picture-error').style.display = '';
|
||||
document.getElementById('menu-picture-ok').style.display = 'none';
|
||||
}
|
||||
},
|
||||
|
||||
update: async () => {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const data = Territory_Manager.info.list;
|
||||
|
||||
data.description = document.getElementById('info-description').value;
|
||||
|
||||
const url = `${CONFIG.api}${type_territory}/${data.id}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
console.log('ok');
|
||||
await response.json();
|
||||
} else {
|
||||
console.log('err');
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('update error', e);
|
||||
}
|
||||
}
|
||||
},
|
||||
entrances: {
|
||||
list: [],
|
||||
loadAPI: async (url) => {
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
Territory_Manager.entrances.list = await fetch(url, {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
});
|
||||
|
||||
Territory_Manager.entrances.list = await response.json();
|
||||
return Territory_Manager.entrances.list;
|
||||
},
|
||||
|
||||
setHTML: async (type, id) => {
|
||||
if (type == "house") {
|
||||
let url = `${CONFIG.api}house/${id}/entrances`;
|
||||
let listEntrances = await Territory_Manager.entrances.loadAPI(url);
|
||||
const container = document.getElementById('territory-entrance');
|
||||
container.innerHTML = "";
|
||||
const sheeps_list = Sheeps.sheeps_list.list;
|
||||
|
||||
document.getElementById('territory-entrance').innerHTML = "";
|
||||
const renderName = (history) => {
|
||||
if (history.name === "Групова") return `<p>${history.name} ${history.group_id}</p>`;
|
||||
const sheep = sheeps_list.find(item => item.name === history.name);
|
||||
return sheep ? `<a href="/sheeps/${sheep.id}" data-route>${history.name}</a>` : `<a>${history.name}</a>`;
|
||||
};
|
||||
|
||||
for (let i = 0; i < listEntrances.length; i++) {
|
||||
const element = listEntrances[i];
|
||||
const renderWorking = (element, i = 0) => `
|
||||
<div class="entrance" data-state="working">
|
||||
<div id="title">
|
||||
<h1>${element.title ?? ''}</h1>
|
||||
<a href="/territory/card/${type}/${id}" title="Редактор квартир" data-route>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="M 12.5 6 C 8.9280619 6 6 8.9280619 6 12.5 L 6 35.5 C 6 39.071938 8.9280619 42 12.5 42 L 35.5 42 C 39.071938 42 42 39.071938 42 35.5 L 42 12.5 C 42 8.9280619 39.071938 6 35.5 6 L 12.5 6 z M 12.5 9 L 14 9 L 14 15 L 9 15 L 9 12.5 C 9 10.549938 10.549938 9 12.5 9 z M 17 9 L 35.5 9 C 37.450062 9 39 10.549938 39 12.5 L 39 15 L 17 15 L 17 9 z M 9 18 L 14 18 L 14 23 L 9 23 L 9 18 z M 17 18 L 39 18 L 39 23 L 17 23 L 17 18 z M 9 26 L 14 26 L 14 31 L 9 31 L 9 26 z M 17 26 L 39 26 L 39 31 L 17 31 L 17 26 z M 9 34 L 14 34 L 14 39 L 12.5 39 C 10.549938 39 9 37.450062 9 35.5 L 9 34 z M 17 34 L 39 34 L 39 35.5 C 39 37.450062 37.450062 39 35.5 39 L 17 39 L 17 34 z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div><h1>Територію опрацьовує:</h1>${renderName(element.history)}</div>
|
||||
<div><h1>Територія видана:</h1><h2>${formattedDate(element.history.date.start)}</h2></div>
|
||||
<div><h1>Варто забрати:</h1><h2>${formattedDate(element.history.date.end) ?? formattedDate(element.history.date.start + (1000 * 2629743 * 4))}</h2></div>
|
||||
<div class="edit_working">
|
||||
<button onclick="Territory_Manager.endWorker('${type}', ${id}, ${element.history.id})" style="color: #121214;background: #c14d4d;">Забрати</button>
|
||||
<button onclick="Territory_Manager.share('${type}'${type === "house" ? `, ${i}` : ""})">Відправити посилання</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
let name = () => {
|
||||
if (element.history.name == "Групова")
|
||||
return `<p>${element.history.name + " " + element.history.group_id}</p>`;
|
||||
else {
|
||||
let sheeps_list = Sheeps.sheeps_list.list;
|
||||
let filtered = sheeps_list.filter(item => item.group_id === Territory_Manager.info.list.group_id);
|
||||
let sheep = filtered.find(item => item.name === element.history.name);
|
||||
const renderFree = (element, i = 0) => `
|
||||
<div class="entrance">
|
||||
<div id="title">
|
||||
<h1>${element.title ?? ''}</h1>
|
||||
<a href="/territory/card/${type}/${id}" title="Редактор квартир" data-route>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="M 12.5 6 C 8.9280619 6 6 8.9280619 6 12.5 L 6 35.5 C 6 39.071938 8.9280619 42 12.5 42 L 35.5 42 C 39.071938 42 42 39.071938 42 35.5 L 42 12.5 C 42 8.9280619 39.071938 6 35.5 6 L 12.5 6 z M 12.5 9 L 14 9 L 14 15 L 9 15 L 9 12.5 C 9 10.549938 10.549938 9 12.5 9 z M 17 9 L 35.5 9 C 37.450062 9 39 10.549938 39 12.5 L 39 15 L 17 15 L 17 9 z M 9 18 L 14 18 L 14 23 L 9 23 L 9 18 z M 17 18 L 39 18 L 39 23 L 17 23 L 17 18 z M 9 26 L 14 26 L 14 31 L 9 31 L 9 26 z M 17 26 L 39 26 L 39 31 L 17 31 L 17 26 z M 9 34 L 14 34 L 14 39 L 12.5 39 C 10.549938 39 9 37.450062 9 35.5 L 9 34 z M 17 34 L 39 34 L 39 35.5 C 39 37.450062 37.450062 39 35.5 39 L 17 39 L 17 34 z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div><h1>Територія не опрацьовується</h1></div>
|
||||
<div><h1>Останнє опрацювання:</h1><h2>${formattedDate(element.history.date.end) ?? "..."}</h2></div>
|
||||
<div class="edit">
|
||||
<button onclick="Territory_Manager.mess.open({type: '${type}', id: ${id}, number: ${i}, mode: false})" style="color: var(--ColorThemes0);background: var(--ColorThemes3);">Призначити груповою</button>
|
||||
<button onclick="Territory_Manager.mess.open({type: '${type}', id: ${id}, number: ${i}, mode: true})">Призначити вісника</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return `<a href="/sheeps/${sheep.uuid}" data-route="">${element.history.name}</a>`;
|
||||
}
|
||||
}
|
||||
let html = "";
|
||||
|
||||
if (element.working) {
|
||||
document.getElementById('territory-entrance').innerHTML += `
|
||||
<div class="entrance" data-state="working">
|
||||
<div id="title">
|
||||
<h1>${element.title}</h1>
|
||||
<a href="/territory/card/${type}/${id}" title="Редактор квартир" data-route>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="M 12.5 6 C 8.9280619 6 6 8.9280619 6 12.5 L 6 35.5 C 6 39.071938 8.9280619 42 12.5 42 L 35.5 42 C 39.071938 42 42 39.071938 42 35.5 L 42 12.5 C 42 8.9280619 39.071938 6 35.5 6 L 12.5 6 z M 12.5 9 L 14 9 L 14 15 L 9 15 L 9 12.5 C 9 10.549938 10.549938 9 12.5 9 z M 17 9 L 35.5 9 C 37.450062 9 39 10.549938 39 12.5 L 39 15 L 17 15 L 17 9 z M 9 18 L 14 18 L 14 23 L 9 23 L 9 18 z M 17 18 L 39 18 L 39 23 L 17 23 L 17 18 z M 9 26 L 14 26 L 14 31 L 9 31 L 9 26 z M 17 26 L 39 26 L 39 31 L 17 31 L 17 26 z M 9 34 L 14 34 L 14 39 L 12.5 39 C 10.549938 39 9 37.450062 9 35.5 L 9 34 z M 17 34 L 39 34 L 39 35.5 C 39 37.450062 37.450062 39 35.5 39 L 17 39 L 17 34 z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територію опрацьовує: </h1>
|
||||
${name()}
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територія видана: </h1>
|
||||
<h2>${formattedDate(element.history.date.start)}</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Варто забрати: </h1>
|
||||
<h2>${formattedDate(element.history.date.end) ?? formattedDate(element.history.date.start + (1000 * 2629743 * 4))}</h2>
|
||||
</div>
|
||||
<div class="edit_working">
|
||||
<button onclick="Territory_Manager.endWorker('${type}', ${id}, ${element.history.id})" id="end-working-button" style="color: #121214;background: #c14d4d;">Забрати</button>
|
||||
<button onclick="Territory_Manager.share('${type}', ${i})">Відправити посилання</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
document.getElementById('territory-entrance').innerHTML += `
|
||||
<div class="entrance">
|
||||
<div id="title">
|
||||
<h1>${element.title}</h1>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територія не опрацьовується</h1>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1>Останнє опрацювання: </h1>
|
||||
<h2>${formattedDate(element.history.date.end) ?? "..."}</h2>
|
||||
</div>
|
||||
|
||||
<div class="edit">
|
||||
<button onclick="Territory_Manager.newWorker('${type}',${id}, ${i}, 'Групова')" id="group-working-button" style="color: var(--ColorThemes0);background: var(--ColorThemes3);">Призначити груповою</button>
|
||||
<button onclick="Territory_Manager.mess.open('${type}', ${id}, ${i})">Призначити вісника</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
console.log(element);
|
||||
if (type === "house") {
|
||||
const url = `${CONFIG.api}house/${id}/entrances`;
|
||||
const list = await Territory_Manager.entrances.loadAPI(url);
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const el = list[i];
|
||||
html += el.working ? renderWorking(el, i) : renderFree(el, i);
|
||||
}
|
||||
} else if (type == "homestead") {
|
||||
let url = `${CONFIG.api}homestead/${id}`;
|
||||
let element = await Territory_Manager.entrances.loadAPI(url);
|
||||
|
||||
document.getElementById('territory-entrance').innerHTML = "";
|
||||
|
||||
let name = () => {
|
||||
if (element.history.name == "Групова")
|
||||
return `<p>${element.history.name + " " + element.history.group_id}</p>`;
|
||||
else
|
||||
return `<a href="/sheeps/${element.history.name}" data-route="">${element.history.name}</a>`;
|
||||
}
|
||||
|
||||
if (element.working) {
|
||||
document.getElementById('territory-entrance').innerHTML += `
|
||||
<div class="entrance" data-state="working">
|
||||
<div>
|
||||
<h1>Територію опрацьовує: </h1>
|
||||
${name()}
|
||||
</div>
|
||||
<div>
|
||||
<h1>Територія видана: </h1>
|
||||
<h2>${formattedDate(element.history.date.start)}</h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Варто забрати: </h1>
|
||||
<h2>${formattedDate(element.history.date.end) ?? formattedDate(element.history.date.start + (1000 * 2629743 * 4))}</h2>
|
||||
</div>
|
||||
<div class="edit_working">
|
||||
<button onclick="Territory_Manager.endWorker('${type}', ${id}, ${element.history.id})" id="end-working-button" style="color: #121214;background: #c14d4d;">Забрати</button>
|
||||
<button onclick="Territory_Manager.share('${type}', ${i})">Відправити посилання</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
document.getElementById('territory-entrance').innerHTML += `
|
||||
<div class="entrance">
|
||||
<div>
|
||||
<h1>Територія не опрацьовується</h1>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1>Останнє опрацювання: </h1>
|
||||
<h2>${formattedDate(element.history.date.end) ?? "..."}</h2>
|
||||
</div>
|
||||
|
||||
<div class="edit">
|
||||
<button onclick="Territory_Manager.newWorker('${type}',${id}, ${i}, 'Групова')" id="group-working-button" style="color: var(--ColorThemes0);background: var(--ColorThemes3);">Призначити груповою</button>
|
||||
<button onclick="Territory_Manager.mess.open('${type}',${id}, ${i})">Призначити вісника</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
console.log(element);
|
||||
} else if (type === "homestead") {
|
||||
const url = `${CONFIG.api}homestead/${id}`;
|
||||
const el = await Territory_Manager.entrances.loadAPI(url);
|
||||
html += el.working ? renderWorking(el) : renderFree(el);
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
}
|
||||
},
|
||||
map: (type, data) => {
|
||||
map_territory = {};
|
||||
let center = { lat: 49.5629016, lng: 25.6145625 };
|
||||
let zoom = 19;
|
||||
let lat = data.geo?.lat ?? data.points?.[0]?.[0]?.[0]?.lat ?? 49.5629016;
|
||||
let lng = data.geo?.lng ?? data.points?.[0]?.[0]?.[0]?.lng ?? 25.6145625;
|
||||
|
||||
let mytile = L.tileLayer('https://tm.rozenrod.com/webp/{z}/{x}/{y}.webp', {
|
||||
if (map_territory && map_territory.remove) map_territory.remove();
|
||||
|
||||
const mapElement = document.getElementById('map_territory_manager');
|
||||
if (!mapElement) return;
|
||||
|
||||
let googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
|
||||
});
|
||||
|
||||
let osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
});
|
||||
|
||||
let mytile = L.tileLayer('https://sheep-service.com/map/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
tms: true
|
||||
});
|
||||
|
||||
map_territory = L.map('map_territory_manager', {
|
||||
map_territory = L.map(mapElement, {
|
||||
renderer: L.canvas(),
|
||||
center,
|
||||
zoom,
|
||||
center: [lat, lng],
|
||||
zoom: 0,
|
||||
zoomControl: false,
|
||||
layers: [
|
||||
googleHybrid,
|
||||
osm,
|
||||
mytile
|
||||
],
|
||||
]
|
||||
});
|
||||
|
||||
map_territory.setZoom((data.zoom - 1));
|
||||
|
||||
let baseMaps = {
|
||||
"Google Hybrid": googleHybrid,
|
||||
"OpenStreetMap": osm,
|
||||
"Sheep Service Map": mytile,
|
||||
};
|
||||
|
||||
let layerControl = L.control.layers(baseMaps, [], { position: 'bottomright' }).addTo(map_territory);
|
||||
|
||||
map_territory.pm.setLang("ua");
|
||||
|
||||
if (type == "homestead") {
|
||||
if (data.geo.lat) map_territory.setView([data.geo.lat, data.geo.lng], 15);
|
||||
else map_territory.setView([data.points[0][0][0].lat, data.points[0][0][0].lng], 15);
|
||||
const polygonOptions = type === "homestead" ? {
|
||||
color: "#f2bd53",
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '20,15',
|
||||
dashOffset: '20',
|
||||
} : {
|
||||
color: "#585858",
|
||||
fillColor: "#f2bd53",
|
||||
fillOpacity: 0.8
|
||||
};
|
||||
|
||||
L.polygon(data.points, {
|
||||
color: colorGroup(data.group_id),
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '20, 15',
|
||||
dashOffset: '20',
|
||||
}).on('click', function (e) {
|
||||
L.polygon(data.points, polygonOptions).addTo(map_territory);
|
||||
|
||||
}).addTo(map_territory);
|
||||
} else if (type == "house") {
|
||||
map_territory.setView([data.geo.lat, data.geo.lng], 17);
|
||||
console.log(data.zoom);
|
||||
|
||||
L.polygon(data.points, {
|
||||
color: "#585858",
|
||||
fillColor: colorGroup(data.group_id),
|
||||
fillOpacity: 0.8,
|
||||
tm_id: `house_${i}`
|
||||
}).on('click', function (e) {
|
||||
|
||||
}).addTo(map_territory);
|
||||
}
|
||||
// setTimeout(() => {
|
||||
// map_territory.setZoom(data.zoom);
|
||||
// }, 200)
|
||||
},
|
||||
mess: {
|
||||
open: (type, id, number) => {
|
||||
open: ({ type, id, number, mode }) => {
|
||||
const block = document.getElementById('territory-new');
|
||||
const new_worker_button = document.getElementById('new-worker-button');
|
||||
const groupInput = document.getElementById('new-worker-group');
|
||||
const nameInput = document.getElementById('new-worker-name');
|
||||
const button = document.getElementById('new-worker-button');
|
||||
|
||||
// Показуємо блок
|
||||
block.style.display = "";
|
||||
setTimeout(() => {
|
||||
block.style.opacity = "1";
|
||||
}, 100)
|
||||
requestAnimationFrame(() => block.style.opacity = "1");
|
||||
|
||||
new_worker_button.setAttribute("onclick", `Territory_Manager.newWorker('${type}', ${id}, ${number})`);
|
||||
groupInput.style.display = mode ? 'none' : 'flex';
|
||||
nameInput.style.display = mode ? 'flex' : 'none';
|
||||
|
||||
button.onclick = () => Territory_Manager.newWorker({ type, id, number, mode });
|
||||
},
|
||||
close: () => {
|
||||
const block = document.getElementById('territory-new');
|
||||
|
||||
close: () => {
|
||||
// Робимо плавне зникнення
|
||||
const block = document.getElementById('territory-new');
|
||||
block.style.opacity = "0";
|
||||
setTimeout(() => {
|
||||
|
||||
const onTransitionEnd = () => {
|
||||
block.style.display = "none";
|
||||
}, 200)
|
||||
block.removeEventListener("transitionend", onTransitionEnd);
|
||||
};
|
||||
block.addEventListener("transitionend", onTransitionEnd);
|
||||
}
|
||||
},
|
||||
newWorker: async (type, id, number, name) => {
|
||||
newWorker: async ({ type, id, number, mode }) => {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const sheepName = document.getElementById('new-worker-name').value;
|
||||
const groupId = Number(document.getElementById('new-worker-group').value);
|
||||
|
||||
const new_worker_button = document.getElementById('new-worker-button');
|
||||
const group_worker_button = document.getElementById('group-working-button');
|
||||
const newButton = document.getElementById('new-worker-button');
|
||||
const groupButton = document.getElementById('group-working-button');
|
||||
|
||||
let URL, territory_id, data;
|
||||
let territory_id;
|
||||
let URL;
|
||||
|
||||
const sheep = Sheeps.sheeps_list.list.find(e => e.name === sheepName);
|
||||
|
||||
const pos = Sheeps.sheeps_list.list.map(e => e.name).indexOf(name ?? document.getElementById("new-worker-name").value);
|
||||
let sheep = Sheeps.sheeps_list.list[pos];
|
||||
|
||||
if (type == "house") {
|
||||
territory_id = Territory_Manager.entrances.list[number].id;
|
||||
data = {
|
||||
name: name ?? document.getElementById("new-worker-name").value,
|
||||
group_id: Territory_Manager.info.list.group_id,
|
||||
sheep_id: sheep ? sheep.id : null
|
||||
}
|
||||
if (type === "house") {
|
||||
territory_id = Territory_Manager.entrances.list[number]?.id;
|
||||
URL = `${CONFIG.api}history/entrance/${territory_id}`;
|
||||
}
|
||||
else if (type == "homestead") {
|
||||
} else if (type === "homestead") {
|
||||
territory_id = Territory_Manager.info.list.id;
|
||||
data = {
|
||||
name: name ?? document.getElementById("new-worker-name").value,
|
||||
group_id: Territory_Manager.info.list.group_id,
|
||||
sheep_id: sheep ? sheep.id : null
|
||||
}
|
||||
URL = `${CONFIG.api}history/homestead/${territory_id}`;
|
||||
}
|
||||
|
||||
console.log(territory_id, data);
|
||||
if (!territory_id || !URL) {
|
||||
console.warn("Невірні дані для призначення.");
|
||||
return;
|
||||
}
|
||||
|
||||
await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => {
|
||||
if (response.status == 200) {
|
||||
Territory_Manager.mess.close();
|
||||
Territory_Manager.entrances.list = [];
|
||||
Territory_Manager.entrances.setHTML(type, id);
|
||||
const data = {
|
||||
name: mode ? sheepName : "Групова",
|
||||
group_id: mode ? sheep?.group_id : groupId,
|
||||
sheep_id: mode ? sheep?.id : null
|
||||
};
|
||||
|
||||
return response.json()
|
||||
} else {
|
||||
console.log('err');
|
||||
new_worker_button.innerText = "Помилка";
|
||||
group_worker_button.innerText = "Помилка";
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
if (!response.ok) throw new Error("Failed to assign");
|
||||
|
||||
Territory_Manager.mess.close();
|
||||
Territory_Manager.entrances.list = [];
|
||||
await Territory_Manager.entrances.setHTML(type, id);
|
||||
} catch (err) {
|
||||
console.error('❌ Error:', err);
|
||||
const errorText = "Помилка";
|
||||
if (newButton) newButton.innerText = errorText;
|
||||
if (groupButton) groupButton.innerText = errorText;
|
||||
}
|
||||
},
|
||||
endWorker: async (type, id, territory_id) => {
|
||||
const end_working_button = document.getElementById('end-working-button');
|
||||
let uuid = localStorage.getItem('uuid');
|
||||
let URL = "";
|
||||
const button = document.getElementById('end-working-button');
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
|
||||
if (type == "house") {
|
||||
URL = `${CONFIG.api}history/entrance/${territory_id}`;
|
||||
const URL = type === "house"
|
||||
? `${CONFIG.api}history/entrance/${territory_id}`
|
||||
: `${CONFIG.api}history/homestead/${territory_id}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(URL, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error("Запит не успішний");
|
||||
|
||||
Territory_Manager.entrances.list = [];
|
||||
await Territory_Manager.entrances.setHTML(type, id);
|
||||
} catch (error) {
|
||||
console.error("❌ Помилка зняття призначення:", error);
|
||||
if (button) button.innerText = "Помилка";
|
||||
}
|
||||
else if (type == "homestead") {
|
||||
URL = `${CONFIG.api}history/homestead/${territory_id}`;
|
||||
}
|
||||
|
||||
await fetch(URL, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
},
|
||||
data: JSON.stringify({})
|
||||
})
|
||||
.then(response => {
|
||||
if (response.status == 200) {
|
||||
Territory_Manager.entrances.list = [];
|
||||
Territory_Manager.entrances.setHTML(type, id);
|
||||
|
||||
return response.json()
|
||||
} else {
|
||||
console.log('err');
|
||||
end_working_button.innerText = "Помилка";
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
},
|
||||
share: async (type, number) => {
|
||||
let territory, id;
|
||||
const isHouse = type === "house";
|
||||
const territory = isHouse ? Territory_Manager.entrances.list[number] : Territory_Manager.info.list;
|
||||
const id = territory.id;
|
||||
|
||||
if (type == "house") {
|
||||
territory = Territory_Manager.entrances.list[number];
|
||||
id = Territory_Manager.entrances.list[number].id;
|
||||
}
|
||||
else if (type == "homestead") {
|
||||
territory = Territory_Manager.info.list;
|
||||
id = Territory_Manager.info.list.id;
|
||||
|
||||
const pos = Sheeps.sheeps_list.list.map(e => e.id).indexOf(territory.history.sheep_id);
|
||||
let sheep = Sheeps.sheeps_list.list[pos];
|
||||
console.log(pos);
|
||||
|
||||
const shareUrl = pos > 0
|
||||
? `\n\nПосилання на програму:\n • https://sheep-service.com/?uuid=${sheep.uuid}`
|
||||
: '';
|
||||
|
||||
const description = Territory_Manager.info.list.description?.length > 0
|
||||
? `\n\nДодатково:\n${Territory_Manager.info.list.description}`
|
||||
: '';
|
||||
|
||||
if (!navigator.share) {
|
||||
console.log("Sorry! Your browser does not support Web Share API");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const baseUrl = "https://sheep-service.com/cards";
|
||||
const url = isHouse
|
||||
? `${baseUrl}/house/T${Territory_Manager.info.list.id}.webp`
|
||||
: `${baseUrl}/homestead/H${Territory_Manager.info.list.id}.webp`;
|
||||
|
||||
let description = () => {
|
||||
if (Territory_Manager.info.list.description && Territory_Manager.info.list.description.length > 0) {
|
||||
return `\n\nДодатково:\n• ${Territory_Manager.info.list.description}`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
let sheepUuid = () => {
|
||||
const pos = Sheeps.sheeps_list.list.map(e => e.name).indexOf(territory.history.name);
|
||||
let sheep = Sheeps.sheeps_list.list[pos];
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error('Image not found');
|
||||
|
||||
if (sheep) {
|
||||
return `\n\nПосилання на Sheep-Service:\n• https://sheep-service.com/?uuid=${sheep.uuid}`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
const blob = await response.blob();
|
||||
const fileName = `${isHouse ? "E" + id : "H" + id}.webp`;
|
||||
const file = new File([blob], fileName, { type: blob.type });
|
||||
|
||||
if (navigator.share) {
|
||||
console.log("Congrats! Your browser supports Web Share API")
|
||||
try {
|
||||
let url;
|
||||
if(type == 'house') url = `https://sheep-service.com/cards/house/T${Territory_Manager.info.list.id}.webp`;
|
||||
if(type == 'homestead') url = `https://sheep-service.com/cards/homestead/H${Territory_Manager.info.list.id}.webp`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const blob = await response.blob();
|
||||
const file = new File([blob], `${type == "house" ? "E" + id : "H" + id}.webp`, { type: blob.type });
|
||||
const shareText = `Територія:\n • ${isHouse ? "E" + id : "H" + id}\n\nНаселений пункт:\n • ${Territory_Manager.info.list.settlement}\n\nВулиця:\n • ${Territory_Manager.info.list.title} ${Territory_Manager.info.list.number} (${territory.title})${description}\n\nПризначення:\n • З ${formattedDate(territory.history.date.start)}\n • До ${formattedDate(territory.history.date.end) ?? formattedDate(territory.history.date.start + (1000 * 2629743 * 4))}${shareUrl}`;
|
||||
|
||||
await navigator.share({
|
||||
text: `Територія:\n• ${type == "house" ? "E" + id : "H" + id}\n\nНаселений пункт:\n• ${Territory_Manager.info.list.settlement}\n\nВулиця:\n• ${Territory_Manager.info.list.title + " " + Territory_Manager.info.list.number}${description()}\n\nПризначення:\n • З ${formattedDate(territory.history.date.start)}\n • До ${formattedDate(territory.history.date.end) ?? formattedDate(territory.history.date.start + (1000 * 2629743 * 4))}${sheepUuid()}`,
|
||||
files: [file]
|
||||
});
|
||||
|
||||
console.log('Успешно отправлено!');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при отправке:', error);
|
||||
}
|
||||
console.log(shareText);
|
||||
|
||||
|
||||
} else {
|
||||
console.log("Sorry! Your browser does not support Web Share API")
|
||||
await navigator.share({
|
||||
text: shareText,
|
||||
files: [file]
|
||||
});
|
||||
|
||||
console.log('Успешно отправлено!');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при отправке:', error);
|
||||
}
|
||||
},
|
||||
getScreen: async () => {
|
||||
const center = map_territory.getCenter();
|
||||
console.log(center.lat, center.lng);
|
||||
const zoom = (map_territory.getZoom() + 2) || 17;
|
||||
const info = Territory_Manager.info.list;
|
||||
|
||||
let lat = center.lat;
|
||||
let lng = center.lng;
|
||||
let wayId = Territory_Manager.info.list.osm_id;
|
||||
let zoom = map_territory.getZoom() + 2 ?? 17;
|
||||
let address = Territory_Manager.info.list.title;
|
||||
let number = Territory_Manager.info.list.number;
|
||||
let id = Territory_Manager.info.list.id;
|
||||
const params = new URLSearchParams({
|
||||
lat: center.lat,
|
||||
lng: center.lng,
|
||||
type: type_territory,
|
||||
wayId: info.osm_id,
|
||||
zoom,
|
||||
address: info.title,
|
||||
number: info.number,
|
||||
id: info.id
|
||||
});
|
||||
|
||||
let url = `https://sheep-service.com/api/generator/cards?lat=${lat}&lng=${lng}&type=${type_territory}&wayId=${wayId}&zoom=${zoom}&address=${address}&number=${number}&id=${id}`;
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
let result = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
const url = `https://sheep-service.com/api/generator/cards?${params.toString()}`;
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
const urlImage = `https://sheep-service.com/cards/${type_territory}/${type_territory === "house" ? "T" : "H"}${info.id}.webp`;
|
||||
const errorElem = document.getElementById('menu-picture-error');
|
||||
const okElem = document.getElementById('menu-picture-ok');
|
||||
|
||||
if (result) {
|
||||
errorElem.style.display = 'none';
|
||||
okElem.style.display = '';
|
||||
okElem.setAttribute("href", urlImage);
|
||||
} else {
|
||||
errorElem.style.display = '';
|
||||
okElem.style.display = 'none';
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
|
||||
|
||||
urlImage = `https://sheep-service.com/cards/${type}/${type == "house" ? "T" : "H"}${id}.webp`;
|
||||
if(result) {
|
||||
document.getElementById('menu-picture-error').style.display = 'none';
|
||||
document.getElementById('menu-picture-ok').style.display = '';
|
||||
document.getElementById('menu-picture-ok').setAttribute("href", urlImage);
|
||||
} else {
|
||||
document.getElementById('menu-picture-error').style.display = '';
|
||||
document.getElementById('menu-picture-ok').style.display = 'none';
|
||||
} catch (err) {
|
||||
console.error('Ошибка при получении скрина:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-image>.menu-picture {
|
||||
#territory-info>.territory-info-image>.menu {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
@@ -71,12 +71,11 @@
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
padding: 5px;
|
||||
border-radius: 6px;
|
||||
min-width: 70px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-image>.menu-picture>a {
|
||||
#territory-info>.territory-info-image>.menu>.menu-picture {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
@@ -85,12 +84,12 @@
|
||||
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-image>.menu-picture>a>svg {
|
||||
#territory-info>.territory-info-image>.menu>.menu-picture>svg {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-image>.menu-picture>button {
|
||||
#territory-info>.territory-info-image>.menu>.menu-edit {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 2px;
|
||||
@@ -99,9 +98,10 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-image>.menu-picture>button>svg {
|
||||
#territory-info>.territory-info-image>.menu>.menu-edit>svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: var(--PrimaryColorText);
|
||||
@@ -121,13 +121,13 @@
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-text>h1 {
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#territory-info>.territory-info-text>h2 {
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 300;
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.8;
|
||||
@@ -139,14 +139,14 @@
|
||||
min-height: 100px;
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
resize: vertical;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#territory-info>#editor_button {
|
||||
width: calc(100% - 20px);
|
||||
font-size: 13px;
|
||||
font-size: var(--FontSize2);
|
||||
font-weight: 400;
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
@@ -196,7 +196,7 @@
|
||||
background: var(--ColorThemes0);
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
font-size: var(--FontSize5);
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -229,7 +229,7 @@
|
||||
}
|
||||
|
||||
#territory-entrance>.entrance>div>h1 {
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 400;
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
@@ -237,7 +237,7 @@
|
||||
#territory-entrance>.entrance>div>h2,
|
||||
#territory-entrance>.entrance>div>a,
|
||||
#territory-entrance>.entrance>div>p {
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 300;
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.8;
|
||||
@@ -271,7 +271,7 @@
|
||||
#territory-entrance>.entrance>.edit_working>button,
|
||||
#territory-entrance>.entrance>.edit>button {
|
||||
width: 100%;
|
||||
font-size: 13px;
|
||||
font-size: var(--FontSize2);
|
||||
font-weight: 400;
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
@@ -308,7 +308,7 @@
|
||||
|
||||
#territory-entrance>.entrance>.apartment_button {
|
||||
width: 100%;
|
||||
font-size: 13px;
|
||||
font-size: var(--FontSize2);
|
||||
font-weight: 400;
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
@@ -340,14 +340,14 @@
|
||||
#territory-new>.mess {
|
||||
display: flex;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
height: 100px;
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
background: var(--ColorThemes0);
|
||||
box-shadow: 0px 2px 3px rgb(0 0 0 / 5%), 0px 5px 15px rgb(0 0 0 / 5%), 0px 4px 8px rgb(0 0 0 / 5%), 0px 0px 1px rgb(0 0 0 / 5%);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -110px;
|
||||
margin-top: -50px;
|
||||
margin-left: -160px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -374,6 +374,16 @@
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#territory-new>.mess>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes2);
|
||||
color: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#territory-new>.mess>div {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -383,7 +393,7 @@
|
||||
|
||||
#territory-new>.mess>div>button {
|
||||
text-decoration: none;
|
||||
font-size: 15px;
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
height: 35px;
|
||||
color: var(--ColorThemes0);
|
||||
|
||||
@@ -1,142 +1,165 @@
|
||||
/**
|
||||
* SPA Router v1.0.0
|
||||
* -----------------
|
||||
* Легкий роутер для односторінкових застосунків з підтримкою:
|
||||
* - History та hash режимів
|
||||
* - Параметрів маршруту та query-параметрів
|
||||
* - Делегування посилань та збереження прокрутки
|
||||
*
|
||||
* Використання:
|
||||
* Router.config({ mode: 'history', root: '/' }).listen().delegateLinks();
|
||||
*
|
||||
* Автор: Rozenrod (https://github.com/rozenrod)
|
||||
* Ліцензія: MIT
|
||||
*/
|
||||
|
||||
const Router = {
|
||||
routes: [],
|
||||
mode: null,
|
||||
root: '/',
|
||||
config: function(options) {
|
||||
this.mode = options && options.mode && options.mode == 'history' && !!(history.pushState) ? 'history' : 'hash';
|
||||
this.root = options && options.root ? '/' + this.clearSlashes(options.root) + '/' : '/';
|
||||
return this;
|
||||
},
|
||||
getFragment: function() {
|
||||
let fragment = '';
|
||||
if(this.mode === 'history') {
|
||||
// fragment = this.clearSlashes(decodeURI(location.pathname + location.search));
|
||||
fragment = this.clearSlashes(decodeURI(window.location.href.replace('/#', '').replace(window.location.origin, '/')));
|
||||
fragment = fragment.replace(/\?(.*)$/, '');
|
||||
fragment = this.root != '/' ? fragment.replace(this.root, '') : fragment;
|
||||
} else {
|
||||
let match = window.location.href.match(/#(.*)$/);
|
||||
fragment = match ? match[1] : '';
|
||||
}
|
||||
return this.clearSlashes(fragment);
|
||||
},
|
||||
getParams: function () {
|
||||
let query = '';
|
||||
if(this.mode === 'history') {
|
||||
query = decodeURI(window.location.href.replace('/#', '')).split("?")[1];
|
||||
} else {
|
||||
let index = window.location.hash.indexOf("?");
|
||||
query = (index !== -1) ? window.location.hash.substring(index) : "";
|
||||
}
|
||||
let _query = {};
|
||||
if (typeof query !== "string") {
|
||||
return _query;
|
||||
}
|
||||
if (query[0] === "?") {
|
||||
query = query.substring(1);
|
||||
}
|
||||
query.split("&").forEach(function (row) {
|
||||
let parts = row.split("=");
|
||||
if (parts[0] !== "") {
|
||||
if (parts[1] === undefined) {
|
||||
parts[1] = true;
|
||||
}
|
||||
_query[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
|
||||
}
|
||||
});
|
||||
return _query;
|
||||
},
|
||||
clearSlashes: function(path) {
|
||||
return path.toString().replace(/\/$/, '').replace(/^\//, '');
|
||||
},
|
||||
add: function(re, handler, options) {
|
||||
if(typeof re == 'function') {
|
||||
handler = re;
|
||||
re = '';
|
||||
}
|
||||
this.routes.push({ re: re, handler: handler, options: options});
|
||||
return this;
|
||||
},
|
||||
remove: function(param) {
|
||||
for(let i=0, r; i < this.routes.length, r = this.routes[i]; i++) {
|
||||
if(r.handler === param || r.re.toString() === param.toString()) {
|
||||
this.routes.splice(i, 1);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
flush: function() {
|
||||
this.routes = [];
|
||||
this.mode = null;
|
||||
this.root = '/';
|
||||
return this;
|
||||
},
|
||||
check: function(f) {
|
||||
let fragment = f || this.getFragment();
|
||||
for(let i=0; i < this.routes.length; i++) {
|
||||
let match = fragment.match(this.routes[i].re);
|
||||
if(fragment == '' || fragment == '/') match = 'home'.match(this.routes[i].re);
|
||||
if(match) {
|
||||
match.shift();
|
||||
let query = this.getParams();
|
||||
this.routes[i].handler.apply({query}, match);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
listen: function() {
|
||||
let self = this;
|
||||
let current = self.getFragment();
|
||||
let current_query = self.getParams();
|
||||
let fn = function() {
|
||||
if(current !== self.getFragment()) {
|
||||
current = self.getFragment();
|
||||
self.check(current);
|
||||
}
|
||||
// if(current !== self.getFragment() || JSON.stringify(current_query) !== JSON.stringify(self.getParams())) {
|
||||
// current = self.getFragment();
|
||||
// current_query = self.getParams();
|
||||
// self.check(current);
|
||||
// }
|
||||
}
|
||||
clearInterval(this.interval);
|
||||
this.interval = setInterval(fn, 50);
|
||||
return this;
|
||||
},
|
||||
navigate: function(path, mode = true) {
|
||||
path = path || '';
|
||||
if(mode){
|
||||
if(this.mode === 'history') {
|
||||
history.replaceState({position: window.pageYOffset}, null);
|
||||
history.pushState({position: 0}, null, this.root + this.clearSlashes(path));
|
||||
} else {
|
||||
window.location.href = window.location.href.replace(/#(.*)$/, '') + '#' + path;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
update: function(key, value) {
|
||||
let url = window.location;
|
||||
let URLParams = new URLSearchParams(url.search);
|
||||
let RouterParams = Router.getParams();
|
||||
URLParams.set(key, value);
|
||||
|
||||
history.replaceState({position: window.pageYOffset}, null, window.location.origin + window.location.pathname + '?' + URLParams.toString());
|
||||
}
|
||||
}
|
||||
routes: [], // Список маршрутів (шаблон + обробник)
|
||||
mode: 'history', // Режим: 'history' або 'hash'
|
||||
root: '/', // Корінь додатку
|
||||
|
||||
// Налаштування роутера
|
||||
config({ mode = 'hash', root = '/' } = {}) {
|
||||
const cleanRoot = '/' + this.clearSlashes(root) + '/';
|
||||
// Якщо браузер підтримує history API та mode === 'history' — використовуємо його
|
||||
this.mode = (mode === 'history' && history.pushState) ? 'history' : 'hash';
|
||||
// Захист від абсолютних URL (наприклад, http://...)
|
||||
this.root = cleanRoot.startsWith('http') ? '/' : cleanRoot;
|
||||
return this;
|
||||
},
|
||||
|
||||
window.addEventListener('click', function (event) {
|
||||
if (!event.target.matches('[data-route]')) return;
|
||||
event.preventDefault();
|
||||
Router.navigate((event.target.href).replace(window.location.origin, ''));
|
||||
}, false);
|
||||
// Прибирає слеші на початку та в кінці шляху
|
||||
clearSlashes(path) {
|
||||
return path.toString().replace(/^\/+|\/+$/g, '');
|
||||
},
|
||||
|
||||
if(Router.mode === 'history'){
|
||||
window.addEventListener('popstate', function (event) {
|
||||
if (!history.state.url) return;
|
||||
Router.navigate(history.state.url);
|
||||
}, false);
|
||||
}
|
||||
// Отримує поточний фрагмент (частину URL після root або після #)
|
||||
getFragment() {
|
||||
let fragment = '';
|
||||
if (this.mode === 'history') {
|
||||
fragment = decodeURI(location.pathname + location.search);
|
||||
fragment = fragment.replace(this.root, '').split('?')[0];
|
||||
} else {
|
||||
fragment = location.hash.slice(1).split('?')[0];
|
||||
}
|
||||
return this.clearSlashes(fragment);
|
||||
},
|
||||
|
||||
// Отримує query-параметри з URL
|
||||
getParams() {
|
||||
let query = this.mode === 'history' ? location.search : location.hash.split('?')[1] || '';
|
||||
const params = {};
|
||||
new URLSearchParams(query).forEach((v, k) => params[k] = v);
|
||||
return params;
|
||||
},
|
||||
|
||||
// Додає новий маршрут
|
||||
add(re, handler, options) {
|
||||
if (typeof re === 'function') {
|
||||
handler = re;
|
||||
re = '';
|
||||
}
|
||||
this.routes.push({ re, handler, options });
|
||||
return this;
|
||||
},
|
||||
|
||||
// Видаляє маршрут за функцією або шаблоном
|
||||
remove(param) {
|
||||
this.routes = this.routes.filter(r =>
|
||||
r.handler !== param && r.re.toString() !== param.toString()
|
||||
);
|
||||
return this;
|
||||
},
|
||||
|
||||
// Очищує усі маршрути та скидає режим
|
||||
flush() {
|
||||
this.routes = [];
|
||||
this.mode = 'hash';
|
||||
this.root = '/';
|
||||
return this;
|
||||
},
|
||||
|
||||
// Перевіряє фрагмент та викликає відповідний обробник маршруту
|
||||
check(fragment = this.getFragment()) {
|
||||
const query = this.getParams();
|
||||
for (const { re, handler } of this.routes) {
|
||||
const match = (fragment || 'home').match(re);
|
||||
if (match) {
|
||||
handler.apply({ query }, match.slice(1));
|
||||
|
||||
// Прокрутка до елемента з id, якщо є #hash
|
||||
if (location.hash.length > 1) {
|
||||
const el = document.getElementById(location.hash.slice(1));
|
||||
if (el) el.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Слухає зміни URL
|
||||
listen() {
|
||||
const onChange = (e) => {
|
||||
this.check();
|
||||
|
||||
// Витягуємо позицію прокрутки зі стану історії
|
||||
const pos = e?.state?.scroll;
|
||||
if (pos) {
|
||||
setTimeout(() => {
|
||||
window.scrollTo(pos.x, pos.y);
|
||||
}, 50);
|
||||
}
|
||||
};
|
||||
if (this.mode === 'history') {
|
||||
window.addEventListener('popstate', onChange);
|
||||
} else {
|
||||
window.addEventListener('hashchange', onChange);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Делегування кліків по посиланнях з data-route
|
||||
delegateLinks() {
|
||||
window.addEventListener('click', (e) => {
|
||||
const target = e.target.closest('[data-route]');
|
||||
if (!target || !target.href) return;
|
||||
|
||||
const path = target.href.replace(location.origin, '');
|
||||
if (path === this.getFragment()) return;
|
||||
|
||||
e.preventDefault();
|
||||
this.navigate(path); // Викликає навігацію без перезавантаження сторінки
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
// Навігація до нового шляху (push або replace)
|
||||
navigate(path = '', push = true, update = true) {
|
||||
const scroll = { x: window.scrollX, y: window.scrollY };
|
||||
history.replaceState({ scroll }, '', location.href);
|
||||
|
||||
if (this.mode === 'history') {
|
||||
const url = new URL(path, location.origin);
|
||||
const relativePath = url.pathname + url.search + url.hash;
|
||||
history[push ? 'pushState' : 'replaceState']({}, '', relativePath);
|
||||
} else {
|
||||
location.hash = this.clearSlashes(path);
|
||||
}
|
||||
|
||||
if(update == true) {
|
||||
window.scrollTo(0, 0); // Скидуємо прокрутку при переході
|
||||
this.check();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Оновлює query-параметр у поточному URL
|
||||
update(key, value) {
|
||||
const params = new URLSearchParams(location.search);
|
||||
params.set(key, value);
|
||||
const newUrl = location.origin + location.pathname + '?' + params.toString();
|
||||
history.replaceState({ position: window.pageYOffset }, '', newUrl);
|
||||
}
|
||||
};
|
||||
@@ -1,78 +1,63 @@
|
||||
Router
|
||||
.add('auth', function () {
|
||||
pageActive('');
|
||||
Auth.init();;
|
||||
})
|
||||
.add('territory/manager/(.*)/(.*)', function (type, id) {
|
||||
pageActive();
|
||||
Territory_Manager.init(type, id);
|
||||
pageActive()
|
||||
routerScroll()
|
||||
})
|
||||
.add('territory/editor/(.*)/(.*)', function (type, id) {
|
||||
pageActive();
|
||||
Editor.init(type, id);
|
||||
pageActive()
|
||||
routerScroll()
|
||||
})
|
||||
.add('territory/card/(.*)/(.*)', function (type, id) {
|
||||
pageActive();
|
||||
Card.init(type, id);
|
||||
pageActive()
|
||||
routerScroll()
|
||||
})
|
||||
.add('territory', function () {
|
||||
pageActive('territory');
|
||||
Territory.init();
|
||||
pageActive('territory')
|
||||
routerScroll()
|
||||
})
|
||||
.add('sheeps/(.*)', function (name) {
|
||||
Sheeps.init(name);
|
||||
routerScroll();
|
||||
pageActive('sheeps')
|
||||
pageActive('sheeps');
|
||||
Sheeps.init(name);;
|
||||
})
|
||||
.add('sheeps', function () {
|
||||
Sheeps.init();
|
||||
routerScroll();
|
||||
pageActive('sheeps')
|
||||
pageActive('sheeps');
|
||||
Sheeps.init();;
|
||||
})
|
||||
.add('home', function () {
|
||||
pageActive('home');
|
||||
Home.init();
|
||||
pageActive('home')
|
||||
routerScroll()
|
||||
})
|
||||
.add('schedule', function () {
|
||||
Options.init();
|
||||
routerScroll();
|
||||
pageActive('schedule')
|
||||
pageActive('schedule');
|
||||
Schedule.init();;
|
||||
})
|
||||
.add('stand', function () {
|
||||
Stand.init();
|
||||
routerScroll();
|
||||
pageActive('stand')
|
||||
pageActive('stand');
|
||||
Stand.init();;
|
||||
})
|
||||
.add('options', function () {
|
||||
Options.init();
|
||||
routerScroll();
|
||||
pageActive('options')
|
||||
pageActive('options');
|
||||
Options.init();;
|
||||
})
|
||||
.add('constructor', function () {
|
||||
Constructor.init();
|
||||
routerScroll();
|
||||
pageActive()
|
||||
pageActive();
|
||||
Constructor.init();;
|
||||
})
|
||||
.add(function () {
|
||||
page_404();
|
||||
routerScroll();
|
||||
page_404();;
|
||||
pageActive();
|
||||
})
|
||||
|
||||
|
||||
function routerScroll() {
|
||||
if (!history.state) return;
|
||||
window.scroll(0, history.state.position);
|
||||
}
|
||||
|
||||
function pageActive(element) {
|
||||
let nav = document.getElementsByTagName("nav")[0];
|
||||
let dots = nav.getElementsByTagName("li");
|
||||
const active = document.querySelector("nav li [data-state='active']");
|
||||
if (active) active.setAttribute('data-state', '');
|
||||
|
||||
for (i = 0; i < dots.length; i++) {
|
||||
dots[i].children[0].setAttribute('data-state', '');
|
||||
if (element) {
|
||||
const target = document.getElementById(`nav-${element}`);
|
||||
if (target) target.setAttribute('data-state', 'active');
|
||||
}
|
||||
if (element) document.getElementById(`nav-${element}`).setAttribute('data-state', 'active')
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user