Додана сторінка "історія служіння"

This commit is contained in:
2025-09-20 20:02:46 +03:00
parent ff393417a1
commit d75fb7ec3d
23 changed files with 3065 additions and 1078 deletions

View File

@@ -0,0 +1,26 @@
const historyApartmentService = require('../services/history.apartment.service');
class historyApartmentController {
async getList(req, res) {
const { limit } = req.query;
if (req.mode == 2) {
let result = await historyApartmentService.getList(limit);
if (result) {
return res
.status(200)
.send(result);
} else {
return res
.status(500)
.send({ message: 'Internal server error.' });
}
} else {
return res
.status(403)
.send({ message: 'The user does not have enough rights.' });
}
}
}
module.exports = new historyApartmentController();

View File

@@ -0,0 +1,10 @@
const express = require('express');
const router = express.Router({ mergeParams: true });
const historyApartmentController = require('../controllers/history.apartment.controller');
const authenticate = require("../middleware/auth");
router
.route('/list')
.get(authenticate, historyApartmentController.getList);
module.exports = router;

View File

@@ -11,6 +11,7 @@ const entrancesRoutes = require('./entrances.routes');
const apartmentsRoutes = require('./apartments.routes'); const apartmentsRoutes = require('./apartments.routes');
const historyEntranceRoutes = require('./history.entrance.routes'); const historyEntranceRoutes = require('./history.entrance.routes');
const historyHomesteadRoutes = require('./history.homestead.routes'); const historyHomesteadRoutes = require('./history.homestead.routes');
const historyApartmentRoutes = require('./history.apartment.routes');
const standRoutes = require('./stand.routes'); const standRoutes = require('./stand.routes');
const pushRoutes = require('./push.routes'); const pushRoutes = require('./push.routes');
@@ -27,6 +28,7 @@ router.use('/house/:house_id/entrances', entrancesRoutes);
router.use('/apartments?/:entrance_id', apartmentsRoutes); router.use('/apartments?/:entrance_id', apartmentsRoutes);
router.use('/history/entrance/:entrance_id', historyEntranceRoutes); router.use('/history/entrance/:entrance_id', historyEntranceRoutes);
router.use('/history/homestead/:homestead_id', historyHomesteadRoutes); router.use('/history/homestead/:homestead_id', historyHomesteadRoutes);
router.use('/history/apartments?', historyApartmentRoutes);
router.use('/stand', standRoutes); router.use('/stand', standRoutes);
router.use('/push', pushRoutes); router.use('/push', pushRoutes);

View File

