- 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
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
- 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
- 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
- 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
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
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
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
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
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
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
- 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
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
- 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
- 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
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
- 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
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
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
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
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
- 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
- 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
When the active header display is 'current_day' (selected day) AND
viewDays === 1, the in-column weekday header duplicates the information
already shown in the top header bar. Added 'header-current-day-single'
class to the container under that condition, then CSS display:none on
.weekly-day-header. With multiple columns visible the header is shown
normally so each day column is still identifiable.
v1.81.9
Both fields existed in the DB but were missing from schema.prisma,
so the Prisma client didn't know about them. The client has been
regenerated (prisma db push). Added both fields to:
- prisma/schema.prisma (with correct defaults)
- GET select, PATCH destructure, updateData, PATCH select in route.ts
This resolves the 500 errors on PATCH /api/user/profile that occurred
when saveSetting() tried to persist these fields.
v1.81.8
1. cellDuration indicator: compare against local `cellDuration` state
(not effectiveCellDuration which reads stale profile.cellDuration
since saveSetting bails early for DEVICE_SETTINGS_KEYS)
2. viewDays on mobile now uses orientation instead of fixed width:
portrait (h > w) → 1 day, landscape → 3 days, for ≤768px.
Applied consistently in useEffect, early profile load, and cookie
override blocks so the responsive value is never overridden by
the saved DB preference on mobile.
3. list-view day header on mobile: changed from sticky to
position:relative so it flows with content and never covers tasks
4. time/day column scroll sync: weekly-days-grid was overflow-y:auto
on mobile, creating an independent scroll container that drifted
from the time column. Changed to overflow-y:visible so only
time-grid-wrapper scrolls. Added touch-action:pan-y to day columns
so iOS handles pan immediately without waiting for JS.
v1.81.7
- Added solid background to .list-view .weekly-day-header so tasks
don't bleed through the transparent sticky header while scrolling
- On mobile, offset sticky top by 48px + safe-area-inset to sit
below the mobile header bar instead of overlapping it
v1.81.6
- Rename options to be clearer:
- "Vollständiges Datum" → "Heutiges Datum" (always today's date)
- "Aktueller Tag" → "Selektierter Tag" with custom format input
- "Benutzerdefiniert" → "Woche Benutzerdefiniert" (week-based tokens)
- Add custom format input for "Selektierter Tag" (headerCurrentDayFormat)
with tokens: DDDD, DDD, DD, MMMM, MMM, MM, YYYY, WW
- Add separate header display settings for Mobile Portrait and
Mobile Landscape (mobilePortraitHeaderDisplay, mobileLandscapeHeaderDisplay)
- Move refresh/sync icon to fixed-width slot right of date — date no
longer shifts when the icon appears or the spinner replaces it
- Add 3 new Prisma fields (db push required on deploy)
- All 5 languages updated (EN, DE, FR, ES, IT)
v1.81.0
- tasks/route.ts: add per-unit instance cap for virtual task projection
(daily: 60, weekly: 26, monthly: 12, yearly: 3) to prevent unbounded
generation from high-frequency recurring tasks
- WeeklyView: extract calendarEditabilityMap as a separate useMemo keyed
on connections; replace O(n²) nested find() loop with O(1) Map.get()
lookup in the calendarEvents deduplication useMemo
v1.79.0
- tasks/sync GET: batch Google/Outlook/Synology credential fetches with
Promise.all instead of sequential awaits; move per-list Synology
findMany outside the loop to eliminate N+1
- calendar/sync: replace fire-and-forget background refresh with 800ms
Promise.race so fast refreshes return fresh data without blocking
- Extract icon data to iconRegistry.ts; lazy-load IconPicker via
next/dynamic so picker UI code is deferred until needed
v1.78.0
The .time-grid-wrapper .weekly-day-header was set to position:sticky, causing
the day name (MITTWOCH 1. APR.) to appear as a ghost header while scrolling.
The correct sticky element on mobile is the existing day-bar overlay (DO 2.4.)
at the top. Reverted .weekly-day-header to position:relative.
v1.77.6
Three root causes fixed:
1. Scroll enforcement interval (every 50ms for 2s) was the main blocker:
The setInterval forced gridRef.scrollTop on every frame, making iOS think
the page was always scrolling programmatically. User touches during those
2 seconds were overridden. The header appeared 'stuck' because the view
was frozen. Replaced with a single setTimeout scroll (300ms on first load,
50ms on subsequent). Added history.scrollRestoration='manual' so Safari
doesn't fight us with scroll position restoration.
2. touch-action: pan-y was only on .time-grid-wrapper — NOT inherited by CSS.
Slot child elements had touch-action: auto (default), so iOS still waited
for JS before committing scroll on day column touches. Added touch-action:
pan-y directly to .time-slots-container (the actual touched element area).
Time column labels have no JS handlers so iOS scrolled them freely — this
explains why time column worked but day columns didn't.
3. align-items: start on .weekly-days-grid was wrong (added in last commit).
Removed — CSS grid default stretch is correct.
v1.77.4
Root cause: React registers onTouchStart props as non-passive listeners at the
app root. iOS Safari sees any non-passive touchstart on an ancestor and blocks
the scroll gesture on those elements, waiting for JS to finish. This is why
the time column (no handlers) scrolled freely but day columns (slots had
onTouchStart) were frozen.
Changes:
- Removed onTouchStart prop from all time-slot divs — no more React touch
handlers in the time grid, so iOS never blocks scroll
- Added data-slot-blocked attribute to occupied/protected slots
- Moved slot long-press logic into the permanent native touchstart listener
on document (passive: true), reading slot/date from data attributes
- Added touch-action: pan-y on .time-grid-wrapper — explicitly tells iOS
that vertical pan = scroll even if child content has touch handlers
- CSS: align-items: start on .weekly-days-grid so sticky headers in each
day column have a proper scroll context
- Reinforced position:sticky on .time-grid-wrapper .weekly-day-header
v1.77.3
.time-slots-container and .time-column-slots had overflow-y: auto which created
independent scroll contexts inside each day column, eating touch events and
preventing the parent time-grid-wrapper from scrolling.
v1.77.1
The time grid previously had two separate overflow-y:auto scroll containers
(the time-column labels + the day columns grid), synced via JS scrollTop
assignment. On iOS Safari, this caused severe desync and bounce effects:
momentum scroll continued after touch-end, and the programmatic scrollTop
correction fought against native momentum, making the grid stutter/bounce.
Changes:
- time-grid-wrapper is now the SINGLE overflow-y:auto scroll container
(ref=gridRef, onScroll handler moved here from weekly-days-grid)
- time-column and weekly-days-grid have overflow:visible — they scroll
with their parent wrapper without fighting each other
- Removed handleTimeColumnScroll, timeColumnRef, timeGridWrapperRef
(all sync logic now redundant)
- jumpToHour and initial scroll position now set only gridRef.scrollTop
- CSS: weekly-days-grid overflow changed to visible
- CSS: re-enabled position:sticky on .weekly-day-header for mobile —
sticky now works correctly since scroll container is an overflow-y parent
- CSS: hid time-column-header on mobile (saves vertical space)
v1.76.2
Users can now create sync rules to automatically sync events between
any two connected calendar providers (Google, Apple, Outlook, Synology).
- New Prisma models: CalendarSyncRule + CalendarSyncMapping
- Sync engine in src/lib/calendar-cross-sync.ts: fingerprint-based
change detection, anti-loop protection, one-way and two-way support
- API routes: GET/POST rules, PATCH/DELETE rule by id, POST run
- CalendarSyncRulesPanel component with rule list, add/edit form,
toggle enable/disable, Sync Now button with result summary
- New "Sync" tab in settings sidebar (between Connections and Account)
- Sync rules run automatically after each forced calendar cache refresh
v1.76.0
- Skip optimistic UI update for new recurring events (causes duplicate
when force-sync fetches expanded instances with different IDs)
- Mobile sticky day bar: listen on gridRef scroll instead of window
(time-grid scrolls inside weekly-days-grid, not window)
- Remove broken position:sticky from mobile day headers (CSS sticky
doesn't work inside CSS grid scroll containers); use fixed overlay only
- Also propagate isRecurring flag in create response for Google/Outlook
v1.75.8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove translateY on first time-slot-label only (via :first-child) instead
of adding padding-top which broke task alignment. Reverts padding approach.
v1.75.6
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The first time-slot label's translateY(-50%) pushed it above the container
top edge. Added padding-top to time-column-slots and time-slots-container,
and disabled the translate on the first label. Reverted 00→0.
v1.75.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Calendar events now use --weekly-task-font, --weekly-task-size,
and --weekly-task-weight instead of separate event font variables,
so events and tasks always look consistent.
v1.74.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
overflow-x: hidden on .simple-view .weekly-day-column was creating a
scrolling context that broke position: sticky on the day header.
Changed to overflow-x: clip which clips content without affecting sticky.
v1.73.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Events created or updated via the API were missing the calendar's
backgroundColor, causing them to render without their provider color.
v1.72.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Drag on empty time slots to create calendar events with pre-filled time range
- Rolling tasks now work per-task without requiring global autoRolling setting
- Add firstDayOfWeek to Outlook weekly recurrence patterns
- Add debug logging for Outlook recurrence creation
v1.72.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Strip HTML tags from descriptions before sending to CalDAV providers (Apple/Synology)
- Show event location underneath time in calendar event blocks (like Google Calendar)
- Fix German umlaut rendering by adding latin-ext font subset
- Fix CalDAV event updates losing TZID on DTSTART/DTEND (Apple Calendar recurring edit fix)
- Add error logging for CalDAV PUT responses
- Reduce wasted space when all-day events section is collapsed (24px max)
- Fix quotes with missing umlauts (ä, ö, ü, ß)
v1.71.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When editing a recurring calendar event (via modal or drag/resize),
the user is now asked whether changes apply to just this instance or
all events in the series.
- Modal: Save button shows "This event" / "All events" options for
recurring events
- Drag/resize: centered overlay prompt with same options + cancel
- API PATCH: editMode=all routes update to the series master ID
(recurringEventId) instead of the instance ID
- Cancel on drag prompt reverts to original position
v1.69.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cross-day drag now works: getEventsForSlot uses drag state's current
start time to assign the dragged event to the correct day column
- Add showCalendarProviderIcon to Prisma schema, profile API GET/PATCH
so the setting persists across sessions (was frontend-only before)
- DB migration applied via prisma db push
v1.68.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix Google recurring events missing isRecurring flag (recurringEventId
was not mapped from Google API response)
- Add note icon (FileText) on events with descriptions, tooltip on hover
- Cross-day drag-and-drop: detect day column under cursor and shift date
- Fix event detail popup opening after drag/resize by setting ref before
async operations
- Add data-date attribute to day columns for drag target detection
- Use CSS class for icon row layout to prevent overlap
v1.67.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add resize handles (top/bottom) on hover to change event duration, and
drag-to-move support with live preview and 5-minute snapping. Includes
3px dead zone to distinguish clicks from drags, optimistic UI updates
with server rollback on failure, and recurring/provider icons on
time-grid events. Also fixes Google delete 410 Gone and Outlook delete
404/encodeURIComponent issues.
v1.66.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The base .time-slot-event and .simple-view .time-slot-event CSS had
left: 0 and right: 0 (with !important) which overrode the inline
overlap layout positioning. Removed so events can be placed side by
side when they overlap.
v1.65.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>