verstak/contrib/plugins/calendar/panels/calendar.html

146 lines
5.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Календарь</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #1a1b1e; color: #e4e4e7; padding: 20px; }
h1 { font-size: 24px; margin-bottom: 16px; color: #fff; }
.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
.nav-btn { background: #27272a; border: 1px solid #3f3f46; color: #e4e4e7;
padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 14px; }
.nav-btn:hover { background: #3f3f46; }
.calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.day-header { text-align: center; font-size: 12px; color: #a1a1aa; padding: 8px 0;
font-weight: 600; text-transform: uppercase; }
.day { aspect-ratio: 1; display: flex; flex-direction: column; align-items: center;
justify-content: center; border-radius: 8px; cursor: pointer; font-size: 14px;
background: #27272a; border: 1px solid #3f3f46; position: relative; }
.day:hover { background: #3f3f46; }
.day.other { opacity: 0.3; }
.day.today { border-color: #3b82f6; background: #1e3a5f; }
.day.has-event::after { content: ''; position: absolute; bottom: 6px; width: 6px; height: 6px;
border-radius: 50%; background: #3b82f6; }
.day.selected { border-color: #8b5cf6; box-shadow: 0 0 0 2px #8b5cf6; }
.events { margin-top: 20px; }
.event { padding: 12px; background: #27272a; border: 1px solid #3f3f46;
border-radius: 8px; margin-bottom: 8px; display: flex; justify-content: space-between; }
.event-title { font-weight: 500; }
.event-time { color: #a1a1aa; font-size: 13px; }
.event-actions { display: flex; gap: 8px; }
.event-actions button { background: none; border: none; color: #a1a1aa;
cursor: pointer; padding: 2px 6px; border-radius: 4px; }
.event-actions button:hover { background: #3f3f46; color: #ef4444; }
</style>
</head>
<body>
<div class="header">
<button class="nav-btn" onclick="prevMonth()"></button>
<h1 id="month-title">Июнь 2025</h1>
<button class="nav-btn" onclick="nextMonth()"></button>
</div>
<div class="calendar-grid" id="calendar"></div>
<div class="events" id="events"></div>
<script>
const MONTHS = ['Январь','Февраль','Март','Апрель','Май','Июнь',
'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'];
const DAYS = ['Пн','Вт','Ср','Чт','Пт','Сб','Вс'];
let currentDate = new Date();
let selectedDate = null;
let events = [];
function render() {
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
document.getElementById('month-title').textContent = MONTHS[month] + ' ' + year;
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const startDay = firstDay.getDay() || 7; // Mon=1, Sun=7
const grid = document.getElementById('calendar');
grid.innerHTML = DAYS.map(d => `<div class="day-header">${d}</div>`).join('');
// Previous month padding
const prevLastDay = new Date(year, month, 0).getDate();
for (let i = startDay - 2; i >= 0; i--) {
grid.innerHTML += `<div class="day other">${prevLastDay - i}</div>`;
}
// Current month
const today = new Date();
for (let d = 1; d <= lastDay.getDate(); d++) {
const dateStr = `${year}-${String(month+1).padStart(2,'0')}-${String(d).padStart(2,'0')}`;
const isToday = today.getFullYear() === year && today.getMonth() === month && today.getDate() === d;
const hasEvent = events.some(e => e.date === dateStr);
const isSelected = selectedDate === dateStr;
let cls = 'day';
if (isToday) cls += ' today';
if (hasEvent) cls += ' has-event';
if (isSelected) cls += ' selected';
grid.innerHTML += `<div class="${cls}" onclick="selectDate('${dateStr}')">${d}</div>`;
}
renderEvents();
}
function renderEvents() {
const el = document.getElementById('events');
if (!selectedDate) { el.innerHTML = '<p style="color:#a1a1aa">Выберите дату</p>'; return; }
const dayEvents = events.filter(e => e.date === selectedDate);
if (dayEvents.length === 0) {
el.innerHTML = '<p style="color:#a1a1aa">Нет событий на этот день</p>';
return;
}
el.innerHTML = '<h2 style="font-size:18px;margin-bottom:12px">События</h2>';
dayEvents.forEach(ev => {
const time = ev.time || 'весь день';
el.innerHTML += `
<div class="event">
<div>
<div class="event-title">${ev.title}</div>
<div class="event-time">${time}${ev.location ? ' · ' + ev.location : ''}</div>
</div>
<div class="event-actions">
<button onclick="deleteEvent('${ev.id}')">✕</button>
</div>
</div>`;
});
}
function selectDate(dateStr) {
selectedDate = dateStr;
render();
}
function prevMonth() {
currentDate.setMonth(currentDate.getMonth() - 1);
selectedDate = null;
render();
}
function nextMonth() {
currentDate.setMonth(currentDate.getMonth() + 1);
selectedDate = null;
render();
}
async function loadEvents() {
// In production, this would call verstak HTTP endpoint or Wails binding
// For now, data is injected via __VERSTAK_DATA__
events = window.__VERSTAK_DATA__ || [];
render();
}
loadEvents();
</script>
</body>
</html>