@@ -69,7 +69,7 @@ class EntrancesService {
`; `;
db.run(sql, [ db.run(sql, [
house_id, Number(house_id),
Number(data.entrance_number), Number(data.entrance_number),
data.title, data.title,
data.description, data.description,
@@ -101,10 +101,6 @@ class EntrancesService {
`; `;
db.run(sql, [ db.run(sql, [
data.title, data.title,
JSON.stringify(data.points),
JSON.stringify(data.points_number),
data.floors_quantity,
data.apartments_quantity,
data.description, data.description,
Math.floor(new Date(Date.now()).getTime()), Math.floor(new Date(Date.now()).getTime()),
data.id data.id

View File

@@ -0,0 +1,69 @@
const db = require("../config/db");
class historyApartmentService {
getList(limit) {
return new Promise((res, rej) => {
let sql = `
SELECT
ah.*,
s.name AS sheep_name,
s.group_id AS sheep_group_id,
s.icon AS sheep_icon,
h.title AS house_title,
h.number AS house_number,
h.id AS house_id,
e.title AS entrance_title,
a.title AS apartment_title
FROM
apartments_history ah
LEFT JOIN
sheeps s ON s.id = ah.sheep_id
LEFT JOIN
apartments a ON a.id = ah.apartments_id
LEFT JOIN
entrance e ON e.id = a.entrance_id
LEFT JOIN
house h ON h.id = e.house_id
ORDER BY
ah.id DESC
LIMIT ${limit ?? 100};
`;
db.all(sql, (err, rows) => {
if (err) {
console.error(err.message);
return res(false);
} else {
let data = rows.map((row) => {
return {
"id": Number(row.id),
"apartments_id": Number(row.apartments_id),
"house_id": Number(row.house_id),
"address": {
"house": {
"title": row.house_title,
"number": row.house_number
},
"entrance": row.entrance_title,
"apartment": row.apartment_title
},
"status": Number(row.status),
"description": row.description,
"sheep": {
"id": Number(row.sheep_id),
"name": row.sheep_name,
"group_id": Number(row.sheep_group_id),
"icon": row.sheep_icon
},
"created_at": Number(row.created_at)
}
})
return res(data);
}
});
});
}
}
module.exports = new historyApartmentService();

View File

@@ -36,8 +36,6 @@ class HousesService {
}, },
"entrance_number": Number(row.entrance_number), "entrance_number": Number(row.entrance_number),
"title": row.title, "title": row.title,
"points": JSON.parse(row.points),
"points_number": JSON.parse(row.points_number),
"floors_quantity": row.floors_quantity, "floors_quantity": row.floors_quantity,
"apartments_quantity": row.apartments_quantity, "apartments_quantity": row.apartments_quantity,
"description": row.description, "description": row.description,

View File

@@ -1,11 +1,11 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap');
:root { :root {
--FontSize1: 12px; --FontSize1: 12px;
--FontSize2: 13px; --FontSize2: 13px;
--FontSize3: 14px; --FontSize3: 14px;
--FontSize4: 15px; --FontSize4: 15px;
--FontSize5: 16px; --FontSize5: 16px;
} }
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
@@ -100,7 +100,12 @@
} }
} }
a { a,
a:visited,
a:hover,
a:active {
color: inherit;
text-decoration: none;
text-decoration: none; text-decoration: none;
font-size: var(--FontSize3); font-size: var(--FontSize3);
font-weight: 700; font-weight: 700;
@@ -708,7 +713,7 @@ body.modal-open {
padding: 0 !important; padding: 0 !important;
} }
.leaflet-popup-content > .map_dell { .leaflet-popup-content>.map_dell {
border-radius: 10px; border-radius: 10px;
padding: 5px 10px; padding: 5px 10px;
width: 100%; width: 100%;
@@ -737,9 +742,11 @@ body.modal-open {
border: 2px solid #fff; border: 2px solid #fff;
margin: -3px 0 0 -3px; margin: -3px 0 0 -3px;
} }
.leaflet-pm-tooltip { .leaflet-pm-tooltip {
display: none !important; display: none !important;
} }
.tooltip-hidden { .tooltip-hidden {
display: none; display: none;
} }

View File

@@ -79,6 +79,9 @@
<script src="/lib/pages/territory_manager/script.js" defer></script> <script src="/lib/pages/territory_manager/script.js" defer></script>
<link href="/lib/pages/territory_manager/style.css" rel="stylesheet" /> <link href="/lib/pages/territory_manager/style.css" rel="stylesheet" />
<script src="/lib/pages/territory_history/script.js" defer></script>
<link href="/lib/pages/territory_history/style.css" rel="stylesheet" />
<script src="/lib/pages/card/script.js" defer></script> <script src="/lib/pages/card/script.js" defer></script>
<link href="/lib/pages/card/style.css" rel="stylesheet" /> <link href="/lib/pages/card/style.css" rel="stylesheet" />

View File

@@ -799,22 +799,37 @@ const Constructor = {
delete(house) { delete(house) {
// убрать слой с карты // убрать слой с карты
if (Constructor.info.type === 'house') { if (Editor.info.type === 'house') {
houseGroup.removeLayer(house); houseGroup.removeLayer(house);
} else if (Constructor.info.type === 'homestead') { } else if (Editor.info.type === 'homestead') {
homesteadGroup.removeLayer(house); homesteadGroup.removeLayer(house);
} }
// найти индекс полигона в points // найти индекс полигона в points
const index = Constructor.info.points.findIndex(p => p === house.getLatLngs()); const target = house.getLatLngs()[0]; // вершины полигона
if (index !== -1) { const index = Editor.info.points.findIndex((p) => {
// удалить из points и points_number по индексу const copy = p.slice(); // делаем копию
Constructor.info.points.splice(index, 1); copy[0].pop(); // убираем последний элемент
Constructor.info.points_number.splice(index, 1);
if (isSamePolygon(p, target)) return true; // проверка как есть
if (isSamePolygon(copy, target)) return true; // проверка без последнего
return false;
});
function isSamePolygon(a, b) {
if (a.length !== b.length) return false;
return a.every((pt, i) => pt.lat === b[i].lat && pt.lng === b[i].lng);
} }
Constructor.osm.autoZoom(Constructor.info.points);
if (index) {
// удалить из points и points_number по индексу
Editor.info.points.splice(index, 1);
Editor.info.points_number.splice(index, 1);
}
Editor.osm.autoZoom(Editor.info.points);
}, },
async getOSM(wayId) { async getOSM(wayId) {

View File

@@ -6,9 +6,9 @@
margin: 20px 20px 0 20px; margin: 20px 20px 0 20px;
} }
#part-1, .page-constructor>#part-1,
#part-2, .page-constructor>#part-2,
#part-3 { .page-constructor>#part-3 {
border-radius: 10px; border-radius: 10px;
width: calc(100% - 40px); width: calc(100% - 40px);
display: flex; display: flex;
@@ -23,9 +23,9 @@
position: relative; position: relative;
} }
#part-1>h1, .page-constructor>#part-1>h1,
#part-2>h1, .page-constructor>#part-2>h1,
#part-3>h1 { .page-constructor>#part-3>h1 {
width: calc(100% - 40px); width: calc(100% - 40px);
color: var(--ColorThemes3); color: var(--ColorThemes3);
border-radius: var(--border-radius); border-radius: var(--border-radius);
@@ -35,19 +35,19 @@
position: relative; position: relative;
} }
#part-1>h1>span, .page-constructor>#part-1>h1>span,
#part-2>h1>span, .page-constructor>#part-2>h1>span,
#part-3>h1>span { .page-constructor>#part-3>h1>span {
font-weight: 500; font-weight: 500;
} }
#part-1>#info-type { .page-constructor>#part-1>#info-type {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
#part-1>#info-type>.tabs { .page-constructor>#part-1>#info-type>.tabs {
display: flex; display: flex;
position: relative; position: relative;
background-color: var(--ColorThemes0); background-color: var(--ColorThemes0);
@@ -58,11 +58,11 @@
} }
#part-1>#info-type>.tabs>input[type="radio"] { .page-constructor>#part-1>#info-type>.tabs>input[type="radio"] {
display: none; display: none;
} }
#part-1>#info-type>.tabs>.tab { .page-constructor>#part-1>#info-type>.tabs>.tab {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -77,23 +77,23 @@
z-index: 2; z-index: 2;
} }
#part-1>#info-type>.tabs>.tab>svg { .page-constructor>#part-1>#info-type>.tabs>.tab>svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
#part-1>#info-type>.tabs>.tab>span { .page-constructor>#part-1>#info-type>.tabs>.tab>span {
margin-left: 6px; margin-left: 6px;
font-size: var(--FontSize1); font-size: var(--FontSize1);
font-weight: 400; font-weight: 400;
} }
#part-1>#info-type>.tabs>input[type="radio"]:checked+label { .page-constructor>#part-1>#info-type>.tabs>input[type="radio"]:checked+label {
color: var(--PrimaryColorText); color: var(--PrimaryColorText);
fill: var(--PrimaryColorText); fill: var(--PrimaryColorText);
} }
#part-1>#info-type>.tabs>.glider { .page-constructor>#part-1>#info-type>.tabs>.glider {
position: absolute; position: absolute;
display: flex; display: flex;
height: 40px; height: 40px;
@@ -105,47 +105,47 @@
} }
@media (min-width: 601px) { @media (min-width: 601px) {
#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider { .page-constructor>#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider {
transform: translateX(0); transform: translateX(0);
} }
#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider { .page-constructor>#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
transform: translateX(100%); transform: translateX(100%);
} }
#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider { .page-constructor>#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider {
transform: translateX(200%); transform: translateX(200%);
} }
} }
@media (max-width: 600px) { @media (max-width: 600px) {
#part-1>#info-type>.tabs { .page-constructor>#part-1>#info-type>.tabs {
flex-direction: column; flex-direction: column;
} }
#part-1>#info-type>.tabs>.tab { .page-constructor>#part-1>#info-type>.tabs>.tab {
width: calc(100% - 8px); width: calc(100% - 8px);
padding: 0 4px; padding: 0 4px;
} }
#part-1>#info-type>.tabs>.glider { .page-constructor>#part-1>#info-type>.tabs>.glider {
width: calc(100% - 8px); width: calc(100% - 8px);
} }
#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider { .page-constructor>#part-1>#info-type>.tabs>input[id="info-type-house"]:checked~.glider {
transform: translateY(0); transform: translateY(0);
} }
#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider { .page-constructor>#part-1>#info-type>.tabs>input[id="info-type-homestead"]:checked~.glider {
transform: translateY(100%); transform: translateY(100%);
} }
#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider { .page-constructor>#part-1>#info-type>.tabs>input[id="info-type-points"]:checked~.glider {
transform: translateY(200%); transform: translateY(200%);
} }
} }
#part-1>form>div { .page-constructor>#part-1>form>div {
width: 100%; width: 100%;
display: flex; display: flex;
margin: 20px 0; margin: 20px 0;
@@ -153,7 +153,7 @@
flex-direction: column; flex-direction: column;
} }
#part-1>form>div>label { .page-constructor>#part-1>form>div>label {
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
@@ -162,7 +162,7 @@
margin-bottom: 5px; margin-bottom: 5px;
} }
#part-1>form>div>input { .page-constructor>#part-1>form>div>input {
width: calc(100% - 10px); width: calc(100% - 10px);
min-width: 140px; min-width: 140px;
padding: 0 5px; padding: 0 5px;
@@ -173,9 +173,9 @@
font-size: var(--FontSize2); font-size: var(--FontSize2);
} }
#part-1>form>button, .page-constructor>#part-1>form>button,
#part-2>button, .page-constructor>#part-2>button,
#part-3>button { .page-constructor>#part-3>button {
border-radius: 6px; border-radius: 6px;
background: var(--PrimaryColor); background: var(--PrimaryColor);
color: var(--PrimaryColorText); color: var(--PrimaryColorText);
@@ -187,27 +187,27 @@
text-transform: uppercase; text-transform: uppercase;
} }
#part-2>.osm-info { .page-constructor>#part-2>.osm-info {
padding-bottom: 20px; padding-bottom: 20px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
#part-2>.osm-info>div { .page-constructor>#part-2>.osm-info>div {
display: flex; display: flex;
align-items: center; align-items: center;
width: 100%; width: 100%;
} }
#part-2>.osm-info>div { .page-constructor>#part-2>.osm-info>div {
width: 100%; width: 100%;
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
flex-direction: column; flex-direction: column;
} }
#part-2>.osm-info>div>label { .page-constructor>#part-2>.osm-info>div>label {
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
@@ -216,13 +216,13 @@
margin-bottom: 5px; margin-bottom: 5px;
} }
#part-2>.osm-info>div>div { .page-constructor>#part-2>.osm-info>div>div {
display: flex; display: flex;
align-items: center; align-items: center;
width: 100%; width: 100%;
} }
#part-2>.osm-info>div>div>input { .page-constructor>#part-2>.osm-info>div>div>input {
width: calc(100% - 10px); width: calc(100% - 10px);
min-width: 140px; min-width: 140px;
padding: 0 5px; padding: 0 5px;
@@ -233,25 +233,25 @@
font-size: var(--FontSize2); font-size: var(--FontSize2);
} }
#part-2>.osm-info>div>div>a { .page-constructor>#part-2>.osm-info>div>div>a {
height: 26px; height: 26px;
width: 26px; width: 26px;
margin-left: 10px; margin-left: 10px;
} }
#part-2>.osm-info>div>div>a>svg { .page-constructor>#part-2>.osm-info>div>div>a>svg {
height: 26px; height: 26px;
width: 26px; width: 26px;
fill: var(--ColorThemes3); fill: var(--ColorThemes3);
} }
#part-2>.osm-info>span { .page-constructor>#part-2>.osm-info>span {
font-size: var(--FontSize5); font-size: var(--FontSize5);
margin: 10px; margin: 10px;
color: var(--ColorThemes3); color: var(--ColorThemes3);
} }
#part-2>.osm-info>button { .page-constructor>#part-2>.osm-info>button {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -267,7 +267,7 @@
font-size: var(--FontSize3); font-size: var(--FontSize3);
} }
#part-2>.block-map { .page-constructor>#part-2>.block-map {
width: 100%; width: 100%;
height: 500px; height: 500px;
border-radius: 6px; border-radius: 6px;
@@ -279,12 +279,12 @@
box-shadow: var(--shadow-l1); box-shadow: var(--shadow-l1);
} }
#part-2>#map { .page-constructor>#part-2>.block-map>#map {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
#part-3>input { .page-constructor>#part-3>input {
font-weight: 500; font-weight: 500;
position: absolute; position: absolute;
right: 0; right: 0;
@@ -298,12 +298,12 @@
width: 40px; width: 40px;
} }
#part-3>#house { .page-constructor>#part-3>#house {
display: flex; display: flex;
overflow: auto; overflow: auto;
} }
#part-3>#house>button { .page-constructor>#part-3>#house>button {
display: flex; display: flex;
position: relative; position: relative;
width: 34px; width: 34px;
@@ -319,14 +319,14 @@
cursor: pointer; cursor: pointer;
} }
#part-3>#house>button>svg { .page-constructor>#part-3>#house>button>svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: var(--PrimaryColorText); fill: var(--PrimaryColorText);
transform: rotate(45deg); transform: rotate(45deg);
} }
#part-3>#house>.entrance { .page-constructor>#part-3>#house>.entrance {
min-height: 200px; min-height: 200px;
border: 1px solid var(--ColorThemes3); border: 1px solid var(--ColorThemes3);
border-style: dashed; border-style: dashed;
@@ -334,7 +334,7 @@
margin: 0 10px 10px 0; margin: 0 10px 10px 0;
} }
#part-3>#house>.entrance>.entrance-info>input { .page-constructor>#part-3>#house>.entrance>.entrance-info>input {
text-align: center; text-align: center;
font-size: var(--FontSize5); font-size: var(--FontSize5);
font-weight: 400; font-weight: 400;
@@ -346,8 +346,8 @@
width: calc(100% - 14px - 20px); width: calc(100% - 14px - 20px);
} }
#part-3>#house>.entrance>.entrance-info>button, .page-constructor>#part-3>#house>.entrance>.entrance-info>button,
#part-3>#house>.entrance>.floor>.floor-info>button { .page-constructor>#part-3>#house>.entrance>.floor>.floor-info>button {
display: flex; display: flex;
position: relative; position: relative;
width: 34px; width: 34px;
@@ -362,15 +362,15 @@
cursor: pointer; cursor: pointer;
} }
#part-3>#house>.entrance>.entrance-info>button>svg, .page-constructor>#part-3>#house>.entrance>.entrance-info>button>svg,
#part-3>#house>.entrance>.floor>.floor-info>button>svg { .page-constructor>#part-3>#house>.entrance>.floor>.floor-info>button>svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: var(--PrimaryColorText); fill: var(--PrimaryColorText);
transform: rotate(45deg); transform: rotate(45deg);
} }
#part-3>#house>.entrance>.floor { .page-constructor>#part-3>#house>.entrance>.floor {
position: relative; position: relative;
display: flex; display: flex;
width: calc(100% - 22px); width: calc(100% - 22px);
@@ -379,7 +379,7 @@
border-radius: 4px; border-radius: 4px;
} }
#part-3>#house>.entrance>.floor>.floor-info>h2 { .page-constructor>#part-3>#house>.entrance>.floor>.floor-info>h2 {
position: absolute; position: absolute;
width: 65px; width: 65px;
right: -1px; right: -1px;
@@ -393,7 +393,7 @@
text-align: center; text-align: center;
} }
#part-3>#house>.entrance>.floor>.apartment { .page-constructor>#part-3>#house>.entrance>.floor>.apartment {
display: flex; display: flex;
position: relative; position: relative;
width: 60px; width: 60px;
@@ -406,7 +406,7 @@
justify-content: center; justify-content: center;
} }
#part-3>#house>.entrance>.floor>.apartment>input { .page-constructor>#part-3>#house>.entrance>.floor>.apartment>input {
width: 50px; width: 50px;
height: 50px; height: 50px;
font-size: var(--FontSize5); font-size: var(--FontSize5);
@@ -416,7 +416,7 @@
background: 0; background: 0;
} }
#part-3>#house>.entrance>.floor>.apartment>button { .page-constructor>#part-3>#house>.entrance>.floor>.apartment>button {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
@@ -433,22 +433,22 @@
justify-content: center; justify-content: center;
} }
#part-3>#house>.entrance>.floor>.apartment>button>svg { .page-constructor>#part-3>#house>.entrance>.floor>.apartment>button>svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
fill: var(--PrimaryColorText); fill: var(--PrimaryColorText);
} }
#part-3>.info {} .page-constructor>#part-3>.info {}
#part-3>.info>p { .page-constructor>#part-3>.info>p {
font-size: var(--FontSize2); font-size: var(--FontSize2);
color: var(--ColorThemes3); color: var(--ColorThemes3);
opacity: 0.8; opacity: 0.8;
font-style: oblique; font-style: oblique;
} }
#part-3>.info>button { .page-constructor>#part-3>.info>button {
border-radius: 6px; border-radius: 6px;
background: var(--ColorThemes3); background: var(--ColorThemes3);
width: fit-content; width: fit-content;
@@ -464,14 +464,14 @@
cursor: pointer; cursor: pointer;
} }
#part-3>.info>button>svg { .page-constructor>#part-3>.info>button>svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: var(--ColorThemes0); fill: var(--ColorThemes0);
margin-right: 10px; margin-right: 10px;
} }
#part-3>.info>button>span { .page-constructor>#part-3>.info>button>span {
font-size: var(--FontSize3); font-size: var(--FontSize3);
font-weight: 400; font-weight: 400;
color: var(--ColorThemes0); color: var(--ColorThemes0);

