Files
Sheep-Service/web/lib/pages/card/script.js
2025-03-31 00:22:21 +03:00

358 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
let socket, username;
let listEntrances = []
let listApartment = []
let holdTimer;
let startTime;
const Card = {
init: async (type, id) => {
let html = await fetch('/lib/pages/card/index.html').then((response) => response.text());
app.innerHTML = html;
house = id;
if (socket) socket.close(1000, "Перезапуск соединения");
if (type == "house") {
getEntrances();
start(makeid(6));
}
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);
}
function handleCancel() {
const holdDuration = Date.now() - startTime; // Считаем, сколько длилось нажатие
if (holdDuration < 1000) {
clearTimeout(holdTimer); // Если нажали менее 1 секунды, сбрасываем таймер
}
}
}
}
// 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
}
}
socket.send(JSON.stringify(message))
};
socket.onmessage = function (event) {
let data = JSON.parse(event.data)
if (data.event == 'connection') {
if (data.username == username) return
console.log(`Добавлен новый пользователь по имени ${data.username}`);
} else if (data.event == 'message') {
update(data);
if (data.username == username) return
console.log(`${data.username} пишет: `, data.data);
}
};
socket.onclose = function (event) {
if (event.wasClean) {
document.getElementById("status").innerText = "WebSocket | close"
console.log(`[WebSocket | close] Соединение закрыто чисто, код=${event.code} причина=${event.reason}`);
} else {
document.getElementById("status").innerText = "WebSocket | close"
console.log('[WebSocket | close] Соединение прервано');
// setTimeout(function() {
// start(username);
// }, 1000);
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>
`;
getApartment(element.id, element.entrance_number);
console.log(element);
}
})
}
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;
data.sort((a, b) => a.apartment_number - b.apartment_number);
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>
`;
}
})
}
function sort(id, entrance_id) {
let child = document.getElementById(`card_${id}`);
document.getElementById(`apartments_${entrance_id}`).removeChild(child);
document.getElementById(`apartments_${entrance_id}`).append(child);
child.style.border = "1px solid var(--PrimaryColor)";
}
function getTimeInSeconds(time = Date.now()) {
// Если время больше 10 знаков (это значит, что время в миллисекундах)
if (time.toString().length < 10) {
// Округляем до секунд, убирая последние 3 цифры (миллисекунды)
time = Math.floor(time * 1000);
}
return time;
}