110 lines
6.3 KiB
TypeScript
110 lines
6.3 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
import React from 'react';
|
|
import { Repeat, X, Trash2 } from 'lucide-react';
|
|
|
|
interface RecurringTasksManagerProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
tasks: any[];
|
|
onStopRecurring: (task: any) => void;
|
|
}
|
|
|
|
export default function RecurringTasksManager({ isOpen, onClose, tasks, onStopRecurring }: RecurringTasksManagerProps) {
|
|
if (!isOpen) return null;
|
|
|
|
// Filter and group recurring tasks by series signature
|
|
// We use title + recurrence settings as the identity of a "series"
|
|
const seriesGroups = new Map<string, any>();
|
|
|
|
tasks.filter(t => t.isRecurring).forEach(t => {
|
|
// Only include those that aren't already ended
|
|
if (t.recurrenceEndDate && new Date(t.recurrenceEndDate) < new Date()) {
|
|
return;
|
|
}
|
|
|
|
const signature = `${t.title}-${t.recurrenceInterval || 1}-${t.recurrenceUnit || 'weeks'}-${t.recurrenceTime || ''}`;
|
|
|
|
// Keep the latest instance to represent the series
|
|
const existing = seriesGroups.get(signature);
|
|
if (!existing || (t.scheduledDate && new Date(t.scheduledDate) > new Date(existing.scheduledDate || 0))) {
|
|
seriesGroups.set(signature, t);
|
|
}
|
|
});
|
|
|
|
const groupedTasks = Array.from(seriesGroups.values());
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black/50 z-[3000] flex items-center justify-center p-4 animate-fadeIn" onClick={onClose}>
|
|
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-2xl w-[600px] max-w-full overflow-hidden flex flex-col animate-scaleIn" onClick={e => e.stopPropagation()}>
|
|
<div className="p-5 flex items-center justify-between border-b border-gray-100 dark:border-gray-800">
|
|
<div className="flex items-center gap-3">
|
|
<div className="p-2 bg-teal-100 dark:bg-teal-900/30 rounded-lg text-teal-600">
|
|
<Repeat size={20} />
|
|
</div>
|
|
<h2 className="text-lg font-bold text-gray-800 dark:text-white">Wiederkehrende Aufgaben</h2>
|
|
</div>
|
|
<button onClick={onClose} className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-full text-gray-400 transition-colors">
|
|
<X size={20} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex-1 overflow-y-auto p-6">
|
|
{groupedTasks.length === 0 ? (
|
|
<div className="flex flex-col items-center justify-center py-12 text-center">
|
|
<div className="w-16 h-16 bg-gray-50 dark:bg-gray-800 rounded-full flex items-center justify-center text-gray-300 mb-4">
|
|
<Repeat size={32} />
|
|
</div>
|
|
<p className="text-gray-500 dark:text-gray-400 max-w-xs">
|
|
Du hast momentan keine aktiven wiederkehrenden Aufgaben.
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{groupedTasks.map(task => (
|
|
<div key={task.id} className="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-800/50 rounded-xl border border-gray-100 dark:border-gray-700/50 hover:border-teal-200 dark:hover:border-teal-900/50 transition-all">
|
|
<div className="flex-1 min-w-0 pr-4">
|
|
<div className="font-semibold text-gray-900 dark:text-white truncate" title={task.title}>
|
|
{task.title}
|
|
</div>
|
|
<div className="flex items-center gap-2 mt-1">
|
|
<span className="text-xs px-2 py-0.5 bg-teal-50 dark:bg-teal-900/20 text-teal-600 dark:text-teal-400 rounded-md font-medium capitalize">
|
|
Alle {task.recurrenceInterval === 1 ? '' : task.recurrenceInterval} {
|
|
task.recurrenceUnit === 'days' ? 'Tage' :
|
|
task.recurrenceUnit === 'weeks' ? 'Wochen' :
|
|
task.recurrenceUnit === 'months' ? 'Monate' : 'Jahre'
|
|
}
|
|
</span>
|
|
{task.recurrenceTime && (
|
|
<span className="text-[10px] text-gray-400">
|
|
um {task.recurrenceTime} Uhr
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={() => {
|
|
if (confirm(`Serie "${task.title}" wirklich beenden?`)) {
|
|
onStopRecurring(task);
|
|
}
|
|
}}
|
|
className="flex items-center gap-2 px-3 py-2 bg-red-50 hover:bg-red-100 dark:bg-red-900/10 dark:hover:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-xs font-bold transition-colors group"
|
|
>
|
|
<Trash2 size={14} className="group-hover:scale-110 transition-transform" />
|
|
Serie beenden
|
|
</button>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="p-3 bg-gray-50 dark:bg-gray-900 border-t border-gray-100 dark:border-gray-800 flex justify-center">
|
|
<p className="text-[10px] text-gray-400 font-medium">
|
|
Tipp: Du kannst Aufgaben jederzeit beim Bearbeiten wiederkehrend machen.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|