timer/index.html
Pavel Gnedov 5b1e7bc7cd dev
2026-03-11 23:54:03 +07:00

234 lines
9.9 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>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: linear-gradient(145deg, #1e2b3a 0%, #0f1a24 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
padding: 1rem;
margin: 0;
}
.card {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 1rem;
padding: 1rem 1rem;
box-shadow: 0 30px 60px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.02) inset;
max-width: 700px;
/* width: 100%; */
transition: all 0.2s ease;
}
.description {
font-size: 1rem;
font-weight: 400;
color: #b3ccff;
letter-spacing: -0.02em;
margin-bottom: 1.2rem;
text-shadow: 0 2px 5px rgba(0, 20, 50, 0.5);
word-break: break-word;
}
.timer {
font-family: 'Fira Mono', 'JetBrains Mono', 'Courier New', monospace;
font-size: 2rem;
font-weight: 600;
color: #ffffff;
line-height: 1.2;
background: rgba(0, 0, 0, 0.35);
padding: 0.75rem 1.5rem;
border-radius: 1rem;
display: inline-block;
border: 1px solid rgba(255, 215, 100, 0.3);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
letter-spacing: 2px;
/* margin: 1rem 0 1.5rem 0; */
backdrop-filter: blur(4px);
}
.note {
color: #9bb5d9;
font-size: 1rem;
border-top: 1px dashed rgba(255, 255, 255, 0.2);
padding-top: 1.5rem;
margin-top: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.note code {
background: rgba(0, 0, 0, 0.4);
padding: 0.2rem 0.6rem;
border-radius: 2rem;
font-size: 0.9rem;
color: #ffd966;
border: 1px solid #3a506b;
display: inline-block;
}
.example {
color: #cddfff;
font-size: 0.95rem;
background: rgba(255, 255, 255, 0.03);
padding: 0.8rem 1rem;
border-radius: 1.2rem;
border: 1px solid #2d3f57;
}
.error-message {
color: #ffa68b;
background: rgba(180, 60, 40, 0.2);
border: 1px solid #b05e4c;
padding: 1rem;
border-radius: 1.5rem;
font-weight: 400;
}
@media (max-width: 500px) {
.card { padding: 1.8rem; }
.description { font-size: 1rem; }
.timer { font-size: 2rem; }
}
</style>
</head>
<body>
<div class="card">
<!-- Заголовок с описанием будет вставлен сюда -->
<div id="description" class="description">⏳ загрузка...</div>
<!-- Блок таймера -->
<div id="timer" class="timer">-- д. --:--</div>
<!-- Информационная панель (всегда видна) -->
<!-- <div class="note"> -->
<!-- <div class="example"> -->
<!-- 🔧 <strong>Параметры URL</strong>: <code>?datetime=2025-12-31T23:59:59&description=Нового%20года</code><br> -->
<!-- <span style="opacity:0.8;">⏱️ Обновление каждые 60 секунд</span> -->
<!-- </div> -->
<!-- </div> -->
</div>
<script>
(function() {
console.debug('page loaded'); // DEBUG
// --- Чтение параметров из строки запроса ---
const urlParams = new URLSearchParams(window.location.search);
let datetimeRaw = urlParams.get('datetime');
let descriptionRaw = urlParams.get('description');
// Флаги для подсказки о демо-режиме
let isDemoDate = false;
let isDemoDesc = false;
// --- Обработка datetime: если нет или невалидный, устанавливаем демо (текущая дата + 7 дней) ---
if (!datetimeRaw) {
const future = new Date();
future.setDate(future.getDate() + 7);
datetimeRaw = future.toISOString();
isDemoDate = true;
}
// --- Обработка description: если нет, ставим заглушку ---
if (!descriptionRaw) {
descriptionRaw = 'события';
isDemoDesc = true;
}
// Парсим целевую дату
const targetDate = new Date(datetimeRaw);
const isValidTarget = !isNaN(targetDate.getTime());
// Элементы DOM
const descEl = document.getElementById('description');
const timerEl = document.getElementById('timer');
// --- Функция обновления отображения таймера (работает, только если дата валидна) ---
function refreshTimer() {
if (!isValidTarget) {
// Случай невалидной даты обрабатывается один раз ниже
console.error(`Не правильная дата`);
return;
}
const now = new Date();
const diffMs = targetDate - now;
// Если время истекло или отрицательное — показываем нули
if (diffMs <= 0) {
timerEl.textContent = '00 д. 00:00';
return;
}
// Вычисляем дни, часы, минуты
const totalSeconds = Math.floor(diffMs / 1000);
const days = Math.floor(totalSeconds / (3600 * 24));
const hours = Math.floor((totalSeconds % (3600 * 24)) / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
// Форматируем часы и минуты всегда с двумя цифрами
const hoursStr = hours.toString().padStart(2, '0');
const minutesStr = minutes.toString().padStart(2, '0');
// Дни выводятся как есть (без ограничения количества знаков)
const daysStr = days.toString();
timerEl.textContent = `${daysStr} д. ${hoursStr}:${minutesStr}`;
}
// --- Устанавливаем текст описания с учётом демо-режима ---
if (!isValidTarget) {
// Некорректная дата: показываем ошибку
descEl.textContent = '❌ Ошибка: некорректная дата';
timerEl.textContent = '-- д. --:--';
// Дополнительно выводим пояснение в консоль (на случай если разработчик смотрит)
console.error('Таймер: передан невалидный datetime =', datetimeRaw);
} else {
// Формируем строку описания
let descriptionText = `${descriptionRaw}`;
if (isDemoDate || isDemoDesc) {
// Если хотя бы один параметр был подставлен автоматически, добавляем метку (демо)
// Но чтобы не загромождать, покажем в скобках, если не было параметра description
if (isDemoDesc && !urlParams.has('description')) {
descriptionText += ' (пример)';
} else if (isDemoDate && !urlParams.has('datetime')) {
descriptionText += ' (демо-дата)';
}
}
descEl.textContent = descriptionText;
// Запускаем обновление таймера
refreshTimer(); // сразу показываем
// Обновление каждые 60 секунд (60000 мс)
setInterval(refreshTimer, 60000);
}
// Дополнительно: если оба параметра не были переданы, добавим подсказку прямо в блок .note (но она уже есть)
// Можно также скорректировать текст примера под текущие значения (необязательно, но красиво)
const exampleHint = document.querySelector('.example code');
if (exampleHint) {
// Показываем актуальный пример с экранированием
const exampleUrl = new URL(window.location.href);
exampleUrl.searchParams.set('datetime', '2025-12-31T23:59:59Z');
exampleUrl.searchParams.set('description', 'Нового года');
exampleHint.textContent = `?datetime=2025-12-31T23:59:59Z&description=Нового%20года`;
}
})();
</script>
</body>
</html>