From a834b440a5d34f7b166737b9dc9d8aed5f592ca6 Mon Sep 17 00:00:00 2001 From: mARTin Date: Fri, 13 Feb 2026 20:12:31 +0100 Subject: [PATCH] Refactor: Rearrange header, streamline settings, fix task hover icons, and overhaul recurring task manager --- src/app/globals.css | 8 +- src/components/RecurringTasksManager.tsx | 143 +++++++------ src/components/WeeklyView.tsx | 245 +++++++++-------------- 3 files changed, 174 insertions(+), 222 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 0494a81..6ab3dc5 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -790,18 +790,20 @@ h3 { background: none; border: none; cursor: pointer; - padding: 4px; + padding: 2px; + width: 20px; + height: 20px; color: var(--weekly-text-light); border-radius: 4px; display: flex; align-items: center; justify-content: center; - transition: color 0.15s; + transition: all 0.15s; } .task-action-btn:hover { color: var(--weekly-text); - background: rgba(0,0,0,0.05); + background: rgba(0,0,0,0.08); } /* Specific button styles */ diff --git a/src/components/RecurringTasksManager.tsx b/src/components/RecurringTasksManager.tsx index 2e249f9..abc2d0c 100644 --- a/src/components/RecurringTasksManager.tsx +++ b/src/components/RecurringTasksManager.tsx @@ -1,96 +1,107 @@ /* 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 }: RecurringTasksManagerProps) { +export default function RecurringTasksManager({ isOpen, onClose, tasks, onStopRecurring }: RecurringTasksManagerProps) { if (!isOpen) return null; - // Filter tasks that are recurring - const recurringTasks = tasks.filter(t => t.isRecurring); + // Filter and group recurring tasks by series signature + // We use title + recurrence settings as the identity of a "series" + const seriesGroups = new Map(); + + 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 ( -
-
e.stopPropagation()}> -
-

Recurring to-dos

-
-
- {recurringTasks.length === 0 ? ( -
-

- You don't have any recurring to-dos yet. +

+ {groupedTasks.length === 0 ? ( +
+
+ +
+

+ Du hast momentan keine aktiven wiederkehrenden Aufgaben.

- - - -

Or, type a frequency to the end of a to-do.

- -
-
-
OCT 5, 2023
-
THURSDAY
-
-
-
- -
-
-

Frequencies:

-
    -
  • every day
  • -
  • every week
  • -
  • every other week
  • -
  • every month
  • -
  • every year
  • -
-
-
-

Examples:

-
    -
  • Brush teeth every day
  • -
  • Management meeting every week
  • -
  • Piano lessons every other week
  • -
  • Pay rent every month
  • -
  • Garret's birthday every year
  • -
-
-
) : ( -
- {recurringTasks.map(task => ( -
-
-
{task.title}
-
- Repeats every {task.recurrenceInterval} {task.recurrenceUnit} +
+ {groupedTasks.map(task => ( +
+
+
+ {task.title} +
+
+ + Alle {task.recurrenceInterval === 1 ? '' : task.recurrenceInterval} { + task.recurrenceUnit === 'days' ? 'Tage' : + task.recurrenceUnit === 'weeks' ? 'Wochen' : + task.recurrenceUnit === 'months' ? 'Monate' : 'Jahre' + } + + {task.recurrenceTime && ( + + um {task.recurrenceTime} Uhr + + )}
- +
))}
)}
-
- +
+

+ Tipp: Du kannst Aufgaben jederzeit beim Bearbeiten wiederkehrend machen. +

diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index 26aa570..345b7c6 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -323,7 +323,6 @@ export default function WeeklyView() { const [somedayLists, setSomedayLists] = useState([]); const [editingTaskId, setEditingTaskId] = useState(null); const [showSettings, setShowSettings] = useState(false); - const [showPreferences, setShowPreferences] = useState(false); const [showDatePicker, setShowDatePicker] = useState(false); const [isAddingSomedayList, setIsAddingSomedayList] = useState(false); const [newSomedayListName, setNewSomedayListName] = useState(''); @@ -1522,16 +1521,32 @@ export default function WeeklyView() { {/* Refactored Header: Left, Center, Right */}
- {/* LEFT SECTION: Days to Show & Time Range */} + {/* LEFT SECTION: Slot Duration & Days to Show */}
+ {/* Slot Duration */} + {showTimeGrid && ( +
+ + {[15, 30, 60].map(duration => ( + + ))} +
+ )} + {/* Days to Show */} -
+
{[1, 3, 5, 7].map(num => ( @@ -1540,7 +1555,7 @@ export default function WeeklyView() { {/* Time Range */} {showTimeGrid && ( -
+
setStartHour(Math.max(0, Math.min(parseInt(e.target.value) || 0, endHour - 1)))} - className="w-12 p-0.5 border border-gray-200 rounded text-center bg-transparent focus:outline-none focus:border-teal-500" + className="w-10 p-0.5 border border-gray-200 dark:border-gray-700 rounded text-center bg-transparent focus:outline-none focus:border-teal-500" /> - setEndHour(Math.max(startHour + 1, Math.min(parseInt(e.target.value) || 24, 24)))} - className="w-12 p-0.5 border border-gray-200 rounded text-center bg-transparent focus:outline-none focus:border-teal-500" + className="w-10 p-0.5 border border-gray-200 dark:border-gray-700 rounded text-center bg-transparent focus:outline-none focus:border-teal-500" />
)} - {/* Day/Night Mode Switch */} - + {/* View Style Toggles */} +
+ + + +
{/* CENTER SECTION: Week/Year, Motto, Focus Mode */} @@ -1638,27 +1666,14 @@ export default function WeeklyView() { {/* RIGHT SECTION: Navigation & Tools */}
- {/* Date Picker Toggle */} -
- - {showDatePicker && ( - { - setCurrentWeekStart(getStartOfWeek(date, weekStartDay)); - setShowDatePicker(false); - }} - onClose={() => setShowDatePicker(false)} - language={language} - /> - )} -
+ {/* Day/Night Mode Switch */} + {/* Navigation Controls */}
@@ -1672,16 +1687,13 @@ export default function WeeklyView() { Today
- {/* Divider */} -
- {/* Search */} - {/* Settings - Actually triggers User Menu in original code? No, settings was separate. */} - {/* Original code had UserMenu handling settings. And a separate sync indicator. */} - {/* The prompt asked for: Search | Settings | User Menu */} - - ))} -
-
- - {/* Show Time Grid */} -
- Time grid -
- -
-
- - {showTimeGrid && ( -
- Slot duration -
- {[15, 30, 60].map(n => ( - - ))} -
-
- )} - - {/* View Style */} -
- View style -
- - -
-
- - {/* Show Someday */} -
- Someday -
- -
-
- - {/* Show All Day */} -
- All-day events -
- -
-
- - {/* Lines */} -
- Protect events -
- -
-
- -
- - {/* Full Settings Link */} - -
- - {/* Close chevron */} - -
- {showPreferences &&
setShowPreferences(false)} />} { selectedTaskForNotes && ( @@ -3090,7 +3029,7 @@ function TaskItem({ task, isEditing, onToggle, onEdit, onUpdate, onDelete, onNot > {/* Edit */} {/* Recurrence */} @@ -3099,7 +3038,7 @@ function TaskItem({ task, isEditing, onToggle, onEdit, onUpdate, onDelete, onNot onClick={(e) => { e.stopPropagation(); onRecurrence(); }} title={task.isRecurring ? "Edit recurrence" : "Make recurring"} > - + @@ -3111,7 +3050,7 @@ function TaskItem({ task, isEditing, onToggle, onEdit, onUpdate, onDelete, onNot onClick={(e) => { e.stopPropagation(); setIsNotesOpen(!isNotesOpen); }} title="Notes" > - + @@ -3125,7 +3064,7 @@ function TaskItem({ task, isEditing, onToggle, onEdit, onUpdate, onDelete, onNot onClick={(e) => { e.stopPropagation(); onRollToggle(); }} title={task.isRolling ? "Disable rolling" : "Enable rolling"} > - + @@ -3134,7 +3073,7 @@ function TaskItem({ task, isEditing, onToggle, onEdit, onUpdate, onDelete, onNot {/* Delete */}