diff --git a/README.md b/README.md index 9d8578f..bcf1a43 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ - 🏷️ **БистСма Ρ‚Π΅Π³ΠΎΠ² с автоматичСским ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΈΠ· Π·Π°ΠΌΠ΅Ρ‚ΠΎΠΊ** (NEW!) - πŸ” **Поиск ΠΏΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠ°ΠΌ с подсвСткой Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²** (NEW!) - πŸ“… **Мини-ΠΊΠ°Π»Π΅Π½Π΄Π°Ρ€ΡŒ для Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠΈ ΠΏΠΎ Π΄Π°Ρ‚Π°ΠΌ Π·Π°ΠΌΠ΅Ρ‚ΠΎΠΊ** (NEW!) +- πŸ“± **Адаптивный Π΄ΠΈΠ·Π°ΠΉΠ½ с Π±ΠΎΠΊΠΎΠ²Ρ‹ΠΌ слайдСром Π½Π° ΠΌΠΎΠ±ΠΈΠ»ΡŒΠ½Ρ‹Ρ…** (NEW!) +- ☰ **ΠœΠΎΠ±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ Π±ΠΎΠΊΠΎΠ²ΠΎΠΉ слайдСр с ΠΊΠ°Π»Π΅Π½Π΄Π°Ρ€Ρ‘ΠΌ, поиском ΠΈ Ρ‚Π΅Π³Π°ΠΌΠΈ** (NEW!) - 🎨 ΠŸΡ€ΠΎΡΡ‚ΠΎΠΉ ΠΈ ΠΈΠ½Ρ‚ΡƒΠΈΡ‚ΠΈΠ²Π½Ρ‹ΠΉ интСрфСйс - πŸ“± Адаптивный Π΄ΠΈΠ·Π°ΠΉΠ½ @@ -128,6 +130,32 @@ npm start НаТмитС ΠΊΠ½ΠΎΠΏΠΊΡƒ "πŸšͺ Π’Ρ‹ΠΉΡ‚ΠΈ" Π² Π²Π΅Ρ€Ρ…Π½Π΅ΠΉ части страницы Π·Π°ΠΌΠ΅Ρ‚ΠΎΠΊ +## Мобильная вСрсия + +### Π‘ΠΎΠΊΠΎΠ²ΠΎΠΉ слайдСр Π½Π° ΠΌΠΎΠ±ΠΈΠ»ΡŒΠ½Ρ‹Ρ… устройствах + +На ΠΌΠΎΠ±ΠΈΠ»ΡŒΠ½Ρ‹Ρ… устройствах (ΡˆΠΈΡ€ΠΈΠ½Π° экрана Π΄ΠΎ 768 пиксСлСй) вмСсто постоянной Π»Π΅Π²ΠΎΠΉ ΠΏΠ°Π½Π΅Π»ΠΈ появляСтся ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ **Π±ΠΎΠΊΠΎΠ²ΠΎΠΉ слайдСр** с ΠΊΠ½ΠΎΠΏΠΊΠΎΠΉ "☰" Π² Π»Π΅Π²ΠΎΠΌ Π²Π΅Ρ€Ρ…Π½Π΅ΠΌ ΡƒΠ³Π»Ρƒ. + +**Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ мобильного слайдСра:** + +1. **Кнопка открытия** - Π½Π°ΠΆΠΌΠΈΡ‚Π΅ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ "☰" Π² Π»Π΅Π²ΠΎΠΌ Π²Π΅Ρ€Ρ…Π½Π΅ΠΌ ΡƒΠ³Π»Ρƒ экрана +2. **Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ слайдСра** Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ всС основныС инструмСнты: + - πŸ“… **ΠšΠ°Π»Π΅Π½Π΄Π°Ρ€ΡŒ** - ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠ°Π»Π΅Π½Π΄Π°Ρ€ΡŒ мСсяца с Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠ΅ΠΉ + - πŸ” **ПолС поиска** - синхронизировано с основным ΠΏΠΎΠ»Π΅ΠΌ поиска + - 🏷️ **Π’Π΅Π³ΠΈ** - всС Ρ‚Π΅Π³ΠΈ с количСством Π·Π°ΠΌΠ΅Ρ‚ΠΎΠΊ +3. **Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ слайдСра**: + - НаТмитС ΠΊΠ½ΠΎΠΏΠΊΡƒ βœ• Π² Π²Π΅Ρ€Ρ…Π½Π΅ΠΌ ΠΏΡ€Π°Π²ΠΎΠΌ ΡƒΠ³Π»Ρƒ слайдСра + - НаТмитС Π½Π° ΡΠ΅Ρ€ΡƒΡŽ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ (ΠΎΠ²Π΅Ρ€Π»Π΅ΠΉ) справа +4. **Бинхронизация** - измСнСния Π² слайдСрС (Π²Ρ‹Π±ΠΎΡ€ Π΄Π°Ρ‚Ρ‹, Π²Π²ΠΎΠ΄ тСкста, ΠΊΠ»ΠΈΠΊ Π½Π° Ρ‚Π΅Π³) автоматичСски ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ΡΡ с основной ПК вСрсиСй + +**ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π° мобильного слайдСра:** + +- βœ… Полная Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΊΠ°ΠΊ Π² ПК вСрсии +- βœ… Экономия мСста Π½Π° экранС мобильного устройства +- βœ… Π›Π΅Π³ΠΊΠΎΠ΅ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅/Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ +- βœ… Удобная навигация ΠΏΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠ°ΠΌ +- βœ… НС Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΏΡ€ΠΈ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠΈ (ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΠ²Π΅Ρ€Π»Π΅ΠΉ) + ## Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ``` diff --git a/public/app.js b/public/app.js index ecb498d..b5b74ca 100644 --- a/public/app.js +++ b/public/app.js @@ -1116,3 +1116,367 @@ function initSearch() { } }); } + +// ==================== ΠœΠžΠ‘Π˜Π›Π¬ΠΠ«Π™ БЛАЙДЕР ==================== + +// Ѐункция для отобраТСния калСндаря Π² мобильном слайдСрС +function renderCalendarMobile() { + const calendarDays = document.getElementById("calendarDaysMobile"); + const monthYear = document.getElementById("monthYearMobile"); + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ Π»ΠΈ элСмСнты калСндаря для мобильной вСрсии + if (!calendarDays || !monthYear) return; + + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + + // Массив Π½Π°Π·Π²Π°Π½ΠΈΠΉ мСсяцСв + const monthNames = [ + "Π―Π½Π²Π°Ρ€ΡŒ", + "Π€Π΅Π²Ρ€Π°Π»ΡŒ", + "ΠœΠ°Ρ€Ρ‚", + "ΠΠΏΡ€Π΅Π»ΡŒ", + "Май", + "Июнь", + "Июль", + "Август", + "Π‘Π΅Π½Ρ‚ΡΠ±Ρ€ΡŒ", + "ΠžΠΊΡ‚ΡΠ±Ρ€ΡŒ", + "ΠΠΎΡΠ±Ρ€ΡŒ", + "Π”Π΅ΠΊΠ°Π±Ρ€ΡŒ", + ]; + + // УстанавливаСм Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ мСсяца ΠΈ Π³ΠΎΠ΄Π° + monthYear.textContent = `${monthNames[month]} ${year}`; + + // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ дСнь мСсяца + const firstDay = new Date(year, month, 1); + // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ послСдний дСнь мСсяца + const lastDay = new Date(year, month + 1, 0); + // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ дСнь Π½Π΅Π΄Π΅Π»ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ дня (0 - Π²ΠΎΡΠΊΡ€Π΅ΡΠ΅Π½ΡŒΠ΅, 1 - понСдСльник ΠΈ Ρ‚.Π΄.) + let firstDayOfWeek = firstDay.getDay(); + // ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅ΠΌ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ понСдСльник Π±Ρ‹Π» ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ Π΄Π½Π΅ΠΌ (0) + firstDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1; + + // ΠžΡ‡ΠΈΡ‰Π°Π΅ΠΌ ΠΊΠ°Π»Π΅Π½Π΄Π°Ρ€ΡŒ + calendarDays.innerHTML = ""; + + // Π‘ΠΎΠ·Π΄Π°Ρ‘ΠΌ Set Π΄Π°Ρ‚, ΠΊΠΎΠ³Π΄Π° Π±Ρ‹Π»ΠΈ созданы Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ + const noteDates = new Set(); + allNotes.forEach((note) => { + noteDates.add(note.date); + }); + + // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ послСдний дСнь ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ мСсяца + const prevMonthLastDay = new Date(year, month, 0).getDate(); + const prevMonth = month === 0 ? 11 : month - 1; + const prevYear = month === 0 ? year - 1 : year; + + // ДобавляСм Π΄Π½ΠΈ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ мСсяца + for (let i = firstDayOfWeek - 1; i >= 0; i--) { + const day = prevMonthLastDay - i; + const dateStr = `${String(day).padStart(2, "0")}.${String( + prevMonth + 1 + ).padStart(2, "0")}.${prevYear}`; + + const dayDiv = document.createElement("div"); + dayDiv.classList.add("calendar-day", "other-month"); + dayDiv.textContent = day; + dayDiv.dataset.date = dateStr; + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π΅ΡΡ‚ΡŒ Π»ΠΈ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ Π½Π° этот дСнь + if (noteDates.has(dateStr)) { + dayDiv.classList.add("has-notes"); + } + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π²Ρ‹Π±Ρ€Π°Π½ Π»ΠΈ этот дСнь + if (selectedDateFilter === dateStr) { + dayDiv.classList.add("selected"); + } + + // ДобавляСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠ° + dayDiv.addEventListener("click", handleDayClickMobile); + + calendarDays.appendChild(dayDiv); + } + + // ДобавляСм Π΄Π½ΠΈ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ мСсяца + const today = new Date(); + for (let day = 1; day <= lastDay.getDate(); day++) { + const dateStr = `${String(day).padStart(2, "0")}.${String( + month + 1 + ).padStart(2, "0")}.${year}`; + + const dayDiv = document.createElement("div"); + dayDiv.classList.add("calendar-day"); + dayDiv.textContent = day; + dayDiv.dataset.date = dateStr; + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, являСтся Π»ΠΈ дСнь сСгодняшним + if ( + day === today.getDate() && + month === today.getMonth() && + year === today.getFullYear() + ) { + dayDiv.classList.add("today"); + } + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π΅ΡΡ‚ΡŒ Π»ΠΈ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ Π½Π° этот дСнь + if (noteDates.has(dateStr)) { + dayDiv.classList.add("has-notes"); + } + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π²Ρ‹Π±Ρ€Π°Π½ Π»ΠΈ этот дСнь + if (selectedDateFilter === dateStr) { + dayDiv.classList.add("selected"); + } + + // ДобавляСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠ° + dayDiv.addEventListener("click", handleDayClickMobile); + + calendarDays.appendChild(dayDiv); + } + + // ДобавляСм Π΄Π½ΠΈ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ мСсяца + const totalCells = calendarDays.children.length; + const remainingCells = 42 - totalCells; // 6 нСдСль ΠΏΠΎ 7 Π΄Π½Π΅ΠΉ + const nextMonth = month === 11 ? 0 : month + 1; + const nextYear = month === 11 ? year + 1 : year; + + for (let day = 1; day <= remainingCells; day++) { + const dateStr = `${String(day).padStart(2, "0")}.${String( + nextMonth + 1 + ).padStart(2, "0")}.${nextYear}`; + + const dayDiv = document.createElement("div"); + dayDiv.classList.add("calendar-day", "other-month"); + dayDiv.textContent = day; + dayDiv.dataset.date = dateStr; + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π΅ΡΡ‚ΡŒ Π»ΠΈ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ Π½Π° этот дСнь + if (noteDates.has(dateStr)) { + dayDiv.classList.add("has-notes"); + } + + // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π²Ρ‹Π±Ρ€Π°Π½ Π»ΠΈ этот дСнь + if (selectedDateFilter === dateStr) { + dayDiv.classList.add("selected"); + } + + // ДобавляСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠ° + dayDiv.addEventListener("click", handleDayClickMobile); + + calendarDays.appendChild(dayDiv); + } +} + +// ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠ° Π½Π° дСнь Π² ΠΊΠ°Π»Π΅Π½Π΄Π°Ρ€Π΅ для мобильной вСрсии +function handleDayClickMobile(event) { + const clickedDate = event.target.dataset.date; + + // Если ΠΊΠ»ΠΈΠΊΠ½ΡƒΠ»ΠΈ Π½Π° Ρ‚ΠΎΡ‚ ΠΆΠ΅ дСнь, снимаСм Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ + if (selectedDateFilter === clickedDate) { + selectedDateFilter = null; + } else { + selectedDateFilter = clickedDate; + } + + // ΠŸΠ΅Ρ€Π΅Ρ€ΠΈΡΠΎΠ²Ρ‹Π²Π°Π΅ΠΌ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ, ΠΎΠ±Π° калСндаря ΠΈ Ρ‚Π΅Π³ΠΈ + renderNotes(allNotes); + renderCalendar(); + renderCalendarMobile(); + renderTags(); + renderTagsMobile(); + updateFilterIndicator(); +} + +// Ѐункция для отобраТСния Ρ‚Π΅Π³ΠΎΠ² Π² мобильном слайдСрС +function renderTagsMobile() { + const tagsContainer = document.getElementById("tagsContainerMobile"); + if (!tagsContainer) return; + + const tagCounts = getAllTags(allNotes); + const sortedTags = Object.keys(tagCounts).sort(); + + if (sortedTags.length === 0) { + tagsContainer.innerHTML = + '
НСт Ρ‚Π΅Π³ΠΎΠ²
'; + return; + } + + tagsContainer.innerHTML = sortedTags + .map((tag) => { + const count = tagCounts[tag]; + const isActive = selectedTagFilter === tag ? "active" : ""; + return `#${tag}${count}`; + }) + .join(""); + + // ДобавляСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ ΠΊΠ»ΠΈΠΊΠΎΠ² для Ρ‚Π΅Π³ΠΎΠ² + tagsContainer.querySelectorAll(".tag").forEach((tagElement) => { + tagElement.addEventListener("click", handleTagClickMobile); + }); +} + +// ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠ° Π½Π° Ρ‚Π΅Π³ Π² мобильном слайдСрС +function handleTagClickMobile(event) { + const clickedTag = event.target.closest(".tag").dataset.tag; + + // Если ΠΊΠ»ΠΈΠΊΠ½ΡƒΠ»ΠΈ Π½Π° Ρ‚ΠΎΡ‚ ΠΆΠ΅ Ρ‚Π΅Π³, снимаСм Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ + if (selectedTagFilter === clickedTag) { + selectedTagFilter = null; + } else { + selectedTagFilter = clickedTag; + } + + // ΠŸΠ΅Ρ€Π΅Ρ€ΠΈΡΠΎΠ²Ρ‹Π²Π°Π΅ΠΌ Π·Π°ΠΌΠ΅Ρ‚ΠΊΠΈ, Ρ‚Π΅Π³ΠΈ ΠΈ ΠΎΠ±Π° калСндаря + renderNotes(allNotes); + renderTags(); + renderTagsMobile(); + renderCalendar(); + renderCalendarMobile(); + updateFilterIndicator(); +} + +// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ мобильного слайдСра +document.addEventListener("DOMContentLoaded", function () { + const mobileMenuBtn = document.getElementById("mobileMenuBtn"); + const sidebarCloseBtn = document.getElementById("sidebarCloseBtn"); + const mobileSidebar = document.getElementById("mobileSidebar"); + const sidebarOverlay = document.getElementById("sidebarOverlay"); + + // ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ слайдСра ΠΏΡ€ΠΈ ΠΊΠ»ΠΈΠΊΠ΅ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ мСню + if (mobileMenuBtn) { + mobileMenuBtn.addEventListener("click", function () { + mobileSidebar.classList.add("open"); + sidebarOverlay.classList.add("open"); + document.body.style.overflow = "hidden"; + }); + } + + // Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ слайдСра ΠΏΡ€ΠΈ ΠΊΠ»ΠΈΠΊΠ΅ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ закрытия + if (sidebarCloseBtn) { + sidebarCloseBtn.addEventListener("click", function () { + mobileSidebar.classList.remove("open"); + sidebarOverlay.classList.remove("open"); + document.body.style.overflow = "auto"; + }); + } + + // Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ слайдСра ΠΏΡ€ΠΈ ΠΊΠ»ΠΈΠΊΠ΅ Π½Π° ΠΎΠ²Π΅Ρ€Π»Π΅ΠΉ + if (sidebarOverlay) { + sidebarOverlay.addEventListener("click", function () { + mobileSidebar.classList.remove("open"); + sidebarOverlay.classList.remove("open"); + document.body.style.overflow = "auto"; + }); + } + + // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ мобильного поиска + initSearchMobile(); + + // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ мобильного калСндаря + renderCalendarMobile(); + renderTagsMobile(); + + // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ для ΠΊΠ½ΠΎΠΏΠΎΠΊ Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠΈ мобильного калСндаря + const prevMonthBtnMobile = document.getElementById("prevMonthMobile"); + const nextMonthBtnMobile = document.getElementById("nextMonthMobile"); + + if (prevMonthBtnMobile) { + prevMonthBtnMobile.addEventListener("click", function () { + currentDate.setMonth(currentDate.getMonth() - 1); + renderCalendar(); + renderCalendarMobile(); + }); + } + + if (nextMonthBtnMobile) { + nextMonthBtnMobile.addEventListener("click", function () { + currentDate.setMonth(currentDate.getMonth() + 1); + renderCalendar(); + renderCalendarMobile(); + }); + } +}); + +// Ѐункция для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ мобильного поиска +function initSearchMobile() { + const searchInput = document.getElementById("searchInputMobile"); + const clearSearchBtn = document.getElementById("clearSearchBtnMobile"); + + if (!searchInput || !clearSearchBtn) return; + + // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π²Π²ΠΎΠ΄Π° Π² ΠΏΠΎΠ»Π΅ поиска с Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ + let searchTimeout; + searchInput.addEventListener("input", function () { + clearTimeout(searchTimeout); + const query = this.value; + + // ΠŸΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ/скрываСм ΠΊΠ½ΠΎΠΏΠΊΡƒ очистки + if (query.trim()) { + clearSearchBtn.style.display = "block"; + } else { + clearSearchBtn.style.display = "none"; + } + + // Π—Π°Π΄Π΅Ρ€ΠΆΠΊΠ° ΠΏΠ΅Ρ€Π΅Π΄ поиском для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ + searchTimeout = setTimeout(() => { + searchNotes(query); + // ОбновляСм основноС ΠΏΠΎΠ»Π΅ поиска + const mainSearchInput = document.getElementById("searchInput"); + if (mainSearchInput) { + mainSearchInput.value = query; + } + const mainClearSearchBtn = document.getElementById("clearSearchBtn"); + if (mainClearSearchBtn) { + if (query.trim()) { + mainClearSearchBtn.style.display = "block"; + } else { + mainClearSearchBtn.style.display = "none"; + } + } + updateFilterIndicator(); + }, 300); + }); + + // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΊΠ»ΠΈΠΊΠ° Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ очистки поиска + clearSearchBtn.addEventListener("click", function () { + searchInput.value = ""; + this.style.display = "none"; + searchQuery = ""; + searchResults = []; + // ОбновляСм основноС ΠΏΠΎΠ»Π΅ поиска + const mainSearchInput = document.getElementById("searchInput"); + if (mainSearchInput) { + mainSearchInput.value = ""; + } + const mainClearSearchBtn = document.getElementById("clearSearchBtn"); + if (mainClearSearchBtn) { + mainClearSearchBtn.style.display = "none"; + } + renderNotes(allNotes); + updateFilterIndicator(); + }); + + // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ клавиши Escape для очистки поиска + searchInput.addEventListener("keydown", function (event) { + if (event.key === "Escape") { + this.value = ""; + clearSearchBtn.style.display = "none"; + searchQuery = ""; + searchResults = []; + // ОбновляСм основноС ΠΏΠΎΠ»Π΅ поиска + const mainSearchInput = document.getElementById("searchInput"); + if (mainSearchInput) { + mainSearchInput.value = ""; + } + const mainClearSearchBtn = document.getElementById("clearSearchBtn"); + if (mainClearSearchBtn) { + mainClearSearchBtn.style.display = "none"; + } + renderNotes(allNotes); + updateFilterIndicator(); + } + }); +} diff --git a/public/notes.html b/public/notes.html index 662cca0..d27cc49 100644 --- a/public/notes.html +++ b/public/notes.html @@ -8,6 +8,76 @@ + +
+ +
+ + +
+ + +
+ + +
+
diff --git a/public/style.css b/public/style.css index 07d87d7..4f2e94e 100644 --- a/public/style.css +++ b/public/style.css @@ -896,8 +896,111 @@ textarea:focus { color: #000; } +/* Π‘Ρ‚ΠΈΠ»ΠΈ для мобильного мСню ΠΈ слайдСра */ +.mobile-menu-btn { + display: none; + position: fixed; + top: 15px; + left: 15px; + z-index: 999; + background: white; + border: 1px solid #ddd; + border-radius: 8px; + padding: 10px 12px; + cursor: pointer; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; +} + +.mobile-menu-btn:hover { + background: #f8f9fa; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.mobile-menu-btn .iconify { + font-size: 24px; + color: #333; +} + +/* ΠœΠΎΠ±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ слайдСр */ +.mobile-sidebar { + display: none; + position: fixed; + top: 0; + left: -300px; + width: 280px; + height: 100vh; + background: white; + box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2); + z-index: 1000; + overflow-y: auto; + transition: left 0.3s ease; + flex-direction: column; +} + +.mobile-sidebar.open { + left: 0; +} + +.sidebar-close-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + padding: 0; + margin: 10px 10px 10px auto; + background: #f8f9fa; + border: 1px solid #ddd; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; + flex-shrink: 0; +} + +.sidebar-close-btn:hover { + background: #e9ecef; +} + +.sidebar-close-btn .iconify { + font-size: 20px; + color: #333; +} + +.sidebar-content { + padding: 10px 12px; + overflow-y: auto; + flex: 1; +} + +/* ΠžΠ²Π΅Ρ€Π»Π΅ΠΉ для закрытия слайдСра */ +.mobile-sidebar-overlay { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 999; + opacity: 0; + transition: opacity 0.3s ease; +} + +.mobile-sidebar-overlay.open { + display: block; + opacity: 1; +} + /* Мобильная адаптация */ @media (max-width: 768px) { + /* ΠŸΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌ мобильноС мСню */ + .mobile-menu-btn { + display: flex; + align-items: center; + justify-content: center; + } + /* Π‘ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ Π»Π΅Π²Ρ‹ΠΉ Π±Π»ΠΎΠΊ с ΠΊΠ°Π»Π΅Π½Π΄Π°Ρ€Π΅ΠΌ, поиском ΠΈ Ρ‚Π΅Π³Π°ΠΌΠΈ */ .container-leftside { display: none !important; @@ -917,6 +1020,7 @@ textarea:focus { width: 100%; max-width: 600px; margin: 0 auto; + margin-top: 60px; } /* АдаптируСм ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Π·Π°ΠΌΠ΅Ρ‚ΠΎΠΊ */