Kontakt-Modul
Dieser Commit ist enthalten in:
committet von
Server Deploy
Ursprung
623bbdf5dd
Commit
7d67557be4
@ -32,10 +32,17 @@ class CalendarViewManager {
|
||||
init() {
|
||||
this.container = $('#view-calendar');
|
||||
|
||||
// Set initial view mode on calendar grid
|
||||
const grid = $('#calendar-grid');
|
||||
if (grid) {
|
||||
grid.classList.add('calendar-month-view');
|
||||
}
|
||||
|
||||
this.bindEvents();
|
||||
|
||||
// Subscribe to store changes
|
||||
store.subscribe('tasks', () => this.render());
|
||||
store.subscribe('reminders', () => this.render());
|
||||
store.subscribe('filters', (filters) => {
|
||||
// Calendar-specific search behavior
|
||||
if (store.get('currentView') === 'calendar') {
|
||||
@ -95,7 +102,7 @@ class CalendarViewManager {
|
||||
// Close popup on outside click
|
||||
document.addEventListener('click', (e) => {
|
||||
if (this.dayDetailPopup && !this.dayDetailPopup.contains(e.target) &&
|
||||
!e.target.closest('.calendar-day')) {
|
||||
!e.target.closest('.calendar-day') && !e.target.closest('.calendar-week-day')) {
|
||||
this.closeDayDetail();
|
||||
}
|
||||
});
|
||||
@ -120,6 +127,12 @@ class CalendarViewManager {
|
||||
grid.classList.add(`calendar-${mode}-view`);
|
||||
}
|
||||
|
||||
// Show/hide weekday headers based on view mode
|
||||
const weekdaysHeader = $('#calendar-weekdays');
|
||||
if (weekdaysHeader) {
|
||||
weekdaysHeader.style.display = mode === 'month' ? 'grid' : 'none';
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
@ -230,13 +243,29 @@ class CalendarViewManager {
|
||||
render() {
|
||||
if (store.get('currentView') !== 'calendar') return;
|
||||
|
||||
// Ensure calendar grid exists and has correct class
|
||||
const grid = $('#calendar-grid');
|
||||
if (!grid) return;
|
||||
|
||||
grid.classList.remove('calendar-month-view', 'calendar-week-view');
|
||||
grid.classList.add(`calendar-${this.viewMode}-view`);
|
||||
|
||||
// Ensure weekday headers visibility matches current view mode
|
||||
const weekdaysHeader = $('#calendar-weekdays');
|
||||
if (weekdaysHeader) {
|
||||
weekdaysHeader.style.display = this.viewMode === 'month' ? 'grid' : 'none';
|
||||
}
|
||||
|
||||
this.updateHeader();
|
||||
|
||||
if (this.viewMode === 'month') {
|
||||
this.renderMonthView();
|
||||
} else {
|
||||
this.renderWeekView();
|
||||
}
|
||||
// Force a small delay to ensure DOM is ready
|
||||
setTimeout(() => {
|
||||
if (this.viewMode === 'month') {
|
||||
this.renderMonthView();
|
||||
} else {
|
||||
this.renderWeekView();
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
updateHeader() {
|
||||
@ -264,7 +293,14 @@ class CalendarViewManager {
|
||||
|
||||
renderMonthView() {
|
||||
const daysContainer = $('#calendar-grid');
|
||||
if (!daysContainer) return;
|
||||
if (!daysContainer) {
|
||||
console.warn('[Calendar] calendar-grid not found for month view');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure correct classes are set
|
||||
daysContainer.classList.remove('calendar-week-view');
|
||||
daysContainer.classList.add('calendar-month-view');
|
||||
|
||||
clearElement(daysContainer);
|
||||
|
||||
@ -334,18 +370,20 @@ class CalendarViewManager {
|
||||
const dateString = this.getDateString(date);
|
||||
const isToday = dateString === todayString;
|
||||
|
||||
daysContainer.appendChild(this.createWeekDayElement(date, tasksByDate, isToday));
|
||||
daysContainer.appendChild(this.createWeekDayElement(date, tasksByDate, isToday, weekStart));
|
||||
}
|
||||
}
|
||||
|
||||
createWeekDayElement(date, tasksByDate, isToday = false) {
|
||||
createWeekDayElement(date, tasksByDate, isToday = false, weekStart = null) {
|
||||
const dateString = this.getDateString(date);
|
||||
const dayTasks = tasksByDate[dateString] || [];
|
||||
const remindersByDate = this.getRemindersByDate();
|
||||
const dayReminders = remindersByDate[dateString] || [];
|
||||
const hasOverdue = dayTasks.some(t => this.isTaskOverdue(t));
|
||||
|
||||
const classes = ['calendar-week-day'];
|
||||
if (isToday) classes.push('today');
|
||||
if (dayTasks.length > 0) classes.push('has-tasks');
|
||||
if (dayTasks.length > 0 || dayReminders.length > 0) classes.push('has-tasks');
|
||||
if (hasOverdue) classes.push('has-overdue');
|
||||
|
||||
const dayEl = createElement('div', {
|
||||
@ -367,12 +405,58 @@ class CalendarViewManager {
|
||||
// Tasks container
|
||||
const tasksContainer = createElement('div', { className: 'calendar-week-day-tasks' });
|
||||
|
||||
if (dayTasks.length === 0) {
|
||||
// Combined array of reminders and tasks
|
||||
const allItems = [];
|
||||
|
||||
// Add tasks first (wichtig für kontinuierliche Balken)
|
||||
dayTasks.forEach(task => {
|
||||
allItems.push({
|
||||
type: 'task',
|
||||
...task
|
||||
});
|
||||
});
|
||||
|
||||
// Add reminders after tasks
|
||||
dayReminders.forEach(reminder => {
|
||||
allItems.push({
|
||||
type: 'reminder',
|
||||
id: reminder.id,
|
||||
title: reminder.title,
|
||||
color: reminder.color || '#F59E0B',
|
||||
time: reminder.reminder_time
|
||||
});
|
||||
});
|
||||
|
||||
if (allItems.length === 0) {
|
||||
tasksContainer.appendChild(createElement('div', {
|
||||
className: 'calendar-week-empty'
|
||||
}, ['Keine Aufgaben']));
|
||||
} else {
|
||||
dayTasks.forEach(task => {
|
||||
allItems.forEach(item => {
|
||||
if (item.type === 'reminder') {
|
||||
// Create reminder element
|
||||
const reminderEl = createElement('div', {
|
||||
className: 'calendar-week-task calendar-reminder-item',
|
||||
dataset: { reminderId: item.id },
|
||||
title: `Erinnerung: ${item.title}${item.time ? ' um ' + item.time : ''}`,
|
||||
onclick: (e) => {
|
||||
e.stopPropagation();
|
||||
this.editReminder(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
// Add title and bell icon
|
||||
reminderEl.appendChild(createElement('span', { className: 'calendar-week-task-title' }, [item.title]));
|
||||
reminderEl.appendChild(createElement('span', { className: 'calendar-reminder-bell' }, ['🔔']));
|
||||
|
||||
// Apply color
|
||||
reminderEl.style.backgroundColor = `${item.color}25`;
|
||||
reminderEl.style.borderLeftColor = item.color;
|
||||
|
||||
tasksContainer.appendChild(reminderEl);
|
||||
} else {
|
||||
// Existing task rendering code
|
||||
const task = item;
|
||||
// Get column color and user badge info
|
||||
const columnColor = this.getColumnColor(task);
|
||||
const userBadge = this.getUserBadgeInfo(task);
|
||||
@ -391,13 +475,20 @@ class CalendarViewManager {
|
||||
taskClasses.push('search-highlight');
|
||||
}
|
||||
|
||||
// Build task element children
|
||||
const children = [
|
||||
createElement('span', { className: 'calendar-week-task-title' }, [task.title])
|
||||
];
|
||||
// Check if this is the first day of the week or the start of the task
|
||||
const isFirstDayOfWeek = weekStart && this.getDateString(date) === this.getDateString(weekStart);
|
||||
const showContent = task.isRangeStart || !task.hasRange || isFirstDayOfWeek;
|
||||
|
||||
// Add user badges if assigned (supports multiple)
|
||||
if (userBadge && userBadge.length > 0) {
|
||||
// Build task element children
|
||||
const children = [];
|
||||
|
||||
// Add title (only at start of task or first day of week)
|
||||
if (showContent) {
|
||||
children.push(createElement('span', { className: 'calendar-week-task-title' }, [task.title]));
|
||||
}
|
||||
|
||||
// Add user badges if assigned (only at start of task or first day of week, supports multiple)
|
||||
if (userBadge && userBadge.length > 0 && showContent) {
|
||||
const badgeContainer = createElement('span', { className: 'calendar-task-badges' });
|
||||
userBadge.forEach(badge => {
|
||||
const badgeEl = createElement('span', { className: 'calendar-task-user-badge' }, [badge.initials]);
|
||||
@ -420,6 +511,7 @@ class CalendarViewManager {
|
||||
}
|
||||
|
||||
tasksContainer.appendChild(taskEl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -452,12 +544,14 @@ class CalendarViewManager {
|
||||
createDayElement(date, dayNumber, isOtherMonth, tasksByDate, isToday = false) {
|
||||
const dateString = this.getDateString(date);
|
||||
const dayTasks = tasksByDate[dateString] || [];
|
||||
const remindersByDate = this.getRemindersByDate();
|
||||
const dayReminders = remindersByDate[dateString] || [];
|
||||
const hasOverdue = dayTasks.some(t => this.isTaskOverdue(t));
|
||||
|
||||
const classes = ['calendar-day'];
|
||||
if (isOtherMonth) classes.push('other-month');
|
||||
if (isToday) classes.push('today');
|
||||
if (dayTasks.length > 0) classes.push('has-tasks');
|
||||
if (dayTasks.length > 0 || dayReminders.length > 0) classes.push('has-tasks');
|
||||
if (hasOverdue) classes.push('has-overdue');
|
||||
|
||||
const dayEl = createElement('div', {
|
||||
@ -470,11 +564,57 @@ class CalendarViewManager {
|
||||
className: 'calendar-day-number'
|
||||
}, [dayNumber.toString()]));
|
||||
|
||||
// Tasks preview (show max 3)
|
||||
if (dayTasks.length > 0) {
|
||||
// Combined container for reminders and tasks
|
||||
const allItems = [];
|
||||
|
||||
// Add tasks first (wichtig für kontinuierliche Balken)
|
||||
dayTasks.forEach(task => {
|
||||
allItems.push({
|
||||
type: 'task',
|
||||
...task
|
||||
});
|
||||
});
|
||||
|
||||
// Add reminders after tasks
|
||||
dayReminders.forEach(reminder => {
|
||||
allItems.push({
|
||||
type: 'reminder',
|
||||
id: reminder.id,
|
||||
title: reminder.title,
|
||||
color: reminder.color || '#F59E0B',
|
||||
time: reminder.reminder_time
|
||||
});
|
||||
});
|
||||
|
||||
// Show max 3 items
|
||||
if (allItems.length > 0) {
|
||||
const tasksContainer = createElement('div', { className: 'calendar-day-tasks' });
|
||||
|
||||
dayTasks.slice(0, 3).forEach(task => {
|
||||
allItems.slice(0, 3).forEach(item => {
|
||||
if (item.type === 'reminder') {
|
||||
// Create reminder element
|
||||
const reminderEl = createElement('div', {
|
||||
className: 'calendar-task calendar-reminder-item',
|
||||
dataset: { reminderId: item.id },
|
||||
title: `Erinnerung: ${item.title}${item.time ? ' um ' + item.time : ''}`,
|
||||
onclick: (e) => {
|
||||
e.stopPropagation();
|
||||
this.editReminder(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
// Add title and bell icon
|
||||
reminderEl.appendChild(createElement('span', { className: 'calendar-task-title' }, [item.title]));
|
||||
reminderEl.appendChild(createElement('span', { className: 'calendar-reminder-bell' }, ['🔔']));
|
||||
|
||||
// Apply color
|
||||
reminderEl.style.backgroundColor = `${item.color}40`;
|
||||
reminderEl.style.borderLeftColor = item.color;
|
||||
|
||||
tasksContainer.appendChild(reminderEl);
|
||||
} else {
|
||||
// Existing task rendering code
|
||||
const task = item;
|
||||
// Get column color and user badge info
|
||||
const columnColor = this.getColumnColor(task);
|
||||
const userBadge = this.getUserBadgeInfo(task);
|
||||
@ -523,12 +663,13 @@ class CalendarViewManager {
|
||||
}
|
||||
|
||||
tasksContainer.appendChild(taskEl);
|
||||
}
|
||||
});
|
||||
|
||||
if (dayTasks.length > 3) {
|
||||
if (allItems.length > 3) {
|
||||
tasksContainer.appendChild(createElement('div', {
|
||||
className: 'calendar-more'
|
||||
}, [`+${dayTasks.length - 3} weitere`]));
|
||||
}, [`+${allItems.length - 3} weitere`]));
|
||||
}
|
||||
|
||||
dayEl.appendChild(tasksContainer);
|
||||
@ -570,18 +711,32 @@ class CalendarViewManager {
|
||||
});
|
||||
}
|
||||
|
||||
// Sort tasks: earliest start date first (so they stay on top throughout their duration),
|
||||
// then alphabetically by title for same start date
|
||||
// Sort tasks: Range tasks first (to ensure continuous bars), then single-day tasks
|
||||
filteredTasks.sort((a, b) => {
|
||||
const startA = a.startDate || a.dueDate || '';
|
||||
const startB = b.startDate || b.dueDate || '';
|
||||
|
||||
// Compare start dates (earliest first = ascending)
|
||||
const endA = a.dueDate || '';
|
||||
const endB = b.dueDate || '';
|
||||
|
||||
// Check if task has range (both start and end date, and they're different)
|
||||
const hasRangeA = a.startDate && a.dueDate && a.startDate !== a.dueDate;
|
||||
const hasRangeB = b.startDate && b.dueDate && b.startDate !== b.dueDate;
|
||||
|
||||
// Range tasks come first
|
||||
if (hasRangeA && !hasRangeB) return -1;
|
||||
if (!hasRangeA && hasRangeB) return 1;
|
||||
|
||||
// If both have ranges or both are single-day, sort by start date
|
||||
if (startA !== startB) {
|
||||
return startA.localeCompare(startB);
|
||||
}
|
||||
|
||||
// Same start date: sort by end date (longer ranges first)
|
||||
if (endA !== endB) {
|
||||
return endB.localeCompare(endA); // Descending to put longer ranges first
|
||||
}
|
||||
|
||||
// Same start date: sort alphabetically by title
|
||||
// Same dates: sort alphabetically by title
|
||||
return (a.title || '').localeCompare(b.title || '', 'de');
|
||||
});
|
||||
|
||||
@ -629,6 +784,32 @@ class CalendarViewManager {
|
||||
return tasksByDate;
|
||||
}
|
||||
|
||||
getRemindersByDate() {
|
||||
const reminders = store.get('reminders') || [];
|
||||
if (!Array.isArray(reminders)) {
|
||||
console.warn('[Calendar] Reminders not available or not an array');
|
||||
return {};
|
||||
}
|
||||
|
||||
const activeReminders = reminders.filter(r => r.is_active);
|
||||
const remindersByDate = {};
|
||||
|
||||
activeReminders.forEach(reminder => {
|
||||
const date = reminder.reminder_date;
|
||||
if (!remindersByDate[date]) {
|
||||
remindersByDate[date] = [];
|
||||
}
|
||||
remindersByDate[date].push(reminder);
|
||||
});
|
||||
|
||||
// Sort reminders by time within each date
|
||||
Object.keys(remindersByDate).forEach(date => {
|
||||
remindersByDate[date].sort((a, b) => (a.reminder_time || '09:00').localeCompare(b.reminder_time || '09:00'));
|
||||
});
|
||||
|
||||
return remindersByDate;
|
||||
}
|
||||
|
||||
getDateString(date) {
|
||||
// Use local date components instead of toISOString() which converts to UTC
|
||||
// This fixes the issue where the date is off by one day due to timezone differences
|
||||
@ -643,9 +824,12 @@ class CalendarViewManager {
|
||||
// =====================
|
||||
|
||||
handleDayClick(e) {
|
||||
console.log('[Calendar] Day click event:', e.target, 'View mode:', this.viewMode);
|
||||
|
||||
// Check if clicked on a specific task
|
||||
const taskEl = e.target.closest('.calendar-task, .calendar-week-task');
|
||||
if (taskEl) {
|
||||
console.log('[Calendar] Task clicked:', taskEl.dataset.taskId);
|
||||
const taskId = parseInt(taskEl.dataset.taskId);
|
||||
this.openTaskModal(taskId);
|
||||
return;
|
||||
@ -653,24 +837,36 @@ class CalendarViewManager {
|
||||
|
||||
// Check if clicked on add button (week view)
|
||||
if (e.target.closest('.calendar-week-add-task')) {
|
||||
console.log('[Calendar] Add task button clicked');
|
||||
return; // Already handled by onclick
|
||||
}
|
||||
|
||||
// For month view, show day detail popup
|
||||
// Show day detail popup for both month and week view
|
||||
if (this.viewMode === 'month') {
|
||||
const dayEl = e.target.closest('.calendar-day');
|
||||
if (!dayEl) return;
|
||||
|
||||
console.log('[Calendar] Month day clicked:', dayEl.dataset.date);
|
||||
const dateString = dayEl.dataset.date;
|
||||
this.showDayDetail(dateString, dayEl);
|
||||
} else if (this.viewMode === 'week') {
|
||||
const dayEl = e.target.closest('.calendar-week-day');
|
||||
console.log('[Calendar] Week day element found:', !!dayEl);
|
||||
if (!dayEl) return;
|
||||
|
||||
console.log('[Calendar] Week day clicked:', dayEl.dataset.date);
|
||||
const dateString = dayEl.dataset.date;
|
||||
this.showDayDetail(dateString, dayEl);
|
||||
}
|
||||
}
|
||||
|
||||
showDayDetail(dateString, anchorEl) {
|
||||
console.log('[Calendar] showDayDetail called:', dateString, anchorEl);
|
||||
this.closeDayDetail();
|
||||
|
||||
const tasksByDate = this.getTasksByDate();
|
||||
const dayTasks = tasksByDate[dateString] || [];
|
||||
console.log('[Calendar] Tasks for date:', dayTasks.length);
|
||||
|
||||
const date = new Date(dateString);
|
||||
const dateDisplay = date.toLocaleDateString('de-DE', {
|
||||
@ -726,13 +922,35 @@ class CalendarViewManager {
|
||||
onclick: () => this.createTaskForDate(dateString)
|
||||
}, ['+ Aufgabe hinzufügen']));
|
||||
|
||||
// Position popup
|
||||
// Add reminder button
|
||||
popup.appendChild(createElement('button', {
|
||||
className: 'btn btn-secondary btn-block',
|
||||
style: { marginTop: 'var(--spacing-sm)' },
|
||||
onclick: () => this.createReminderForDate(dateString)
|
||||
}, ['🔔 Erinnerung hinzufügen']));
|
||||
|
||||
// Position popup - different logic for week vs month view
|
||||
const rect = anchorEl.getBoundingClientRect();
|
||||
popup.style.top = `${rect.bottom + 8}px`;
|
||||
popup.style.left = `${Math.min(rect.left, window.innerWidth - 350)}px`;
|
||||
|
||||
let popupTop, popupLeft;
|
||||
|
||||
if (this.viewMode === 'week') {
|
||||
// For week view, position at the top of the day element
|
||||
popupTop = Math.max(150, rect.top + 50); // Ensure it's visible, minimum 150px from top
|
||||
popupLeft = Math.min(rect.left, window.innerWidth - 350);
|
||||
} else {
|
||||
// For month view, position below the day element
|
||||
popupTop = rect.bottom + 8;
|
||||
popupLeft = Math.min(rect.left, window.innerWidth - 350);
|
||||
}
|
||||
|
||||
popup.style.top = `${popupTop}px`;
|
||||
popup.style.left = `${popupLeft}px`;
|
||||
console.log('[Calendar] Popup positioning for', this.viewMode, '- Top:', popup.style.top, 'Left:', popup.style.left);
|
||||
|
||||
document.body.appendChild(popup);
|
||||
this.dayDetailPopup = popup;
|
||||
console.log('[Calendar] Popup created and appended to body');
|
||||
}
|
||||
|
||||
closeDayDetail() {
|
||||
@ -778,6 +996,155 @@ class CalendarViewManager {
|
||||
}));
|
||||
}
|
||||
|
||||
createReminderForDate(dateString) {
|
||||
this.closeDayDetail();
|
||||
|
||||
window.dispatchEvent(new CustomEvent('modal:open', {
|
||||
detail: {
|
||||
modalId: 'reminder-modal',
|
||||
mode: 'create',
|
||||
data: {
|
||||
prefill: {
|
||||
date: dateString
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
showRemindersForDate(dateString, anchorEl) {
|
||||
const reminders = this.getRemindersByDate();
|
||||
const dayReminders = reminders[dateString] || [];
|
||||
|
||||
if (dayReminders.length === 0) return;
|
||||
|
||||
// Close existing popup
|
||||
this.closeDayDetail();
|
||||
|
||||
// Create popup
|
||||
const popup = createElement('div', {
|
||||
className: 'calendar-day-detail calendar-reminder-detail',
|
||||
onclick: (e) => e.stopPropagation()
|
||||
});
|
||||
|
||||
this.dayDetailPopup = popup;
|
||||
|
||||
// Header
|
||||
const header = createElement('h3', {}, [`Erinnerungen für ${formatDate(dateString)}`]);
|
||||
popup.appendChild(header);
|
||||
|
||||
// Reminders list
|
||||
const remindersList = createElement('div', { className: 'calendar-detail-reminders' });
|
||||
|
||||
dayReminders.forEach(reminder => {
|
||||
// Create reminder content (clickable for edit)
|
||||
const reminderContent = createElement('div', {
|
||||
className: 'reminder-content',
|
||||
onclick: () => this.editReminder(reminder.id)
|
||||
}, [
|
||||
createElement('div', {
|
||||
className: 'reminder-time',
|
||||
style: { color: reminder.color || '#F59E0B' }
|
||||
}, [reminder.reminder_time || '09:00']),
|
||||
createElement('div', { className: 'reminder-title' }, [reminder.title]),
|
||||
reminder.description ? createElement('div', { className: 'reminder-description' }, [reminder.description]) : null
|
||||
].filter(Boolean));
|
||||
|
||||
// Create delete button
|
||||
const deleteBtn = createElement('button', {
|
||||
className: 'reminder-delete-btn',
|
||||
title: 'Erinnerung löschen',
|
||||
onclick: (e) => {
|
||||
e.stopPropagation();
|
||||
this.deleteReminder(reminder.id, reminder.title);
|
||||
}
|
||||
}, [
|
||||
createElement('svg', {
|
||||
viewBox: '0 0 24 24',
|
||||
width: '16',
|
||||
height: '16'
|
||||
}, [
|
||||
createElement('path', {
|
||||
d: 'M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '2',
|
||||
fill: 'none',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round'
|
||||
})
|
||||
])
|
||||
]);
|
||||
|
||||
// Container with content and delete button
|
||||
const reminderItem = createElement('div', {
|
||||
className: 'calendar-detail-reminder'
|
||||
}, [reminderContent, deleteBtn]);
|
||||
|
||||
remindersList.appendChild(reminderItem);
|
||||
});
|
||||
|
||||
popup.appendChild(remindersList);
|
||||
|
||||
// Add reminder button
|
||||
popup.appendChild(createElement('button', {
|
||||
className: 'btn btn-secondary btn-block',
|
||||
style: { marginTop: 'var(--spacing-md)' },
|
||||
onclick: () => this.createReminderForDate(dateString)
|
||||
}, ['+ Weitere Erinnerung']));
|
||||
|
||||
// Position popup
|
||||
const rect = anchorEl.getBoundingClientRect();
|
||||
let popupTop = rect.bottom + 8;
|
||||
let popupLeft = Math.min(rect.left, window.innerWidth - 350);
|
||||
|
||||
popup.style.top = `${popupTop}px`;
|
||||
popup.style.left = `${popupLeft}px`;
|
||||
|
||||
document.body.appendChild(popup);
|
||||
}
|
||||
|
||||
editReminder(reminderId) {
|
||||
this.closeDayDetail();
|
||||
|
||||
window.dispatchEvent(new CustomEvent('modal:open', {
|
||||
detail: {
|
||||
modalId: 'reminder-modal',
|
||||
mode: 'edit',
|
||||
data: { reminderId }
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
async deleteReminder(reminderId, reminderTitle) {
|
||||
if (!confirm(`Erinnerung "${reminderTitle}" wirklich löschen?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Import reminder manager if needed
|
||||
if (typeof reminderManager !== 'undefined') {
|
||||
await reminderManager.deleteReminder(reminderId);
|
||||
} else {
|
||||
// Fallback direct API call
|
||||
await api.request(`/reminders/${reminderId}`, { method: 'DELETE' });
|
||||
|
||||
// Update store
|
||||
const reminders = store.get('reminders') || [];
|
||||
const updatedReminders = reminders.filter(r => r.id !== reminderId);
|
||||
store.setReminders(updatedReminders);
|
||||
}
|
||||
|
||||
// Close popup and refresh calendar
|
||||
this.closeDayDetail();
|
||||
this.render();
|
||||
|
||||
console.log(`[Calendar] Reminder ${reminderId} deleted`);
|
||||
} catch (error) {
|
||||
console.error('[Calendar] Failed to delete reminder:', error);
|
||||
alert('Fehler beim Löschen der Erinnerung. Bitte versuche es erneut.');
|
||||
}
|
||||
}
|
||||
|
||||
// =====================
|
||||
// HELPERS
|
||||
// =====================
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren