Commit Graph

473 Commits

Author SHA1 Message Date
1051dfd96c feat: list-style PDF layout with per-hour weather symbols
Layout — switched from absolute-positioned calendar grid to agenda/list:
- Each day column divided into equal-height hour rows (flex: 1)
- Tasks listed as text rows within their hour slot (time + title inline)
- No absolute positioning, no background stripes, no floating blocks
- External calendar events: light tinted row with left border + bold title
- User tasks with project: left border in project color
- User tasks without project: plain text, no border
- Time column updated to flex rows, stays aligned with day column rows

Weather — switched to hourly API data (temperature_2m + weather_code):
- Small colored circle + temperature shown in top-right of each hour row
- Color encodes condition: amber=clear, gray=cloudy, blue=rain,
  pale-blue=snow, purple=thunderstorm
- Removed WMO text dictionaries (no more written-out condition text)

v1.96.3
2026-04-13 12:56:55 +02:00
c414c2718d fix: move weather from day header to time-grid cell (top-right chip)
Matches webapp behaviour where weather appears as a chip in the top-right
corner of each day's time grid area, not inside the day header.

v1.96.2
2026-04-13 12:46:27 +02:00
38462c50f7 fix: PDF export style and header fixes
- Fix weather toggle disabled when lat/lon set but weatherEnabled=false:
  now enabled whenever a weather location is configured
- Default task duration: no-endTime tasks default to 30min (not 60min)
- Tasks without a project: remove left border entirely — only project-
  assigned tasks show a colored left border; this matches the user's
  explicit request that only calendar events have background/indicators
- Header order: show date first (top), then weekday name below — matches
  webapp "above" date layout setting
