Додан моніторінг застосунку
Додани веб компоненти карточок територій та повідомлень
This commit is contained in:
323
web/lib/customElements/territoryCard.js
Normal file
323
web/lib/customElements/territoryCard.js
Normal file
@@ -0,0 +1,323 @@
|
||||
const appTerritoryCardStyles = new CSSStyleSheet();
|
||||
appTerritoryCardStyles.replaceSync(`
|
||||
:host {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
}
|
||||
@media (max-width: 2300px) {
|
||||
:host {
|
||||
width: calc((100% / 5) - 40px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1960px) {
|
||||
:host {
|
||||
width: calc((100% / 4) - 40px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1640px) {
|
||||
:host {
|
||||
width: calc((100% / 3) - 40px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
:host {
|
||||
width: calc((100% / 2) - 40px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 650px) {
|
||||
:host {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.card {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background-color: var(--ColorThemes2, #525151);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border-radius: calc(var(--border-radius, 15px) - 5px);
|
||||
}
|
||||
@media(hover: hover) {
|
||||
.card:hover {
|
||||
opacity: 0.8;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
filter: blur(3px);
|
||||
}
|
||||
.contents {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: rgb(64 64 64 / 0.7);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
border-radius: calc(var(--border-radius, 15px) - 5px);
|
||||
}
|
||||
.address {
|
||||
margin: 10px;
|
||||
height: 35px;
|
||||
display: flex;
|
||||
background: var(--ColorThemes0, #1c1c19);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: var(--FontSize3, 14px);
|
||||
color: var(--ColorThemes3, #f3f3f3);
|
||||
border-radius: calc(var(--border-radius, 15px) - 5px - 4px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Стили для режима 'sheep' */
|
||||
.sheep {
|
||||
margin: 10px;
|
||||
max-height: 50px;
|
||||
border-radius: calc(var(--border-radius, 15px) - 5px - 4px);
|
||||
padding: 10px 0;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
background: var(--PrimaryColor, #cb9e44);
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.sheep span {
|
||||
color: var(--PrimaryColorText, #2e2e2e);
|
||||
font-size: var(--FontSize3, 14px);
|
||||
font-weight: 400;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.sheep p {
|
||||
color: var(--PrimaryColorText, #2e2e2e);
|
||||
font-size: var(--FontSize4, 15px);
|
||||
font-weight: 400;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
/* Стили для режима 'info' (прогресс) */
|
||||
.info {
|
||||
margin: 10px;
|
||||
}
|
||||
.info > div {
|
||||
position: relative;
|
||||
background-color: var(--ColorThemes0, #1c1c19);;
|
||||
border-radius: calc(var(--border-radius, 15px) - 5px - 4px);
|
||||
overflow: hidden;
|
||||
padding: 5px 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 25px;
|
||||
}
|
||||
.info span {
|
||||
z-index: 2;
|
||||
font-size: var(--FontSize1, 12px);
|
||||
color: var(--ColorThemes3, #f3f3f3);
|
||||
}
|
||||
.info p {
|
||||
z-index: 2;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
font-size: var(--FontSize3, 14px);
|
||||
color: var(--ColorThemes3, #f3f3f3);
|
||||
}
|
||||
.progress {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
background-color: var(--PrimaryColor, #cb9e44);
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
a {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 10;
|
||||
}
|
||||
`);
|
||||
|
||||
class AppTerritoryCard extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
|
||||
if (this.shadowRoot.adoptedStyleSheets) {
|
||||
this.shadowRoot.adoptedStyleSheets = [appTerritoryCardStyles];
|
||||
}
|
||||
}
|
||||
|
||||
// Определяем, какие атрибуты будем отслеживать
|
||||
static get observedAttributes() {
|
||||
return ['image', 'address', 'sheep', 'link', 'atWork', 'quantity'];
|
||||
}
|
||||
|
||||
get image() {
|
||||
return this.getAttribute('image');
|
||||
}
|
||||
set image(newValue) {
|
||||
if (newValue === null) {
|
||||
this.removeAttribute('image');
|
||||
} else {
|
||||
this.setAttribute('image', newValue);
|
||||
}
|
||||
}
|
||||
|
||||
get address() {
|
||||
return this.getAttribute('address');
|
||||
}
|
||||
set address(newValue) {
|
||||
if (newValue === null) {
|
||||
this.removeAttribute('address');
|
||||
} else {
|
||||
this.setAttribute('address', newValue);
|
||||
}
|
||||
}
|
||||
|
||||
get sheep() {
|
||||
return this.getAttribute('sheep');
|
||||
}
|
||||
set sheep(newValue) {
|
||||
if (newValue === null) {
|
||||
this.removeAttribute('sheep');
|
||||
} else {
|
||||
this.setAttribute('sheep', newValue);
|
||||
}
|
||||
}
|
||||
|
||||
get link() {
|
||||
return this.getAttribute('link');
|
||||
}
|
||||
set link(newValue) {
|
||||
if (newValue === null) {
|
||||
this.removeAttribute('link');
|
||||
} else {
|
||||
this.setAttribute('link', newValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get atWork() {
|
||||
return this.getAttribute('atWork');
|
||||
}
|
||||
set atWork(newValue) {
|
||||
if (newValue === null) {
|
||||
this.removeAttribute('atWork');
|
||||
} else {
|
||||
this.setAttribute('atWork', String(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
get quantity() {
|
||||
return this.getAttribute('quantity');
|
||||
}
|
||||
set quantity(newValue) {
|
||||
if (newValue === null) {
|
||||
this.removeAttribute('quantity');
|
||||
} else {
|
||||
this.setAttribute('quantity', String(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
// Вызывается при добавлении элемента в DOM
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
// Вызывается при изменении одного из отслеживаемых атрибутов
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
if (oldValue !== newValue) {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const image = this.getAttribute('image') || '';
|
||||
const address = this.getAttribute('address') || '';
|
||||
const sheep = this.getAttribute('sheep'); // Может быть null или ""
|
||||
const link = this.getAttribute('link') || '#';
|
||||
const atWork = this.getAttribute('atWork'); // Может быть null
|
||||
const quantity = this.getAttribute('quantity'); // Может быть null
|
||||
|
||||
// --- Логика определения контента ---
|
||||
let contentHTML = '';
|
||||
const isProgressMode = atWork !== null && quantity !== null && !isNaN(parseInt(atWork)) && !isNaN(parseInt(quantity));
|
||||
const hasSheep = sheep !== null && sheep !== '';
|
||||
|
||||
if (isProgressMode) {
|
||||
// Режим прогресса (свободные подъезды)
|
||||
const atWorkNum = parseInt(atWork);
|
||||
const quantityNum = parseInt(quantity);
|
||||
|
||||
const free = quantityNum - atWorkNum;
|
||||
const progressPercent = quantityNum > 0 ? (atWorkNum / quantityNum) * 100 : 100;
|
||||
|
||||
contentHTML = `
|
||||
<div class="info">
|
||||
<div>
|
||||
<div class="progress" style="width: ${progressPercent}%"></div>
|
||||
<span>Вільні під'їзди:</span>
|
||||
<p>${free} / ${quantityNum}</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else if (sheep !== null && sheep !== '') {
|
||||
// Режим ответственного
|
||||
contentHTML = `
|
||||
<div class="sheep">
|
||||
<span>Територію опрацьовує:</span>
|
||||
<p>${sheep}</p>
|
||||
</div>
|
||||
`;
|
||||
} else if (sheep !== null) {
|
||||
// Режим "не опрацьовується"
|
||||
contentHTML = `
|
||||
<div class="sheep">
|
||||
<span>Територія не опрацьовується</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// --- Сборка всего шаблона ---
|
||||
this.shadowRoot.innerHTML = `
|
||||
<div class="card">
|
||||
<img src="${image}" alt="${address}" />
|
||||
<div class="contents">
|
||||
<h1 class="address">${address}</h1>
|
||||
${contentHTML}
|
||||
</div>
|
||||
<a href="${link}" data-route=""></a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Регистрируем веб-компонент
|
||||
customElements.define('app-territory-card', AppTerritoryCard);
|
||||
|
||||
// document.getElementById('app-territory-card-1').setAttribute('sheep', 'test')
|
||||
|
||||
Reference in New Issue
Block a user