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 += ` `; } 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) => { 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 `

${history.name} ${history.group_id}

`; const sheep = sheeps_list.find(item => item.name === history.name); return sheep ? `${history.name}` : `${history.name}`; }; const renderWorking = (element, i = 0) => `

${element.title ?? ''}

Територію опрацьовує:

${renderName(element.history)}

Територія видана:

${formattedDate(element.history.date.start)}

Варто забрати:

${formattedDate(element.history.date.end) ?? formattedDate(element.history.date.start + (1000 * 2629743 * 4))}

`; const renderFree = (element, i = 0) => { let name = () => { if(element.history.name == "Групова") return `Групова №${element.history.group_id}` else return element.history.name ?? "..." } return `

${element.title ?? ''}

Територія не опрацьовується

Останнє опрацювання:

${formattedDate(element.history.date.end) ?? "..."} (${name()})

` }; 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); console.log(data.zoom); // setTimeout(() => { // map_territory.setZoom(data.zoom); // }, 200) }, mess: { open: ({ type, id, number, mode }) => { const block = document.getElementById('territory-new'); const groupInput = document.getElementById('new-worker-group'); const nameInput = document.getElementById('new-worker-name'); const button = document.getElementById('new-worker-button'); // Показуємо блок 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').value; const groupId = Number(document.getElementById('new-worker-group').value); const newButton = document.getElementById('new-worker-button'); const groupButton = document.getElementById('group-working-button'); let territory_id; let URL; const sheep = Sheeps.sheeps_list.list.find(e => e.name === sheepName); 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 ? sheepName : "Групова", group_id: mode ? sheep?.group_id : groupId, sheep_id: mode ? sheep?.id : null }; 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"); 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 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); } catch (error) { console.error("❌ Помилка зняття призначення:", 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); } } }