- Lighten grid lines (#ececec) and stripes (#fafafa/#f0f7ff) to reduce
  the heavy calendar-grid appearance; remove half-hour separator lines
- Lighten outer grid border and time-column border/bg to match

v1.96.1
2026-04-13 12:41:15 +02:00
62ebc56c71 feat: fix PDF export style, add calendar events, add print button
- Query CachedCalendarEvent table for all-day and timed external calendar
  events (Google/MS/Apple), so GANZ-TAG strip now shows actual events
- Regular user tasks: remove white background — transparent with left
  border only, matching the webapp's simple view style
- All-day strip: calendar events show light tinted chip, user tasks show
  left-border text only (no fill background)
- Add 'Im Browser drucken / Print in Browser' button to the print modal
  (opens PDF inline in new tab so browser print dialog can be triggered)
- Fix Content-Disposition to 'inline' when ?inline=1 param is passed
- Update modal preview to show left-border task style (not solid blocks)

v1.96.0
2026-04-13 10:14:05 +02:00
27ccd275f6 fix: S/M/L font size buttons now take effect immediately
saveSetting() for DEVICE_SETTINGS_KEYS (viewDays, cellDuration, startHour,
endHour, fontSize, showSubHourSlots) was saving to the cookie but returning
early before calling setProfile — so profile.fontSize never changed and the
CSS class font-size-s/m/l was never applied. Adding setProfile() to the
device-settings path fixes all of these keys at once while still keeping
the setting out of the DB.

v1.95.6
2026-04-13 09:56:19 +02:00
8fb9e04346 fix: plain style for user tasks, colored boxes only for calendar events
Per webapp behavior: regular user tasks render as white background with a
thin colored left border (clean/minimal); external calendar events
(externalProvider != null) get a light tinted background box. Completed
tasks use a subtle gray style. The all-day strip keeps solid bars for all
entries (matching the webapp's ALL DAY section).

v1.95.5
2026-04-13 09:45:33 +02:00
da31128121 fix: match webapp style — solid task blocks, fix all-day events, tab-sorted someday
- Fix all-day events: remove externalProvider distinction — ALL tasks with
  scheduledDate but no startTime belong in the GANZ-TAG strip regardless of
  source; was incorrectly routing them to a separate noTime strip that didn't
  show external-provider=null events
- Remove noTime calendar strip: it was a wrong concept; tasks outside the
  time window are simply not shown; someday page handles unscheduled tasks
- Solid task blocks: revert from light+border back to solid fill (matching
  the webapp); use contrastColor() helper to pick white or dark text
  automatically based on background luminance
- All-day strip also uses solid blocks (same style as webapp's ALL DAY bars)
- Someday page: group lists by their tab with a tab header row; query now
  sorts by [tab, order]; lists without a tab get a General/Allgemein header
- Show up to 5 all-day tasks per column (was 4)

v1.95.4
2026-04-13 09:36:38 +02:00
3fd738b185 fix: restore full day names, fix Oswald font, add someday page to PDF
- Always use full weekday names (MONTAG, DIENSTAG…) at all column counts;
  adaptive font size 8.5pt–16pt based on number of columns
- Fix Oswald detection: Font.getRegisteredFontFamilies() doesn't exist in
  react-pdf — now use module-level _oswaldRegistered flag set on successful
  Font.register() call, so Oswald actually gets applied
- Fix headline fallback: Helvetica-Bold (not plain Helvetica) when no Oswald
- Increase strip heights: ALL_DAY_H 38→40, NO_TIME_H 28→52, DAY_HDR_H 40→44
- Show 4 tasks in both all-day and anyday strips (was 2/3)
- Add someday page: last page (portrait) with all SomedayList tasks grouped
  by list, shown when showNoTime is enabled

v1.95.3
2026-04-13 09:23:21 +02:00
9703d9ffa3 chore: bump version to 1.95.2
v1.95.2
2026-04-13 09:08:26 +02:00
786ccf6921 fix: improve PDF export layout and task block styling
- Separate all-day (external calendar events) from anyday (user tasks
  without time) using externalProvider field; each gets its own strip
- Increase ALL_DAY_H from 22→38px and add NO_TIME_H=28px so both rows
  are actually visible
- Task blocks switch from solid fill to light-tinted background + colored
  left border (Google Calendar style) — much easier to read in print
- Use user's taskColor setting as fallback instead of hardcoded indigo
- Show up to 3 items in all-day strip, 2 in anyday strip with overflow count
- GRID_H now accounts for both optional strips in height calculation

v1.95.2
2026-04-13 09:08:16 +02:00
7ab6dd5aa8 chore: bump version to 1.95.1
v1.95.1
2026-04-09 12:20:59 +02:00
72c51c2bea fix: use per-day-of-week colors in PDF export (weekday/sat/sun)
The PDF was showing all day headers in the same weekdayColor. The webapp
uses three separate color settings: weekdayColor (Mon–Fri), weekendColorSat,
and weekendColorSun. Fetch both weekend colors from DB and apply via
dayColor() helper based on d.getDay().

v1.95.1
2026-04-09 10:31:43 +02:00
f75bd6ebe5 feat: add week view PDF/print export with live preview
Adds a print/export modal (WeekPrintModal) accessible via a Printer icon
in the header toolbar. Users can configure date range, time window (startHour–endHour),
number of days, and toggle all-day, no-time, and weather sections. A live
CSS-grid preview updates as settings change. The PDF is generated server-side
via @react-pdf/renderer on the /api/user/export-week-view route:
- Landscape A4 with absolute-positioned time-spanning task blocks
- Day headers use the user's weekdayColor/dateColor/headlineFontWeight from DB
- Oswald font loaded dynamically from Google Fonts (falls back to Helvetica-Bold)
- Timezone-aware task grouping (±1 day query buffer + local date key)
- Optional weather line (Open-Meteo) and all-day strip
- Footer with date range, username, and page numbers

v1.95.0
2026-04-09 10:26:06 +02:00
075ccdba04 feat: persist view style and start-on preference per device
viewStyle, showTimeGrid, and startDayOffset now also write to a device
cookie so each device remembers its own view independently. Cookie
wins over DB on load, giving phone/desktop their own default view
without losing the cross-device DB fallback.

- DEVICE_ALSO_COOKIE_KEYS: viewStyle, showTimeGrid, startDayOffset
- saveSetting writes cookie for these in addition to DB
- viewStyle and showTimeGrid lazy-init from cookie on first render
- Both fetchProfile and fetchUserInfo apply cookie overrides last

v1.94.1
2026-04-07 23:29:35 +02:00
0b40974b88 feat: persist sidebar toggle settings per-device via cookies
The sidebar eye-toggles (Someday, All-day, Checkboxes, Project Icons,
Weather) and the sub-hour slots toggle now save to a device-local
cookie instead of the DB, so phone and desktop can have independent
display preferences.

- DEVICE_SETTINGS_KEYS extended with showSubHourSlots
- New DEVICE_VIEW_SETTINGS_KEYS for per-view sidebar toggles
  (showSomeday, showAllDayEvents, showTaskCheckboxes, showProjectIcons, weatherEnabled)
- saveViewSetting writes cookie-only for device keys; DB untouched
- getEffective checks device cookie before DB per-view overrides
- Cookie restores applied after DB load in both fetchProfile and
  fetchUserInfo so device preference always wins

v1.94.0
2026-04-07 10:10:37 +02:00
36744d0e09 fix: save font size per-device in cookie instead of DB
Font size (S/M/L) is now stored in the browser cookie
'setting_fontSize' alongside the other per-device settings
(viewDays, cellDuration, startHour, endHour).

This means mobile and desktop can each keep their own preferred font
size — changing it on your phone no longer overwrites the setting on
your desktop monitor and vice versa.

The cookie is read immediately at component init (before the DB load),
so there is no flash of the wrong size on page load. The DB value is
still written so that the setting has a reasonable default on new
devices before a local preference is set.

v1.93.1
2026-04-07 09:58:46 +02:00
9485e78dab feat: PDF work report export + Goal of the Week + weekGoal field
Added @react-pdf/renderer for server-side PDF generation.

PDF report (/api/user/export-pdf):
- Indigo cover band: title, user name, period, export date
- Summary cards: total tasks / calendar weeks / projects
- Per-week sections with indigo header bar showing week label + count
- Goal of the week banner (blue left-border callout) when set
- Task table: priority-color dot, title, then selected columns
- Alternating row shading, column headers in grey
- Page numbers in footer
- A4, respects same field selection as CSV

CSV report updated:
- Added 'Goal of the week' as a section marker row (italic prefix)
- weekGoal field is default-on alongside week grouping

Both exports:
- New 'weekGoal' field in EXPORT_FIELDS (default on): shows the weekly
  goal text only when the user has customised it (skips default placeholder)
- Language-aware (de/en) labels and date formats

Settings UI:
- Two download buttons: CSV (plain) + PDF (indigo, prominent)
- weekGoal checkbox in field picker grid

v1.93.0
2026-04-07 09:37:57 +02:00
51e2b13ec6 feat: configurable field picker for work report CSV export
Users can now choose exactly which columns appear in the CSV:
- Title (always included)
- Calendar week grouping header
- Completed date, Scheduled date, Created date
- Project, List
- Priority (Eisenhower label or ABCDE grade)
- Link / URL
- Notes, Description
- Delegated to, Delegation note
- Start time, Kanban stage

UI additions in Settings > Data Export:
- 2-column checkbox grid with Select All / Default reset buttons
- Quick date presets: This week / This month / Last month / This year
- Download button shows the active column count

Default-on fields: week, completed date, scheduled date,
project, list, priority. All others opt-in.

API: fields passed as comma-separated ?fields= param; falls back to
defaults when omitted. Column headers are language-aware (de/en).

v1.92.0
2026-04-07 09:27:02 +02:00
f9b27fe56c chore: update Claude Code permission settings
v1.91.1
2026-04-07 09:14:22 +02:00
6836cf58bc feat: filters in all priority mode right columns + work report CSV
Priority View: filter panel (project / list / timespan) is now always
visible in the right column of every priority mode — Eisenhower,
ABCDE, Ivy Lee, and 80/20. Removed the collapse toggle. An 'active'
indicator in the header shows when any filter is set. On mobile the
filter appears above the main content.

Work Report CSV (Settings > Data Export):
- Columns: Week / Completed / Scheduled / Created / Task / Project /
  List / Priority / Delegated to / Notes
- Rows grouped by calendar week (ISO week, most recent first), with a
  section header row showing "KW 14 — 2026 (30 Mär – 05 Apr)"
- Priority shows Eisenhower label (Sofort erledigen / Planen /
  Delegieren / Eliminieren) or ABCDE grade
- Includes project name, Someday list name, delegation info and notes
- UTF-8 BOM prepended so Excel opens German umlauts correctly
- Language-aware column headers (de/en) via ?lang= param
- Filename: arbeitsbericht_YYYY-MM-DD_bis_YYYY-MM-DD_date.csv

v1.91.0
2026-04-07 00:03:09 +02:00
3ee5bf33b5 feat: two-column priority layout + German ABCDE translations
All four priority modes (Eisenhower, ABCDE, Ivy Lee, Pareto) now use a
two-column layout on desktop: main content on the left, secondary panel
(unassigned tasks / pool / remaining) on the right. On mobile (<768px)
the layout stacks vertically automatically.

Eisenhower: filters are now always visible in the right panel instead
of behind a toggle button, making project/list/timespan selection more
accessible. The filter button is hidden for Eisenhower mode.

ABCDE: added full German translations for grade labels and descriptions
(A–E now show "Kritisch", "Sollte erledigt werden", etc. in German).
Ungraded tasks appear in the right column instead of below the buckets.

Pareto: remaining tasks (80%) are always visible in the right column,
no longer behind a show/hide toggle.

v1.90.0
2026-04-06 20:48:03 +02:00
0a84bf3114 feat: preserve tabs on sync disconnect/reconnect
Disconnecting a synced list (Google/Outlook/Synology) now uses a
soft-disconnect: tasks are soft-deleted and the external link is
cleared, but the SomedayList record is kept with its tab assignment
intact. When the user reconnects, the import route finds the list by
title, re-links the external provider, and restores tasks (clearing
deletedAt). Tabs survive the full disconnect/reconnect cycle without
the user needing to drag lists back to tabs.

Also clears deletedAt on task re-import so previously disconnected
tasks become visible again on reconnect.

v1.89.0
2026-04-06 18:07:03 +02:00
d8d1003e78 feat: show priority & delegation icons in all views
A small icon appears before each task title whenever priority has been set
in the Priority View. Works in simple, calendar, list, someday, and kanban.

Icon + color mapping
   Zap         red  #ef4444  Sofort erledigen  (urgent + important / ABCDE A)
  🕐 CalendarClock blue #3b82f6  Planen           (important, not urgent / B)
  ↗ CornerUpRight orange #f97316 Delegieren       (urgent, not important / D)
  📦 Archive     gray #9ca3af  Eliminieren       (neither / E)
  🕐 Clock       yellow #eab308 ABCDE C only

Delegation badge
  🤖 Bot   purple  task.delegatedTo === "AI"
  👤 User  purple  task.delegatedTo = person name

Hover tooltip shows the full label (e.g. "Sofort erledigen", "Planen").
Icons are 11–12 px so they sit inline without disrupting the task row.

v1.88.2
2026-04-06 16:03:16 +02:00
a3b0849525 fix: hide completed tasks from priority view immediately
- Priority view is "what to do next" — completed tasks have no place there.
  Always filter them out; removed the "show completed" toggle button.
- Optimistic local hide: when you check a task off inside priority view it
  disappears immediately (no waiting for API round-trip + parent re-render).
  A `locallyDone` Set tracks tasks marked complete in the current session.

v1.88.1
2026-04-06 15:04:18 +02:00
149f0cf021 feat: priority view resize handle + dense task cards with actions
Resize handle:
- Drag the divider between priority panel and calendar to resize it
- Height persists in cookie (priorityViewHeight)

Dense task cards:
- Single-row compact layout: [✓] date · title · action icons
- Date shown before the title
- Action icon bar: rename (✏), note (📝), link (🔗), project (📁), delegate (👤), remove (×)
- Inline title editing: double-click or click ✏ icon
- Inline note textarea: toggles on 📝 click, saves on blur
- Inline URL input with open-link button: toggles on 🔗 click
- Inline project selector: toggles on 📁 click
- Icons colored when field has a value (note, url, project, delegate)
- Export/import now round-trips url, kanbanStage, recurrenceDays fields

v1.88.0
2026-04-06 12:25:05 +02:00
8ffc127671 fix: improve import — surface real errors, restore all task fields
- Export now includes kanbanStage, url, urgency, importance, priority,
  delegatedTo, delegationNote, recurrenceDays so backups are complete
- Import now handles those same fields (round-trip fidelity)
- Error handler returns the actual error message instead of the generic
  "Import failed. Please check the file format." — makes failures diagnosable
- Guard against empty task title with fallback '(untitled)'

v1.87.2
2026-04-06 11:42:21 +02:00
a117b60d84 fix: add drag-and-drop from week/someday lists into Priority View
Tasks dragged from any view (simple, list, someday sidebar) now land
in the Priority View:

- Eisenhower: drag onto any quadrant → highlights with dashed border
  + color tint; drops immediately set urgency/importance on the task
- ABCDE: drag onto any grade section (A–E) → same visual feedback;
  drops set the priority grade
- Ivy Lee: drag onto the Top-6 zone → adds task to selection (up to 6)
- TaskCard inside PriorityView is now draggable too, so tasks can be
  re-classified by dragging between quadrants/grades

All drop zones show "Drop here" hint text when a drag is in progress
and collapse-state is respected (collapsed zones still accept drops).
allTasks (unfiltered) passed to sub-components so IDs from external
drags resolve correctly even when the task is filtered out.

v1.87.1
2026-04-06 11:01:03 +02:00
46a05a87c3 feat: add Priority View — Eisenhower, ABCDE, Ivy Lee, Pareto, delegation
New "Priority View" (Target icon in toolbar) fusing four prioritization
frameworks into a single, filterable view:

- Eisenhower Matrix: 4 quadrants (Do/Schedule/Delegate/Delete) based on
  urgency × importance; unclassified tasks shown below for quick assignment
- ABCDE Method: five collapsible groups (A=Critical → E=Eliminate) with
  inline grade assignment buttons
- Ivy Lee Method: pick exactly 6 tasks for tomorrow, ordered by priority
- Pareto 80/20: highlights the important 20% of tasks with a progress bar
  and one-click "mark as important" for the rest

New DB fields: urgency (Boolean), importance (Boolean), priority (A–E),
delegatedTo, delegationNote — all persisted via Prisma + API.

Filters: by project, someday list (incl. scheduled / unscheduled), and
timespan (today / this week / next week / all).

Delegation modal: assign to a named person or to AI with optional
instruction notes; displayed as inline badge on task cards.

v1.87.0
2026-04-06 02:07:05 +02:00
8ffb6a0690 feat: accessibility follow-up — heading hierarchy, keyboard resize, contrast fix
- Fix heading hierarchy: modal titles h3→h2 (RecurrenceModal, two WeeklyView dialogs),
  SettingsSidebar h4→h3 for Localisation, Data Export, Backup & Restore sections
- Add keyboard resize handle: role=slider, tabIndex, aria-valuemin/max/now/text,
  ArrowUp/Down keys to adjust task duration in 15-min increments
- Add aria-label to CalendarEventModal notes textarea fallback
- Color contrast: raise --weekly-text-light from #a6a6a7 (~2.4:1) to #767676 (~4.5:1)
  on white background to meet WCAG AA

v1.86.0
2026-04-06 00:25:08 +02:00
5c01869444 feat: comprehensive accessibility pass — ARIA, focus traps, keyboard move, live regions
- Modals (SearchModal, ImportListModal, CalendarEventModal): role=dialog,
  aria-modal, aria-label, focus trap via keydown Tab handler, aria-hidden on backdrop
- OnboardingWizard: role=dialog on card, aria-hidden on overlay, aria-current=step
  on progress dots wrapped in <nav><ol>, aria-label on nav buttons
- GridTaskBlock: aria-label on all ~12 action buttons (complete, edit, add subtask,
  notes, rolling, recurrence, project, link, delete, move), aria-expanded/aria-pressed
  where applicable, aria-hidden on all decorative SVGs, aria-label on inline edit
  textarea and subtask inputs; note indicator div → button
- Keyboard task move: new "Move Task" dialog in GridTaskBlock with date+time
  inputs, routed via onMoveTask prop → moveTaskToSlot in WeeklyView
- WeeklyView: visually-hidden aria-live="polite" region with announce() helper;
  announces task add, complete/incomplete, delete, sync complete/failed
- Forms: aria-invalid + aria-describedby + role=alert on error paragraphs in
  TaskForm; auth error div gets id + role=alert; email input gets aria-describedby;
  show/hide password button gets aria-label + aria-pressed
- Spinners: role=status + aria-label on standalone spinners (TaskItem delete,
  WeeklyView sync); aria-hidden on inline button spinners (AuthForm, TaskForm,
  CalendarSettings, SettingsSidebar, EmailAuthForm)
- layout.tsx: Open Graph and Twitter Card meta tags added

v1.85.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 18:18:08 +02:00
04b72a326a feat: integrate zitat-service.de API for DE/EN/ES quotes
- Add zitat-service.de as built-in multilingual fallback in goal API:
  tries the user's preferred language (de/en/es) automatically before
  falling back to ZenQuotes (EN) and then local curated quotes
- Parser now also handles {quote, authorName} response format from
  zitat-service.de alongside all previously supported formats
- Preset source pills in settings: add Zitat-Service (DE), (EN), (ES)
  (supports de, en, es — no fr/it available from that API)
- Remove Forismatic from presets (unreliable, often returns empty)
- Update hint text to reflect DE/EN/ES API availability vs FR/IT local

v1.84.1
2026-04-05 18:08:05 +02:00
2ec1278b19 feat: quote sources — preset buttons, universal parser, expanded local collection
Goal API (route.ts):
- Now actually uses profile.quoteSourceUrls — tries each user-configured URL
  in order before falling back to ZenQuotes
- Universal JSON parser handles ZenQuotes [{q,a}], Quotable {content,author},
  Forismatic {quoteText,quoteAuthor}, generic {text/quote/body, author/by},
  nested {data:{...}}, and advice-slip {slip:{advice}} formats
- ZenQuotes remains the built-in EN fallback when no user URLs are configured

SettingsSidebar:
- Adds clickable preset-source pill buttons below the "Add source" button:
  ZenQuotes, Stoic Quotes, Quotable, Forismatic (EN), Advice Slip
- Pills show ✓ and are disabled when the URL is already in the list
- Note explains DE/FR/IT/ES are served from the curated local collection

quotes.ts:
- Updated PRESET_QUOTE_SOURCES to match the 5 working English APIs
- +14 French quotes (Marcus Aurelius, Lombardi, Ali, MLK, Picasso, etc.)
- +13 Spanish quotes (Collier, Eliot, Darwin, Voltaire, Ashe, etc.)
- +13 Italian quotes (Collier, Eliot, Ali, MLK, Aurelius, da Vinci, etc.)

v1.84.0
2026-04-05 12:50:46 +02:00
2016b1cb18 fix: weather sidebar toggle — remove sub-checkboxes, fix toggle reliability
Remove the per-field weather checkboxes from the quick-settings sidebar;
those belong in the full settings modal only.

Also make the toggle more reliable: it now updates both the per-view
viewSettings override (saveViewSetting) AND the local profile state
(setProfile) so that effectiveWeatherEnabled is guaranteed to flip on
the next render regardless of which branch getEffective() takes.

v1.83.4
2026-04-05 12:42:41 +02:00
b6c47c81b3 fix: show weather sidebar section when weatherEnabled even without location
The previous condition only checked weatherLat || weatherLon, so users
who enabled weather in settings but hadn't picked a city yet would never
see the sidebar toggle. Now shows if weatherEnabled OR lat/lon is set.

v1.83.3
2026-04-05 12:35:57 +02:00
1a44f769a7 feat: add weather display checkboxes to left sidebar quick-settings
When weather is enabled and a location is configured, the sidebar now
shows per-item checkboxes (Symbol, Temperatur, Gefühlt, Wind, Böen,
Regenw., Niederschlag, Luftfeuchte, UV) below the weather toggle.
Checkboxes are hidden when weather is toggled off. All changes go
through saveViewSetting("weatherDisplay", ..., true) — same path as
the settings modal — so they stay view-specific and persist correctly.

v1.83.2
2026-04-05 12:28:48 +02:00
55c21ff6a6 fix: sidebar toggles now correctly update per-view settings
Someday, All-day, Checkboxes, Project-Icons, and Weather toggles in the
left quick-settings panel were calling saveSetting() (global profile PATCH)
instead of saveViewSetting(..., true) (per-view override).

getEffective() checks the per-view override first, so whenever a per-view
setting existed (set via the settings modal) the global update was silently
ignored and the toggle appeared broken.

All five toggles now call saveViewSetting(key, !value, true) which updates
viewSettings[currentView][key] directly — matching exactly what the settings
modal's view-tab checkboxes do.

v1.83.1
2026-04-05 12:14:52 +02:00
a6a1a68c73 feat: upgrade notes/url to full sidebar+kanban coverage, fix onNotes save bug, harden URL sanitization
- Fix onNotes prop in all three TaskItem render sites: was calling
  setSelectedTaskForNotes (ignoring HTML), now correctly calls
  updateTaskNotes so inline RichTextEditor saves on every change
- NotesSidebar: replace plain markdown textarea+toolbar with RichTextEditor;
  add URL field with open/clear actions
- Kanban detail modal: add URL field; replace plain textarea with RichTextEditor
- Tasks API: add sanitizeUrl() helper — strips javascript:/data: schemes,
  normalises missing protocol to https:// before storing
- Remove dead code in TaskItem: notesRef, handleNotesBlur, insertMarkdown
  (all replaced by RichTextEditor)

v1.83.0
2026-04-05 11:59:44 +02:00
388618e62c fix: URL and rich-text notes now work in someday area tasks
TaskItem (used for all someday list tasks) was missing URL support entirely.
Added:
- onUrl prop wired to updateTaskUrl at both someday TaskItem render sites
  (slot tasks and unindexed/remaining tasks)
- URL indicator (clickable link badge) shown inline on the task row
- Link action button in the task-actions bar that opens an inline URL editor
- URL popup with input, clear button, and open-in-new-tab shortcut

Also upgraded TaskItem's notes editor from plain markdown textarea to
RichTextEditor (same as GridTaskBlock), so inline hyperlinks in notes work
in the someday area too.

v1.82.1
2026-04-05 11:43:57 +02:00
7bc43d3c98 feat: add hyperlink support to tasks
Option A — URL field per task:
- New url String? column in Task schema (migration: 20260403_add_task_url)
- Link icon button in GridTaskBlock action bar; click to open inline URL popup
  with input, clear (×) button, and open-in-new-tab shortcut
- Blue link indicator shown inline on the task card when a URL is set
- updateTaskUrl() in WeeklyView persists to DB via PATCH /api/tasks

Option B — Rich text notes with inline hyperlinks:
- GridTaskBlock notes popup upgraded from plain markdown textarea to
  RichTextEditor (Tiptap), which already has bold/italic/underline/
  bullet/blockquote/link toolbar and full link support
- Notes now save on every change via onChange (no blur required)

v1.82.0
2026-04-03 15:04:44 +02:00
f94f83af73 fix: restore project icons and persist someday tab assignments across reconnects
Project icons (faHeart, faBriefcase etc.) were rendering as literal text in
GridTaskBlock because the lookup skipped the legacy "faX" → "x" normalization
that ProjectIcon does. Added the same normalization before allIcons.find().

Someday list tabs now survive provider disconnects and reconnects:
- customTabs (empty tabs) saved to viewSettings in DB instead of localStorage only
- assignListToTab saves a title→tab mapping in viewSettings.somedayTabPrefs
- Profile load merges DB customTabs with localStorage for migration
- Import route reads somedayTabPrefs and auto-applies tab when creating/
  relinking a SomedayList by title match

v1.81.20
2026-04-03 11:11:11 +02:00
0371532e7d fix: resolve stale session ID in someday-lists and calendar/events routes
All handlers in someday-lists/route.ts and calendar/events/route.ts were
using (session.user as any).id which can be stale after DB restore/migration.
Fixed to look up by session.user.email instead — matching the pattern already
established in tasks/route.ts and calendar/sync/route.ts.

This was causing other users to see empty someday lists while their tasks
(fetched via the already-fixed tasks route) still had somedayListId references,
triggering false RESCUE recoveries on every load.

Also fixed outlook/callback/route.ts fallback which could still use stale ID.

v1.81.19
2026-04-03 11:04:32 +02:00
4cab83e545 fix: slot buttons now update the time grid via saveViewSetting
The SettingsSidebar stores cellDuration in viewSettings (per-view) via
saveViewSetting, so getEffective() returns that value and ignores local
state. The QuickSettings/header/mobile buttons were only calling
setCellDuration (local state) + saveSetting (cookie), which getEffective
overrides. Now all three button groups also call saveViewSetting so the
grid immediately reflects the selected slot size.

v1.81.18
2026-04-02 22:58:15 +02:00
ca67817b7b fix: revert slot options to 15/20/30/60, fix sidebar indicator
- Removed 45m, restored 60m in CellDuration type and all button groups
- Slot indicator now correctly highlights the active slot in the sidebar
  (was broken because 60m users had no matching button when 45 was listed)

v1.81.17
2026-04-02 22:51:01 +02:00
6f45140d26 feat: add 45m slot option, replace 60m in sub-hour controls
- CellDuration now includes 45 (15 | 20 | 30 | 45 | 60)
- getTimeSlots rewritten to use minutes-based generation so 45-min slots
  work correctly (08:00, 08:45, 09:30, 10:15...) — also cleaner for all
  other durations
- getSlotHeight(45) = 45px (1px per minute, proportional)
- All three slot button groups (sidebar, desktop header, mobile) now show
  [15, 20, 30, 45] instead of [15, 20, 30, 60]

v1.81.16
2026-04-02 22:43:01 +02:00
09caf5ffa0 fix: email-based user lookup, slot controls, sub-hour toggle
API routes (goal, weather, calendar/sync, calendar/events):
- All user lookups now use session email instead of session ID so stale
  JWTs after DB restore/migration no longer break requests (P2003 FK error)

WeeklyView QuickSettings sidebar:
- effectiveCellDuration now uses local cellDuration state as fallback
  instead of stale profile.cellDuration — slot buttons now actually update
  the time grid
- Added 20m slot option to all three button groups (sidebar, header, mobile)
- Added :15/:30/:45 sub-hour slots toggle to QuickSettings sidebar
- Slot controls now highlight using effectiveCellDuration (per-view aware)
- Someday and All-day toggles now use effective value, not global profile

v1.81.15
2026-04-02 22:34:26 +02:00
2d785ea2bf fix: suppress weather 400 noise, calendar sync email fallback
- Weather API returns empty hourly data (200) when lat/lon not configured,
  matching the 502 fix — no more browser console errors for weather
- Calendar sync route falls back to email lookup when session user ID
  doesn't match a DB record (handles stale JWT after DB restore/migration)

v1.81.14
2026-04-02 13:24:18 +02:00
86c462c920 fix: all-day label top-aligned, weather 502 silent, toggle consistency
- All-day label column uses flex-start so label is visible in small area
- Weather API returns empty data (200) instead of 502 when forecast range
  is out of bounds, suppressing console noise on future/past navigation
- QuickSettings toggles for project icons and checkboxes now use effective
  (per-view-aware) value, consistent with other toggles

v1.81.13
2026-04-02 13:10:25 +02:00
091004e87e fix: all-day badge shows count for visible days only
Previously showed total allDayEvents.length (all events in the loaded
week). Now counts unique events that appear on at least one currently
visible day column, so in 1-day view it shows that day's count, in
3-day view the count across those 3 days, etc.

v1.81.12
2026-04-02 10:39:51 +02:00
024ceaf255 chore: remove redundant Zeitplan/Schedule toggle from QuickSettings
The showTimeGrid toggle is now implicit in the view style selector
(list → grid off, simple/calendar → grid on), making the explicit
Schedule eye toggle obsolete.

v1.81.11
2026-04-02 10:36:58 +02:00
1201e3f169 fix: remove stray .profile. dereference causing TypeError on SSE sync
Line 2243 read data.user.profile.viewStyle — data.user.profile is
undefined (the shape is data.user.viewStyle), causing:
  TypeError: Cannot read properties of undefined (reading 'viewStyle')
This crash fired every time the SSE sync callback received new data.

v1.81.10
2026-04-02 10:35:42 +02:00