View File

@@ -1,89 +1,84 @@
<div class="page-editor"> <div class="page-editor">
<details id="details-info" open> <div id="part-1" class="part_block">
<summary> <h1>
<span>Крок 1.</span> Інформація про будинок, територію, точки на карті <span>Крок 1.</span> Інформація про будинок, територію, точки на карті
</summary> </h1>
<form id="info-form"> <form id="info-form">
<div id="details-info-address" class="details-info-input"> <div>
<label for="info-address-title">Назва вулиці</label> <label for="info-title">Назва вулиці</label>
<input <input
type="text" type="text"
id="info-address-title" id="info-title"
name="address" name="address"
required required
value="" value=""
/> />
</div> </div>
<div id="details-info-number" class="details-info-input"> <div>
<label for="info-number-title">Номер будинку</label> <label for="info-number">Номер будинку / частини</label>
<input <input type="text" id="info-number" name="number" required value="" />
type="text"
id="info-number-title"
name="number"
required
value=""
/>
</div> </div>
<div id="details-info-settlement" class="details-info-input"> <div>
<label for="info-settlement-title">Місто</label> <label for="info-settlement">Місто</label>
<input <input
type="text" type="text"
id="info-settlement-title" id="info-settlement"
name="settlement" name="settlement"
required required
value="" value="Тернопіль"
/> />
</div> </div>
</form> </form>
</details> </div>
<details id="details-map" open> <div id="part-2" class="part_block">
<summary id="details-map-title"><span>Крок 2.</span> Перегляд</summary> <h1 id="part-2-title"><span>Крок 2.</span> Створення будинку / ділянки</h1>
<form id="map-form">
<div <div class="osm-info">
class="editor-buttons" <div>
id="details-map-buttons-homestead" <label for="info-osm">OSM iD</label>
style="display: none" <div>
> <input
id="info-osm"
type="text"
placeholder="123, 345, 678"
onchange="Editor.osm.autoPoligon(this.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"
></path>
</svg>
</a>
</div>
</div> </div>
<span>або</span>
<button onclick="Editor.osm.newPoligon()">Обрати на карті</button>
</div>
<div class="block-map"> <div class="block-map">
<button <div id="map"></div>
type="button" </div>
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>
</form>
</details>
<details id="details-area" open style="display: none"> <button type="button" id="part-2-button" onclick="Editor.save()">Зберегти</button>
<summary> </div>
<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="part-3" class="part_block" style="display: none">
<div id="list-area"></div> <h1 id="part-3-title"><span>Крок 3.</span> Створення квартир</h1>
</form>
</details> <div id="house"></div>
</div>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@@ -6,21 +6,11 @@
margin: 20px 20px 0 20px; margin: 20px 20px 0 20px;
} }
.page-editor form>button { .page-editor>#part-1,
border-radius: 6px; .page-editor>#part-2,
background: var(--PrimaryColor); .page-editor>#part-3 {
color: var(--PrimaryColorText);
width: 100%;
height: 40px;
font-size: var(--FontSize3);
font-weight: 400;
margin: 20px 0;
text-transform: uppercase;
}
.page-editor details {
border-radius: 10px; border-radius: 10px;
width: 100%; width: calc(100% - 40px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
@@ -29,36 +19,169 @@
color: var(--ColorThemes3); color: var(--ColorThemes3);
border: 1px solid var(--ColorThemes2); border: 1px solid var(--ColorThemes2);
box-shadow: var(--shadow-l1); box-shadow: var(--shadow-l1);
padding: 0 20px;
position: relative;
} }
.page-editor>details[disabled] summary, .page-editor>#part-1>h1,
.page-editor>details.disabled summary { .page-editor>#part-2>h1,
pointer-events: none; .page-editor>#part-3>h1 {
user-select: none;
}
.page-editor>details summary::-webkit-details-marker,
.page-editor>details summary::marker {
display: none;
content: "";
}
.page-editor summary {
width: calc(100% - 40px); width: calc(100% - 40px);
cursor: pointer;
color: var(--ColorThemes3); color: var(--ColorThemes3);
border-radius: var(--border-radius); border-radius: var(--border-radius);
font-size: var(--FontSize5); font-size: var(--FontSize5);
font-weight: 300; font-weight: 300;
padding: 20px; padding: 20px 0;
position: relative; position: relative;
} }
.page-editor summary span { .page-editor>#part-1>h1>span,
.page-editor>#part-2>h1>span,
.page-editor>#part-3>h1>span {
font-weight: 500; font-weight: 500;
} }
.page-editor summary input { .page-editor>#part-1>form>div {
width: 100%;
display: flex;
margin: 0 0 20px 0;
align-items: flex-start;
flex-direction: column;
}
.page-editor>#part-1>form>div>label {
display: flex;
justify-content: center;
flex-direction: column;
font-size: var(--FontSize1);
font-weight: 500;
margin-bottom: 5px;
}
.page-editor>#part-1>form>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-editor>#part-1>form>button,
.page-editor>#part-2>button,
.page-editor>#part-3>button {
border-radius: 6px;
background: var(--PrimaryColor);
color: var(--PrimaryColorText);
width: 100%;
height: 40px;
font-size: var(--FontSize3);
font-weight: 400;
margin: 0 0 20px 0;
text-transform: uppercase;
}
.page-editor>#part-2>.osm-info {
padding-bottom: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.page-editor>#part-2>.osm-info>div {
display: flex;
align-items: center;
width: 100%;
}
.page-editor>#part-2>.osm-info>div {
width: 100%;
display: flex;
align-items: flex-start;
flex-direction: column;
}
.page-editor>#part-2>.osm-info>div>label {
display: flex;
justify-content: center;
flex-direction: column;
font-size: var(--FontSize1);
font-weight: 500;
margin-bottom: 5px;
}
.page-editor>#part-2>.osm-info>div>div {
display: flex;
align-items: center;
width: 100%;
}
.page-editor>#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-editor>#part-2>.osm-info>div>div>a {
height: 26px;
width: 26px;
margin-left: 10px;
}
.page-editor>#part-2>.osm-info>div>div>a>svg {
height: 26px;
width: 26px;
fill: var(--ColorThemes3);
}
.page-editor>#part-2>.osm-info>span {
font-size: var(--FontSize5);
margin: 10px;
color: var(--ColorThemes3);
}
.page-editor>#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);
}
.page-editor>#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);
margin-bottom: 20px;
}
.page-editor>#part-2>.block-map>#map {
width: 100%;
height: 100%;
}
.page-editor>#part-3>input {
font-weight: 500; font-weight: 500;
position: absolute; position: absolute;
right: 0; right: 0;
@@ -72,177 +195,49 @@
width: 40px; width: 40px;
} }
.page-editor #info-form, .page-editor>#part-3>#house {
.page-editor #map-form,
.page-editor #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-editor .details-info-input {
width: 100%;
display: flex;
margin: 20px 0;
align-items: flex-start;
flex-direction: column;
}
.page-editor .details-info-input label {
display: flex;
justify-content: center;
flex-direction: column;
font-size: var(--FontSize1);
font-weight: 500;
margin-bottom: 5px;
}
.page-editor .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-editor #details-info-osm div {
display: flex;
align-items: center;
width: 100%;
}
.page-editor #details-info-osm input {
width: calc(100% - 10px);
min-width: 140px;
padding: 0 5px;
border-radius: 6px;
height: 30px;
}
.page-editor .details-info-input a {
height: 26px;
width: 26px;
margin-left: 10px;
}
.page-editor .details-info-input a>svg {
height: 26px;
width: 26px;
fill: var(--ColorThemes3)
}
.page-editor #list-area {
display: flex; display: flex;
overflow: auto; overflow: auto;
margin: 15px 0 20px 0;
} }
.page-editor #list-area h3 { .page-editor>#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;
}
.page-editor>#part-3>#house>button>svg {
width: 20px;
height: 20px;
fill: var(--PrimaryColorText);
transform: rotate(45deg);
}
.page-editor>#part-3>#house>.entrance {
min-height: 200px;
border: 1px solid var(--ColorThemes3);
border-style: dashed;
border-radius: 6px;
margin: 0 10px 10px 0;
}
.page-editor>#part-3>#house>.entrance>.entrance-info>.entrance-header {
display: flex;
align-items: center;
min-width: 180px;
}
.page-editor>#part-3>#house>.entrance>.entrance-info>.entrance-header>input {
text-align: center; text-align: center;
font-size: var(--FontSize5); font-size: var(--FontSize5);
font-weight: 400; font-weight: 400;
@@ -251,18 +246,29 @@
color: var(--ColorThemes0); color: var(--ColorThemes0);
background: var(--ColorThemes3); background: var(--ColorThemes3);
border-radius: 4px; border-radius: 4px;
width: calc(100% - 14px - 20px);
} }
.block-area { .page-editor>#part-3>#house>.entrance>.entrance-info>.entrance-header>button {
min-height: 200px; display: flex;
border: 1px solid var(--ColorThemes3); margin: 10px 10px 10px 0px;
border-style: dashed; border-radius: 4px;
border-radius: 6px; min-width: 33px;
margin: 0 10px 10px 0; min-height: 33px;
align-items: center;
justify-content: center;
cursor: pointer;
} }
.addFloors, .page-editor>#part-3>#house>.entrance>.entrance-info>.entrance-header>button>svg {
.addApartment { width: 16px;
height: 16px;
fill: #C14D4D;
}
.page-editor>#part-3>#house>.entrance>.entrance-info>button,
.page-editor>#part-3>#house>.entrance>.floor>.floor-info>button {
display: flex; display: flex;
position: relative; position: relative;
width: 34px; width: 34px;
@@ -277,15 +283,15 @@
cursor: pointer; cursor: pointer;
} }
.addFloors>svg, .page-editor>#part-3>#house>.entrance>.entrance-info>button>svg,
.addApartment>svg { .page-editor>#part-3>#house>.entrance>.floor>.floor-info>button>svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: var(--PrimaryColorText); fill: var(--PrimaryColorText);
transform: rotate(45deg); transform: rotate(45deg);
} }
.block-apartments-floors { .page-editor>#part-3>#house>.entrance>.floor {
position: relative; position: relative;
display: flex; display: flex;
width: calc(100% - 22px); width: calc(100% - 22px);
@@ -294,7 +300,7 @@
border-radius: 4px; border-radius: 4px;
} }
.block-apartments-floors h2 { .page-editor>#part-3>#house>.entrance>.floor>.floor-info>h2 {
position: absolute; position: absolute;
width: 65px; width: 65px;
right: -1px; right: -1px;
@@ -308,7 +314,7 @@
text-align: center; text-align: center;
} }
.block-apartments-number { .page-editor>#part-3>#house>.entrance>.floor>.apartment {
display: flex; display: flex;
position: relative; position: relative;
width: 60px; width: 60px;
@@ -321,7 +327,7 @@
justify-content: center; justify-content: center;
} }
.block-apartments-number input { .page-editor>#part-3>#house>.entrance>.floor>.apartment>input {
width: 50px; width: 50px;
height: 50px; height: 50px;
font-size: var(--FontSize5); font-size: var(--FontSize5);
@@ -331,7 +337,7 @@
background: 0; background: 0;
} }
.block-apartments-number button { .page-editor>#part-3>#house>.entrance>.floor>.apartment>button {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
@@ -348,189 +354,45 @@
justify-content: center; justify-content: center;
} }
.block-apartments-number button>svg { .page-editor>#part-3>#house>.entrance>.floor>.apartment>button>svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
fill: var(--PrimaryColorText); fill: var(--PrimaryColorText);
} }
.page-editor>#part-3>.info {}
.block-map { .page-editor>#part-3>.info>p {
width: 100%; font-size: var(--FontSize2);
height: 500px;
border-radius: 6px;
overflow: hidden;
margin-bottom: 20px;
position: relative;
background: var(--ColorThemes1);
color: var(--ColorThemes3); color: var(--ColorThemes3);
border: 1px solid var(--ColorThemes2); opacity: 0.8;
box-shadow: var(--shadow-l1); font-style: oblique;
} }
#homestead-editing { .page-editor>#part-3>.info>button {
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; 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 {
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); background: var(--ColorThemes3);
color: var(--ColorThemes1); width: fit-content;
width: 100%; height: 40px;
margin: 0; padding: 0 10px;
border-radius: 6px; margin-bottom: 20px;
text-transform: uppercase; text-transform: uppercase;
font-weight: 400;
font-size: var(--FontSize1);
}
.page-editor #list-entranse,
.page-editor #list-homestead {
width: 100%;
min-height: 86px;
display: flex; display: flex;
flex-direction: row; 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;
position: relative;
}
.page-editor #list-entranse>.house,
.page-editor #list-homestead>.house {
display: flex;
position: relative;
width: 60px;
height: 60px;
min-width: 60px;
min-height: 60px;
background: var(--ColorThemes1);
border: 2px solid var(--PrimaryColor);
margin: 10px;
border-radius: 4px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer;
} }
.page-editor>#part-3>.info>button>svg {
.page-editor #list-entranse>.house>input,
.page-editor #list-homestead>.house>input,
.page-editor #list-entranse>.house>p,
.page-editor #list-homestead>.house>p {
width: 50px;
height: 50px;
font-size: var(--FontSize5);
font-weight: 400;
text-align: center;
color: var(--ColorThemes3);
background: 0;
display: flex;
align-items: center;
justify-content: center;
}
.page-editor #list-entranse>.house>button,
.page-editor #list-homestead>.house>button {
position: absolute;
top: 0;
right: 0;
width: 20px; width: 20px;
height: 20px; height: 20px;
border-radius: 0 4px 0 4px; fill: var(--ColorThemes0);
background: var(--PrimaryColor); margin-right: 10px;
font-size: var(--FontSize5);
margin: -2px;
border: 0;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
} }
.page-editor #list-entranse>.house>button>svg, .page-editor>#part-3>.info>button>span {
.page-editor #list-homestead>.house>button>svg { font-size: var(--FontSize3);
width: 16px; font-weight: 400;
height: 16px; color: var(--ColorThemes0);
fill: var(--PrimaryColorText);
} }

