Додані повідомлення та перепрацьована структура застосунку та api

This commit is contained in:
2026-03-15 00:25:10 +02:00
parent 85483b85bb
commit 4bc9c11512
101 changed files with 5763 additions and 2546 deletions

View File

@@ -32,7 +32,6 @@ const Territory_card = {
// Застосовуємо режим сортування
this.sort(localStorage.getItem('territory_card_sort'), false);
this.getEntrances({ update: false });
} else if (type === "homestead") {
this.getHomestead.map({});
}
@@ -40,7 +39,7 @@ const Territory_card = {
const ids = ['cloud_1', 'cloud_2', 'cloud_3'];
ids.forEach((id, idx) => {
const el = document.getElementById(id);
if(!el) return;
if (!el) return;
el.setAttribute('data-state', ['sync', 'ok', 'err'].indexOf(Cloud.status) === idx ? 'active' : '');
});
@@ -134,10 +133,18 @@ const Territory_card = {
if (navigator.onLine && Cloud.socket?.readyState === WebSocket.OPEN) {
Cloud.socket.send(JSON.stringify(message));
} else {
if (confirm("З'єднання розірвано! Перепідключитись?")) {
Cloud.start();
Territory_card.getEntrances({ update: true });
}
Notifier.click({
title: `Запис не додано!`,
text: `Натисніть, щоб перепідключитись!`
}, {
type: 'warn',
f: () => {
Cloud.reconnecting = true;
Cloud.reconnectAttempts = 0;
Cloud.start();
},
timeout: 0
});
}
},
@@ -181,9 +188,18 @@ const Territory_card = {
if (navigator.onLine && Cloud.socket?.readyState === WebSocket.OPEN) {
Cloud.socket.send(JSON.stringify(message));
} else {
if (confirm("З'єднання розірвано! Перепідключитись?")) {
Territory_card.cloud.start();
}
Notifier.click({
title: `Запис не додано!`,
text: `Натисніть, щоб перепідключитись!`
}, {
type: 'warn',
f: () => {
Cloud.reconnecting = true;
Cloud.reconnectAttempts = 0;
Cloud.start();
},
timeout: 0
});
}
}
},
@@ -211,12 +227,14 @@ const Territory_card = {
return;
}
Territory_card.info(data);
const fragment = document.createDocumentFragment();
const canManage = USER.mode === 2 || (USER.mode === 1 && USER.possibilities.can_manager_territory);
for (const element of data) {
const { id, entrance_number, title, history, working } = element;
const { id, entrance_number, title, history, working, address } = element;
const isMy = ((history.name === "Групова" && history.group_id == USER.group_id) || history.name === USER.name);
const show = (isMy && working) ? "open" : canManage ? "close" : null;
@@ -310,8 +328,9 @@ const Territory_card = {
div.style = style;
div.innerHTML = `
<span>Квартира ${apt.title}</span>
<hr>
<div class="info">
<span>кв.${apt.title}</span>
<select id="status_${apt.id}" onchange="Territory_card.cloud.messApartment({number:${number},id:${apt.id},update:true})" style="${style}">
${statusOptions(apt.status)}
</select>
@@ -350,9 +369,6 @@ const Territory_card = {
async map({ homestead_id = Territory_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;
@@ -483,10 +499,116 @@ const Territory_card = {
Territory_card.getHomestead.markers[element.id] = marker; // сохраним ссылку на маркер
}
if((USER.possibilities.can_joint_territory && data.history.sheep_id == USER.id) || USER.mode == 2){
this.joint.setHTML(homestead_id);
}
},
joint: {
async setHTML(homestead_id){
let lest = await this.getJoint(homestead_id);
let block_info = document.getElementById('page-card-info');
block_info.style.display = "flex";
block_info.innerHTML = `
<h2>Надати спільний доступ:</h2>
<smart-select type="number" id="joint-${homestead_id}" onchange="Territory_card.getHomestead.joint.setJoint('${homestead_id}')" max="30" placeholder="Оберіть вісників..." title="Оберіть вісників, з якими хочете поділитись територією">
${Sheeps.sheeps_list.list.map(p => {
const isSelected = lest.some(item => item.sheep_id === p.id);
if(USER.id === Number(p.id) && USER.mode != 2) return
return `<div
slot="option"
data-value="${Number(p.id)}"
${isSelected ? 'data-selected' : ''}>
${p.name}
</div>`;
}).join('')}
</smart-select>
`;
},
setJoint(homestead_id){
const select = document.getElementById(`joint-${homestead_id}`);
if (!select) return;
console.log(select.getClick);
if(select.getClick.state == "add"){
this.addSheep(homestead_id, select.getClick.value);
} else if(select.getClick.state == "delete"){
this.delSheep(homestead_id, select.getClick.value);
}
},
async getJoint(homestead_id){
let uuid = localStorage.getItem("uuid");
return await fetch(`${CONFIG.api}homestead/joint/${homestead_id}`, {
method: 'GET',
headers: {
"Content-Type": "application/json",
"Authorization": uuid
}
}).then((response) => response.json());
},
async addSheep(homestead_id, sheep_id){
const uuid = localStorage.getItem('uuid');
if (!homestead_id) {
console.warn("Невірні дані для наданя доступу.");
return;
}
try {
const response = await fetch(`${CONFIG.api}homestead/joint/${homestead_id}`, {
method: 'POST',
headers: {
"Content-Type": "application/json",
"Authorization": uuid
},
body: JSON.stringify({"sheep_id": sheep_id})
});
if (!response.ok) throw new Error("Failed to assign");
Notifier.success('Віснику успішно надано доступ.');
} catch (err) {
console.error('❌ Error:', err);
Notifier.error('Помилка надання доступу.');
}
},
async delSheep(homestead_id, sheep_id){
const uuid = localStorage.getItem('uuid');
if (!homestead_id) {
console.warn("Невірні дані для відкликання доступу.");
return;
}
try {
const response = await fetch(`${CONFIG.api}homestead/joint/${homestead_id}`, {
method: 'DELETE',
headers: {
"Content-Type": "application/json",
"Authorization": uuid
},
body: JSON.stringify({"sheep_id": sheep_id})
});
if (!response.ok) throw new Error("Failed to assign");
Notifier.success('Доступ успішно відкликанно.');
} catch (err) {
console.error('❌ Error:', err);
Notifier.error('Помилка при відкликанні доступу.');
}
}
}
},
async reload(){
async reload() {
Territory_card.getEntrances({ update: true });
},
@@ -547,5 +669,39 @@ const Territory_card = {
}
this.close();
}
},
info(data) {
let block_info = document.getElementById('page-card-info');
block_info.style.display = "flex";
block_info.innerHTML = `
<a href="https://www.google.com/maps?q=${data[0].address.points_number.lat},${data[0].address.points_number.lng}">${data[0].address.title} ${data[0].address.number}</a>
<hr>
<h2>Терміни опрацювання:</h2>
`
for (let index = 0; index < data.length; index++) {
const element = data[index];
const canManage = USER.mode === 2 || (USER.mode === 1 && USER.possibilities.can_manager_territory);
const isMy = ((element.history.name === "Групова" && element.history.group_id == USER.group_id) || element.history.name === USER.name);
let date_start = element.history.date.start;
let date_end = date_start + (1000 * 2629743 * 4);
let red = () => {
if(Date.now() > date_end) return `color: #ec2d2d;`
return
}
if (element.working && (isMy || canManage)) {
block_info.innerHTML += `
<div>
<h3>${element.title}</h3>
<h4>${formattedDate(date_start)} — <span style="${red()}">${formattedDate(date_end)}</span></h4>
</div>
`;
}
}
}
}