diff --git a/app.js b/app.js
index e27c281..d1a0859 100644
--- a/app.js
+++ b/app.js
@@ -14,36 +14,6 @@
dayLabel: $("dayLabel"),
selectedEvents: $("selectedEvents"),
upcomingEvents: $("upcomingEvents"),
- feature
- noResults: $("noResults"),
-
- addBtn: $("addBtn"),
- editBtn: $("editBtn"),
- deleteSideBtn: $("deleteSideBtn"),
- exportBtn: $("exportBtn"),
- clearAllBtn: $("clearAllBtn"),
-
- modal: $("eventModal"),
- eventForm: $("eventForm"),
- closeBtn: $("closeBtn"),
- cancelBtn: $("cancelBtn"),
- deleteBtn: $("deleteBtn"),
-
- modalTitle: $("modalTitle"),
- modalSub: $("modalSub"),
-
- idInput: $("idInput"),
- titleInput: $("titleInput"),
- dateInput: $("dateInput"),
- endDateInput: $("endDateInput"),
- startInput: $("startInput"),
- endInput: $("endInput"),
- descInput: $("descInput"),
- remindInput: $("remindInput"),
- colorInput: $("colorInput"),
-
- conflictBox: $("conflictBox"),
-
addBtn: $("addBtn"),
editBtn: $("editBtn"),
deleteSideBtn: $("deleteSideBtn"),
@@ -71,16 +41,12 @@
notifBanner: $("notifBanner"),
notifAllowBtn: $("notifAllowBtn"),
notifDismissBtn:$("notifDismissBtn"),
- feature
- main
-
importModal: $("importModal"),
importCloseBtn: $("importCloseBtn"),
importCancelBtn:$("importCancelBtn"),
importConfirmBtn:$("importConfirmBtn"),
importFileInput:$("importFileInput"),
importError: $("importError")
- main
};
var STORAGE_KEY = "calendra_lite_events_v2";
@@ -339,38 +305,11 @@
});
els.closeBtn.addEventListener("click", closeModal);
els.cancelBtn.addEventListener("click", closeModal);
- feature
-
- // Auto-suggest titles while typing
- els.titleInput.addEventListener("input", () => {
- const { titleFrequency } = analyzeEventPatterns();
- const input = normalizeStr(els.titleInput.value);
-
- const suggestions = Object.keys(titleFrequency)
- .filter(title => normalizeStr(title).startsWith(input))
- .sort((a, b) => titleFrequency[b] - titleFrequency[a]);
-
- if (suggestions.length > 0 && input.length > 0) {
- els.titleInput.setAttribute("placeholder", `Suggested: ${suggestions[0]}`);
- }
- });
-
- els.eventForm.addEventListener("submit", (e) => {
- e.preventDefault();
- onSave();
- });
-
-
els.backdrop.addEventListener("click", closeModal);
- feature
- els.eventForm.addEventListener("submit", e => { e.preventDefault(); onSave(); });
- main
-
els.eventForm.addEventListener("submit", function(e) {
e.preventDefault();
onSave();
});
- main
els.deleteBtn.addEventListener("click", onDelete);
["dateInput", "endDateInput", "startInput", "endInput"].forEach(function(id) {
@@ -398,16 +337,7 @@
while (cells.length % 7 !== 0) cells.push({ empty: true });
while (cells.length < 42) cells.push({ empty: true });
- feature
- feature
- const q = normalizeStr(els.searchInput.value).trim();
-
-
- const q = (els.searchInput.value || "").trim().toLowerCase();
- main
-
var q = (els.searchInput.value || "").trim().toLowerCase();
- main
els.grid.innerHTML = "";
cells.forEach(function(cellData) {
@@ -481,18 +411,6 @@
els.grid.appendChild(cell);
});
- feature
- feature
- // "No results" message for search
- if (q && !anyMatch) {
- els.noResults.style.display = "block";
- } else {
- els.noResults.style.display = "none";
- }
-
- let noResultEl = document.getElementById("noResults");
- if (!noResultEl) { noResultEl = document.createElement("div"); noResultEl.id = "noResults"; Object.assign(noResultEl.style, { textAlign: "center", padding: "10px", fontWeight: "bold", color: "red" }); els.grid.parentNode.appendChild(noResultEl); }
-
var noResultEl = document.getElementById("noResults");
if (!noResultEl) {
noResultEl = document.createElement("div");
@@ -503,65 +421,14 @@
noResultEl.style.color = "red";
els.grid.parentNode.appendChild(noResultEl);
}
- main
noResultEl.style.display = (q && !anyMatch) ? "block" : "none";
if (q && !anyMatch) noResultEl.textContent = "No events found";
- main
}
// ─── RENDER DAY PANEL ────────────────────────────────────────────────────
function renderDayPanel() {
- feature
- const selectedContainer = els.selectedEvents;
- const upcomingContainer = els.upcomingEvents;
- feature
-
- selectedContainer.innerHTML = "";
- upcomingContainer.innerHTML = "";
-
- const selected = new Date(selectedDate + "T00:00:00");
-
- els.dayLabel.textContent = selected.toLocaleDateString(undefined, {
- weekday: "long",
- year: "numeric",
- month: "long",
- day: "numeric"
- });
-
- const q = normalizeStr(els.searchInput.value).trim();
-
- // ===== SELECTED DAY EVENTS =====
- const dayEvents = getEventsOnDate(selectedDate)
- .filter(ev => !q || formatSearch(ev).includes(q))
- .sort((a, b) => (a.start || "").localeCompare(b.start || ""));
-
- if (!dayEvents.length) {
- selectedContainer.innerHTML = `
No events for this day.
`;
- } else {
- dayEvents.forEach(ev => {
- const item = createEventCard(ev);
- selectedContainer.appendChild(item);
- });
- }
-
- // ===== UPCOMING EVENTS =====
- const upcoming = events
- .filter(ev => ev.date > selectedDate)
- .sort((a, b) => a.date.localeCompare(b.date))
- .slice(0, 5);
-
- if (!upcoming.length) {
- upcomingContainer.innerHTML = `No upcoming events.
`;
- } else {
- upcoming.forEach(ev => {
- const item = createEventCard(ev, true);
- upcomingContainer.appendChild(item);
- });
-
-
var selectedContainer = els.selectedEvents;
var upcomingContainer = els.upcomingEvents;
- main
selectedContainer.innerHTML = "";
upcomingContainer.innerHTML = "";
@@ -592,64 +459,15 @@
if (!upcoming.length) {
upcomingContainer.innerHTML = 'No upcoming events.
';
} else {
- feature
- upcoming.forEach(ev => upcomingContainer.appendChild(createEventCard(ev, true)));
- main
-
upcoming.forEach(function(ev) {
upcomingContainer.appendChild(createEventCard(ev, true));
});
- main
}
}
function createEventCard(ev, showDate) {
var item = document.createElement("div");
item.className = "day-item";
- feature
-
- if (ev.color && ev.color !== "default") {
- item.dataset.color = ev.color;
- }
-
- let tag = "All day";
- if (ev.start && ev.end) {
- tag = `${ev.start} – ${ev.end}`;
- }
-
- const dateText = showDate ? `${ev.date}
` : "";
-
- item.innerHTML = `
-
-
-
${escapeHtml(ev.title)}
- ${dateText}
-
${escapeHtml(tag)}
-
-
-
-
-
-
-
- `;
-
- item.querySelector(".edit-btn").addEventListener("click", (e) => {
- e.stopPropagation();
- openModalForEdit(ev.id);
- });
-
- item.querySelector(".delete-btn").addEventListener("click", (e) => {
- e.stopPropagation();
- editingId = ev.id;
- onDelete();
- });
-
- return item;
- }
-
- // ---------- MODAL ----------
-
if (ev.color && ev.color !== "default") item.dataset.color = ev.color;
var tag = "All day";
@@ -693,7 +511,6 @@
}
// ─── MODAL ───────────────────────────────────────────────────────────────
- main
function openModalForDate(dateKey) {
editingId = null;
els.deleteBtn.hidden = true;
@@ -812,28 +629,15 @@
toast("Deleted");
}
- feature
- feature
- function showModal() {
-
function showModal() {
els.backdrop.hidden = false;
- main
els.modal.showModal();
}
function closeModal() {
- feature
- els.modal.close();
- }
-
- function showModal() { els.backdrop.hidden = false; els.modal.showModal(); }
- function closeModal() { els.modal.close(); els.backdrop.hidden = true; }
- main
if (els.modal.open) els.modal.close();
els.backdrop.hidden = true;
}
- main
// ─── EXPORT ──────────────────────────────────────────────────────────────
function exportEvents() {
@@ -863,103 +667,6 @@
toast("Events exported!");
}
- feature
- feature
- // ---------- SEARCH / CONFLICTS ----------
- function formatSearch(ev) {
- return normalizeStr(ev.title + " " + (ev.description || ""));
- }
-
- function getEventsOnDate(dateKey) {
- const d = new Date(dateKey + "T00:00:00");
- return events.filter(ev => {
- const eventStart = new Date(ev.date + "T00:00:00");
- const eventEnd = ev.endDate ? new Date(ev.endDate + "T00:00:00") : eventStart;
- return d >= eventStart && d <= eventEnd;
- });
- }
-
- function detectConflicts(candidate, excludeId = null) {
- if (!candidate.start || !candidate.end) return [];
- const candidateStart = new Date(`${candidate.date}T${candidate.start}`);
- const candidateEnd = new Date(`${candidate.endDate || candidate.date}T${candidate.end}`);
-
- return events
- .filter(e => e.id !== excludeId && e.start && e.end)
- .filter(e => {
- const existingStart = new Date(`${e.date}T${e.start}`);
- const existingEnd = new Date(`${e.endDate || e.date}T${e.end}`);
- return candidateStart < existingEnd && existingStart < candidateEnd;
- });
- }
-
- function updateConflictWarning(excludeId = null) {
- const d = draftFromForm();
- if (!d.date || !d.start || !d.end) {
- els.conflictBox.hidden = true;
- return;
- }
- els.conflictBox.hidden = detectConflicts(d, excludeId).length === 0;
- }
-
- // ---------- SMART PATTERN ANALYSIS ----------
- function analyzeEventPatterns() {
- const titleFrequency = {};
- const weekdayTimePatterns = {};
-
- events.forEach(ev => {
- // Count title usage
- if (ev.title) {
- titleFrequency[ev.title] = (titleFrequency[ev.title] || 0) + 1;
- }
-
- // Track weekday + time pattern
- if (ev.start && ev.end) {
- const weekday = new Date(ev.date + "T00:00:00").getDay();
-
- if (!weekdayTimePatterns[weekday]) {
- weekdayTimePatterns[weekday] = {};
- }
-
- const timeKey = `${ev.start}-${ev.end}`;
- weekdayTimePatterns[weekday][timeKey] =
- (weekdayTimePatterns[weekday][timeKey] || 0) + 1;
- }
- });
-
- return { titleFrequency, weekdayTimePatterns };
- }
-
- // ---------- LOCAL STORAGE ----------
- function loadEvents() {
- try {
- const raw = localStorage.getItem(STORAGE_KEY);
- const items = raw ? JSON.parse(raw) : [];
- return Array.isArray(items) ? items : [];
- } catch {
- return [];
- }
- }
-
- function saveEvents(list) {
- localStorage.setItem(STORAGE_KEY, JSON.stringify(list));
- }
-
- // ---------- DATE HELPERS ----------
- function toDateKey(d) {
- const y = d.getFullYear();
- const m = String(d.getMonth() + 1).padStart(2, "0");
- const day = String(d.getDate()).padStart(2, "0");
- return `${y}-${m}-${day}`;
- }
-
- function addMonths(d, n) {
- return new Date(d.getFullYear(), d.getMonth() + n, 1);
- }
-
- // ---------- POPUP REMINDERS ----------
-
-
// ─── IMPORT ──────────────────────────────────────────────────────────────
function initImportModal() {
els.importCloseBtn.addEventListener("click", function() {
@@ -1028,9 +735,7 @@
importParsed = [];
}
- main
// ─── POPUP REMINDERS ─────────────────────────────────────────────────────
- main
function checkPopupReminders() {
var todayKey = toDateKey(new Date());
var seen = {};
@@ -1080,24 +785,6 @@
});
}
- feature
- feature
- // ---------- UTILS ----------
- function normalizeStr(str) {
- return (str || "").toString().toLocaleLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
- }
-
- function safeUUID() {
- return (crypto && crypto.randomUUID)
- ? crypto.randomUUID()
- : String(Date.now()) + "_" + Math.random().toString(16).slice(2);
-
- function detectConflicts(candidate, excludeId = null) {
- if (!candidate.start || !candidate.end) return [];
- const cs = new Date(candidate.date + "T" + candidate.start), ce = new Date((candidate.endDate || candidate.date) + "T" + candidate.end);
- return events.filter(e => e.id !== excludeId && e.start && e.end).filter(e => { const es = new Date(e.date + "T" + e.start), ee = new Date((e.endDate || e.date) + "T" + e.end); return cs < ee && es < ce; });
- main
-
function detectConflicts(candidate, excludeId) {
if (!candidate.start || !candidate.end) return [];
var cs = new Date(candidate.date + "T" + candidate.start);
@@ -1109,7 +796,6 @@
var ee = new Date((e.endDate || e.date) + "T" + e.end);
return cs < ee && es < ce;
});
- main
}
function updateConflictWarning(excludeId) {
diff --git a/index.html b/index.html
index 208cbcf..4ffc094 100644
--- a/index.html
+++ b/index.html
@@ -67,39 +67,21 @@ Calendar
Wed
Thu
Fri
Sat
- feature
-
- No events found
-
- main