View File

@@ -0,0 +1,89 @@
<div class="page-editor">
<details id="details-info" open>
<summary>
<span>Крок 1.</span> Інформація про будинок, територію, точки на карті
</summary>
<form id="info-form">
<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>
</form>
</details>
<details id="details-map" open>
<summary id="details-map-title"><span>Крок 2.</span> Перегляд</summary>
<form id="map-form">
<div
class="editor-buttons"
id="details-map-buttons-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>
</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>
<form id="area-form">
<div id="list-area"></div>
</form>
</details>
</div>

View File

@@ -0,0 +1,636 @@
const Editor = {
async init(type, id) {
let html = await fetch('/lib/pages/editor/index.html').then((response) => response.text());
app.innerHTML = html;
map = "";
houseGroup = "";
entransePolygonsGroup = "";
entranseNumPolygonsGroup = "";
splitPolygonsGroup = "";
RectangleGroup = "";
numApartments = 1;
Editor.info.setHTML(type, id);
},
async loadAPI(URL) {
let uuid = localStorage.getItem("uuid");
return await fetch(URL, {
method: 'GET',
headers: {
"Content-Type": "application/json",
"Authorization": uuid
}
}).then((response) => response.json());
},
info: {
list: {
type: null, title: null, number: null,
points: [], points_number: [], point_icons: [],
geo: [], osm_id: [], settlement: [], description: null,
entrance: [], apartments: {}
},
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);
els.title.value = this.list.title;
els.number.value = this.list.number;
els.settlement.value = this.list.settlement;
Editor.osm.init();
this.setMap();
if (type == "house") {
Editor.entrances.setHTML(id);
document.getElementById('details-area').style.display = "";
} else if (type == "homestead") {
Editor.homestead.init(id);
}
},
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([this.list.geo.lat, this.list.geo.lng], this.list.zoom);
L.polygon(element, {
color: "#f2bd53",
radius: 500,
fillOpacity: 0.3,
dashArray: '20,15',
dashOffset: '20',
}).addTo(houseGroup);
} else if (Editor.info.list.type == "house") {
map.setView([this.list.geo.lat, this.list.geo.lng], this.list.zoom);
L.polygon(element, {
color: "#585858",
fillColor: "#f2bd53",
fillOpacity: 0.8,
tm_id: `house_${i}`
}).addTo(houseGroup);
}
}
}
},
osm: {
init() {
const googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
});
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();
entransePolygonsGroup = new L.FeatureGroup();
entranseNumPolygonsGroup = new L.FeatureGroup();
map = L.map('map', {
renderer: L.canvas(), zoom: 17,
layers: [googleHybrid, osm, mytile, houseGroup,
entransePolygonsGroup, entranseNumPolygonsGroup,
splitPolygonsGroup, RectangleGroup],
zoomControl: false
});
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,
drawPolyline: false,
drawPolygon: false,
drawRectangle: false,
drawCircle: false,
drawText: false,
drawMarker: false,
cutPolygon: false,
tooltips: false
});
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("Натискаючи на карту будуть створюватись нові точки (будинки)");
},
}
}

