Enhance calendar layout and duty list rendering
- Introduced a sticky header for the calendar to improve navigation. - Updated the duty list display to highlight today's date with a distinct style. - Added new CSS styles for better visual presentation of duty days and improved layout consistency.
This commit is contained in:
@@ -368,6 +368,7 @@
|
|||||||
grouped[date].push(d);
|
grouped[date].push(d);
|
||||||
});
|
});
|
||||||
const dates = Object.keys(grouped).sort();
|
const dates = Object.keys(grouped).sort();
|
||||||
|
const todayKey = localDateString(new Date());
|
||||||
let html = "";
|
let html = "";
|
||||||
/** Format UTC date from ISO string as DD.MM for display. */
|
/** Format UTC date from ISO string as DD.MM for display. */
|
||||||
function formatDateKey(isoDateStr) {
|
function formatDateKey(isoDateStr) {
|
||||||
@@ -376,9 +377,16 @@
|
|||||||
const month = String(d.getUTCMonth() + 1).padStart(2, "0");
|
const month = String(d.getUTCMonth() + 1).padStart(2, "0");
|
||||||
return day + "." + month;
|
return day + "." + month;
|
||||||
}
|
}
|
||||||
|
/** Format YYYY-MM-DD as DD.MM for list header. */
|
||||||
|
function dateKeyToDDMM(key) {
|
||||||
|
return key.slice(8, 10) + "." + key.slice(5, 7);
|
||||||
|
}
|
||||||
dates.forEach(function (date) {
|
dates.forEach(function (date) {
|
||||||
const list = grouped[date];
|
const list = grouped[date];
|
||||||
html += "<h2>" + date + "</h2>";
|
const isToday = date === todayKey;
|
||||||
|
const dayBlockClass = "duty-list-day" + (isToday ? " duty-list-day--today" : "");
|
||||||
|
const titleText = isToday ? "Сегодня, " + dateKeyToDDMM(date) : dateKeyToDDMM(date);
|
||||||
|
html += "<div class=\"" + dayBlockClass + "\"><h2 class=\"duty-list-day-title\">" + escapeHtml(titleText) + "</h2>";
|
||||||
list.forEach(function (d) {
|
list.forEach(function (d) {
|
||||||
const startDate = new Date(d.start_at);
|
const startDate = new Date(d.start_at);
|
||||||
const endDate = new Date(d.end_at);
|
const endDate = new Date(d.end_at);
|
||||||
@@ -396,6 +404,7 @@
|
|||||||
}
|
}
|
||||||
html += "<div class=\"" + itemClass + "\"><span class=\"duty-item-type\">" + escapeHtml(typeLabel) + "</span> <span class=\"name\">" + escapeHtml(d.full_name) + "</span><div class=\"time\">" + timeOrRange + "</div></div>";
|
html += "<div class=\"" + itemClass + "\"><span class=\"duty-item-type\">" + escapeHtml(typeLabel) + "</span> <span class=\"name\">" + escapeHtml(d.full_name) + "</span><div class=\"time\">" + timeOrRange + "</div></div>";
|
||||||
});
|
});
|
||||||
|
html += "</div>";
|
||||||
});
|
});
|
||||||
dutyListEl.innerHTML = html;
|
dutyListEl.innerHTML = html;
|
||||||
}
|
}
|
||||||
@@ -527,8 +536,20 @@
|
|||||||
loadMonth();
|
loadMonth();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function bindStickyScrollShadow() {
|
||||||
|
var stickyEl = document.getElementById("calendarSticky");
|
||||||
|
if (!stickyEl || document._stickyScrollBound) return;
|
||||||
|
document._stickyScrollBound = true;
|
||||||
|
function updateScrolled() {
|
||||||
|
stickyEl.classList.toggle("is-scrolled", window.scrollY > 0);
|
||||||
|
}
|
||||||
|
window.addEventListener("scroll", updateScrolled, { passive: true });
|
||||||
|
updateScrolled();
|
||||||
|
}
|
||||||
|
|
||||||
runWhenReady(function () {
|
runWhenReady(function () {
|
||||||
requireTelegramOrLocalhost(function () {
|
requireTelegramOrLocalhost(function () {
|
||||||
|
bindStickyScrollShadow();
|
||||||
loadMonth();
|
loadMonth();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,15 +8,17 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<header class="header">
|
<div class="calendar-sticky" id="calendarSticky">
|
||||||
<button type="button" class="nav" id="prevMonth" aria-label="Предыдущий месяц">‹</button>
|
<header class="header">
|
||||||
<h1 class="title" id="monthTitle"></h1>
|
<button type="button" class="nav" id="prevMonth" aria-label="Предыдущий месяц">‹</button>
|
||||||
<button type="button" class="nav" id="nextMonth" aria-label="Следующий месяц">›</button>
|
<h1 class="title" id="monthTitle"></h1>
|
||||||
</header>
|
<button type="button" class="nav" id="nextMonth" aria-label="Следующий месяц">›</button>
|
||||||
<div class="weekdays">
|
</header>
|
||||||
<span>Пн</span><span>Вт</span><span>Ср</span><span>Чт</span><span>Пт</span><span>Сб</span><span>Вс</span>
|
<div class="weekdays">
|
||||||
|
<span>Пн</span><span>Вт</span><span>Ср</span><span>Чт</span><span>Пт</span><span>Сб</span><span>Вс</span>
|
||||||
|
</div>
|
||||||
|
<div class="calendar" id="calendar"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="calendar" id="calendar"></div>
|
|
||||||
<div class="duty-list" id="dutyList"></div>
|
<div class="duty-list" id="dutyList"></div>
|
||||||
<div class="loading" id="loading">Загрузка…</div>
|
<div class="loading" id="loading">Загрузка…</div>
|
||||||
<div class="error" id="error" hidden></div>
|
<div class="error" id="error" hidden></div>
|
||||||
|
|||||||
@@ -73,6 +73,19 @@ body {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calendar-sticky {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background: var(--bg);
|
||||||
|
padding-bottom: 12px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-sticky.is-scrolled {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
.calendar {
|
.calendar {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(7, 1fr);
|
grid-template-columns: repeat(7, 1fr);
|
||||||
@@ -215,6 +228,26 @@ body {
|
|||||||
margin: 0 0 8px 0;
|
margin: 0 0 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.duty-list-day {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duty-list-day--today .duty-list-day-title {
|
||||||
|
color: var(--today);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duty-list-day--today .duty-list-day-title::before {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
width: 4px;
|
||||||
|
height: 1em;
|
||||||
|
background: var(--today);
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-right: 8px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
.duty-item {
|
.duty-item {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 5.5em 1fr;
|
grid-template-columns: 5.5em 1fr;
|
||||||
|
|||||||
Reference in New Issue
Block a user