543 lines
23 KiB
JavaScript
543 lines
23 KiB
JavaScript
let map_territory, type_territory;
|
|
|
|
const Territory_Manager = {
|
|
init: async (type, id) => {
|
|
let html = await fetch('/lib/pages/territory/manager/index.html').then((response) => response.text());
|
|
app.innerHTML = html;
|
|
|
|
type_territory = type;
|
|
|
|
let sheeps_list = [];
|
|
if (Sheeps.sheeps_list.list.length == 0) {
|
|
sheeps_list = await Sheeps.sheeps_list.loadAPI();
|
|
} else {
|
|
sheeps_list = Sheeps.sheeps_list.list;
|
|
}
|
|
|
|
let editor_button = document.getElementById('editor_button');
|
|
if (USER.possibilities.can_add_territory) {
|
|
editor_button.style.display = "";
|
|
editor_button.setAttribute("href", `/territory/editor/${type}/${id}`)
|
|
}
|
|
|
|
await Territory_Manager.info.setHTML(type, id);
|
|
Territory_Manager.entrances.setHTML(type, id);
|
|
|
|
for (let i = 0; i < sheeps_list.length; i++) {
|
|
const element = sheeps_list[i];
|
|
|
|
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';
|
|
}
|
|
|
|
Territory_Manager.mess.init();
|
|
},
|
|
info: {
|
|
list: {},
|
|
loadAPI: async (url) => {
|
|
const uuid = localStorage.getItem("uuid");
|
|
|
|
const response = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Authorization": uuid
|
|
}
|
|
});
|
|
|
|
Territory_Manager.info.list = await response.json();
|
|
return Territory_Manager.info.list;
|
|
},
|
|
|
|
setHTML: async (type, id) => {
|
|
const url = `${CONFIG.api}${type}/${id}`;
|
|
const data = await Territory_Manager.info.loadAPI(url);
|
|
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');
|
|
|
|
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.dataset.listener = "true";
|
|
}
|
|
|
|
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) => {
|
|
const uuid = localStorage.getItem("uuid");
|
|
const response = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Authorization": uuid
|
|
}
|
|
});
|
|
|
|
Territory_Manager.entrances.list = await response.json();
|
|
return Territory_Manager.entrances.list;
|
|
},
|
|
|
|
setHTML: async (type, id) => {
|
|
const container = document.getElementById('territory-entrance');
|
|
container.innerHTML = "";
|
|
const sheeps_list = Sheeps.sheeps_list.list;
|
|
|
|
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>`;
|
|
};
|
|
|
|
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>
|
|
`;
|
|
|
|
const renderFree = (element, i = 0) => {
|
|
let name = () => {
|
|
if(element.history.name == "Групова") return `Групова №${element.history.group_id}`
|
|
else return element.history.name ?? "..."
|
|
}
|
|
|
|
return `
|
|
<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) ?? "..."} (${name()})</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>
|
|
`
|
|
};
|
|
|
|
let html = "";
|
|
|
|
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") {
|
|
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) => {
|
|
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;
|
|
|
|
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(mapElement, {
|
|
renderer: L.canvas(),
|
|
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");
|
|
|
|
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, polygonOptions).addTo(map_territory);
|
|
},
|
|
mess: {
|
|
init: () => {
|
|
let block_new_sheep = document.getElementById('new-worker-sheep');
|
|
block_new_sheep.innerHTML = `
|
|
<smart-select type="number" onchange="Territory_Manager.mess.select_close()" id="new-worker-name" max="1" placeholder="Оберіть вісника..." title="Оберіть вісника, якому хочете призначити цю територію">
|
|
${Sheeps.sheeps_list.list.map(p => {
|
|
return `<div
|
|
slot="option"
|
|
data-value="${Number(p.id)}">
|
|
${p.name}
|
|
</div>`;
|
|
}).join('')}
|
|
</smart-select>
|
|
`;
|
|
},
|
|
|
|
select_close: () => {
|
|
const select = document.getElementById(`new-worker-name`);
|
|
if (!select) return;
|
|
console.log(select.getClick);
|
|
|
|
if(select.getClick.state == "add"){
|
|
select.removeAttribute("open")
|
|
}
|
|
},
|
|
|
|
open: ({ type, id, number, mode }) => {
|
|
const block = document.getElementById('territory-new');
|
|
const groupInput = document.getElementById('new-worker-group');
|
|
const nameInput = document.getElementById('new-worker-sheep');
|
|
const button = document.getElementById('new-worker-button');
|
|
|
|
button.removeAttribute("disabled")
|
|
|
|
// Показуємо блок
|
|
block.style.display = "";
|
|
requestAnimationFrame(() => block.style.opacity = "1");
|
|
|
|
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');
|
|
block.style.opacity = "0";
|
|
|
|
const onTransitionEnd = () => {
|
|
block.style.display = "none";
|
|
block.removeEventListener("transitionend", onTransitionEnd);
|
|
};
|
|
block.addEventListener("transitionend", onTransitionEnd);
|
|
}
|
|
},
|
|
newWorker: async ({ type, id, number, mode }) => {
|
|
const uuid = localStorage.getItem('uuid');
|
|
|
|
const sheepName = document.getElementById(`new-worker-name`);
|
|
const groupId = Number(document.getElementById('new-worker-group').value);
|
|
|
|
if (!sheepName.value[0] && !groupId) return;
|
|
|
|
const newButton = document.getElementById('new-worker-button');
|
|
const groupButton = document.getElementById('group-working-button');
|
|
|
|
newButton.setAttribute("disabled", "");
|
|
|
|
let territory_id;
|
|
let URL;
|
|
|
|
const sheep = Sheeps.sheeps_list.list.find(e => e.id === sheepName.value[0]);
|
|
|
|
if (type === "house") {
|
|
territory_id = Territory_Manager.entrances.list[number]?.id;
|
|
URL = `${CONFIG.api}history/entrance/${territory_id}`;
|
|
} else if (type === "homestead") {
|
|
territory_id = Territory_Manager.info.list.id;
|
|
URL = `${CONFIG.api}history/homestead/${territory_id}`;
|
|
}
|
|
|
|
if (!territory_id || !URL) {
|
|
console.warn("Невірні дані для призначення.");
|
|
return;
|
|
}
|
|
|
|
const data = {
|
|
name: mode ? sheep?.name : "Групова",
|
|
group_id: mode ? sheep?.group_id : groupId,
|
|
sheep_id: mode ? sheep?.id : null
|
|
};
|
|
|
|
console.log(data);
|
|
|
|
|
|
try {
|
|
const response = await fetch(URL, {
|
|
method: 'POST',
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Authorization": uuid
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
if (!response.ok) throw new Error("Failed to assign");
|
|
|
|
Notifier.success('Територія призначина успішно');
|
|
|
|
Territory_Manager.mess.close();
|
|
Territory_Manager.entrances.list = [];
|
|
await Territory_Manager.entrances.setHTML(type, id);
|
|
|
|
Territory_list.house.list = [];
|
|
Territory_list.homestead.list = [];
|
|
Territory_list.house.loadAPI();
|
|
Territory_list.homestead.loadAPI();
|
|
} catch (err) {
|
|
console.error('❌ Error:', err);
|
|
Notifier.error('Помилка призначення території');
|
|
const errorText = "Помилка";
|
|
if (newButton) newButton.innerText = errorText;
|
|
if (groupButton) groupButton.innerText = errorText;
|
|
}
|
|
},
|
|
endWorker: async (type, id, territory_id) => {
|
|
const button = document.getElementById('end-working-button');
|
|
const uuid = localStorage.getItem('uuid');
|
|
|
|
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);
|
|
|
|
Territory_list.house.list = [];
|
|
Territory_list.homestead.list = [];
|
|
Territory_list.house.loadAPI();
|
|
Territory_list.homestead.loadAPI();
|
|
|
|
Notifier.success('Територія забрана успішно');
|
|
} catch (error) {
|
|
console.error("❌ Помилка зняття призначення:", error);
|
|
Notifier.error('Помилка зняття призначення');
|
|
if (button) button.innerText = "Помилка";
|
|
}
|
|
},
|
|
share: async (type, number) => {
|
|
const isHouse = type === "house";
|
|
const territory = isHouse ? Territory_Manager.entrances.list[number] : Territory_Manager.info.list;
|
|
const id = territory.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`;
|
|
|
|
const response = await fetch(url);
|
|
if (!response.ok) throw new Error('Image not found');
|
|
|
|
const blob = await response.blob();
|
|
const fileName = `${isHouse ? "E" + id : "H" + id}.webp`;
|
|
const file = new File([blob], fileName, { 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}`;
|
|
|
|
console.log(shareText);
|
|
|
|
|
|
await navigator.share({
|
|
text: shareText,
|
|
files: [file]
|
|
});
|
|
|
|
console.log('Успешно отправлено!');
|
|
} catch (error) {
|
|
console.error('Ошибка при отправке:', error);
|
|
}
|
|
},
|
|
getScreen: async () => {
|
|
const center = map_territory.getCenter();
|
|
const zoom = (map_territory.getZoom() + 2) || 17;
|
|
const info = Territory_Manager.info.list;
|
|
|
|
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
|
|
});
|
|
|
|
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';
|
|
}
|
|
} catch (err) {
|
|
console.error('Ошибка при получении скрина:', err);
|
|
}
|
|
}
|
|
} |