View File

@@ -0,0 +1,536 @@
.page-editor {
width: calc(100% - 40px);
display: flex;
flex-direction: column;
align-items: center;
margin: 20px 20px 0 20px;
}
.page-editor 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-editor 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-editor>details[disabled] summary,
.page-editor>details.disabled summary {
pointer-events: none;
user-select: none;
}
.page-editor>details summary::-webkit-details-marker,
.page-editor>details summary::marker {
display: none;
content: "";
}
.page-editor 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-editor summary span {
font-weight: 500;
}
.page-editor 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-editor #info-form,
.page-editor #map-form,
.page-editor #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-editor .details-info-input {
width: 100%;
display: flex;
margin: 20px 0;
align-items: flex-start;
flex-direction: column;
}
.page-editor .details-info-input label {
display: flex;
justify-content: center;
flex-direction: column;
font-size: var(--FontSize1);
font-weight: 500;
margin-bottom: 5px;
}
.page-editor .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-editor #details-info-osm div {
display: flex;
align-items: center;
width: 100%;
}
.page-editor #details-info-osm input {
width: calc(100% - 10px);
min-width: 140px;
padding: 0 5px;
border-radius: 6px;
height: 30px;
}
.page-editor .details-info-input a {
height: 26px;
width: 26px;
margin-left: 10px;
}
.page-editor .details-info-input a>svg {
height: 26px;
width: 26px;
fill: var(--ColorThemes3)
}
.page-editor #list-area {
display: flex;
overflow: auto;
margin: 15px 0 20px 0;
}
.page-editor #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;
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 {
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-editor #list-entranse,
.page-editor #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;
position: relative;
}
.page-editor #list-entranse>.house,
.page-editor #list-homestead>.house {
display: flex;
position: relative;
width: 60px;
height: 60px;
min-width: 60px;
min-height: 60px;
background: var(--ColorThemes1);
border: 2px solid var(--PrimaryColor);
margin: 10px;
border-radius: 4px;
align-items: center;
justify-content: center;
}
.page-editor #list-entranse>.house>input,
.page-editor #list-homestead>.house>input,
.page-editor #list-entranse>.house>p,
.page-editor #list-homestead>.house>p {
width: 50px;
height: 50px;
font-size: var(--FontSize5);
font-weight: 400;
text-align: center;
color: var(--ColorThemes3);
background: 0;
display: flex;
align-items: center;
justify-content: center;
}
.page-editor #list-entranse>.house>button,
.page-editor #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-editor #list-entranse>.house>button>svg,
.page-editor #list-homestead>.house>button>svg {
width: 16px;
height: 16px;
fill: var(--PrimaryColorText);
}

