Код:
<!--HTML-->
<style>
.advent-calendar {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.calendar-cell {
position: relative;
aspect-ratio: 1;
border: 2px solid #efefef;
border-radius: 10px;
/*background: linear-gradient(90deg, #21985e 0%, #ffffff 99%, #ffffff 49%);*/
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 1.5em;
overflow: hidden;
transition: all 0.3s ease;
}
.cell-content {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
padding: 10px;
box-sizing: border-box;
text-align: center;
word-wrap: break-word;
overflow: hidden;
font-size: 12px;
background: #efefef;
}
/* Стили для закрытых ячеек */
.closed .cell-content {
background-image: url(https://upforme.ru/uploads/0010/a8/ca/7506/19647.png);
font-size: 1.2em;
color: transparent;
}
/* Стили для открытых ячеек */
.opened .cell-content {
background: white;
color: #333;
font-size: 12px;
font-weight: normal;
line-height: 1.3;
overflow-y: auto;
flex-direction: column;
gap: 5px;
}
.opened .cell-content a {
color: #27ae60;
text-decoration: none;
font-weight: bold;
padding: 3px 8px;
border: 1px solid #27ae60;
border-radius: 5px;
background: white;
transition: all 0.3s ease;
font-size: 0.8em;
text-transform: uppercase;
}
.opened .cell-content a:hover {
background: white;
border: 1px solid black;
color: black;
}
/* Стили для завершенных ячеек */
.completed .cell-content {
/*background-size: cover;*/
background-position: center;
background-repeat: no-repeat;
position: relative;
}
.completed .cell-date {
display: none;
}
.completed .cell-content::after {
content: attr(title);
position: absolute;
bottom: 0;
left: 0;
right: 0;
/* background: rgba(0, 0, 0, 0.7); */
color: black;
padding: 5px;
font-size: 10px;
text-align: center;
font-weight: normal;
text-align: center;
}
.cell-number {
position: absolute;
top: 5px;
right: 5px;
color: black;
padding: 2px 8px;
border-radius: 50%;
font-size: 0.8em;
z-index: 2;
}
.cell-date {
position: absolute;
bottom: 5px;
left: 5px;
background: rgba(0,0,0,0.6);
color: white;
padding: 2px 6px;
border-radius: 5px;
font-size: 0.6em;
z-index: 2;
}
/* Индикатор статуса */
.status-indicator {
position: absolute;
top: 5px;
left: 5px;
padding: 2px 6px;
border-radius: 10px;
font-size: 0.6em;
background: rgba(0,0,0,0.7);
text-transform: uppercase;
color: white;
z-index: 2;
}
.closed .status-indicator {
background: #bc1131;
}
.opened .status-indicator {
background: #f39c12;
}
.completed .status-indicator {
background: #27ae60;
}
@media (max-width: 768px) {
.advent-calendar {
grid-template-columns: repeat(2, 1fr);
}
.opened .cell-content {
font-size: 0.75em;
}
}
@media (max-width: 480px) {
.advent-calendar {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="advent-calendar" id="adventCalendar">
<!-- Ячейки будут созданы через JavaScript -->
</div>
<script>
// Данные для адвент-календаря
const calendarData = {
completed: [
['1','https://i.imgur.com/TTKMSyE.png','50 фишек тотемов'],
['2','https://i.imgur.com/rHIceK0.png','аватар в подарок'],
['3','https://i.imgur.com/DX69oiJ.png','случайный необычный купон'],
['4','https://i.imgur.com/ZBpk6Xr.png','25 000 сакр'],
['5','https://i.imgur.com/7i7mtQD.png','случайный ключ'],
['6','https://i.imgur.com/7hKbPsS.png','подарок в профиль'],
['7','https://i.imgur.com/Fj9vd6p.png','специальная плашка'],
['8','https://i.imgur.com/TTKMSyE.png','50 фишек тотемов'],
['9','https://i.imgur.com/cCpA6TY.png','тотем воин'],
['10','https://i.imgur.com/ZBpk6Xr.png','50 000 сакр'],
['11','https://i.imgur.com/WPzCJ12.png','случайный редкий купон'],
['12','https://i.imgur.com/oJgatHn.png','тотем люцифер'],
['13','https://i.imgur.com/TaHIWuO.png','иконка в подарок'],
['14','https://i.imgur.com/Nhmg1eG.png','подарок в профиль'],
['15','https://i.imgur.com/TTKMSyE.png','50 фишек тотемов'],
['16','https://i.imgur.com/rHIceK0.png','аватар в подарок'],
['17','https://i.imgur.com/7i7mtQD.png','случайный ключ'],
['18','https://i.imgur.com/WFDkjhG.png','тотем золотой воин'],
['19','https://i.imgur.com/7i7mtQD.png','случайный ключ'],
['20','https://i.imgur.com/PD4qXI6.png','случайный эпический купон'],
['21','https://i.imgur.com/TaHIWuO.png','иконка в подарок'],
['22','https://i.imgur.com/IF3GSet.png','подарок в профиль'],
['23','https://i.imgur.com/ZBpk6Xr.png','100 000 сакр'],
['24','https://i.imgur.com/svt1U8O.png','тотем викинг'],
['25','https://i.imgur.com/TTKMSyE.png','50 фишек тотемов'],
['26','https://i.imgur.com/Fj9vd6p.png','специальная плашка'],
['27','https://i.imgur.com/7i7mtQD.png','универсальный ключ'],
['28','https://i.imgur.com/ZBpk6Xr.png','150 000 сакр'],
['29','https://i.imgur.com/TaHIWuO.png','иконка в подарок'],
['30','https://i.imgur.com/PD4qXI6.png','случайный эпический купон'],
['31','https://i.imgur.com/ZBpk6Xr.png','200 000 сакр'],
],
opened: [
['1', 'поздравить сакру с др в теме', 'https://sacramento.rusff.me/viewtopic.php?id=50878#p5167068' ],
['2', 'отметиться в онлайне', 'https://sacramento.rusff.me/viewtopic.php?id=50521' ],
['3', 'выложить вечериночный пост в инстаграм', 'https://sacramento.rusff.me/viewtopic.php?id=50110' ],
['4', 'отметиться в я люблю тебя (100 символов)', 'https://sacramento.rusff.me/viewtopic.php?id=50527' ],
['5', 'поставить 10 плюсов', '' ],
['6', 'отметиться в смайломании', 'https://sacramento.rusff.me/viewtopic.php?id=49683' ],
['7', 'отметиться в топотыке', 'https://sacramento.rusff.me/viewtopic.php?id=50548' ],
['8', 'выложить летнюю фотку в инсту', 'https://sacramento.rusff.me/viewtopic.php?id=50110' ],
['9', 'отметиться в бутылочке', 'https://sacramento.rusff.me/viewtopic.php?id=50618' ],
['10', 'оставить соо в клубах по интересам', 'https://sacramento.rusff.me/viewforum.php?id=105' ],
['11', 'выложить мем в тему адвента', '' ],
['12', 'принести рандомное заполненное бинго', 'https://sacramento.rusff.me/viewtopic.php?id=50086' ],
['13', 'оставить 10 сообщений в игротеке', 'https://sacramento.rusff.me/viewforum.php?id=30' ],
['14', 'отметиться в теме адвента', '' ],
['15', 'отметиться в онлайне', 'https://sacramento.rusff.me/viewtopic.php?id=50521' ],
['16', 'оставить осмысленную мысль в мыслях', 'https://sacramento.rusff.me/viewtopic.php?id=50855' ],
['17', 'отметиться в плюсомании', 'https://sacramento.rusff.me/viewtopic.php?id=50574' ],
['18', 'выложить трек дня в колонки', 'https://sacramento.rusff.me/viewtopic.php?id=50049' ],
['19', 'выложить фотку любимого летнего блюда в foodporn', 'https://sacramento.rusff.me/viewtopic.php?id=20361' ],
['20', 'рассказать что по погоде', 'https://sacramento.rusff.me/viewtopic.php?id=45093' ],
['21', 'написать доброе пожелание в теме адвента', '' ],
['22', 'играем в слова прямо в теме адвента! я начну: слово "праздник" - первому в теме на "к" и так далее друг за другом', '' ],
['23', 'отметиться в топотыке', 'https://sacramento.rusff.me/viewtopic.php?id=50548' ],
['24', 'рассказать про планы на лето в теме адвента', '' ],
['25', 'написать летний факт о себе', 'https://sacramento.rusff.me/viewtopic.php?id=49501' ],
['26', 'поставить 10 плюсов', '' ],
['27', 'отметиться в онлайне', 'https://sacramento.rusff.me/viewtopic.php?id=50521' ],
['28', 'написать рандомный факт о персонаже', 'https://sacramento.rusff.me/viewtopic.php?id=50276' ],
['29', 'выложить подборку', 'https://sacramento.rusff.me/viewtopic.php?id=50112#p5069518' ],
['30', 'отметиться в топотыке', 'https://sacramento.rusff.me/viewtopic.php?id=50548' ],
['31', 'отметиться в теме адвента', '' ],
]
};
// Настройка дат: 1 ячейка = 13 июня 2026
const START_DATE = new Date(2026, 5, 13); // 13 июня 2026 (месяц 5 = июнь)
// Функция для получения статуса ячейки на основе даты
function getCellStatusByDate(cellIndex) {
const now = new Date();
const currentDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
// Вычисляем дату для этой ячейки (индекс начинается с 1)
const cellDate = new Date(START_DATE);
cellDate.setDate(START_DATE.getDate() + (cellIndex - 1));
const cellDateOnly = new Date(cellDate.getFullYear(), cellDate.getMonth(), cellDate.getDate());
// Вычисляем дату следующего дня (когда ячейка становится completed)
const nextDayDate = new Date(cellDateOnly);
nextDayDate.setDate(cellDateOnly.getDate() + 1);
// Определяем статус
if (currentDate >= nextDayDate) {
return 'completed';
} else if (currentDate >= cellDateOnly) {
return 'opened';
} else {
return 'closed';
}
}
// Функция для форматирования даты
function formatDate(date) {
const months = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'];
return `${date.getDate()} ${months[date.getMonth()]}`;
}
// Функция для обновления статуса одной ячейки
function updateCellStatus(cellElement, cellId, newStatus) {
const oldStatus = cellElement.className.split(' ')[1];
if (oldStatus === newStatus) return;
// Обновляем класс
cellElement.className = `calendar-cell ${newStatus}`;
// Обновляем содержимое
const content = cellElement.querySelector('.cell-content');
const statusIndicator = cellElement.querySelector('.status-indicator');
// Очищаем содержимое
content.innerHTML = '';
if (newStatus === 'closed') {
content.textContent = cellId;
statusIndicator.textContent = 'Закрыто';
} else if (newStatus === 'opened') {
const taskData = calendarData.opened.find(item => item[0] === cellId);
if (taskData) {
const taskText = document.createElement('span');
taskText.textContent = taskData[1];
content.appendChild(taskText);
if (taskData[2]) {
const link = document.createElement('a');
link.href = taskData[2];
link.target = '_blank';
link.textContent = 'Перейти →';
content.appendChild(link);
}
} else {
content.textContent = 'Задание не найдено';
}
statusIndicator.textContent = 'Открыто';
} else if (newStatus === 'completed') {
const completedItem = calendarData.completed.find(item => item[0] === cellId);
if (completedItem) {
content.style.backgroundImage = `url('${completedItem[1]}')`;
content.setAttribute('title', completedItem[2]);
content.textContent = '';
}
statusIndicator.textContent = 'Выполнено';
}
// Сохраняем статус в localStorage
saveCellStatus(cellId, newStatus);
}
// Сохранение статуса ячейки
function saveCellStatus(cellId, status) {
let savedStatuses = localStorage.getItem('adventCalendarStatuses');
savedStatuses = savedStatuses ? JSON.parse(savedStatuses) : {};
savedStatuses[cellId] = status;
localStorage.setItem('adventCalendarStatuses', JSON.stringify(savedStatuses));
}
// Загрузка сохраненных статусов
function loadSavedStatus(cellId) {
const savedStatuses = localStorage.getItem('adventCalendarStatuses');
if (savedStatuses) {
const statuses = JSON.parse(savedStatuses);
return statuses[cellId] || null;
}
return null;
}
// Проверка и обновление всех ячеек
function updateAllCells() {
for (let i = 1; i <= 31; i++) {
const cell = document.querySelector(`.calendar-cell[data-id='${i}']`);
if (cell) {
const calculatedStatus = getCellStatusByDate(i);
const savedStatus = loadSavedStatus(i);
// Используем сохраненный статус, если он есть (чтобы не перезаписывать completed)
let finalStatus = calculatedStatus;
if (savedStatus === 'completed' && calculatedStatus !== 'completed') {
// Если пользователь вручную отметил как выполненное, сохраняем этот статус
finalStatus = 'completed';
} else if (savedStatus === 'opened' && calculatedStatus === 'closed') {
finalStatus = 'opened';
} else {
finalStatus = calculatedStatus;
}
updateCellStatus(cell, i.toString(), finalStatus);
}
}
}
// Функция для создания календаря
function createCalendar() {
const calendar = document.getElementById('adventCalendar');
calendar.innerHTML = '';
for (let i = 1; i <= 31; i++) {
const cell = document.createElement('div');
cell.className = 'calendar-cell';
cell.dataset.id = i.toString();
// Вычисляем дату для этой ячейки
const cellDate = new Date(START_DATE);
cellDate.setDate(START_DATE.getDate() + (i - 1));
const content = document.createElement('div');
content.className = 'cell-content';
const number = document.createElement('div');
number.className = 'cell-number';
number.textContent = i;
const dateElement = document.createElement('div');
dateElement.className = 'cell-date';
dateElement.textContent = formatDate(cellDate);
const status = document.createElement('div');
status.className = 'status-indicator';
// Определяем начальный статус
let cellStatus = getCellStatusByDate(i);
const savedStatus = loadSavedStatus(i.toString());
// Применяем сохраненный статус, если он есть и не противоречит логике
if (savedStatus === 'completed') {
cellStatus = 'completed';
} else if (savedStatus === 'opened' && cellStatus === 'closed') {
cellStatus = 'opened';
}
// Устанавливаем класс
cell.classList.add(cellStatus);
// Заполняем контент
if (cellStatus === 'closed') {
content.textContent = i;
status.textContent = 'Закрыто';
} else if (cellStatus === 'opened') {
const taskData = calendarData.opened.find(item => item[0] === i.toString());
if (taskData) {
const taskText = document.createElement('span');
taskText.textContent = taskData[1];
content.appendChild(taskText);
if (taskData[2]) {
const link = document.createElement('a');
link.href = taskData[2];
link.target = '_blank';
link.textContent = 'Перейти →';
content.appendChild(link);
}
} else {
content.textContent = 'Задание не найдено';
}
status.textContent = 'Открыто';
} else if (cellStatus === 'completed') {
const completedItem = calendarData.completed.find(item => item[0] === i.toString());
if (completedItem) {
content.style.backgroundImage = `url('${completedItem[1]}')`;
content.setAttribute('title', completedItem[2]);
content.textContent = '';
}
status.textContent = 'Выполнено';
}
cell.appendChild(content);
cell.appendChild(number);
cell.appendChild(dateElement);
cell.appendChild(status);
// Добавляем обработчик клика для ручного завершения задания
if (cellStatus === 'opened') {
cell.style.cursor = 'pointer';
cell.addEventListener('click', () => {
if (confirm('Отметить задание как выполненное?')) {
updateCellStatus(cell, i.toString(), 'completed');
}
});
}
calendar.appendChild(cell);
}
}
// Запускаем проверку статусов каждую минуту
function startAutoUpdate() {
// Проверяем каждую минуту
setInterval(() => {
updateAllCells();
}, 60000);
// Дополнительная проверка в полночь (каждый час)
setInterval(() => {
const now = new Date();
if (now.getHours() === 0 && now.getMinutes() === 0) {
updateAllCells();
}
}, 60000);
}
// Инициализация при загрузке
document.addEventListener('DOMContentLoaded', () => {
createCalendar();
startAutoUpdate();
// Выводим информацию в консоль для отладки
console.log('Календарь создан. Первая ячейка (№1) откроется:', new Date(START_DATE).toLocaleDateString('ru-RU'));
console.log('Текущая дата:', new Date().toLocaleDateString('ru-RU'));
});
</script>
- Подпись автора

♥️
поле чудес х rich bitch x капсула х капсула'23
«good morning, reasons why I drink.»










































