Spaces:
Running
Running
| <html lang="ru"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Добро пожаловать | Привет Dashboard</title> | |
| <!-- Importing FontAwesome for Icons --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| /* --- CSS Variables & Reset --- */ | |
| :root { | |
| --primary-color: #6366f1; | |
| --secondary-color: #a855f7; | |
| --accent-color: #ec4899; | |
| --bg-gradient: linear-gradient(135deg, #0f172a 0%, #1e1b4b 50%, #312e81 100%); | |
| --glass-bg: rgba(255, 255, 255, 0.05); | |
| --glass-border: rgba(255, 255, 255, 0.1); | |
| --text-main: #f8fafc; | |
| --text-muted: #94a3b8; | |
| --card-radius: 16px; | |
| --shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5); | |
| --font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: var(--font-family); | |
| background: var(--bg-gradient); | |
| color: var(--text-main); | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| overflow-x: hidden; | |
| position: relative; | |
| } | |
| /* --- Background Animated Blobs --- */ | |
| .blob { | |
| position: absolute; | |
| border-radius: 50%; | |
| filter: blur(80px); | |
| opacity: 0.4; | |
| z-index: -1; | |
| animation: float 10s infinite alternate; | |
| } | |
| .blob-1 { top: -10%; left: -10%; width: 500px; height: 500px; background: var(--primary-color); animation-delay: 0s; } | |
| .blob-2 { bottom: -10%; right: -10%; width: 400px; height: 400px; background: var(--secondary-color); animation-delay: 2s; } | |
| .blob-3 { top: 40%; left: 40%; width: 300px; height: 300px; background: var(--accent-color); animation-delay: 4s; } | |
| @keyframes float { | |
| 0% { transform: translate(0, 0) scale(1); } | |
| 100% { transform: translate(30px, 50px) scale(1.1); } | |
| } | |
| /* --- Header --- */ | |
| header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 1.5rem 2rem; | |
| backdrop-filter: blur(10px); | |
| border-bottom: 1px solid var(--glass-border); | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| } | |
| .logo { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| background: linear-gradient(to right, #818cf8, #c084fc); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .anycoder-link { | |
| font-size: 0.9rem; | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| padding: 8px 16px; | |
| border: 1px solid var(--glass-border); | |
| border-radius: 20px; | |
| transition: all 0.3s ease; | |
| background: rgba(255,255,255,0.05); | |
| } | |
| .anycoder-link:hover { | |
| background: var(--primary-color); | |
| color: white; | |
| border-color: var(--primary-color); | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(99, 102, 241, 0.4); | |
| } | |
| /* --- Main Layout --- */ | |
| main { | |
| flex: 1; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 2rem; | |
| width: 100%; | |
| display: grid; | |
| grid-template-columns: 2fr 1fr; | |
| gap: 2rem; | |
| } | |
| /* --- Hero Section (Greeting) --- */ | |
| .hero-section { | |
| grid-column: 1 / -1; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| min-height: 300px; | |
| text-align: center; | |
| background: var(--glass-bg); | |
| border: 1px solid var(--glass-border); | |
| border-radius: var(--card-radius); | |
| padding: 3rem; | |
| position: relative; | |
| overflow: hidden; | |
| box-shadow: var(--shadow); | |
| backdrop-filter: blur(20px); | |
| } | |
| .hero-content { | |
| z-index: 2; | |
| } | |
| .greeting-title { | |
| font-size: 4rem; | |
| font-weight: 800; | |
| margin-bottom: 1rem; | |
| background: linear-gradient(to right, #fff, #cbd5e1); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| letter-spacing: -1px; | |
| } | |
| .time-display { | |
| font-size: 2rem; | |
| font-weight: 300; | |
| color: var(--text-muted); | |
| font-family: 'Courier New', monospace; | |
| margin-bottom: 1.5rem; | |
| } | |
| .date-display { | |
| font-size: 1.1rem; | |
| color: var(--primary-color); | |
| font-weight: 600; | |
| text-transform: uppercase; | |
| letter-spacing: 2px; | |
| } | |
| /* --- Cards & Widgets --- */ | |
| .card { | |
| background: var(--glass-bg); | |
| border: 1px solid var(--glass-border); | |
| border-radius: var(--card-radius); | |
| padding: 1.5rem; | |
| backdrop-filter: blur(20px); | |
| box-shadow: var(--shadow); | |
| transition: transform 0.3s ease; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .card:hover { | |
| transform: translateY(-5px); | |
| border-color: rgba(255, 255, 255, 0.2); | |
| } | |
| .card-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1.5rem; | |
| border-bottom: 1px solid var(--glass-border); | |
| padding-bottom: 0.8rem; | |
| } | |
| .card-title { | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| color: var(--text-main); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| /* --- Focus Timer Styles --- */ | |
| .timer-display { | |
| font-size: 3.5rem; | |
| font-weight: 700; | |
| text-align: center; | |
| margin: 1rem 0; | |
| color: var(--text-main); | |
| } | |
| .timer-controls { | |
| display: flex; | |
| justify-content: center; | |
| gap: 1rem; | |
| } | |
| .btn { | |
| padding: 0.6rem 1.2rem; | |
| border: none; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| font-weight: 600; | |
| transition: all 0.2s; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .btn-primary { | |
| background: var(--primary-color); | |
| color: white; | |
| } | |
| .btn-primary:hover { | |
| background: #4f46e5; | |
| } | |
| .btn-secondary { | |
| background: rgba(255,255,255,0.1); | |
| color: var(--text-main); | |
| } | |
| .btn-secondary:hover { | |
| background: rgba(255,255,255,0.2); | |
| } | |
| /* --- Todo List Styles --- */ | |
| .todo-input-group { | |
| display: flex; | |
| gap: 10px; | |
| margin-bottom: 1rem; | |
| } | |
| .todo-input { | |
| flex: 1; | |
| background: rgba(0,0,0,0.2); | |
| border: 1px solid var(--glass-border); | |
| padding: 0.8rem; | |
| border-radius: 8px; | |
| color: white; | |
| outline: none; | |
| } | |
| .todo-input:focus { | |
| border-color: var(--primary-color); | |
| } | |
| .todo-list { | |
| list-style: none; | |
| overflow-y: auto; | |
| max-height: 250px; | |
| } | |
| .todo-item { | |
| background: rgba(255,255,255,0.03); | |
| margin-bottom: 8px; | |
| padding: 10px; | |
| border-radius: 6px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| animation: slideIn 0.3s ease; | |
| } | |
| @keyframes slideIn { | |
| from { opacity: 0; transform: translateX(-10px); } | |
| to { opacity: 1; transform: translateX(0); } | |
| } | |
| .todo-item.completed span { | |
| text-decoration: line-through; | |
| color: var(--text-muted); | |
| } | |
| .delete-btn { | |
| background: none; | |
| border: none; | |
| color: #ef4444; | |
| cursor: pointer; | |
| opacity: 0.7; | |
| transition: opacity 0.2s; | |
| } | |
| .delete-btn:hover { | |
| opacity: 1; | |
| } | |
| /* --- Footer --- */ | |
| footer { | |
| text-align: center; | |
| padding: 2rem; | |
| color: var(--text-muted); | |
| font-size: 0.9rem; | |
| border-top: 1px solid var(--glass-border); | |
| background: rgba(15, 23, 42, 0.8); | |
| } | |
| /* --- Responsive Design --- */ | |
| @media (max-width: 768px) { | |
| main { | |
| grid-template-columns: 1fr; | |
| padding: 1rem; | |
| } | |
| .greeting-title { | |
| font-size: 2.5rem; | |
| } | |
| .timer-display { | |
| font-size: 2.5rem; | |
| } | |
| header { | |
| padding: 1rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Background Blobs --> | |
| <div class="blob blob-1"></div> | |
| <div class="blob blob-2"></div> | |
| <div class="blob blob-3"></div> | |
| <header> | |
| <div class="logo"> | |
| <i class="fa-solid fa-layer-group"></i> | |
| <span>MySpace</span> | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link"> | |
| Built with anycoder <i class="fa-solid fa-arrow-up-right-from-square" style="font-size: 0.7em; margin-left: 5px;"></i> | |
| </a> | |
| </header> | |
| <main> | |
| <!-- Hero / Greeting Section --> | |
| <section class="hero-section"> | |
| <div class="hero-content"> | |
| <h1 class="greeting-title" id="greeting-text">Привет!</h1> | |
| <div class="time-display" id="clock">00:00:00</div> | |
| <div class="date-display" id="date">Загрузка даты...</div> | |
| </div> | |
| </section> | |
| <!-- Widget 1: Focus Timer --> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title"> | |
| <i class="fa-solid fa-hourglass-half" style="color: var(--accent-color);"></i> | |
| Фокус Таймер | |
| </div> | |
| <i class="fa-solid fa-ellipsis text-muted"></i> | |
| </div> | |
| <div class="timer-display" id="timer">25:00</div> | |
| <div class="timer-controls"> | |
| <button class="btn btn-primary" id="start-timer" onclick="toggleTimer()"> | |
| <i class="fa-solid fa-play"></i> Старт | |
| </button> | |
| <button class="btn btn-secondary" onclick="resetTimer()"> | |
| <i class="fa-solid fa-rotate-right"></i> Сброс | |
| </button> | |
| </div> | |
| </section> | |
| <!-- Widget 2: Quick Tasks --> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title"> | |
| <i class="fa-solid fa-check-double" style="color: var(--secondary-color);"></i> | |
| Задачи | |
| </div> | |
| <span id="task-count" style="background: rgba(255,255,255,0.1); padding: 2px 8px; border-radius: 10px; font-size: 0.8rem;">0</span> | |
| </div> | |
| <div class="todo-input-group"> | |
| <input type="text" id="todo-input" class="todo-input" placeholder="Добавить задачу..." onkeypress="handleEnter(event)"> | |
| <button class="btn btn-primary" onclick="addTodo()"> | |
| <i class="fa-solid fa-plus"></i> | |
| </button> | |
| </div> | |
| <ul class="todo-list" id="todo-list"> | |
| <!-- Tasks will appear here --> | |
| </ul> | |
| </section> | |
| </main> | |
| <footer> | |
| <p>© 2023 MySpace Dashboard. Дизайн создан с любовью и кодом.</p> | |
| </footer> | |
| <script> | |
| // --- Greeting & Clock Logic --- | |
| function updateTime() { | |
| const now = new Date(); | |
| // Time Formatting | |
| const hours = String(now.getHours()).padStart(2, '0'); | |
| const minutes = String(now.getMinutes()).padStart(2, '0'); | |
| const seconds = String(now.getSeconds()).padStart(2, '0'); | |
| document.getElementById('clock').textContent = `${hours}:${minutes}:${seconds}`; | |
| // Date Formatting (Russian locale) | |
| const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; | |
| document.getElementById('date').textContent = now.toLocaleDateString('ru-RU', options); | |
| // Dynamic Greeting | |
| const hour = now.getHours(); | |
| const greetingElement = document.getElementById('greeting-text'); | |
| let greetingText = 'Привет!'; | |
| if (hour >= 5 && hour < 12) greetingText = 'Доброе утро!'; | |
| else if (hour >= 12 && hour < 18) greetingText = 'Добрый день!'; | |
| else if (hour >= 18 && hour < 23) greetingText = 'Добрый вечер!'; | |
| else greetingText = 'Доброй ночи!'; | |
| // Only update DOM if text changes to prevent flicker/layout shift | |
| if (greetingElement.textContent !== greetingText) { | |
| greetingElement.textContent = greetingText; | |
| } | |
| } | |
| setInterval(updateTime, 1000); | |
| updateTime(); // Initial call | |
| // --- Focus Timer Logic --- | |
| let timerInterval; | |
| let timeLeft = 25 * 60; // 25 minutes in seconds | |
| let isRunning = false; | |
| function formatTime(seconds) { | |
| const m = Math.floor(seconds / 60); | |
| const s = seconds % 60; | |
| return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`; | |
| } | |
| function updateTimerDisplay() { | |
| document.getElementById('timer').textContent = formatTime(timeLeft); | |
| } | |
| function toggleTimer() { | |
| const btn = document.getElementById('start-timer'); | |
| if (isRunning) { | |
| clearInterval(timerInterval); | |
| btn.innerHTML = '<i class="fa-solid fa-play"></i> Старт'; | |
| btn.classList.remove('btn-secondary'); | |
| btn.classList.add('btn-primary'); | |
| } else { | |
| timerInterval = setInterval(() => { | |
| if (timeLeft > 0) { | |
| timeLeft--; | |
| updateTimerDisplay(); | |
| } else { | |
| clearInterval(timerInterval); | |
| isRunning = false; | |
| alert("Время вышло! Сделайте перерыв."); // Simple feedback | |
| resetTimer(); | |
| } | |
| }, 1000); | |
| btn.innerHTML = '<i class="fa-solid fa-pause"></i> Пауза'; | |
| btn.classList.remove('btn-primary'); | |
| btn.classList.add('btn-secondary'); | |
| } | |
| isRunning = !isRunning; | |
| } | |
| function resetTimer() { | |
| clearInterval(timerInterval); | |
| isRunning = false; | |
| timeLeft = 25 * 60; | |
| updateTimerDisplay(); | |
| const btn = document.getElementById('start-timer'); | |
| btn.innerHTML = '<i class="fa-solid fa-play"></i> Старт'; | |
| btn.classList.remove('btn-secondary'); | |
| btn.classList.add('btn-primary'); | |
| } | |
| // --- Todo List Logic --- | |
| const todoInput = document.getElementById('todo-input'); | |
| const todoList = document.getElementById('todo-list'); | |
| const taskCount = document.getElementById('task-count'); | |
| let todos = []; | |
| function handleEnter(e) { | |
| if (e.key === 'Enter') addTodo(); | |
| } | |
| function addTodo() { | |
| const text = todoInput.value.trim(); | |
| if (text === '') return; | |
| const todo = { | |
| id: Date.now(), | |
| text: text, | |
| completed: false | |
| }; | |
| todos.push(todo); | |
| renderTodos(); | |
| todoInput.value = ''; | |
| } | |
| function toggleTodo(id) { | |
| todos = todos.map(t => t.id === id ? {...t, completed: !t.completed} : t); | |
| renderTodos(); | |
| } | |
| function deleteTodo(id) { | |
| todos = todos.filter(t => t.id !== id); | |
| renderTodos(); | |
| } | |
| function renderTodos() { | |
| todoList.innerHTML = ''; | |
| taskCount.textContent = todos.filter(t => !t.completed).length; | |
| todos.forEach(todo => { | |
| const li = document.createElement('li'); | |
| li.className = `todo-item ${todo.completed ? 'completed' : ''}`; | |
| li.innerHTML = ` | |
| <div style="display:flex; align-items:center; gap:10px; cursor:pointer;" onclick="toggleTodo(${todo.id})"> | |
| <i class="fa-regular ${todo.completed ? 'fa-circle-check' : 'fa-circle'}" style="color: var(--primary-color);"></i> | |
| <span>${todo.text}</span> | |
| </div> | |
| <button class="delete-btn" onclick="deleteTodo(${todo.id})"> | |
| <i class="fa-solid fa-trash"></i> | |
| </button> | |
| `; | |
| todoList.appendChild(li); | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> |