View File

@@ -15,9 +15,27 @@
</a> </a>
<button onclick="Territory.report()"> <button onclick="Territory.report()">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M13.13,2H5.958c-1.1,0-2,0.9-2,2v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8.828c0-0.53-0.211-1.039-0.586-1.414l-4.828-4.828 C14.169,2.211,13.66,2,13.13,2z M11.255,17.711l-1.297-1.297l-1.251,1.293c-0.39,0.39-1.024,0.39-1.414,0l0,0 c-0.39-0.39-0.39-1.024,0-1.414l1.958-1.989c0.39-0.396,1.027-0.398,1.42-0.006l1.287,1.287l2.335-2.293 c0.39-0.39,1.024-0.39,1.414,0l0,0c0.39,0.39,0.39,1.024,0,1.414l-3.042,3.008C12.274,18.102,11.644,18.1,11.255,17.711z M12.958,9 V3.5l5.5,5.5H12.958z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<span>Звіт опрацьовання</span> <path
d="M13.13,2H5.958c-1.1,0-2,0.9-2,2v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8.828c0-0.53-0.211-1.039-0.586-1.414l-4.828-4.828 C14.169,2.211,13.66,2,13.13,2z M11.255,17.711l-1.297-1.297l-1.251,1.293c-0.39,0.39-1.024,0.39-1.414,0l0,0 c-0.39-0.39-0.39-1.024,0-1.414l1.958-1.989c0.39-0.396,1.027-0.398,1.42-0.006l1.287,1.287l2.335-2.293 c0.39-0.39,1.024-0.39,1.414,0l0,0c0.39,0.39,0.39,1.024,0,1.414l-3.042,3.008C12.274,18.102,11.644,18.1,11.255,17.711z M12.958,9 V3.5l5.5,5.5H12.958z"
/>
</svg>
<span>Звіт опрацьовання</span>
</button> </button>
<a
href="/territory/history"
data-route
id="historyButton"
style="display: none"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<path
d="M 8.5 4 A 1.50015 1.50015 0 0 0 7.0761719 5.9746094 L 9.0761719 11.974609 A 1.50015 1.50015 0 0 0 10.5 13 L 13.025391 13 C 13.01166 13.081566 13 13.164544 13 13.25 C 13 17.87 15.519516 21.898375 19.228516 23.984375 C 15.518516 26.028375 13 29.974 13 34.5 C 13 34.676122 13.036016 34.84296 13.091797 35 L 10.5 35 A 1.50015 1.50015 0 0 0 9.0761719 36.025391 L 7.0761719 42.025391 A 1.50015 1.50015 0 0 0 8.5 44 L 41.5 44 A 1.50015 1.50015 0 0 0 42.923828 42.025391 L 40.923828 36.025391 A 1.50015 1.50015 0 0 0 39.5 35 L 36.908203 35 C 36.963984 34.84296 37 34.676122 37 34.5 C 37 29.974 34.480484 26.028375 30.771484 23.984375 C 34.480484 21.898375 37 17.87 37 13.25 C 37 13.164544 36.98834 13.081566 36.974609 13 L 39.5 13 A 1.50015 1.50015 0 0 0 40.923828 11.974609 L 42.923828 5.9746094 A 1.50015 1.50015 0 0 0 41.5 4 L 8.5 4 z M 15.974609 13 L 34.025391 13 C 34.01166 13.081566 34 13.164544 34 13.25 C 34 18.003 30.493 21.926453 26 22.439453 L 26 25.558594 C 30.493 26.058594 34 29.876 34 34.5 C 34 34.676122 34.036016 34.84296 34.091797 35 L 15.908203 35 C 15.963984 34.84296 16 34.676122 16 34.5 C 16 29.875 19.507 26.057594 24 25.558594 L 24 22.439453 C 19.507 21.926453 16 18.002 16 13.25 C 16 13.164544 15.98834 13.081566 15.974609 13 z M 28.554688 18 C 26.811688 18 23.189312 17.999859 21.445312 18.005859 C 21.284312 18.005859 21.140937 18.107766 21.085938 18.259766 C 21.030938 18.411766 21.075219 18.580594 21.199219 18.683594 C 22.240219 19.507594 23.563 20 25 20 C 26.437 20 27.757688 19.507453 28.804688 18.689453 C 28.930688 18.584453 28.977875 18.412813 28.921875 18.257812 C 28.865875 18.102813 28.718688 18 28.554688 18 z M 25 28 C 22.215 28 19.866719 29.847234 19.136719 32.365234 C 19.097719 32.517234 19.129562 32.680687 19.226562 32.804688 C 19.322563 32.928687 19.471906 33 19.628906 33 C 21.700906 33 28.298094 32.999234 30.371094 32.990234 C 30.525094 32.990234 30.670625 32.920828 30.765625 32.798828 C 30.860625 32.676828 30.893469 32.517187 30.855469 32.367188 C 30.133469 29.848187 27.784 28 25 28 z"
/>
</svg>
<span>Історія служіння</span>
</a>
</div> </div>
<div class="list-controls"> <div class="list-controls">

