commit 9e8ed6749f16e162a1ae8ab8a2abf8b3af082413 Author: lotkov Date: Thu Feb 19 18:22:36 2026 +0100 Загрузить файлы в «/» diff --git a/app.js b/app.js new file mode 100644 index 0000000..13dd456 --- /dev/null +++ b/app.js @@ -0,0 +1,173 @@ +const HabitTrackerApp = { + elements: { + habitGrid: null, + addHabitForm: null, + addHabbitButton: null, + filterButtons: [] + }, + + currentFilter: 'all', + + init: function() { + this.loadElements(); + this.render(); + this.setupEventListeners(); + }, + + setupEventListeners: function() { + // Обработчики для кнопок фильтров + this.elements.filterButtons.forEach(button => { + button.addEventListener('click', (event) => { + const filter = event.target.dataset.filter; + this.applyFilter(filter); + }); + }); + + // Делегирование событий для кнопок в карточках привычек + this.elements.habitGrid.addEventListener('click', (event) => { + const habitCard = event.target.closest('.habit-card'); + if (!habitCard) return; + + const habitId = parseInt(habitCard.dataset.habitId); + + if (event.target.classList.contains('js-habit-done')) { + HabitManager.markHabitDone(habitId); + HabitManager.saveToLocalStorage(); + this.render(); + } else if (event.target.classList.contains('js-habit-delete')) { + HabitManager.deleteHabit(habitId); + HabitManager.saveToLocalStorage(); + this.render(); + } + }); + }, + + loadElements: function() { + this.elements.habitGrid = document.getElementById('habits-grid'); + this.elements.filterButtons = document.querySelectorAll('.filters__button'); + }, + + applyFilter: function(filter) { + this.currentFilter = filter; + + // Обновление активной кнопки фильтра + this.elements.filterButtons.forEach(button => { + if (button.dataset.filter === filter) { + button.classList.remove('button--secondary'); + button.classList.add('button--primary'); + } else { + button.classList.remove('button--primary'); + button.classList.add('button--secondary'); + } + }); + + this.render(); + }, + + render: function() { + const filteredHabits = HabitManager.getFilteredHabits(this.currentFilter); + + const habitsHTML = filteredHabits.map(habit => { + const progress = (habit.currentCount / habit.targetCount) * 100; + + // Определение классов для карточки + const cardClasses = ['habit-card']; + if (habit.isCompleted) cardClasses.push('habit-card--completed'); + if (habit.isImportant) cardClasses.push('habit-card--important'); + if (habit.currentStreak >= 3) cardClasses.push('habit-card--streak'); + if (habit.currentCount === 0) cardClasses.push('habit-card--new'); + + // Выбор иконки в зависимости от названия привычки + let icon = '⭐'; + if (habit.name.includes('Медитация')) icon = '🧘'; + if (habit.name.includes('Учить')) icon = '💻'; + if (habit.name.includes('Спорт')) icon = '💪'; + if (habit.name.includes('Чтение')) icon = '📚'; + + return ` +
+
+
${icon}
+

${habit.name}

+
+

${habit.description}

+
+
+ Прогресс + ${Math.round(progress)}% +
+
+
+
+
+
+ + +
+
+ `; + }).join(''); + + this.elements.habitGrid.innerHTML = habitsHTML; + + // Обновление статистики в заголовке + this.updateStats(); + }, + + updateStats: function() { + const totalHabits = HabitManager.habits.length; + const completedHabits = HabitManager.habits.filter(h => h.isCompleted).length; + const totalProgress = totalHabits > 0 ? Math.round((completedHabits / totalHabits) * 100) : 0; + + document.querySelector('.stats-panel__value:nth-child(1)').textContent = totalHabits; + document.querySelector('.stats-panel__value:nth-child(2)').textContent = `${totalProgress}%`; + document.querySelector('.stats-panel__value:nth-child(3)').textContent = HabitManager.stats.currentStreak; + } +} + +HabitTrackerApp.loadFromLocalStorage = function() { + HabitManager.loadFromLocalStorage(); + + if (HabitManager.habits.length === 0) { + // Создание демо-привычек + HabitManager.createHabit('Учить JavaScript', 'Писать код каждый день', 5, true); + HabitManager.createHabit('Медитация', 'Ежедневная практика медитации по 10 минут', 1, false); + HabitManager.createHabit('Спорт', 'Тренировка 30 минут', 3, true); + HabitManager.createHabit('Чтение', 'Читать 20 страниц в день', 7, false); + HabitManager.saveToLocalStorage(); + } +} + +function openModal() { + const modal = document.getElementById('habit-modal'); + modal.classList.add('modal--open'); + document.body.style.overflow = 'hidden'; + document.getElementById('habit-name').focus(); +} + +function closeModal() { + const modal = document.getElementById('habit-modal'); + modal.classList.remove('modal--open'); + document.body.style.overflow = ''; +} + + document.getElementById('add-habbit-button').addEventListener('click', openModal); + document.querySelector('.modal__close').addEventListener('click', closeModal); + document.getElementById('cancel-button').addEventListener('click', closeModal); + + document.querySelector('.modal__overlay').addEventListener('click',closeModal); + + document.addEventListener('keydown', function(event) { + if (event.key === 'Escape') { + closeModal(); + } + }); + + document.getElementById('habit-form').addEventListener('submit', function(event) { + event.preventDefault(); + + alert('Привычка добавлена!'); + closeModal(); + }); \ No newline at end of file diff --git a/habbit-manager.html b/habbit-manager.html new file mode 100644 index 0000000..f473a16 --- /dev/null +++ b/habbit-manager.html @@ -0,0 +1,121 @@ + + + + + + Трекер привычек + + + +
+ + + + +
+ + + + +
+ + +
+
+
+
🧘
+

Медитация

+
+

Ежедневная медитации по 10 минут

+
+
+ Прогресс + 30% +
+
+
+
+
+
+ + +
+
+ +
+
+
💧
+

Учить js

+
+

Писать не менее 1000000000 строк кода в день

+
+
+ Прогресс + 0% +
+
+
+
+
+
+ + +
+
+
+ + +
+ +
+ +
+ + + + \ No newline at end of file diff --git a/habbit-style.css b/habbit-style.css new file mode 100644 index 0000000..7b71193 --- /dev/null +++ b/habbit-style.css @@ -0,0 +1,357 @@ + /* Базовые стили */ + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: 'Arial', sans-serif; + line-height: 1.6; + color: #333; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + padding: 20px; + } + + /* Блок container */ + .container { + max-width: 1200px; + margin: 0 auto; + } + + /* Блок page-header */ + .page-header { + background: white; + border-radius: 20px; + padding: 40px; + margin-bottom: 30px; + text-align: center; + box-shadow: 0 10px 30px rgba(0,0,0,0.1); + } + + .page-header__title { + color: #4CAF50; + font-size: 2.5em; + margin-bottom: 10px; + } + + .page-header__subtitle { + color: #666; + font-size: 1.2em; + margin-bottom: 30px; + } + + /* Блок stats-panel */ + .stats-panel { + display: flex; + gap: 20px; + justify-content: center; + flex-wrap: wrap; + } + + .stats-panel__item { + background: #f8f9fa; + padding: 15px 25px; + border-radius: 10px; + text-align: center; + } + + .stats-panel__value { + font-size: 2em; + font-weight: bold; + color: #4CAF50; + } + + .stats-panel__label { + color: #666; + font-size: 0.9em; + } + + /* Блок filters */ + .filters { + display: flex; + gap: 10px; + justify-content: center; + margin-bottom: 30px; + flex-wrap: wrap; + } + + .filters__button { + flex: 0 1 auto; + } + + /* Блок habits-grid */ + .habits-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 25px; + margin-bottom: 40px; + } + + /* Блок habit-card - ОСНОВНОЙ БЛОК ДЛЯ РАБОТЫ */ + .habit-card { + background: white; + border-radius: 20px; + padding: 25px; + box-shadow: 0 5px 15px rgba(0,0,0,0.1); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + animation: fadeInUp 0.5s ease; + border-left: 5px solid #d32f2f; + } + + .habit-card:hover { + transform: translateY(-5px); + box-shadow: 0 10px 25px rgba(0,0,0,0.15); + } + + .habit-card__header { + display: flex; + align-items: center; + margin-bottom: 15px; + } + + .habit-card__icon { + font-size: 2.5em; + margin-right: 15px; + } + + .habit-card__title { + color: #2c3e50; + font-size: 1.4em; + margin: 0; + } + + .habit-card__description { + color: #666; + margin-bottom: 20px; + line-height: 1.5; + } + + .habit-card__progress { + margin-bottom: 20px; + } + + .habit-card__progress-info { + display: flex; + justify-content: space-between; + margin-bottom: 8px; + font-size: 0.9em; + color: #666; + } + + .habit-card__progress-bar { + background: #e0e0e0; + border-radius: 10px; + height: 8px; + overflow: hidden; + } + + .habit-card__progress-fill { + background: #4CAF50; + height: 100%; + width: 0%; + transition: width 0.5s ease; + } + + .habit-card__actions { + display: flex; + gap: 10px; + } + + /* Блок button */ + .button { + padding: 10px 20px; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 0.9em; + transition: all 0.3s ease; + flex: 1; + } + + .button--primary { + background: #4CAF50; + color: white; + } + + .button--primary:hover { + background: #45a049; + transform: translateY(-2px); + } + + .button--secondary { + background: #f0f0f0; + color: #333; + } + + .button--secondary:hover { + background: #e0e0e0; + transform: translateY(-2px); + } + + .button--success { + background: #4CAF50; + color: white; + } + + .button--success:hover { + background: #45a049; + transform: translateY(-2px); + } + + .button--danger { + background: #af0606; + color: white; + } + + .button--danger:hover { + background: #750404; + transform: translateY(-2px); + } + + /* Модификаторы для habit-card */ + .habit-card--important { + border-left: 5px solid #ff6b6b; + } + + .habit-card--completed { + opacity: 0.8; + } + + .habit-card--new { + border: 2px dashed #08cf0e; + background: #8DA180; + } + + .habit-card--streak { + position: relative; + } + + .habit-card--streak::before { + content: '🔥'; + position: absolute; + top: 10px; + right: 10px; + font-size: 1.5em; + } + + /* Блок new-habit-form */ + .new-habit-form { + background: white; + border-radius: 15px; + padding: 30px; + box-shadow: 0 5px 15px rgba(0,0,0,0.1); + + } + + .new-habit-form__title { + color: #2c3e50; + margin-bottom: 20px; + text-align: center; + } + + /* Анимации */ + @keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + /* Стили для модального окна */ +.modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + display: none; + align-items: center; + justify-content: center; +} + +.modal--open { + display: flex; +} + +.modal__overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); +} + +.modal__content { + position: relative; + background: white; + border-radius: 20px; + padding: 30px; + max-width: 500px; + width: 90%; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 30px rgba(0,0,0,0.3); +} + +.modal__close { + position: absolute; + top: 15px; + right: 15px; + background: none; + border: none; + font-size: 1.5em; + cursor: pointer; + color: #666; +} + +.modal__title { + margin-bottom: 20px; + color: #2c3e50; +} + +.form-group { + margin-bottom: 20px; +} + +.form-group label { + display: block; + margin-bottom: 5px; + color: #333; + font-weight: bold; +} + +.form-control { + width: 100%; + padding: 10px; + border: 1px solid #ddd; + border-radius: 8px; + font-size: 1em; +} + +.modal__actions { + display: flex; + gap: 10px; + justify-content: flex-end; + margin-top: 30px; +} +.new-habit-form__button { + background: none; + border: none; + width: 100%; + cursor: pointer; + padding: 0; +} + +.new-habit-form__button:hover .new-habit-form__title { + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(0,0,0,0.15); +} \ No newline at end of file