v1.0.0
This commit is contained in:
@@ -15,14 +15,6 @@
|
||||
background-size: 0.55rem auto;
|
||||
}
|
||||
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
#header p {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -76,7 +68,7 @@
|
||||
summary p {
|
||||
padding: 0 10px;
|
||||
color: var(--PrimaryColorText);
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
font-weight: 500;
|
||||
}
|
||||
summary svg {
|
||||
@@ -98,9 +90,16 @@
|
||||
padding: 1px;
|
||||
}
|
||||
}
|
||||
.apartments_list > div {
|
||||
.apartments_list > p {
|
||||
font-size: var(--FontSize5);
|
||||
text-align: center;
|
||||
color: var(--ColorThemes3);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card_info {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
border-radius: 8px;
|
||||
margin: 10px 10px 15px 10px;
|
||||
flex-direction: column;
|
||||
@@ -108,20 +107,24 @@
|
||||
border: 1px solid var(--ColorThemes3);
|
||||
background: var(--ColorThemes2);
|
||||
}
|
||||
.apartments_list > div > .info {
|
||||
.card_info_homestead {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.card_info > .info {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.apartments_list > div > .info > span {
|
||||
.card_info > .info > span {
|
||||
min-width: 40px;
|
||||
font-size: 12px;
|
||||
font-size: var(--FontSize1);
|
||||
position: relative;
|
||||
margin: 5px;
|
||||
}
|
||||
.apartments_list > div > .info > select {
|
||||
.card_info > .info > select {
|
||||
color: #3d3d3d;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #eaebef;
|
||||
@@ -129,28 +132,38 @@
|
||||
background-color: var(--ColorThemes3);
|
||||
min-width: 110px;
|
||||
width: 100%;
|
||||
padding: 4px 20px 4px 4px;
|
||||
padding: 4px;
|
||||
height: 30px;
|
||||
}
|
||||
.apartments_list > div > .info > input {
|
||||
color: #3d3d3d;
|
||||
.card_info > .info > input,
|
||||
.card_info > .info > button {
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #eaebef;
|
||||
margin: 5px;
|
||||
background-color: var(--ColorThemes3);
|
||||
background-color: var(--ColorThemes0);
|
||||
border: 1px solid var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
width: 100%;
|
||||
max-width: 170px;
|
||||
min-width: 70px;
|
||||
padding: 0 4px;
|
||||
height: calc(30px - 2px);
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
}
|
||||
.apartments_list > div > textarea {
|
||||
.card_info > .info > button > svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
fill: var(--ColorThemes3);
|
||||
}
|
||||
.card_info > textarea {
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-size: var(--FontSize3);
|
||||
margin: 5px;
|
||||
background-color: var(--ColorThemes0);
|
||||
border: 1px solid var(--ColorThemes1);
|
||||
@@ -163,13 +176,231 @@
|
||||
resize: vertical;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.card_info > textarea::placeholder {
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.card_info > textarea::-webkit-input-placeholder {
|
||||
color: var(--ColorThemes3);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#map_card {
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: calc(100vh - 100px);
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="page-card">
|
||||
<div id="header">
|
||||
<p id="status"></p>
|
||||
<p id="hash"></p>
|
||||
<div class="list-controls" id="page-card-controls" style="display: none">
|
||||
<div id="page-card-sort">
|
||||
<button id="sort_1" onclick="Card.sort('2')" data-state="active">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 32.476562 5.9785156 A 1.50015 1.50015 0 0 0 31 7.5 L 31 37.878906 L 26.560547 33.439453 A 1.50015 1.50015 0 1 0 24.439453 35.560547 L 31.439453 42.560547 A 1.50015 1.50015 0 0 0 33.560547 42.560547 L 40.560547 35.560547 A 1.50015 1.50015 0 1 0 38.439453 33.439453 L 34 37.878906 L 34 7.5 A 1.50015 1.50015 0 0 0 32.476562 5.9785156 z M 14.375 8.0058594 C 14.257547 8.01575 14.139641 8.0379219 14.025391 8.0761719 L 11.025391 9.0761719 C 10.239391 9.3381719 9.8141719 10.188609 10.076172 10.974609 C 10.338172 11.760609 11.190609 12.188828 11.974609 11.923828 L 13 11.580078 L 13 20.5 C 13 21.329 13.671 22 14.5 22 C 15.329 22 16 21.329 16 20.5 L 16 9.5 C 16 9.018 15.767953 8.5652031 15.376953 8.2832031 C 15.082953 8.0717031 14.727359 7.9761875 14.375 8.0058594 z M 14 27 C 11.344 27 9.387625 28.682109 9.015625 31.287109 C 8.898625 32.107109 9.4671094 32.867375 10.287109 32.984375 C 11.106109 33.102375 11.867375 32.533891 11.984375 31.712891 C 12.096375 30.931891 12.537 30 14 30 C 15.103 30 16 30.897 16 32 C 16 33.103 15.103 34 14 34 C 11.592 34 9 35.721 9 39.5 C 9 40.329 9.672 41 10.5 41 L 17.5 41 C 18.329 41 19 40.329 19 39.5 C 19 38.671 18.329 38 17.5 38 L 12.308594 38 C 12.781594 37.093 13.664 37 14 37 C 16.757 37 19 34.757 19 32 C 19 29.243 16.757 27 14 27 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_2" onclick="Card.sort('3')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 31.478516 6 A 1.50015 1.50015 0 0 0 30.439453 6.4394531 L 23.439453 13.439453 A 1.50015 1.50015 0 1 0 25.560547 15.560547 L 30 11.121094 L 30 41.5 A 1.50015 1.50015 0 1 0 33 41.5 L 33 11.121094 L 37.439453 15.560547 A 1.50015 1.50015 0 1 0 39.560547 13.439453 L 32.560547 6.4394531 A 1.50015 1.50015 0 0 0 31.478516 6 z M 13.375 8.0058594 C 13.257547 8.01575 13.139641 8.0379219 13.025391 8.0761719 L 10.025391 9.0761719 C 9.2393906 9.3381719 8.8141719 10.188609 9.0761719 10.974609 C 9.3381719 11.760609 10.190609 12.188828 10.974609 11.923828 L 12 11.580078 L 12 20.5 C 12 21.329 12.671 22 13.5 22 C 14.329 22 15 21.329 15 20.5 L 15 9.5 C 15 9.018 14.767953 8.5652031 14.376953 8.2832031 C 14.082953 8.0717031 13.727359 7.9761875 13.375 8.0058594 z M 13 27 C 10.344 27 8.387625 28.682109 8.015625 31.287109 C 7.898625 32.107109 8.4671094 32.867375 9.2871094 32.984375 C 10.106109 33.102375 10.867375 32.533891 10.984375 31.712891 C 11.096375 30.931891 11.537 30 13 30 C 14.103 30 15 30.897 15 32 C 15 33.103 14.103 34 13 34 C 10.592 34 8 35.721 8 39.5 C 8 40.329 8.672 41 9.5 41 L 16.5 41 C 17.329 41 18 40.329 18 39.5 C 18 38.671 17.329 38 16.5 38 L 11.308594 38 C 11.781594 37.093 12.664 37 13 37 C 15.757 37 18 34.757 18 32 C 18 29.243 15.757 27 13 27 z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_3" onclick="Card.sort('4')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
transform="rotate(180 32.5 24.5106)"
|
||||
id="svg_1"
|
||||
d="m32.47852,6a1.50015,1.50015 0 0 0 -1.03907,0.43945l-7,7a1.50015,1.50015 0 1 0 2.1211,2.1211l4.43945,-4.43946l0,30.37891a1.50015,1.50015 0 1 0 3,0l0,-30.37891l4.43945,4.43946a1.50015,1.50015 0 1 0 2.1211,-2.1211l-7,-7a1.50015,1.50015 0 0 0 -1.08203,-0.43945z"
|
||||
></path>
|
||||
<path
|
||||
d="m16,6c-5.511,0 -10,4.489 -10,10c0,5.511 4.489,10 10,10c5.511,0 10,-4.489 10,-10c0,-5.511 -4.489,-10 -10,-10zm0,2c4.43012,0 8,3.56988 8,8c0,4.43012 -3.56988,8 -8,8c-4.43012,0 -8,-3.56988 -8,-8c0,-4.43012 3.56988,-8 8,-8zm-1,2l0,6.41406l4.29297,4.29297l1.41406,-1.41406l-3.70703,-3.70703l0,-5.58594l-2,0z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="sort_4" onclick="Card.sort('1')" data-state="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
id="svg_1"
|
||||
d="m32.47852,6a1.50015,1.50015 0 0 0 -1.03907,0.43945l-7,7a1.50015,1.50015 0 1 0 2.1211,2.1211l4.43945,-4.43946l0,30.37891a1.50015,1.50015 0 1 0 3,0l0,-30.37891l4.43945,4.43946a1.50015,1.50015 0 1 0 2.1211,-2.1211l-7,-7a1.50015,1.50015 0 0 0 -1.08203,-0.43945z"
|
||||
></path>
|
||||
<path
|
||||
d="m16,22.85262c-5.511,0 -10,4.489 -10,10c0,5.511 4.489,10 10,10c5.511,0 10,-4.489 10,-10c0,-5.511 -4.489,-10 -10,-10zm0,2c4.43012,0 8,3.56988 8,8c0,4.43012 -3.56988,8 -8,8c-4.43012,0 -8,-3.56988 -8,-8c0,-4.43012 3.56988,-8 8,-8zm-1,2l0,6.41406l4.29297,4.29297l1.41406,-1.41406l-3.70703,-3.70703l0,-5.58594l-2,0z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="page-card-status">
|
||||
<div id="cloud_1" data-state="active" title="Йде синхронізація...">
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
version="1.1"
|
||||
>
|
||||
<g>
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)" opacity="1">
|
||||
<g transform="translate(24 29)">
|
||||
<g transform="rotate(0)">
|
||||
<g transform="scale(1 1)">
|
||||
<g transform="translate(-24 -29)">
|
||||
<g opacity="1">
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 18.772, 33.991)"
|
||||
opacity="1"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
>
|
||||
<path
|
||||
d="M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
>
|
||||
<animate
|
||||
calcMode="spline"
|
||||
repeatCount="indefinite"
|
||||
attributeName="d"
|
||||
dur="1.166667"
|
||||
begin="0.000000"
|
||||
keyTimes="0; 0.107143; 0.178571; 0.821429; 0.892857; 1"
|
||||
keySplines="0 0 1 1; 0.333000 0.000000 0.667000 1.000000; 0.167000 0.167000 0.833000 0.833000; 0.333000 0.000000 0.667000 1.000000; 0.000000 0.000000 0.000000 0.000000"
|
||||
values="M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055; M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055; M -1.771,-2.28 C -1.771,-2.28 -1.761,-2.279 -1.761,-2.279 -1.761,-2.279 -1.78,-2.283 -1.78,-2.283; M -1.768,-2.281 C -1.768,-2.281 -1.758,-2.28 -1.758,-2.28 -1.758,-2.28 -1.778,-2.284 -1.778,-2.284; M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055; M -2.708,2.491 C -2.708,2.491 -2.273,-2.49 -2.273,-2.49 -2.273,-2.49 2.708,-2.055 2.708,-2.055"
|
||||
></animate>
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 24.037, 34)"
|
||||
opacity="1"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
>
|
||||
<path
|
||||
d="M 7.036,-2.5 C 6.006,0.413 3.228,2.5 -0.036,2.5 -3.227,2.5 -5.953,0.507 -7.036,-2.303"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
></path>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 29.227, 24.009)"
|
||||
opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
>
|
||||
<path
|
||||
d="M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
>
|
||||
<animate
|
||||
calcMode="spline"
|
||||
repeatCount="indefinite"
|
||||
attributeName="d"
|
||||
dur="1.166667"
|
||||
begin="0.000000"
|
||||
keyTimes="0; 0.107143; 0.178571; 0.821429; 0.892857; 1"
|
||||
keySplines="0 0 1 1; 0.333000 0.000000 0.667000 1.000000; 0.167000 0.167000 0.833000 0.833000; 0.333000 0.000000 0.667000 1.000000; 0.000000 0.000000 0.000000 0.000000"
|
||||
values="M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055; M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055; M 1.775,2.301 C 1.775,2.301 1.775,2.298 1.775,2.298 1.775,2.298 1.777,2.29 1.777,2.29; M 1.767,2.292 C 1.767,2.292 1.767,2.289 1.767,2.289 1.767,2.289 1.768,2.281 1.768,2.281; M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055; M 2.708,-2.49 C 2.708,-2.49 2.273,2.491 2.273,2.491 2.273,2.491 -2.708,2.055 -2.708,2.055"
|
||||
></animate>
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1, 0, 0, 1, 23.963, 24)"
|
||||
opacity="1"
|
||||
stroke="var(--ColorThemes3)"
|
||||
stroke-width="3"
|
||||
stroke-opacity="1"
|
||||
>
|
||||
<path
|
||||
d="M -7.036,2.5 C -6.006,-0.413 -3.229,-2.5 0.036,-2.5 3.228,-2.5 5.953,-0.507 7.036,2.303"
|
||||
style="
|
||||
fill: none;
|
||||
stroke-dasharray: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
"
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<animateTransform
|
||||
calcMode="spline"
|
||||
repeatCount="indefinite"
|
||||
attributeName="transform"
|
||||
dur="1.166667"
|
||||
begin="0.000000"
|
||||
type="rotate"
|
||||
keyTimes="0; 0.107143; 0.821429; 0.892857; 1"
|
||||
keySplines="0 0 1 1; 0.333000 0.000000 0.667000 1.000000; 0.333000 0.000000 0.667000 1.000000; 0.000000 0.000000 0.000000 0.000000"
|
||||
values="0; 0; 380; 360; 360"
|
||||
></animateTransform>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)" opacity="1">
|
||||
<g
|
||||
fill-opacity="1"
|
||||
transform="matrix(1, 0, 0, 1, 24, 22.5)"
|
||||
opacity="1"
|
||||
fill="var(--ColorThemes3)"
|
||||
>
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccccccccccccccccccc"
|
||||
d="M 15,-2.5 C 15,-2.5 14.42,-2.5 14.42,-2.5 13.67,-9.79 7.49,-15.5 0,-15.5 -7.49,-15.5 -13.67,-9.79 -14.42,-2.5 -14.42,-2.5 -15,-2.5 -15,-2.5 -19.96,-2.5 -24,1.54 -24,6.5 -24,11.46 -19.96,15.5 -15,15.5 -15,15.5 -12.17,15.5 -12.17,15.5 -12.38,14.91 -12.48,14.26 -12.42,13.59 -12.42,13.59 -12.32,12.5 -12.32,12.5 -12.32,12.5 -15,12.5 -15,12.5 -18.31,12.5 -21,9.81 -21,6.5 -21,3.19 -18.31,0.5 -15,0.5 -15,0.5 -13,0.5 -13,0.5 -12.17,0.5 -11.5,-0.17 -11.5,-1 -11.5,-7.34 -6.34,-12.5 0,-12.5 6.34,-12.5 11.5,-7.34 11.5,-1 11.5,-0.17 12.17,0.5 13,0.5 13,0.5 15,0.5 15,0.5 18.31,0.5 21,3.19 21,6.5 21,9.81 18.31,12.5 15,12.5 15,12.5 10.38,12.5 10.38,12.5 9.73,13.64 8.89,14.66 7.92,15.5 7.92,15.5 15,15.5 15,15.5 19.96,15.5 24,11.46 24,6.5 24,1.54 19.96,-2.5 15,-2.5 Z"
|
||||
style=""
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="cloud_2" data-state="" title="Синхронізовано">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 7 C 16.51 7 10.330078 12.71 9.5800781 20 L 9 20 C 4.04 20 0 24.04 0 29 C 0 33.96 4.04 38 9 38 L 16.640625 38 L 13.640625 35 L 9 35 C 5.69 35 3 32.31 3 29 C 3 25.69 5.69 23 9 23 L 11 23 C 11.83 23 12.5 22.33 12.5 21.5 C 12.5 15.16 17.66 10 24 10 C 30.34 10 35.5 15.16 35.5 21.5 C 35.5 22.33 36.17 23 37 23 L 39 23 C 42.31 23 45 25.69 45 29 C 45 32.31 42.31 35 39 35 L 29.839844 35 L 26.539062 38 L 39 38 C 43.96 38 48 33.96 48 29 C 48 24.04 43.96 20 39 20 L 38.419922 20 C 37.669922 12.71 31.49 7 24 7 z M 32.542969 24.986328 A 1.50015 1.50015 0 0 0 31.490234 25.390625 L 21.548828 34.427734 L 16.560547 29.439453 A 1.50015 1.50015 0 1 0 14.439453 31.560547 L 20.439453 37.560547 A 1.50015 1.50015 0 0 0 22.509766 37.609375 L 33.509766 27.609375 A 1.50015 1.50015 0 0 0 32.542969 24.986328 z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="cloud_3" data-state="" title="Помилка синхронізації">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
|
||||
<path
|
||||
d="M 24 8 C 16.51 8 10.330078 13.71 9.5800781 21 L 9 21 C 4.04 21 0 25.04 0 30 C 0 34.96 4.04 39 9 39 L 19.099609 39 C 18.899609 38 18.999922 36.95 19.419922 36 L 9 36 C 5.69 36 3 33.31 3 30 C 3 26.69 5.69 24 9 24 L 11 24 C 11.83 24 12.5 23.33 12.5 22.5 C 12.5 16.16 17.66 11 24 11 C 30.34 11 35.5 16.16 35.5 22.5 C 35.5 23.33 36.17 24 37 24 L 39 24 C 42.31 24 45 26.69 45 30 C 45 33.31 42.31 36 39 36 L 28.580078 36 C 29.000078 36.95 29.100391 38 28.900391 39 L 39 39 C 43.96 39 48 34.96 48 30 C 48 25.04 43.96 21 39 21 L 38.419922 21 C 37.669922 13.71 31.49 8 24 8 z M 23.976562 20.978516 A 1.50015 1.50015 0 0 0 22.5 22.5 L 22.5 31.5 A 1.50015 1.50015 0 1 0 25.5 31.5 L 25.5 22.5 A 1.50015 1.50015 0 0 0 23.976562 20.978516 z M 24 36 A 2 2 0 0 0 24 40 A 2 2 0 0 0 24 36 z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="list"></div>
|
||||
<div id="map_card"></div>
|
||||
</div>
|
||||
|
||||
<div id="card-new-date" style="display: none; opacity: 0">
|
||||
<div class="mess">
|
||||
<button id="card-new-date-button">Оновити дату</button>
|
||||
<input type="datetime-local" id="card-new-date-input" placeholder="Дата" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,358 +1,641 @@
|
||||
let socket, username;
|
||||
|
||||
let listEntrances = []
|
||||
let listApartment = []
|
||||
|
||||
let holdTimer;
|
||||
let startTime;
|
||||
let map_card;
|
||||
|
||||
const Card = {
|
||||
init: async (type, id) => {
|
||||
let html = await fetch('/lib/pages/card/index.html').then((response) => response.text());
|
||||
// Глобальні змінні стану
|
||||
id: null,
|
||||
socket: null,
|
||||
reconnectTimeout: null,
|
||||
reconnectAttempts: 0,
|
||||
username: null,
|
||||
listEntrances: [],
|
||||
listApartment: [],
|
||||
listBuilding: [],
|
||||
|
||||
// Кольори статусів квартир
|
||||
color_status: [
|
||||
["var(--ColorThemes2)", "var(--ColorThemes3)"],
|
||||
["#fbf1e0", "#ff8300"],
|
||||
["#fce3e2", "#ff0000"],
|
||||
["#d7ddec", "#2919bd"],
|
||||
["#d5e9dd", "#11a568"],
|
||||
["#d7ebfa", "#3fb4fc"],
|
||||
["#e8dbf5", "#b381eb"]
|
||||
],
|
||||
|
||||
// Ініціалізація сторінки
|
||||
async init(type, Id) {
|
||||
// Завантажуємо HTML
|
||||
const html = await fetch('/lib/pages/card/index.html').then(r => r.text());
|
||||
app.innerHTML = html;
|
||||
Card.id = Id;
|
||||
|
||||
house = id;
|
||||
// Закриваємо старий WebSocket
|
||||
if (this.socket) this.socket.close(1000, "Перезапуск з'єднання");
|
||||
this.cloud.start(makeid(6));
|
||||
|
||||
if (socket) socket.close(1000, "Перезапуск соединения");
|
||||
// Якщо це сторінка будинку, отримуємо під’їзди та стартуємо WebSocket
|
||||
if (type === "house") {
|
||||
const controls = document.getElementById('page-card-controls');
|
||||
controls.style.display = "flex";
|
||||
|
||||
if (type == "house") {
|
||||
getEntrances();
|
||||
start(makeid(6));
|
||||
// Застосовуємо режим сортування
|
||||
this.sort(localStorage.getItem('sort_mode'), false);
|
||||
this.getEntrances({ update: false });
|
||||
} else if (type === "homestead") {
|
||||
this.getHomestead.map({});
|
||||
}
|
||||
|
||||
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);
|
||||
// Додаємо обробник закриття попапу
|
||||
const popup = document.getElementById('card-new-date');
|
||||
if (!popup.dataset.listenerAdded) {
|
||||
popup.addEventListener('click', (e) => {
|
||||
if (!popup.querySelector('.mess').contains(e.target)) {
|
||||
this.dateEditor.close();
|
||||
}
|
||||
});
|
||||
popup.dataset.listenerAdded = 'true';
|
||||
}
|
||||
},
|
||||
|
||||
function handleCancel() {
|
||||
const holdDuration = Date.now() - startTime; // Считаем, сколько длилось нажатие
|
||||
// Робота з WebSocket
|
||||
cloud: {
|
||||
start(name) {
|
||||
if (!name) return;
|
||||
Card.username = name;
|
||||
|
||||
if (holdDuration < 1000) {
|
||||
clearTimeout(holdTimer); // Если нажали менее 1 секунды, сбрасываем таймер
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const ws = new WebSocket(`${CONFIG.wss}?uuid=${uuid}`);
|
||||
Card.socket = ws;
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("[WebSocket] З'єднання встановлено");
|
||||
Card.cloud.setStatus('ok');
|
||||
ws.send(JSON.stringify({
|
||||
event: 'connection',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
uuid,
|
||||
username: name,
|
||||
data: {}
|
||||
}));
|
||||
Card.reconnectAttempts = 0;
|
||||
clearTimeout(Card.reconnectTimeout);
|
||||
};
|
||||
|
||||
ws.onmessage = (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.event === 'connection' && data.username !== Card.username) {
|
||||
console.log(`Новий користувач: ${data.username}`);
|
||||
}
|
||||
if (data.event === 'message') {
|
||||
Card.cloud.update(data);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
console.warn("[WebSocket] З'єднання розірвано");
|
||||
Card.cloud.setStatus('err');
|
||||
Card.reconnectAttempts++;
|
||||
if (Card.reconnectAttempts <= 5) {
|
||||
Card.reconnectTimeout = setTimeout(() => {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}, 1000);
|
||||
} else {
|
||||
if (confirm("З'єднання розірвано! Перепідключитись?")) {
|
||||
Card.reconnectAttempts = 0;
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = (err) => {
|
||||
console.error("[WebSocket] Помилка", err);
|
||||
Card.cloud.setStatus('err');
|
||||
};
|
||||
},
|
||||
|
||||
setStatus(mode) {
|
||||
const ids = ['cloud_1', 'cloud_2', 'cloud_3'];
|
||||
ids.forEach((id, idx) => {
|
||||
const el = document.getElementById(id);
|
||||
el.setAttribute('data-state', ['sync', 'ok', 'err'].indexOf(mode) === idx ? 'active' : '');
|
||||
});
|
||||
},
|
||||
|
||||
update(msg) {
|
||||
if (msg.type !== "apartment" && msg.type !== "building") return;
|
||||
|
||||
const [bg, color] = Card.color_status[msg.data.status];
|
||||
|
||||
const id = msg.data.id;
|
||||
const el = document.getElementById(`status_${id}`);
|
||||
const redDot = document.getElementById(`redDot_${id}`);
|
||||
|
||||
if (msg.type === "building") {
|
||||
redDot.style = `background:${bg};border:2px solid ${color}`;
|
||||
const apt = Card.listBuilding.find(e => e.id === id);
|
||||
|
||||
if (!apt) return;
|
||||
|
||||
apt.status = msg.data.status;
|
||||
apt.description = msg.data.description;
|
||||
apt.updated_at = msg.data.updated_at;
|
||||
} else if (msg.type === "apartment") {
|
||||
if (!el) return;
|
||||
|
||||
document.getElementById(`card_${id}`).style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
el.value = msg.data.status;
|
||||
el.style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
document.getElementById(`description_${id}`).value = msg.data.description;
|
||||
document.getElementById(`date_text_${id}`).innerText = formattedDateTime(msg.data.updated_at);
|
||||
}
|
||||
},
|
||||
|
||||
messApartment({ number, id, update, time }) {
|
||||
const apt = Card.listApartment[number]?.find(e => e.id === id);
|
||||
if (!apt) return;
|
||||
|
||||
const statusEl = document.getElementById(`status_${id}`);
|
||||
const descEl = document.getElementById(`description_${id}`);
|
||||
|
||||
let date = () => {
|
||||
if (!update && !time) {
|
||||
return apt.updated_at;
|
||||
} else if (update && !time) {
|
||||
return getTimeInSeconds();
|
||||
} else if (update && time) {
|
||||
return getTimeInSeconds(time);
|
||||
}
|
||||
}
|
||||
|
||||
apt.status = Number(statusEl.value);
|
||||
apt.description = descEl.value;
|
||||
apt.updated_at = date();
|
||||
|
||||
const [bg, color] = Card.color_status[apt.status];
|
||||
statusEl.style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
const message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
username: Card.username,
|
||||
type: "apartment",
|
||||
data: {
|
||||
...apt,
|
||||
sheep_id: USER.id
|
||||
}
|
||||
};
|
||||
|
||||
if (Card.socket?.readyState === WebSocket.OPEN) {
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
} else {
|
||||
if (confirm("З'єднання розірвано! Перепідключитись?")) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
messBuildings({ id, update, time }) {
|
||||
const apt = Card.listBuilding.find(e => e.id === id);
|
||||
if (!apt) return;
|
||||
|
||||
const statusEl = document.getElementById(`status_${id}`);
|
||||
const descEl = document.getElementById(`description_${id}`);
|
||||
|
||||
let date = () => {
|
||||
if (!update && !time) {
|
||||
return apt.updated_at;
|
||||
} else if (update && !time) {
|
||||
return getTimeInSeconds();
|
||||
} else if (update && time) {
|
||||
return getTimeInSeconds(time);
|
||||
}
|
||||
}
|
||||
|
||||
apt.status = Number(statusEl.value);
|
||||
apt.description = descEl.value;
|
||||
apt.updated_at = date();
|
||||
|
||||
const [bg, color] = Card.color_status[apt.status];
|
||||
statusEl.style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
const message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
username: Card.username,
|
||||
type: "building",
|
||||
data: {
|
||||
...apt,
|
||||
sheep_id: USER.id
|
||||
}
|
||||
};
|
||||
|
||||
if (Card.socket?.readyState === WebSocket.OPEN) {
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
} else {
|
||||
if (confirm("З'єднання розірвано! Перепідключитись?")) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 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
|
||||
// Отримання під’їздів
|
||||
async getEntrances({ house_id = Card.id, update = false }) {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
const res = await fetch(`${CONFIG.api}/house/${house_id}/entrances`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
this.listEntrances = data;
|
||||
|
||||
const container = document.getElementById('list');
|
||||
if (!update) container.innerHTML = "";
|
||||
|
||||
if (update) {
|
||||
for (const { id, entrance_number } of data) {
|
||||
this.getApartment({ id, number: entrance_number, update: true });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
socket.send(JSON.stringify(message))
|
||||
};
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
socket.onmessage = function (event) {
|
||||
let data = JSON.parse(event.data)
|
||||
const canManage = USER.mode === 2 || (USER.mode === 1 && USER.possibilities.can_manager_territory);
|
||||
|
||||
if (data.event == 'connection') {
|
||||
if (data.username == username) return
|
||||
for (const element of data) {
|
||||
const { id, entrance_number, title, history, working } = element;
|
||||
const isMy = ((history.name === "Групова" && history.group_id == USER.group_id) || history.name === USER.name);
|
||||
|
||||
console.log(`Добавлен новый пользователь по имени ${data.username}`);
|
||||
} else if (data.event == 'message') {
|
||||
update(data);
|
||||
const show = (isMy && working) ? "open" : canManage ? "close" : null;
|
||||
if (!show) continue;
|
||||
|
||||
if (data.username == username) return
|
||||
const icon = isMy && working
|
||||
? `<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>`
|
||||
: `<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>`;
|
||||
|
||||
console.log(`${data.username} пишет: `, data.data);
|
||||
const details = document.createElement('details');
|
||||
if (show === "open") details.setAttribute('open', '');
|
||||
details.innerHTML = `
|
||||
<summary><p>${title}</p>${icon}</summary>
|
||||
<div id="apartments_${id}" class="apartments_list"></div>
|
||||
`;
|
||||
fragment.appendChild(details);
|
||||
|
||||
this.getApartment({ id, number: entrance_number, update: false });
|
||||
}
|
||||
};
|
||||
|
||||
socket.onclose = function (event) {
|
||||
if (event.wasClean) {
|
||||
document.getElementById("status").innerText = "WebSocket | close"
|
||||
console.log(`[WebSocket | close] Соединение закрыто чисто, код=${event.code} причина=${event.reason}`);
|
||||
container.appendChild(fragment);
|
||||
},
|
||||
|
||||
async getApartment({ id, number, update }) {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const res = await fetch(`${CONFIG.api}/apartment/${id}`, {
|
||||
headers: { "Authorization": uuid }
|
||||
});
|
||||
const data = await res.json();
|
||||
this.listApartment[number] = data;
|
||||
|
||||
const sort_mode = localStorage.getItem('sort_mode') ?? "1";
|
||||
const sorters = {
|
||||
"1": (a, b) => a.apartment_number - b.apartment_number,
|
||||
"2": (a, b) => b.apartment_number - a.apartment_number,
|
||||
"3": (a, b) => a.updated_at - b.updated_at,
|
||||
"4": (a, b) => b.updated_at - a.updated_at,
|
||||
};
|
||||
data.sort(sorters[sort_mode] || sorters["1"]);
|
||||
|
||||
const container = document.getElementById(`apartments_${id}`);
|
||||
if (!update) container.innerHTML = "";
|
||||
|
||||
const statusOptions = (selected) => {
|
||||
const labels = ["", "Відмова (Не цікавить)", "Не заходити (Груба відмова)", "Нема домофона", "Повторна відвідина", "Немає вдома", "Свідки Єгови"];
|
||||
return labels.map((txt, i) => `<option value="${i}" ${i === selected ? "selected" : ""}>${txt}</option>`).join("");
|
||||
};
|
||||
|
||||
if (update) {
|
||||
for (const apt of data) {
|
||||
const [bg, color] = this.color_status[apt.status];
|
||||
const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
const dateEl = document.getElementById(`date_${apt.id}`);
|
||||
const cardEl = document.getElementById(`card_${apt.id}`);
|
||||
const statusEl = document.getElementById(`status_${apt.id}`);
|
||||
const dateTextEl = document.getElementById(`date_text_${apt.id}`);
|
||||
const descEl = document.getElementById(`description_${apt.id}`);
|
||||
|
||||
if (cardEl) cardEl.style = style;
|
||||
if (statusEl) {
|
||||
statusEl.value = apt.status;
|
||||
statusEl.style = style;
|
||||
}
|
||||
if (dateEl) dateEl.setAttribute('onclick', `Card.dateEditor.open({id: ${apt.id}, number: ${number}, updated_at: ${apt.updated_at}})`);
|
||||
if (dateTextEl) dateTextEl.innerText = formattedDateTime(apt.updated_at);
|
||||
if (descEl) descEl.innerText = apt.description ?? "";
|
||||
}
|
||||
} else {
|
||||
document.getElementById("status").innerText = "WebSocket | close"
|
||||
console.log('[WebSocket | close] Соединение прервано');
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// setTimeout(function() {
|
||||
// start(username);
|
||||
// }, 1000);
|
||||
if (data.length == 0) {
|
||||
const p = document.createElement('p');
|
||||
|
||||
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>
|
||||
p.innerHTML = `
|
||||
Інформація про цей під'їзд відсутня. Надайте інформацію відповідальному за території.
|
||||
`;
|
||||
getApartment(element.id, element.entrance_number);
|
||||
|
||||
console.log(element);
|
||||
return container.appendChild(p);
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
for (const apt of data) {
|
||||
const [bg, color] = this.color_status[apt.status];
|
||||
const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
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;
|
||||
const div = document.createElement('div');
|
||||
|
||||
data.sort((a, b) => a.apartment_number - b.apartment_number);
|
||||
div.className = `card_info`;
|
||||
div.id = `card_${apt.id}`;
|
||||
div.style = style;
|
||||
|
||||
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.innerHTML = `
|
||||
<div class="info">
|
||||
<span>кв.${apt.title}</span>
|
||||
<select id="status_${apt.id}" onchange="Card.cloud.messApartment({number:${number},id:${apt.id},update:true})" style="${style}">
|
||||
${statusOptions(apt.status)}
|
||||
</select>
|
||||
<button id="date_${apt.id}" onclick="Card.dateEditor.open({id:${apt.id},number:${number},updated_at:${apt.updated_at}})">
|
||||
<p id="date_text_${apt.id}">${formattedDateTime(apt.updated_at)}</p>
|
||||
<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>
|
||||
<textarea id="description_${apt.id}" onchange="Card.cloud.messApartment({number:${number},id:${apt.id}})" placeholder="Коротка нотатка.">${apt.description || ""}</textarea>
|
||||
`;
|
||||
|
||||
fragment.appendChild(div);
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
container.appendChild(fragment);
|
||||
}
|
||||
},
|
||||
|
||||
function sort(id, entrance_id) {
|
||||
let child = document.getElementById(`card_${id}`);
|
||||
getHomestead: {
|
||||
markers: {},
|
||||
|
||||
document.getElementById(`apartments_${entrance_id}`).removeChild(child);
|
||||
async loadAPI({ url }) {
|
||||
const uuid = localStorage.getItem("uuid");
|
||||
|
||||
document.getElementById(`apartments_${entrance_id}`).append(child);
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
});
|
||||
|
||||
child.style.border = "1px solid var(--PrimaryColor)";
|
||||
}
|
||||
return await response.json();
|
||||
},
|
||||
|
||||
function getTimeInSeconds(time = Date.now()) {
|
||||
// Если время больше 10 знаков (это значит, что время в миллисекундах)
|
||||
if (time.toString().length < 10) {
|
||||
// Округляем до секунд, убирая последние 3 цифры (миллисекунды)
|
||||
time = Math.floor(time * 1000);
|
||||
async map({ homestead_id = Card.id }) {
|
||||
let data = await this.loadAPI({ url: `${CONFIG.api}homestead/${homestead_id}` });
|
||||
|
||||
console.log(data);
|
||||
|
||||
|
||||
let lat = data.geo?.lat ?? data.points?.[0]?.[0]?.[0]?.lat ?? 49.5629016;
|
||||
let lng = data.geo?.lng ?? data.points?.[0]?.[0]?.[0]?.lng ?? 25.6145625;
|
||||
let zoom = 15;
|
||||
|
||||
if (map_card && map_card.remove) {
|
||||
map_card.stopLocate();
|
||||
map_card.remove();
|
||||
}
|
||||
|
||||
const mapElement = document.getElementById('map_card');
|
||||
mapElement.style.display = "flex";
|
||||
if (!mapElement) return;
|
||||
|
||||
let googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3']
|
||||
});
|
||||
|
||||
let osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
});
|
||||
|
||||
let mytile = L.tileLayer('https://sheep-service.com/map/{z}/{x}/{y}.webp', {
|
||||
maxZoom: 20,
|
||||
minZoom: 15,
|
||||
tms: true
|
||||
});
|
||||
|
||||
map_card = L.map(mapElement, {
|
||||
renderer: L.canvas(),
|
||||
center: [lat, lng],
|
||||
zoom,
|
||||
zoomControl: false,
|
||||
layers: [
|
||||
googleHybrid,
|
||||
osm,
|
||||
mytile
|
||||
]
|
||||
});
|
||||
|
||||
// слежение в реальном времени
|
||||
map_card.locate({ setView: false, watch: true, enableHighAccuracy: true });
|
||||
map_card.on('locationfound', (e) => {
|
||||
if (!map_card._userMarker) {
|
||||
map_card._userMarker = L.marker(e.latlng).addTo(map_card)
|
||||
.bindPopup("Ви тут!");
|
||||
} else {
|
||||
map_card._userMarker.setLatLng(e.latlng);
|
||||
}
|
||||
});
|
||||
|
||||
let baseMaps = {
|
||||
"Google Hybrid": googleHybrid,
|
||||
"OpenStreetMap": osm,
|
||||
"Sheep Service Map": mytile,
|
||||
};
|
||||
|
||||
let layerControl = L.control.layers(baseMaps, [], { position: 'bottomright' }).addTo(map_card);
|
||||
|
||||
map_card.pm.setLang("ua");
|
||||
|
||||
const polygonOptions = {
|
||||
color: "#f2bd53",
|
||||
radius: 500,
|
||||
fillOpacity: 0.3,
|
||||
dashArray: '20,15',
|
||||
dashOffset: '20',
|
||||
};
|
||||
|
||||
L.polygon(data.points, polygonOptions).addTo(map_card);
|
||||
|
||||
map_card.setZoom(data.zoom);
|
||||
|
||||
// map_card.getZoom()
|
||||
|
||||
// console.log(data.zoom);
|
||||
|
||||
|
||||
Card.listBuilding = await this.loadAPI({ url: `${CONFIG.api}building/${homestead_id}` });
|
||||
|
||||
const statusOptions = (selected) => {
|
||||
const labels = ["", "Відмова (Не цікавить)", "Не заходити (Груба відмова)", "Нема домофона", "Повторна відвідина", "Немає вдома", "Свідки Єгови"];
|
||||
return labels.map((txt, i) => `<option value="${i}" ${i === selected ? "selected" : ""}>${txt}</option>`).join("");
|
||||
};
|
||||
|
||||
|
||||
// for (let i = 0; i < Card.listBuilding.length; i++) {
|
||||
// const element = Card.listBuilding[i];
|
||||
// const [bg, color] = Card.color_status[element.status];
|
||||
// const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
// const div = document.createElement('div');
|
||||
|
||||
// const redDot = L.divIcon({
|
||||
// className: "leaflet_drop",
|
||||
// html: `<div id="redDot_${element.id}" style='background:${bg};border:2px solid ${color}'></div>`,
|
||||
// iconSize: [16, 16],
|
||||
// iconAnchor: [8, 8]
|
||||
// });
|
||||
|
||||
// div.className = `card_info card_info_homestead`;
|
||||
// div.id = `card_${element.id}`;
|
||||
// div.style = style;
|
||||
|
||||
// div.innerHTML = `
|
||||
// <div class="info">
|
||||
// <select id="status_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id},update:true})" style="${style}">
|
||||
// ${statusOptions(element.status)}
|
||||
// </select>
|
||||
// <button id="date_${element.id}" onclick="Card.dateEditor.open({id:${element.id},updated_at:${element.updated_at}})">
|
||||
// <p id="date_text_${element.id}">${formattedDateTime(element.updated_at)}</p>
|
||||
// <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>
|
||||
// <textarea id="description_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id}})" placeholder="Коротка нотатка.">${element.description || ""}</textarea>
|
||||
// `;
|
||||
|
||||
// L.marker(element.geo, { icon: redDot }).addTo(map_card)
|
||||
// .bindPopup(div);
|
||||
// }
|
||||
|
||||
for (let i = 0; i < Card.listBuilding.length; i++) {
|
||||
const element = Card.listBuilding[i];
|
||||
const [bg, color] = Card.color_status[element.status];
|
||||
|
||||
const redDot = L.divIcon({
|
||||
className: "leaflet_drop",
|
||||
html: `<div id="redDot_${element.id}" style='background:${bg};border:2px solid ${color}'></div>`,
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8]
|
||||
});
|
||||
|
||||
// создаём маркер
|
||||
const marker = L.marker(element.geo, { icon: redDot }).addTo(map_card);
|
||||
|
||||
marker.bindPopup("");
|
||||
|
||||
// при открытии popup генерим div заново
|
||||
marker.on("popupopen", () => {
|
||||
const el = Card.listBuilding.find(e => e.id === element.id);
|
||||
const [bg, color] = Card.color_status[el.status];
|
||||
const style = `background:${bg};color:${color};border:1px solid ${color}`;
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "card_info card_info_homestead";
|
||||
div.id = `card_${el.id}`;
|
||||
div.style = style;
|
||||
|
||||
let date = new Date(el.updated_at);
|
||||
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
||||
|
||||
div.innerHTML = `
|
||||
<div class="info">
|
||||
<select id="status_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id},update:true})" style="${style}">
|
||||
${statusOptions(element.status)}
|
||||
</select>
|
||||
<input type="datetime-local" id="date_${element.id}" placeholder="Дата" onchange="Card.cloud.messBuildings({id:${element.id}})" value="${date.toISOString().slice(0, 16)}">
|
||||
</div>
|
||||
<textarea id="description_${element.id}" onchange="Card.cloud.messBuildings({id:${element.id}})" placeholder="Коротка нотатка.">${element.description || ""}</textarea>
|
||||
`;
|
||||
|
||||
marker.setPopupContent(div);
|
||||
});
|
||||
|
||||
Card.getHomestead.markers[element.id] = marker; // сохраним ссылку на маркер
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// Сортування
|
||||
sort(mode, load) {
|
||||
const idx = Math.max(1, Math.min(4, Number(mode) || 1));
|
||||
['sort_1', 'sort_2', 'sort_3', 'sort_4'].forEach((id, i) => {
|
||||
document.getElementById(id)?.setAttribute('data-state', i + 1 === idx ? 'active' : '');
|
||||
});
|
||||
localStorage.setItem('sort_mode', idx);
|
||||
if (!load) this.getEntrances({ update: false });
|
||||
},
|
||||
|
||||
// Редактор дати
|
||||
dateEditor: {
|
||||
open({ id, number, updated_at }) {
|
||||
const block = document.getElementById('card-new-date');
|
||||
const input = document.getElementById('card-new-date-input');
|
||||
const button = document.getElementById('card-new-date-button');
|
||||
|
||||
// Приводимо дату до ISO без зсуву часового поясу
|
||||
let date = new Date(updated_at == 0 ? Date.now() : updated_at);
|
||||
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
||||
input.value = date.toISOString().slice(0, 16)
|
||||
|
||||
// Призначаємо обробники
|
||||
input.setAttribute("onchange", `Card.dateEditor.edit({ id: ${id}, number: ${number} })`)
|
||||
button.setAttribute("onclick", `Card.dateEditor.edit({ id: ${id}, number: ${number}, type: 'now'})`)
|
||||
|
||||
|
||||
// Показуємо блок
|
||||
block.style.display = "";
|
||||
requestAnimationFrame(() => block.style.opacity = "1");
|
||||
},
|
||||
close() {
|
||||
// Робимо плавне зникнення
|
||||
const block = document.getElementById('card-new-date');
|
||||
block.style.opacity = "0";
|
||||
|
||||
const onTransitionEnd = () => {
|
||||
block.style.display = "none";
|
||||
block.removeEventListener("transitionend", onTransitionEnd);
|
||||
};
|
||||
block.addEventListener("transitionend", onTransitionEnd);
|
||||
},
|
||||
edit({ id, number, type }) {
|
||||
let input = document.getElementById('card-new-date-input').value;
|
||||
|
||||
if (type == "now") {
|
||||
Card.cloud.messApartment({ number: number, id: id, update: true });
|
||||
} else {
|
||||
if (input) {
|
||||
const ts = new Date(input).getTime();
|
||||
Card.cloud.messApartment({ number, id, update: true, time: ts });
|
||||
} else {
|
||||
Card.cloud.messApartment({ number: number, id: id });
|
||||
}
|
||||
}
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
452
web/lib/pages/card/script_old.js
Normal file
452
web/lib/pages/card/script_old.js
Normal file
@@ -0,0 +1,452 @@
|
||||
|
||||
const Card = {
|
||||
socket: null,
|
||||
reconnectTimeout: null,
|
||||
reconnectNumber: 0,
|
||||
username: null,
|
||||
listEntrances: [],
|
||||
listApartment: [],
|
||||
color_status: [
|
||||
["var(--ColorThemes2)", "var(--ColorThemes3)"],
|
||||
["#fbf1e0", "#ff8300"],
|
||||
["#fce3e2", "#ff0000"],
|
||||
["#d7ddec", "#2919bd"],
|
||||
["#d5e9dd", "#11a568"],
|
||||
["#d7ebfa", "#3fb4fc"],
|
||||
["#e8dbf5", "#b381eb"]
|
||||
],
|
||||
init: async (type, id) => {
|
||||
let html = await fetch('/lib/pages/card/index.html').then((response) => response.text());
|
||||
app.innerHTML = html;
|
||||
|
||||
house = id;
|
||||
|
||||
if (Card.socket) Card.socket.close(1000, "Перезапуск соединения");
|
||||
|
||||
Card.sort(localStorage.getItem('sort_mode'), false)
|
||||
|
||||
if (type == "house") {
|
||||
Card.getEntrances({ update: false });
|
||||
Card.cloud.start(makeid(6));
|
||||
}
|
||||
|
||||
|
||||
// Закриття вікно popup при натисканні за його межі
|
||||
const block_card = document.getElementById('card-new-date');
|
||||
const mess = block_card.querySelector('.mess');
|
||||
if (!block_card.dataset.listenerAdded) {
|
||||
block_card.addEventListener('click', function (event) {
|
||||
if (!mess.contains(event.target)) {
|
||||
Card.dateEditor.close();
|
||||
}
|
||||
});
|
||||
block_card.dataset.listenerAdded = 'true';
|
||||
}
|
||||
},
|
||||
cloud: {
|
||||
status: (mode) => {
|
||||
|
||||
let cloud_1 = document.getElementById('cloud_1');
|
||||
let cloud_2 = document.getElementById('cloud_2');
|
||||
let cloud_3 = document.getElementById('cloud_3');
|
||||
|
||||
switch (mode) {
|
||||
case 'sync':
|
||||
cloud_1.setAttribute('data-state', 'active');
|
||||
cloud_2.setAttribute('data-state', '');
|
||||
cloud_3.setAttribute('data-state', '');
|
||||
break;
|
||||
case 'ok':
|
||||
cloud_1.setAttribute('data-state', '');
|
||||
cloud_2.setAttribute('data-state', 'active');
|
||||
cloud_3.setAttribute('data-state', '');
|
||||
break;
|
||||
case 'err':
|
||||
cloud_1.setAttribute('data-state', '');
|
||||
cloud_2.setAttribute('data-state', '');
|
||||
cloud_3.setAttribute('data-state', 'active');
|
||||
break;
|
||||
}
|
||||
},
|
||||
start: (name) => {
|
||||
if (!name) return;
|
||||
|
||||
Card.username = name;
|
||||
|
||||
let uuid = localStorage.getItem("uuid");
|
||||
Card.socket = new WebSocket(`${CONFIG.wss}?uuid=${uuid}`);
|
||||
|
||||
Card.socket.onopen = function (e) {
|
||||
console.log("[WebSocket | open] З'єднання встановлено");
|
||||
Card.cloud.status('ok');
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
|
||||
Card.reconnectNumber = 0;
|
||||
clearTimeout(Card.reconnectTimeout);
|
||||
};
|
||||
|
||||
Card.socket.onmessage = function (event) {
|
||||
let data = JSON.parse(event.data)
|
||||
|
||||
if (data.event == 'connection') {
|
||||
if (data.username == Card.username) return
|
||||
|
||||
console.log(`Доданий новий користувач на ім'я ${data.username}`);
|
||||
} else if (data.event == 'message') {
|
||||
Card.cloud.update(data);
|
||||
|
||||
if (data.username == Card.username) return
|
||||
|
||||
console.log(`${data.username} пише: `, data.data);
|
||||
}
|
||||
};
|
||||
|
||||
Card.socket.onclose = function (event) {
|
||||
if (event.wasClean) {
|
||||
console.log(`[WebSocket | close] З'єднання закрито чисто, код =${event.code} причина=${event.reason}`);
|
||||
Card.cloud.status('err');
|
||||
} else {
|
||||
console.log(`[WebSocket | close] З'єднання перервано`);
|
||||
Card.cloud.status('err');
|
||||
|
||||
Card.reconnectTimeout = setTimeout(function () {
|
||||
Card.reconnectNumber++;
|
||||
if (Card.reconnectNumber > 5) {
|
||||
Card.reconnectNumber = 0;
|
||||
clearTimeout(Card.reconnectTimeout);
|
||||
|
||||
const result = confirm(`З'єднання розірвано! Перепідключитись?`);
|
||||
if (result) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
} else {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.cloud.start(Card.username);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
Card.socket.onerror = function (error) {
|
||||
console.log(`[WebSocket | error]`);
|
||||
Card.cloud.status('err');
|
||||
};
|
||||
},
|
||||
mess: ({ number, id, update, time }) => {
|
||||
const pos = Card.listApartment[number].map(e => e.id).indexOf(id);
|
||||
let apartment = Card.listApartment[number][pos];
|
||||
|
||||
|
||||
let status = document.getElementById(`status_${id}`);
|
||||
let description = document.getElementById(`description_${id}`);
|
||||
|
||||
let date = () => {
|
||||
if (!update && !time) {
|
||||
return apartment.updated_at;
|
||||
} else if (update && !time) {
|
||||
return getTimeInSeconds();
|
||||
} else if (update && time) {
|
||||
return getTimeInSeconds(time);
|
||||
}
|
||||
}
|
||||
|
||||
apartment.description = description.value;
|
||||
apartment.status = Number(status.value);
|
||||
apartment.updated_at = date();
|
||||
|
||||
status.style.backgroundColor = Card.color_status[status.value][0];
|
||||
status.style.color = Card.color_status[status.value][1];
|
||||
status.style.border = `1px solid ${Card.color_status[status.value][1]}`;
|
||||
|
||||
let message = {
|
||||
event: 'message',
|
||||
id: getTimeInSeconds(),
|
||||
date: getTimeInSeconds(),
|
||||
|
||||
username: Card.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,
|
||||
sheep_id: USER.id
|
||||
}
|
||||
}
|
||||
|
||||
if (Card.socket && Card.socket.readyState === WebSocket.OPEN) {
|
||||
Card.socket.send(JSON.stringify(message));
|
||||
} else {
|
||||
console.warn("WebSocket не підключено. Повідомлення не надіслано.");
|
||||
const result = confirm(`З'єднання розірвано! Перепідключитись?`);
|
||||
if (result) {
|
||||
Card.getEntrances({ update: true });
|
||||
Card.start(Card.username);
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
let sort_mode = localStorage.getItem('sort_mode') ?? '1';
|
||||
|
||||
if (sort_mode == '3') {
|
||||
let child = document.getElementById(`card_${apartment.id}`);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).removeChild(child);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).append(child);
|
||||
child.style.border = "1px solid var(--PrimaryColor)";
|
||||
} else if (sort_mode == '4') {
|
||||
let child = document.getElementById(`card_${apartment.id}`);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).removeChild(child);
|
||||
document.getElementById(`apartments_${apartment.entrance_id}`).prepend(child);
|
||||
child.style.border = "1px solid var(--PrimaryColor)";
|
||||
}
|
||||
}
|
||||
},
|
||||
update: (message) => {
|
||||
if (!document.getElementById(`status_${message.data.id}`)) return;
|
||||
|
||||
document.getElementById(`card_${message.data.id}`).style.backgroundColor = Card.color_status[message.data.status][0];
|
||||
document.getElementById(`card_${message.data.id}`).style.color = Card.color_status[message.data.status][1];
|
||||
document.getElementById(`card_${message.data.id}`).style.border = `1px solid ${Card.color_status[message.data.status][1]}`;
|
||||
|
||||
document.getElementById(`status_${message.data.id}`).style.backgroundColor = Card.color_status[message.data.status][0];
|
||||
document.getElementById(`status_${message.data.id}`).style.color = Card.color_status[message.data.status][1];
|
||||
document.getElementById(`status_${message.data.id}`).style.border = `1px solid ${Card.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_text_${message.data.id}`).innerText = formattedDateTime(message.data.updated_at);
|
||||
}
|
||||
},
|
||||
getEntrances: ({ house_id = house, update = false }) => {
|
||||
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) {
|
||||
Card.listEntrances = data;
|
||||
|
||||
const element_list = document.getElementById('list');
|
||||
|
||||
if (update) {
|
||||
for (let i = 0; i < Card.listEntrances.length; i++) {
|
||||
const element = Card.listEntrances[i];
|
||||
Card.getApartment({ id: element.id, number: element.entrance_number, update: update });
|
||||
}
|
||||
} else {
|
||||
element_list.innerHTML = "";
|
||||
for (let i = 0; i < Card.listEntrances.length; i++) {
|
||||
const element = Card.listEntrances[i];
|
||||
|
||||
let status = () => {
|
||||
if ((element.history.name == "Групова" || element.history.name == USER.name) && element.working) return "open";
|
||||
else if (USER.mode == 2 || (USER.mode == 1 && USER.possibilities.can_manager_territory)) return "close";
|
||||
else 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>'
|
||||
}
|
||||
|
||||
element_list.innerHTML += `
|
||||
<details ${status()}>
|
||||
<summary>
|
||||
<p>${element.title}</p>
|
||||
${statusIcon()}
|
||||
</summary>
|
||||
<div id="apartments_${element.id}" class="apartments_list">
|
||||
|
||||
</div>
|
||||
</details>
|
||||
`;
|
||||
Card.getApartment({ id: element.id, number: element.entrance_number, update: false });
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
getApartment: ({ id, number, update }) => {
|
||||
const uuid = localStorage.getItem('uuid');
|
||||
const URL = `${CONFIG.api}/apartment/${id}`;
|
||||
fetch(URL, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": uuid
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
Card.listApartment[number] = data;
|
||||
|
||||
if (update) {
|
||||
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)
|
||||
|
||||
document.getElementById(`card_${element.id}`).setAttribute('style', `border: 1px solid ${Card.color_status[element.status][1]};background: ${Card.color_status[element.status][0]};color: ${Card.color_status[element.status][1]};`);
|
||||
document.getElementById(`status_${element.id}`).value = element.status;
|
||||
document.getElementById(`status_${element.id}`).setAttribute('style', `background-color: ${Card.color_status[element.status][0]}; color: ${Card.color_status[element.status][1]}; border: 1px solid ${Card.color_status[element.status][1]};`);
|
||||
document.getElementById(`date_${element.id}`).setAttribute('onclick', `Card.dateEditor.open({id: ${element.id}, number: ${number}, updated_at: ${element.updated_at}})`);
|
||||
document.getElementById(`date_text_${element.id}`).innerText = element.updated_at ? formattedDateTime(element.updated_at) : "0.0.0000 00:00";
|
||||
document.getElementById(`description_${element.id}`).innerText = element.description ?? "";
|
||||
}
|
||||
} else {
|
||||
let sort_mode = localStorage.getItem('sort_mode') ?? 1;
|
||||
|
||||
if (sort_mode == "1")
|
||||
data.sort((a, b) => a.apartment_number - b.apartment_number);
|
||||
else if (sort_mode == "2")
|
||||
data.sort((a, b) => b.apartment_number - a.apartment_number);
|
||||
else if (sort_mode == "3")
|
||||
data.sort((a, b) => a.updated_at - b.updated_at);
|
||||
else if (sort_mode == "4")
|
||||
data.sort((a, b) => b.updated_at - a.updated_at);
|
||||
else
|
||||
data.sort((a, b) => a.apartment_number - b.apartment_number);
|
||||
|
||||
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.possibilities.can_manager_territory) return '';
|
||||
else if (element.status == 2) return "disabled";
|
||||
}
|
||||
|
||||
document.getElementById(`apartments_${id}`).innerHTML += `
|
||||
<div id="card_${element.id}" style="border: 1px solid ${Card.color_status[element.status][1]};background: ${Card.color_status[element.status][0]};color: ${Card.color_status[element.status][1]};">
|
||||
<div class="info">
|
||||
<span>кв.${element.title}</span>
|
||||
<select id="status_${element.id}" onchange="Card.cloud.mess({ number: ${number}, id: ${element.id}, update: true})" style="background-color: ${Card.color_status[element.status][0]}; color: ${Card.color_status[element.status][1]}; border: 1px solid ${Card.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>
|
||||
<button placeholder="Дата" id="date_${element.id}" onclick="Card.dateEditor.open({id: ${element.id}, number: ${number}, updated_at: ${element.updated_at}})" ${disabled()}>
|
||||
<p id="date_text_${element.id}">${element.updated_at ? formattedDateTime(element.updated_at) : "0.0.0000 00:00"}</p>
|
||||
<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>
|
||||
<textarea onchange="Card.cloud.mess({ number: ${number}, id: ${element.id}})" id="description_${element.id}" placeholder="Нотатки..." ${disabled()}}>${element.description ?? ""}</textarea>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
sort: (mode, load) => {
|
||||
const sortIds = ['sort_1', 'sort_2', 'sort_3', 'sort_4'];
|
||||
|
||||
sortIds.forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.setAttribute('data-state', '');
|
||||
});
|
||||
|
||||
let index = parseInt(mode, 10);
|
||||
if (isNaN(index) || index < 1 || index > 4) index = 1;
|
||||
|
||||
const activeEl = document.getElementById(`sort_${index}`);
|
||||
if (activeEl) activeEl.setAttribute('data-state', 'active');
|
||||
|
||||
localStorage.setItem('sort_mode', index.toString());
|
||||
|
||||
if (!load) Card.getEntrances({ update: false });
|
||||
},
|
||||
dateEditor: {
|
||||
open: ({ id, number, updated_at }) => {
|
||||
const block = document.getElementById('card-new-date');
|
||||
const card_new_date_input = document.getElementById('card-new-date-input');
|
||||
const card_new_date_button = document.getElementById('card-new-date-button');
|
||||
|
||||
let now = new Date(updated_at);
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
now = now.toISOString().slice(0, 16)
|
||||
|
||||
card_new_date_input.value = now;
|
||||
card_new_date_input.setAttribute("onchange", `Card.dateEditor.edit({ id: ${id}, number: ${number} })`)
|
||||
card_new_date_button.setAttribute("onclick", `Card.dateEditor.edit({ id: ${id}, number: ${number}, type: 'now'})`)
|
||||
|
||||
block.style.display = "";
|
||||
setTimeout(() => {
|
||||
block.style.opacity = "1";
|
||||
}, 100)
|
||||
|
||||
},
|
||||
close: () => {
|
||||
const block = document.getElementById('card-new-date');
|
||||
|
||||
block.style.opacity = "0";
|
||||
setTimeout(() => {
|
||||
block.style.display = "none";
|
||||
}, 200)
|
||||
},
|
||||
edit: ({ id, number, type }) => {
|
||||
const card_new_date_input = document.getElementById('card-new-date-input');
|
||||
|
||||
if (type == "now") {
|
||||
Card.cloud.mess({ number: number, id: id, update: true });
|
||||
} else {
|
||||
if (card_new_date_input.value) {
|
||||
let date = new Date(card_new_date_input.value);
|
||||
const timestamp = date.getTime();
|
||||
Card.cloud.mess({ number: number, id: id, update: true, time: timestamp });
|
||||
} else {
|
||||
Card.cloud.mess({ number: number, id: id });
|
||||
}
|
||||
}
|
||||
|
||||
Card.dateEditor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,150 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 20px 20px 0 20px;
|
||||
}
|
||||
|
||||
|
||||
.page-card>.list-controls {
|
||||
padding: 10px;
|
||||
margin: 0px 0 10px 0;
|
||||
background: var(--ColorThemes1);
|
||||
color: var(--ColorThemes3);
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#page-card-sort {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-card-sort button {
|
||||
display: none;
|
||||
font-size: 18px;
|
||||
background: 0;
|
||||
cursor: pointer;
|
||||
min-width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin-right: 10px;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
color: var(--ColorThemes3);
|
||||
border-radius: calc(var(--border-radius) - 5px - 2px);
|
||||
border: 1px solid var(--ColorThemes0);
|
||||
}
|
||||
|
||||
#page-card-sort button[data-state="active"] {
|
||||
background: var(--PrimaryColor);
|
||||
}
|
||||
|
||||
#page-card-sort button:hover {
|
||||
background: var(--ColorThemes3);
|
||||
}
|
||||
|
||||
#page-card-sort button>svg {
|
||||
width: 22px;
|
||||
fill: var(--PrimaryColorText);
|
||||
}
|
||||
|
||||
#page-card-sort button:hover svg {
|
||||
fill: var(--ColorThemes1);
|
||||
}
|
||||
|
||||
#page-card-sort button:hover {
|
||||
display: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#page-card-sort button[data-state="active"] {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-card-status {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#page-card-status>div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-card-status>div[data-state="active"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
#page-card-status>div>svg {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: var(--ColorThemes3);
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
|
||||
#card-new-date {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
background: rgb(31 31 33 / 41%);
|
||||
transition: all .2s ease 0s;
|
||||
}
|
||||
|
||||
#card-new-date>.mess {
|
||||
display: flex;
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
border: 1px solid var(--ColorThemes2);
|
||||
background: var(--ColorThemes0);
|
||||
box-shadow: 0px 2px 3px rgb(0 0 0 / 5%), 0px 5px 15px rgb(0 0 0 / 5%), 0px 4px 8px rgb(0 0 0 / 5%), 0px 0px 1px rgb(0 0 0 / 5%);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -50px;
|
||||
margin-left: -160px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
padding: 10px;
|
||||
border-radius: 15px;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
#card-new-date>.mess>button {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background-color: var(--PrimaryColor);
|
||||
color: var(--PrimaryColorText);
|
||||
cursor: pointer;
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#card-new-date>.mess>input {
|
||||
width: calc(100% - 10px);
|
||||
min-width: 140px;
|
||||
padding: 0 5px;
|
||||
border-radius: 6px;
|
||||
height: 30px;
|
||||
background-color: var(--ColorThemes2);
|
||||
color: var(--ColorThemes3);
|
||||
cursor: pointer;
|
||||
font-size: var(--FontSize4);
|
||||
font-weight: 400;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
Reference in New Issue
Block a user