View File

@@ -9,6 +9,7 @@ const Territory = {
if (USER.mode == 2) { if (USER.mode == 2) {
document.getElementById("buttons-list").style.display = "flex"; document.getElementById("buttons-list").style.display = "flex";
document.getElementById("historyButton").style.display = "";
} }
if (USER.possibilities.can_add_territory) { if (USER.possibilities.can_add_territory) {
document.getElementById("buttons-list").style.display = "flex"; document.getElementById("buttons-list").style.display = "flex";

View File

@@ -0,0 +1,3 @@
<div class="page-territory_history">
<div id="list"></div>
</div>

View File

@@ -0,0 +1,82 @@
const Territory_History = {
list: [],
async init() {
let html = await fetch('/lib/pages/territory_history/index.html').then((response) => response.text());
app.innerHTML = html;
this.setHTML()
},
async loadAPI(url) {
const uuid = localStorage.getItem("uuid");
const response = await fetch(url, {
method: 'GET',
headers: {
"Content-Type": "application/json",
"Authorization": uuid
}
});
return await response.json();
},
async setHTML() {
const block_list = document.getElementById('list');
const url = `${CONFIG.api}history/apartments/list?limit=5000`;
let list = this.list.length > 0 ? this.list : await this.loadAPI(url);
list.sort((a, b) => b.id - a.id);
let html = "";
for (const element of list) {
html += this.renderCard({ element });
}
block_list.innerHTML = html;
},
renderCard: ({ element }) => {
console.log(element);
const labels = ["", "Відмова (Не цікавить)", "Не заходити (Груба відмова)", "Нема домофона", "Повторна відвідина", "Немає вдома", "Свідки Єгови"];
const color_status = [
["var(--ColorThemes2)", "var(--ColorThemes3)"],
["#fbf1e0", "#ff8300"],
["#fce3e2", "#ff0000"],
["#d7ddec", "#2919bd"],
["#d5e9dd", "#11a568"],
["#d7ebfa", "#3fb4fc"],
["#e8dbf5", "#b381eb"]
];
const [bg, color] = color_status[element.status];
let description = element.description
? `<div class="description"><p>${element.description}</p></div>`
: ``;
return `
<div class="card" style="background:${bg};color:${color};border:1px solid ${color}">
<div class="info">
<a href="/territory/card/house/${element.house_id}" class="address">
<p title="${element.address.entrance}">${element.address.house.title} ${element.address.house.number}</p>
</a>
<div class="apartment">
<p>кв. ${element.address.apartment}</p>
</div>
<div class="status">
<p>${labels[element.status]}</p>
</div>
<a href="/sheeps/${element.sheep.id}" class="name">
<p>${element.sheep.name}</p>
</a>
<div class="date">
<p>${formattedDateTime(element.created_at)}</p>
</div>
</div>
${description}
</div>
`;
},
}

View File

@@ -0,0 +1,71 @@
.page-territory_history {
width: calc(100% - 18px);
display: flex;
flex-direction: row;
margin: 20px 9px 0 9px;
justify-content: space-between;
position: relative;
}
.page-territory_history>#list {
width: 100%;
}
.page-territory_history>#list>.card {
display: flex;
width: calc(100% - 2px);
background: var(--ColorThemes1);
border: 1px solid var(--ColorThemes2);
border-radius: var(--border-radius);
margin-bottom: 10px;
flex-direction: column;
position: relative;
}
.page-territory_history>#list>.card>.info {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px;
}
.page-territory_history>#list>.card>.info>div {
text-align: center;
}
.page-territory_history>#list>.card>.info>div>a,
.page-territory_history>#list>.card>.info>div>p {
font-size: var(--FontSize3);
}
.page-territory_history>#list>.card>.info>.address {
width: 20%;
text-align: left;
}
.page-territory_history>#list>.card>.info>.apartment {
width: 60px;
}
.page-territory_history>#list>.card>.info>.status {
width: 180px;
}
.page-territory_history>#list>.card>.info>.name {
width: 150px;
text-align: center;
}
.page-territory_history>#list>.card>.info>.date {
width: 125px;
}
.page-territory_history>#list>.card>.description {
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 10px 10px 10px;
background: var(--ColorThemes0);
padding: 10px;
border-radius: 8px;
}

View File

@@ -15,6 +15,10 @@ Router
pageActive(); pageActive();
Card.init(type, id); Card.init(type, id);
}) })
.add('territory/history', function () {
pageActive();
Territory_History.init();
})
.add('territory', function () { .add('territory', function () {
pageActive('territory'); pageActive('territory');
Territory.init(); Territory.init();

View File

@@ -108,7 +108,7 @@ function updateDatabase(message) {
Number(message.data.status), Number(message.data.status),
message.data.description, message.data.description,
message.data.sheep_id, message.data.sheep_id,
message.data.updated_at Math.floor(Date.now())
], function (err) { ], function (err) {
if (err) { if (err) {
console.error(err.message); console.error(err.message);
@@ -144,7 +144,7 @@ function updateDatabase(message) {
Number(message.data.status), Number(message.data.status),
message.data.description, message.data.description,
message.data.sheep_id, message.data.sheep_id,
message.data.updated_at Math.floor(Date.now())
], function (err) { ], function (err) {
if (err) { if (err) {
console.error(err.message); console.error(err.message);