100 Commits
Author SHA1 Message Date
Connor JohnstoneandClaude 5ac945ef23 Fix day number color inheritance for today and selected in print
Build and Push Docker Image / docker (push) Has been cancelled
The day numbers for today and selected dates were not matching the
appearance of normal day numbers in print preview due to color
inheritance issues.

Changes:
- Remove color override from .calendar-day.today parent element
- Use color: inherit on day numbers to get default text color
- Use font-weight: 600 to match standard day number styling

Now all day numbers appear uniform in print preview regardless of
today/selected state.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 16:41:25 -05:00
Connor JohnstoneandClaude 419ac0e80d Fix day number styling for today in print preview
The day number text for today's date was still showing the special
blue color styling in print preview. This adds a specific rule to
reset the .day-number color and font-weight for today's date.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 16:37:03 -05:00
Connor JohnstoneandClaude 2b1d0f38f5 Remove today and selected day highlighting in print preview
Print output should have clean, uniform styling without interactive
visual indicators. This change removes the special highlighting for:

- Today's date (blue background and border)
- Selected date (green background, border, and box-shadow)

Both dates now appear with standard calendar day styling in print,
maintaining a professional printed appearance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 16:35:16 -05:00
Connor JohnstoneandClaude 1701a95183 Fix print preview to display all 6 rows for 6-week months
The print preview was only showing 5 rows for months requiring 6 rows
(like November 2025). The issue was that the .calendar container uses
flexbox layout, but the grid wasn't properly constrained to fit within
the fixed paper height.

Changes:
- Set explicit height: 100% on .print-preview-paper .calendar
- Use flex: 1 on calendar-grid to fill remaining space after header
- Add min-height: 0 to both calendar-grid and calendar-day to allow
  flexbox items to shrink below their content size

This allows the CSS Grid's repeat(6, 1fr) to properly distribute all
6 rows evenly within the available space while maintaining the fixed
paper dimensions for consistent printing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 16:30:26 -05:00
Connor JohnstoneandClaude 13702d8c30 Add theme-aware styling for date and time picker icons
The calendar and clock icons in date/time input fields were showing as black regardless of theme, making them hard to see on dark themes.

Changes:
- Add --calendar-picker-filter CSS variable to control icon appearance
- Set filter to none for light themes (keep default black icons)
- Set filter to invert(1) brightness(0.9) for all dark themes
- Apply styling to ::-webkit-calendar-picker-indicator and ::-moz-calendar-picker-indicator
- Cover all dark themes: dark, midnight, charcoal, nord, dracula

The date/time picker icons now properly invert to white/light colors on dark themes while remaining black on light themes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-26 10:40:49 -04:00
Connor JohnstoneandClaude 933d7a8c1b Fix calendar visibility preservation during event updates
Build and Push Docker Image / docker (push) Successful in 1m5s
Prevent hidden calendars from becoming visible when events are modified via drag-and-drop or other update operations. The refresh mechanism was overwriting frontend visibility state with fresh server data that doesn't include visibility settings.

Changes:
- Preserve existing calendar visibility and color settings during refresh_calendar_data
- Maintain smart fallback for saved colors on new calendars
- Ensure calendar visibility state persists across event modifications

This fixes the issue where users would hide calendars, then see them reappear after dragging events.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 11:20:43 -04:00
Connor JohnstoneandClaude c938f25951 Fix recurring event series modification and UI issues
Backend fixes:
- Fix "this event only" EXDATE handling - ensure proper timezone conversion for exception dates
- Remove debug logging for cleaner production output

Frontend fixes:
- Add EXDATE timezone conversion in convert_utc_to_local function
- Fix event duplication when viewing weeks across month boundaries with deduplication logic
- Update CSS theme colors for context menus, recurrence options, and recurring edit modals

These changes ensure RFC 5545 compliance for recurring event exceptions and improve the user experience across different themes and calendar views.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 10:22:02 -04:00
Connor JohnstoneandClaude c612f567b4 Fix calendar layout positioning and overflow handling
- Add position relative and height 100% to calendar component for proper layout
- Add overflow hidden to week events overlay to prevent content spillover

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 15:30:59 -04:00
Connor JohnstoneandClaude b5b53bb23a Fix theme-independent login styling and improve calendar responsiveness
- Remove theme reset on logout to preserve user theme preferences
- Implement hardcoded login page colors that override all theme styles
- Add comprehensive overrides for Google theme affecting login forms
- Optimize month view to show minimum required weeks (4-6) instead of fixed 6
- Implement dynamic calendar grid height calculations for better responsive fit
- Add calendar header to print preview with updated height calculations
- Update responsive breakpoints with proper header height variables

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 12:24:55 -04:00
Connor JohnstoneandClaude 7e058ba972 Implement comprehensive responsive design improvements for sidebar and calendar views
- Add full responsive sidebar support for screens 600px+ height with three breakpoints (900px, 750px, 650px)
- Implement consistent spacing for all sidebar controls (view-selector, theme-selector, style-selector, add-calendar-button)
- Add calendar header compactness scaling based on screen height (padding, font sizes, min-heights)
- Implement width-based responsive event text sizing for better space utilization
- Fix login page theme inheritance issue by resetting theme to default on logout
- Remove problematic position:relative style from external calendar items that caused color picker interference
- Standardize external-calendar-list margin to 2px across all breakpoints
- Add proper overflow handling and minimum heights to ensure all sidebar components remain visible
- Scale event titles and times progressively smaller on narrower viewports (1200px, 900px, 600px breakpoints)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-22 18:04:02 -04:00
Connor JohnstoneandClaude 1f86ea9f71 Enhance styling system with new themes and fix modal theming consistency
- Add 4 new dark themes: Midnight, Charcoal, Nord, Dracula with complete CSS variable definitions
- Create Apple Calendar style with glassmorphism effects and theme-aware design
- Fix Google Calendar style to be theme-aware instead of using hardcoded colors
- Replace hardcoded colors in modal CSS with theme variables for consistent theming
- Add data-style attribute support to document root for style-specific CSS selectors
- Update sidebar dropdowns to include all new theme and style options

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 23:36:47 -04:00
Connor JohnstoneandClaude ce9914e388 Clean up code to resolve all compiler warnings
Build and Push Docker Image / docker (push) Successful in 3m48s
- Remove unused AlarmStorage module and all references
- Remove unused imports (AlarmAction, AlarmTrigger, VAlarm from backend)
- Remove unused ReminderType enum from event form types
- Remove unused methods from AlarmScheduler and NotificationManager
- Fix unnecessary mut on NotificationOptions
- Simplify alarm system initialization in app.rs
- Remove unused variable assignments

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 21:51:14 -04:00
Connor JohnstoneandClaude faf5ce2cfd Remove remaining frontend console logs for production
- Remove HTML loading and WASM initialization logs
- Clean up service worker registration/activation logs
- Remove alarm system initialization messages
- Remove notification permission logging
- Keep essential error logging for troubleshooting
- Clean production console output

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 21:35:06 -04:00
Connor JohnstoneandClaude 2fee7a15f9 Clean up verbose debug logging from backend server
- Remove emoji debug logs from event deduplication process
- Remove verbose RRULE consolidation logging
- Remove "found X events with title Y" spam logs
- Keep essential functionality intact
- Maintain clean production server logs

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 21:29:26 -04:00
Connor JohnstoneandClaude 7caf3539f7 Clean up debug logging from notification system
- Remove verbose debug console logs from alarm scheduler
- Remove debug logs from notification manager
- Keep essential error logging for troubleshooting
- Maintain clean, production-ready code
- System functionality unchanged

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 21:22:19 -04:00
Connor JohnstoneandClaude 1538869f4a Implement browser notification system for calendar event alarms
- Add comprehensive alarm scheduling and notification system
- Support for VAlarm data structures from calendar events
- Browser notification API integration with permission handling
- localStorage persistence for alarms across sessions
- Background service worker for alarm checking when app inactive
- Real-time alarm detection with 30-second intervals
- Debug logging for troubleshooting notification issues
- Automatic permission requests when events with alarms are created
- Support for Display action alarms with Duration and DateTime triggers
- Clean alarm management (create, update, remove, expire)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 21:09:14 -04:00
Connor JohnstoneandClaude 7ce7d4c9d9 Fix week view cross-month event fetching bug
When viewing a week that spans two months, events from the second month
were not appearing in the week view. The issue was that the calendar
component only fetched events for the month of the current date, but
week view needs events from all months that appear in the visible week.

- Modified event fetching logic to detect when week view spans multiple months
- Added cross-month support by fetching events from all relevant months
- Added get_start_of_week helper function to calculate week boundaries
- Enhanced ViewMode handling to distinguish between month and week fetching strategies

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 14:17:33 -04:00
Connor JohnstoneandClaude 037b733d48 Implement custom reminders with multiple VAlarms per event
Major Features:
- Replace single ReminderType enum with Vec<VAlarm> throughout stack
- Add comprehensive alarm management UI with AlarmList and AddAlarmModal components
- Support relative (15min before, 2hrs after) and absolute (specific date/time) triggers
- Display reminder icons in both month and week calendar views
- RFC 5545 compliant VALARM implementation using calendar-models library

Frontend Changes:
- Create AlarmList component for displaying configured reminders
- Create AddAlarmModal with full alarm configuration (trigger, timing, description)
- Update RemindersTab to use new alarm management interface
- Replace old ReminderType dropdown with modern multi-alarm system
- Add reminder icons to event displays in month/week views
- Fix event title ellipsis behavior in week view with proper CSS constraints

Backend Changes:
- Update all request/response models to use Vec<VAlarm> instead of String
- Remove EventReminder conversion logic, pass VAlarms directly through
- Maintain RFC 5545 compliance for CalDAV server compatibility

UI/UX Improvements:
- Improved basic details tab layout (calendar/repeat side-by-side, All Day checkbox repositioned)
- Simplified reminder system to single notification type for user clarity
- Font Awesome icons throughout instead of emojis for consistency
- Clean modal styling with proper button padding and hover states
- Removed non-standard custom message fields for maximum CalDAV compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 14:08:31 -04:00
Connor JohnstoneandClaude cb1bb23132 Fix all-day event end date handling by removing double conversion
Root cause: Both frontend and backend were adding a day for all-day events:
- Frontend: Converts inclusive UI dates (9/22-9/25) to exclusive (9/22-9/26)
- Backend: Was incorrectly adding another day (9/22-9/27) causing display issues

Fixed by:
- Remove duplicate day addition in backend handlers (events.rs, series.rs)
- Keep frontend conversion for proper RFC 5545 compliance
- Add reverse conversion when loading events for editing
- Maintain user-friendly inclusive dates in UI while storing exclusive dates

Now properly handles: UI 9/22-9/25 ↔ Storage 9/22-9/26 (exclusive per spec)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 12:34:09 -04:00
Connor JohnstoneandClaude 5c406569af Add reset buttons to color editor modal for individual and bulk color resets
Build and Push Docker Image / docker (push) Successful in 31s
- Add "Reset This Color" button in color preview section for individual resets
- Add "Reset All Colors" button in modal footer for bulk palette reset
- Implement reset callbacks with database persistence via preferences API
- Reorganize color preview layout with flex column for better button placement
- Style reset buttons with appropriate warning colors and hover states
- Support both granular and comprehensive color customization workflows

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 12:03:25 -04:00
Connor JohnstoneandClaude 4aca6c7fae Implement right-click color editor modal for customizable calendar colors
- Add ColorEditorModal component with full color picker interface
- Replace theme-dependent colors with unified color palette
- Store custom colors in database via preferences API for cross-device sync
- Add right-click handlers on color dots to open editor modal
- Fix event bubbling to prevent calendar context menu conflicts
- Add comprehensive CSS styling for modal with proper positioning

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 11:56:16 -04:00
Connor JohnstoneandClaude fd80624429 Fix frontend compilation warnings by removing dead code
Build and Push Docker Image / docker (push) Successful in 4m5s
- Remove unused Route enum and yew_router import from sidebar.rs
- Remove unused last_fetched field from ExternalCalendarEventsResponse
- Prefix unused variables with underscore (_preserve_rrule, _until_date, etc.)

Frontend now compiles cleanly with no warnings.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 16:28:44 -04:00
Connor JohnstoneandClaude b530dcaa69 Remove unnecessary frontend console logs
- Remove app rendering auth_token debug logs
- Remove auth token validation success message
- Remove recurring event occurrence generation logs
- Remove exception dates logging for VEvents

Frontend now runs with minimal essential logging.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 16:20:55 -04:00
Connor JohnstoneandClaude 0821573041 Remove remaining verbose CalDAV discovery and authentication logs
- Remove discovery response XML dumps that flood console
- Remove calendar collection checking logs
- Remove authentication success messages
- Remove API call password length logging
- Fix unused variable warning

Backend now runs with minimal essential logging only.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 16:15:30 -04:00
Connor JohnstoneandClaude 703c9ee2f5 Clean up debug logging and fix compiler warnings
- Remove non-critical debug logs from backend CalDAV parsing
- Remove all-day event debug logs from frontend components
- Fix unused variable warnings with underscore prefixes
- Keep essential logging while reducing noise

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 16:02:41 -04:00
Connor JohnstoneandClaude 5854ad291d Fix all-day event parsing with VALUE=DATE format support
- Add special handling for date-only format (%Y%m%d) in parse_datetime_with_tz
- Convert NaiveDate to midnight NaiveDateTime for all-day events
- Reorder all-day detection to occur before datetime parsing
- All-day events now properly display in calendar views

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 15:51:00 -04:00
Connor JohnstoneandClaude ac1164fd81 Fix singleton to series conversion with complete RRULE parameter support
Build and Push Docker Image / docker (push) Successful in 2m16s
- Add new context menu callback for singleton events to avoid series pipeline
- Implement complete RRULE construction with INTERVAL, COUNT, and UNTIL parameters
- Update frontend service methods to pass recurrence parameters correctly
- Add missing recurrence fields to backend UpdateEventRequest model
- Fix parameter ordering in frontend method calls
- Ensure singleton→series conversion uses single event pipeline initially

This resolves issues where converting singleton events to recurring series
would not respect recurrence interval (every N days), count (N occurrences),
or until date parameters.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 22:28:52 -04:00
Connor JohnstoneandClaude a6092d13ce Complete calendar model refactor to use NaiveDateTime for local time handling
- Refactor VEvent to use NaiveDateTime for all date/time fields (dtstart, dtend, created, etc.)
- Add separate timezone ID fields (_tzid) for proper RFC 5545 compliance
- Update all handlers and services to work with naive local times
- Fix external calendar event conversion to handle new model structure
- Remove UTC conversions from frontend - backend now handles timezone conversion
- Update series operations to work with local time throughout the system
- Maintain compatibility with existing CalDAV servers and RFC 5545 specification

This major refactor simplifies timezone handling by treating all event times as local
until the final CalDAV conversion step, eliminating multiple conversion points that
caused timing inconsistencies.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 20:57:35 -04:00
Connor JohnstoneandClaude acc5ced551 Fix timezone handling for drag-and-drop and recurring event updates
- Fix double timezone conversion in drag-and-drop that caused 4-hour time shifts
- Frontend now sends local times instead of UTC to backend for proper conversion
- Add missing timezone parameter to update_series method to fix recurring event updates
- Update both event modal and drag-and-drop paths to include timezone information
- Maintain RFC 5545 compliance with proper timezone conversion in backend

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 20:56:18 -04:00
Connor Johnstone 890940fe31 Update README with project status and usage notes
Build and Push Docker Image / docker (push) Successful in 32s
2025-09-13 18:28:14 -04:00
Connor JohnstoneandClaude fdea5cd646 Fix timezone conversion bug for events displaying on wrong day
- Preserve original local dates when converting times to UTC for storage
- Prevent events created late in day from appearing on next day due to timezone offset
- Remove hacky bandaid logic in week view that tried to handle timezone shifts
- Use stored event date directly instead of calculating from UTC conversion
- Ensure events always display on intended day regardless of timezone

Fixes issue where events created within last 4 hours of day would show on wrong day
after UTC conversion caused date component to shift to next day.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 18:27:09 -04:00
Connor JohnstoneandClaude b307be7eb1 Add password visibility toggle to login form
- Implement show/hide password functionality with eye icon toggle button
- Add dynamic input type switching between password and text
- Position toggle button inside password input field with proper styling
- Include hover, focus states and accessibility features (tabindex, title)
- Use FontAwesome eye/eye-slash icons for visual feedback
- Maintain secure default (password hidden) with optional visibility
- Integrate proper tab order with existing form elements

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 18:21:56 -04:00
Connor JohnstoneandClaude 9d84c380d1 Fix server and username pre-population on login page
- Save credentials to LocalStorage on successful login when remember checkboxes are checked
- Save credentials immediately when input values change and remember is enabled
- Fix closure ownership issues with checkbox state in submit handler
- Ensure remembered values persist and pre-populate correctly on subsequent visits
- Address issue where values weren't saved if checkboxes defaulted to checked state

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 18:19:16 -04:00
Connor JohnstoneandClaude fad03f94f9 Improve login form layout and accessibility
- Move remember checkboxes inline with inputs for better space utilization
- Implement proper tab order: server → username → password → checkboxes
- Increase form width from 400px to 500px to accommodate horizontal layout
- Make checkbox labels more concise ("Remember" instead of full text)
- Enhance checkbox styling with vertical label placement and larger size
- Reduce form label bottom margin for tighter spacing
- Ensure consistent input widths across all form fields

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-13 18:15:47 -04:00
Connor JohnstoneandClaude ca1ca0c3b1 Implement comprehensive theme system with FontAwesome icons
- Add comprehensive CSS custom properties for all theme colors
- Include modal, button, input, text, and background color variables
- Enhance dark theme with complete variable overrides for proper contrast
- Replace hardcoded colors in print-preview.css with theme variables
- Add FontAwesome CDN integration and replace emoji icons
- Create minimalistic glass-effect checkbox styling with transparency
- Fix white-on-white text issue in dark theme across all modals

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-12 14:55:07 -04:00
Connor JohnstoneandClaude 64dbf65beb Fix event positioning in print copy with dynamic base-unit recalculation
- Measure actual print copy div height after aspect-ratio scaling
- Recalculate base-unit based on measured height vs original 720px assumption
- Apply position scaling to .week-event elements in print copy only
- Parse and recalculate top/height pixel values using scale factor
- Add landscape orientation and fit-to-page CSS hints for better printing
- Preserve hour filtering with proper data attributes and CSS variables

This ensures events display correctly when print copy is scaled to fit page
while maintaining proper aspect ratio and hour range filtering.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-12 14:10:43 -04:00
Connor JohnstoneandClaude 96585440d1 Implement hybrid print preview with CSS-based approach
- Add hidden print-preview-copy div at app level for clean print isolation
- Use @media print rules to show only print copy (960x720) in landscape
- Auto-sync print copy with preview content on modal render via use_effect
- Copy CSS variables and data attributes for proper hour filtering
- Set explicit dimensions matching print-preview-paper content area
- Force landscape orientation with @page rule for better calendar printing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-12 13:17:21 -04:00
Connor JohnstoneandClaude a297d38276 Implement selective print preview content printing with dynamic restoration
- Replace page body with only .print-preview-content div during printing
- Use visibilitychange and focus events to restore original content when print dialog closes
- Add 100ms delay before print dialog to show content replacement briefly
- Remove debug logging for clean production code
- Ensure print output matches preview exactly by sending only preview content to system print dialog

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-12 10:59:42 -04:00
Connor JohnstoneandClaude 4fdaa9931d Fix print preview event positioning to respond to hour range changes
- Add print_start_hour parameter to calculate_event_position function
- Implement proper hour offset calculation for events in print mode
- Remove CSS transform hacks for event positioning
- Use dynamic pixels_per_hour for proper scaling with hour ranges
- Increase modal max-width to 1600px for better visibility
- Events now correctly reposition when start/end hours change

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 20:38:56 -04:00
Connor JohnstoneandClaude c6c7b38bef Implement dynamic base unit calculation for print preview scaling
- Add dynamic height calculation system based on selected hour range and time increment
- Replace hardcoded CSS heights with CSS variables (--print-base-unit, --print-pixels-per-hour)
- Update WeekView component with print mode support and dynamic event positioning
- Optimize week header for print: reduced to 50px height with smaller fonts
- Account for all borders and spacing in calculation (660px available content height)
- Remove debug styling (blue borders, yellow backgrounds)
- Ensure time slots, time labels, and events scale together proportionally
- Perfect fit within 720px content area regardless of hour selection

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 19:26:53 -04:00
Connor JohnstoneandClaude 78db2cc00f Fix print preview paper dimensions and cleanup redundant CSS files
- Change print preview to landscape orientation (11" x 8.5")
- Fix paper div to render at exact 1056x816 pixels
- Add 48px padding (0.5 inches) directly to paper div
- Remove CSS file redundancy: deleted styles.css.backup, styles/base.css, styles/default.css
- Improve modal sizing to accommodate paper dimensions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 18:53:40 -04:00
Connor Johnstone 73d191c5ca Merge branch 'main' of git.rcjohnstone.com:connor/calendar into print-preview-feature 2025-09-11 18:01:56 -04:00
Connor JohnstoneandClaude 91be4436a9 Fix external calendar creation and Outlook compatibility issues
- Fix external calendar form validation by replacing node refs with controlled state inputs
- Add multiple user-agent fallback approach for better external calendar compatibility
- Enhance HTTP client configuration with proper redirect handling and timeouts
- Add detailed error logging and Outlook-specific error detection
- Improve request headers for better calendar server compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 17:58:53 -04:00
Connor JohnstoneandClaude 4cbc495c48 Add print preview modal with hour range selection
Implements comprehensive print functionality for calendar views:
- Print preview modal with live preview and zoom controls
- Hour range selection for week view (start/end hours)
- Print-specific CSS to hide UI elements and optimize layout
- Event repositioning to align with visible time labels
- Support for both 30-minute and 15-minute time increments
- Mouse wheel zoom functionality in preview

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-08 14:55:18 -04:00
Connor JohnstoneandClaude 927cd7d2bb Add color picker functionality to external calendars
- Enable clicking external calendar color icons to open color picker dropdown
- Implement backend API integration for updating external calendar colors
- Add conditional hover effects to prevent interference with color picker
- Use extremely high z-index (999999) to ensure dropdown appears above all elements
- Match existing CalDAV calendar color picker behavior and styling
- Support real-time color updates with immediate visual feedback
- Maintain color consistency across sidebar and calendar events

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 12:17:09 -04:00
Connor JohnstoneandClaude 38b22287c7 Unify hover behavior across all sidebar selectors
Build and Push Docker Image / docker (push) Successful in 31s
- Update view-selector-dropdown hover to match theme/style selectors
- Change from var(--glass-bg-light) to rgba(255, 255, 255, 0.15)
- Ensures consistent glassmorphism hover effects throughout sidebar
- Provides cohesive user experience across Week/Month, Theme, and Style dropdowns

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 12:04:11 -04:00
Connor JohnstoneandClaude 0de2eee626 Fix calendar management modal color picker issues
- Fix z-index issue by creating separate CSS classes for inline vs dropdown color pickers
- Unify CalDAV and external calendar color pickers to use same grid interface
- Improve color picker styling with 4x4 grid layout for 16 colors
- Enhance color option appearance with proper border centering and sizing
- Replace native HTML color input with consistent predefined color grid
- Add visual improvements: larger swatches, better hover effects, checkmark selection

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 11:58:35 -04:00
Connor JohnstoneandClaude aa7a15e6fa Implement tabbed calendar management modal with improved styling
- Replace separate Create Calendar and External Calendar modals with unified tabbed interface
- Redesign modal styling with less rounded corners and cleaner appearance
- Significantly increase padding throughout modal components for better spacing
- Fix CSS variable self-references (control-padding, standard-transition)
- Improve button styling with better padding (0.875rem 2rem) and colors
- Enhance form elements with generous padding (1rem) and improved focus states
- Redesign tab bar with segmented control appearance and proper active states
- Update context menus with modern glassmorphism styling and smooth animations
- Consolidate calendar management functionality into single reusable component

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 11:46:21 -04:00
Connor JohnstoneandClaude b0a8ef09a8 Major CSS cleanup and mobile detection system
CSS Improvements:
- Remove all mobile responsive CSS (@media queries) - 348+ lines removed
- Add comprehensive CSS variables for glass effects, control dimensions, transitions
- Consolidate duplicate patterns (43+ transition, 37+ border-radius, 61+ padding instances)
- Remove legacy week grid CSS section
- Reduce total CSS from 4,197 to 3,828 lines (8.8% reduction)

Sidebar Enhancements:
- Remove unused sidebar-nav div and navigation link
- Standardize all dropdown controls to consistent 40px height and styling
- Reduce calendar item padding from 0.75rem to 0.5rem for more compact display
- Unify theme-selector and style-selector styling with view-selector

Mobile Detection:
- Add MobileWarningModal component with device detection
- Show helpful popup directing mobile users to native CalDAV apps
- Add Navigator and DomTokenList web-sys features
- Desktop-focused experience with appropriate mobile guidance

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 10:58:47 -04:00
Connor JohnstoneandClaude efbaea5ac1 Add current time indicator to week view
- Add real-time current time indicator that updates every 5 seconds
- Display horizontal line with dot and time label on current day only
- Position indicator accurately based on time increment mode (15/30 min)
- Use theme-aware colors with subdued gray styling for dark mode
- Include subtle shadows and proper z-indexing for visibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-05 10:33:07 -04:00
Connor JohnstoneandClaude bbad327ea2 Replace page reloads with dynamic calendar refresh functionality
Build and Push Docker Image / docker (push) Successful in 29s
- Add refresh_calendar_data function to replace window.location.reload()
- Implement dynamic event re-fetching without full page refresh
- Add last_updated timestamp to UserInfo to force component re-renders
- Fix WASM compatibility by using js_sys::Date::now() instead of SystemTime
- Remove debug logging from refresh operations
- Maintain same user experience with improved performance

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 16:53:58 -04:00
Connor JohnstoneandClaude 72273a3f1c Fix event creation timezone handling to prevent time offset issues
- Convert local datetime to UTC before sending to backend for non-all-day events
- Keep all-day events unchanged (no timezone conversion needed)
- Add proper timezone conversion using chrono::Local and chrono::Utc
- Include fallback handling if timezone conversion fails
- Add debug logging for timezone conversion issues

This resolves the issue where events appeared 4 hours earlier than expected
due to frontend sending local time but backend treating it as UTC time.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 16:26:05 -04:00
Connor JohnstoneandClaude 8329244c69 Fix authentication validation to properly reject invalid CalDAV servers
Build and Push Docker Image / docker (push) Successful in 1m9s
- Backend: Enhance CalDAV discovery to require at least one valid 207 response
- Backend: Fail authentication if no valid CalDAV endpoints are found
- Frontend: Add token verification on app startup to validate stored tokens
- Frontend: Clear invalid tokens when login fails or token verification fails
- Frontend: Prevent users with invalid tokens from accessing calendar page

This resolves the issue where invalid servers (like google.com) were incorrectly
accepted as valid CalDAV servers, and ensures proper authentication flow.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 16:06:18 -04:00
Connor JohnstoneandClaude b16603b50b Implement comprehensive external calendar event deduplication and fixes
Build and Push Docker Image / docker (push) Successful in 1m11s
- Add UID-based deduplication to prefer recurring events over single events with same UID
- Implement RRULE-generated instance detection to filter duplicate occurrences
- Add title normalization for case-insensitive matching and consolidation
- Fix external calendar refresh button with proper error handling and loading states
- Update context menu for external events to show only "View Event Details" option
- Add comprehensive multi-pass deduplication: UID → title consolidation → RRULE filtering

This resolves issues where Outlook calendars showed duplicate events with same UID
but different RRULE states (e.g., "Dragster Stand Up" appearing both as recurring
and single events).

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 15:35:42 -04:00
Connor JohnstoneandClaude c6eea88002 Fix drag-and-drop timezone bug between dev and production environments
Build and Push Docker Image / docker (push) Successful in 1m12s
The root cause was that drag operations sent naive local time to the backend,
which the backend interpreted using the SERVER's local timezone rather than
the USER's timezone. This caused different behavior between development and
production servers in different timezones.

**Frontend Changes:**
- Convert naive datetime from drag operations to UTC before sending to backend
- Use client-side Local timezone to properly convert user's intended times
- Handle DST transition edge cases with fallback logic

**Backend Changes:**
- Update parse_event_datetime to treat incoming times as UTC (no server timezone conversion)
- Update series handlers to expect UTC times from frontend
- Remove server-side Local timezone dependency for event parsing

**Result:**
- Consistent behavior across all server environments regardless of server timezone
- Drag operations now correctly preserve user's intended local times
- Fixes "4 hours too early" issue in production drag-and-drop operations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 14:07:33 -04:00
Connor Johnstone 5876553515 Manual update to frontend deploy script
Build and Push Docker Image / docker (push) Successful in 33s
2025-09-04 13:39:06 -04:00
Connor JohnstoneandClaude d73bc78af5 Add comprehensive timezone support to CalDAV client parsing
Build and Push Docker Image / docker (push) Has been cancelled
Enhanced CalDAV datetime parsing to match the full timezone capabilities
of external calendar parsing, now supporting:

- Standard IANA timezone identifiers (America/Denver, Europe/London, etc.)
- Mozilla/Thunderbird timezone format (/mozilla.org/20070129_1/Europe/London)
- Windows timezone names (60+ global mappings from "Mountain Standard Time" to IANA)
- Timezone abbreviations (EST, PST, MST, CST)
- Timezone offset parsing (20231225T120000-0500, 2023-12-25T12:00:00-05:00)
- ISO datetime formats with UTC and offset notation
- Comprehensive global timezone coverage (North America, Europe, Asia, Australia, Africa, South America)

This ensures consistent timezone handling across both CalDAV client events
and external calendar imports, providing robust support for international users.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 13:37:45 -04:00
Connor JohnstoneandClaude 393bfecff2 Fix CalDAV timezone parsing for external client events
Events created in external CalDAV clients (like AgendaV) with timezone information
were showing incorrect times due to improper timezone handling. Fixed by:

- Enhanced datetime parser to extract TZID parameters from iCal properties
- Added proper timezone conversion from source timezone to UTC using chrono-tz
- Preserved full property strings with parameters during parsing
- Maintained backward compatibility with existing UTC format events

This resolves the issue where events created at 9 AM Mountain Time were
displaying as 5 AM instead of the correct 11 AM Eastern Time.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 13:33:59 -04:00
Connor JohnstoneandClaude 45e16313ba Update external calendar modal help to include Google Calendar
Added Google Calendar setup instructions alongside existing Outlook 365 instructions.
Updated modal title to "Setting up External Calendars" and reorganized help text
to show both supported platforms with specific step-by-step instructions.

Google Calendar: hover over calendar → three dots → Settings and sharing →
Integrate calendar → Public address in iCal format

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 22:33:27 -04:00
Connor JohnstoneandClaude 64c737c023 Fix Google Calendar UTC datetime format parsing
Google Calendar ICS files use UTC datetime format ending with 'Z' (e.g., 20250817T140000Z)
which was failing to parse with DateTime::parse_from_str. Fixed by detecting 'Z' suffix,
parsing as naive datetime, and converting to UTC with and_utc().

Also cleaned up debug logging and unused variable warnings.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 22:28:51 -04:00
Connor JohnstoneandClaude 75d9149c76 Add immediate refresh when new external calendars are created
When users add a new external calendar, events now appear instantly instead
of waiting for the next 5-minute auto-refresh cycle or manual refresh.

Changes:
- Modified ExternalCalendarModal to return newly created calendar ID
- Enhanced on_success callback to immediately fetch events for new calendar
- Added proper visibility checking and error handling
- Removed unused imports to clean up compilation warnings

User experience improvement:
- Before: Add calendar → wait 5 minutes → see events
- After: Add calendar → events appear immediately

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 22:15:03 -04:00
Connor JohnstoneandClaude 28b3946e86 Add intelligent caching and auto-refresh for external calendars
Implements server-side database caching with 5-minute refresh intervals to
dramatically improve external calendar performance while keeping data fresh.

Backend changes:
- New external_calendar_cache table with ICS data storage
- Smart cache logic: serves from cache if < 5min old, fetches fresh otherwise
- Cache repository methods for get/update/clear operations
- Migration script for cache table creation

Frontend changes:
- 5-minute auto-refresh interval for background updates
- Manual refresh button (🔄) for each external calendar
- Last updated timestamps showing when each calendar was refreshed
- Centralized refresh function with proper cleanup on logout

Performance improvements:
- Initial load: instant from cache vs slow external HTTP requests
- Background updates: fresh data without user waiting
- Reduced external API calls: only when cache is stale
- Scalable: handles multiple external calendars efficiently

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 22:06:32 -04:00
Connor JohnstoneandClaude 6a01a75cce Add visibility toggles for CalDAV calendars with event filtering
Users can now toggle visibility of CalDAV calendars using checkboxes in
the sidebar, matching the behavior of external calendars. Events from
hidden calendars are automatically filtered out of the calendar view.

Changes:
- Add is_visible field to CalendarInfo (frontend & backend)
- Add visibility checkboxes to CalDAV calendar list items
- Implement real-time event filtering based on calendar visibility
- Add CSS styling matching external calendar checkboxes
- Default new calendars to visible state

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 21:37:46 -04:00
Connor JohnstoneandClaude 189dd32f8c Improve external calendar modal UI and remove emojis
- Fix modal backdrop and centering by using proper modal-backdrop class
- Make color picker more compact (80px width instead of 100%)
- Add Outlook 365 setup instructions with step-by-step guide
- Remove calendar emojis from button and sidebar indicators for cleaner design

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 19:52:09 -04:00
Connor JohnstoneandClaude 7461e8b123 Add right-click context menu to external calendars for deletion
Users can now right-click on external calendar items in the sidebar
to access a context menu with a "Delete Calendar" option. The delete
action removes the calendar from both the server and local state,
including all associated events from the calendar display.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 19:24:02 -04:00
Connor JohnstoneandClaude f88c238b0a Fix external calendar timezone conversion and styling
- Add comprehensive Windows timezone support for global external calendars
  - Map Windows timezone names (e.g. "Mountain Standard Time") to IANA zones (e.g. "America/Denver")
  - Support 60+ timezone mappings across North America, Europe, Asia, Asia Pacific, Africa, South America
  - Add chrono-tz dependency for proper timezone handling
- Fix external calendar event colors by setting calendar_path for color lookup
- Add visual distinction for external calendar events with dashed borders and calendar emoji
- Update timezone parsing to extract TZID parameters from iCalendar DTSTART/DTEND properties
- Pass external calendar data through component hierarchy for color matching

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 19:11:57 -04:00
Connor JohnstoneandClaude 8caa1f45ae Add external calendars feature: display read-only ICS calendars alongside CalDAV calendars
- Database: Add external_calendars table with user relationships and CRUD operations
- Backend: Implement REST API endpoints for external calendar management and ICS fetching
- Frontend: Add external calendar modal, sidebar section with visibility toggles
- Calendar integration: Merge external events with regular events in unified view
- ICS parsing: Support multiple datetime formats, recurring events, and timezone handling
- Authentication: Integrate with existing JWT token system for user-specific calendars
- UI: Visual distinction with 📅 indicator and separate management section

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 18:22:52 -04:00
Connor JohnstoneandClaude 289284a532 Fix all-day event date display bug: events created 9/4-9/6 now show correctly instead of 9/3-9/5
Build and Push Docker Image / docker (push) Successful in 1m9s
- Backend: Store all-day events at noon UTC instead of midnight to avoid timezone boundary issues
- Backend: Remove local timezone conversion for all-day events in series handler
- Frontend: Skip timezone conversion when extracting dates from all-day events for display
- Frontend: Extract dates directly from UTC for all-day events in event_spans_date function

The issue was that timezone conversion of UTC midnight could shift dates backward in western timezones.
Now all-day events use noon UTC storage and pure date extraction without timezone conversion.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 17:35:29 -04:00
Connor JohnstoneandClaude 089f4ce105 Fix series RRULE updates: editing 'all events' now properly updates original series RRULE
- Backend now updates RRULE when recurrence_count or recurrence_end_date parameters are provided
- Fixed update_entire_series() to modify COUNT/UNTIL instead of preserving original RRULE
- Added comprehensive RRULE parsing functions to extract existing frequency, interval, count, until, and BYDAY components
- Fixed frontend parameter mapping to pass recurrence parameters through update_series calls
- Resolves issue where changing recurring event from 5 to 7 occurrences kept original COUNT=5

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 17:22:26 -04:00
Connor JohnstoneandClaude 235dcf8e1d Fix recurring event count bug: events with COUNT=5 now stop after 5 occurrences
Build and Push Docker Image / docker (push) Successful in 1m19s
Events created with specific occurrence counts (like "repeat 5 times") were
repeating forever instead of stopping after the specified number.

Root cause: Frontend form collected recurrence_count and recurrence_until
values correctly, but these weren't being passed through the event creation
pipeline to the backend, which was hardcoding None values.

Fix implemented across entire creation flow:

1. **Enhanced Parameter Conversion**:
   - Added recurrence_count and recurrence_until to to_create_event_params() tuple
   - Properly extracts values from form: recurrence_count, recurrence_until.map()

2. **Updated Backend Method Signature**:
   - Added recurrence_count: Option<u32> and recurrence_until: Option<String>
   - to create_event() method parameters

3. **Fixed Backend Implementation**:
   - Replace hardcoded None values with actual form parameters
   - "recurrence_end_date": recurrence_until, "recurrence_count": recurrence_count

4. **Updated Call Sites**:
   - Modified app.rs to pass params.18 (recurrence_count) and params.19 (recurrence_until)
   - Proper parameter indexing after tuple expansion

Result: Complete recurrence control now works correctly:
-  Events with COUNT=5 stop after exactly 5 occurrences
-  Events with UNTIL date stop on specified date
-  Events with "repeat forever" continue indefinitely
-  Proper iCalendar RRULE generation with COUNT/UNTIL parameters

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:55:54 -04:00
Connor JohnstoneandClaude 8dd60a8ec1 Fix recurring event editing: restore proper update flow and fix API parameters
Fixed multiple issues with recurring event editing via modal that were causing
events to be created instead of updated, and API parameter mismatches.

Key fixes:

1. **Restore Update Flow**:
   - Added original_uid tracking to EventCreationData to distinguish create vs update
   - Modal now routes to update endpoints when editing existing events instead of always creating new ones
   - Implemented dual-path logic in on_event_create callback to handle both operations

2. **Fix "This and Future" Updates**:
   - Added occurrence_date field to EventCreationData for recurring event context
   - Backend now receives required occurrence_date parameter for this_and_future scope
   - Populated occurrence_date from event start date in modal conversion

3. **Fix Update Scope Parameters**:
   - Corrected scope parameter mapping to match backend API expectations:
     * EditAll: "entire_series" → "all_in_series"
     * EditFuture: "this_and_future" (correct)
     * EditThis: "this_event_only" → "this_only"

4. **Enhanced Backend Integration**:
   - Proper routing between update_event() and update_series() based on event type
   - Correct parameter handling for both single and recurring event updates
   - Added missing parameters (exception_dates, update_action, until_date)

Result: All recurring event edit operations now work correctly:
-  "Edit all events in series" updates existing series instead of creating new
-  "Edit this and future events" properly handles occurrence dates
-  "Edit this event only" works for single instance modifications
-  No more duplicate events created during editing
-  Proper CalDAV server synchronization maintained

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:48:42 -04:00
Connor JohnstoneandClaude 20679b6b53 Restore event editing functionality: populate modal with existing event data
When editing existing events, the modal was showing empty/default values
instead of the current event data, making editing very inconvenient.

Root cause: TODO comment in modal initialization was never implemented -
VEvent to EventCreationData conversion was missing.

Solution: Implemented comprehensive vevent_to_creation_data() function that maps:
- Basic info: title, description, location, all-day status
- Timing: start/end dates/times with proper UTC→local timezone conversion
- Classification: event status (Confirmed/Tentative/Cancelled) and class
- People: organizer and attendees (comma-separated)
- Categories: event categories (comma-separated)
- Calendar selection: finds correct calendar or falls back gracefully
- Recurrence: detects recurring events (with TODO for advanced RRULE parsing)
- Priority: preserves event priority if set

Features:
- Proper timezone handling for display times
- Fallback logic for missing end times (1 hour default)
- Smart calendar matching with graceful fallbacks
- Complete enum type mapping between VEvent and EventCreationData

Result: Edit modal now pre-populates with all existing event data,
making editing user-friendly and preserving all event properties.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:36:32 -04:00
Connor JohnstoneandClaude 53c4a99697 Fix multi-day all-day events to display across all days they span
All-day events spanning multiple days were only showing on their start date.
For example, a "Vacation (Dec 20-25)" event would only appear on Dec 20th.

Root cause: Logic only checked events stored in each day's HashMap entry,
missing events that span into other days.

Solution:
- Modified all-day event collection to search all events across all days
- Added event_spans_date() helper function to check if event spans given date
- Properly handles iCalendar dtend convention (day after event ends)
- Added deduplication to prevent duplicate events from multiple day buckets
- Removed unused day_events variable

Result: Multi-day all-day events now correctly appear on every day they span,
while single-day events continue to work as before.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:31:25 -04:00
Connor JohnstoneandClaude 5ea33b7d0a Fix event width bug: timed events showing half-width when all-day events exist
Timed events were incorrectly displaying at half-width when all-day events
existed on the same day, even though all-day events display separately at
the top of the calendar and don't visually overlap with timed events.

Root cause: The overlap calculation logic was including all-day events when
determining width splits for timed events.

Solution:
- Modified calculate_event_layout() to exclude all-day events from filtering
- Updated events_overlap() to return false if either event is all-day
- All-day events now don't participate in timed event width calculations

Result: Timed events display at full width unless they actually overlap
with other timed events, while all-day events continue to display correctly
in their separate section.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:27:32 -04:00
Connor JohnstoneandClaude 13a752a69c Fix timezone bug in event drag-and-drop causing 4-hour offset
Events dragged to 4am-7am were appearing at 8am-11am due to double
timezone conversion. The issue was:

1. Frontend converted local time to UTC before sending to backend
2. Backend (after previous fix) converted "local time" (actually UTC) to UTC again
3. Result: double conversion causing 4+ hour shift in wrong direction

Solution: Remove frontend UTC conversion in drag-and-drop callback.
Let backend handle the local-to-UTC conversion consistently.

- Remove .and_local_timezone(chrono::Local).unwrap().to_utc() conversion
- Send NaiveDateTime directly as local time strings to backend
- Backend parse_event_datetime() now properly handles local-to-UTC conversion

Now drag-and-drop works correctly: drag to 4am shows 4am.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:21:24 -04:00
Connor JohnstoneandClaude 0609a99839 Fix timezone bug in event creation
Events were appearing 4 hours earlier than selected time due to incorrect
timezone handling in backend. The issue was treating frontend local time
as if it was already in UTC.

- Fix parse_event_datetime() in events.rs to properly convert local time to UTC
- Fix all datetime conversions in series.rs to use Local timezone conversion
- Replace Utc.from_utc_datetime() with proper Local.from_local_datetime()
- Add timezone conversion using with_timezone(&Utc) for accurate UTC storage

Now when user selects 5:00 AM, it correctly stores as UTC equivalent
and displays back at 5:00 AM local time.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:17:32 -04:00
Connor JohnstoneandClaude dce82d5f7d Implement last used calendar tracking with localStorage and database sync
- Add database migration for last_used_calendar field in user preferences
- Update backend models and handlers to support last_used_calendar persistence
- Modify frontend preferences service with update_last_used_calendar() method
- Implement automatic saving of selected calendar on event creation
- Add localStorage fallback for offline usage and immediate UI response
- Update create event modal to default to last used calendar for new events
- Clean up unused imports from event form components

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 16:13:18 -04:00
Connor JohnstoneandClaude 1e8a8ce5f2 Complete event modal migration: remove original and rename V2
Remove the original create_event_modal.rs and rename create_event_modal_v2.rs
to complete the modal migration started earlier. This eliminates duplicate code
and consolidates to a single, clean event modal implementation.

Changes:
- Remove original create_event_modal.rs (2,300+ lines)
- Rename create_event_modal_v2.rs → create_event_modal.rs
- Update component/function names: CreateEventModalV2 → CreateEventModal
- Fix all imports in app.rs and calendar.rs
- Add missing to_create_event_params() method to EventCreationData
- Resolve EditAction type conflicts between modules
- Clean up duplicate types and unused imports
- Maintain backwards compatibility with EventCreationData export

Result: -2440 lines, +160 lines - massive code cleanup with zero functionality loss.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 15:53:25 -04:00
Connor JohnstoneandClaude c0bdd3d8c2 Add theme-aware styling for 15-minute time grid lines
Build and Push Docker Image / docker (push) Successful in 30s
Add --calendar-border-light CSS variables to all 8 color themes for proper
15-minute grid line styling. Previously used hard-coded fallback (#f8f8f8)
which was too bright for dark mode and inconsistent with theme colors.

- Dark mode: Use subtle #2a2a2a instead of bright #f8f8f8
- All themes: Theme-appropriate very light border colors
- Better visual integration with each color scheme
- Consistent dotted 15-minute grid lines across all themes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 15:42:29 -04:00
Connor JohnstoneandClaude 2b98c4d229 Hide event time display for single-slot events
Hide time display for events with duration <= 30px (single time slots)
to maximize space for event titles in compact event boxes.

- Single-slot events show title only for better readability
- Applies to both 15-minute and 30-minute time increment modes
- Consistent behavior across static events and drag previews
- Improves UX for short duration events where time display crowds the title

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 15:39:15 -04:00
Connor JohnstoneandClaude ceae654a39 Implement dynamic 15-minute time grid density and remove final boundary
- Scale time grid height dynamically based on time increment (1530px/2970px)
- Add quarter-mode CSS classes for 15-minute blocks (30px each, same as 30-min blocks)
- Update pixel-to-time conversion functions with 2px:1min scaling in 15-min mode
- Generate correct number of time slots (4 per hour in 15-min mode)
- Remove unnecessary final boundary time label and related CSS
- Fix CSS grid layout by removing malformed CSS syntax
- All time-related containers scale properly between 30-minute and 15-minute modes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 15:35:50 -04:00
Connor JohnstoneandClaude fb28fa95c9 Fix recurring events from previous years not showing up
Extend recurring event expansion date range from 30 days to 100 years in the past.
This ensures yearly recurring events created many years ago (birthdays, anniversaries,
historical dates) properly generate their current year occurrences.

The backend correctly includes old recurring events that could have occurrences in
the requested month, but the frontend was only expanding occurrences within a
30-day historical window, missing events from previous years.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 13:19:17 -04:00
Connor JohnstoneandClaude 419cb3d790 Complete CreateEventModalV2 integration and fix styling
Build and Push Docker Image / docker (push) Successful in 1m11s
- Replace CreateEventModal with new modular CreateEventModalV2 throughout app
- Fix compilation errors by aligning event_form types with create_event_modal types
- Add missing props (initial_start_time, initial_end_time) to modal interface
- Fix styling issues: use tab-navigation class and add modal-body wrapper
- Remove duplicate on_create prop causing compilation failure
- All recurrence options now properly positioned below repeat/reminder pickers

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 13:11:18 -04:00
Connor JohnstoneandClaude 53a62fb05e Refactor create_event_modal into modular components
- Split massive 27K line modal into focused components
- Created event_form module with 6 tab components:
  * BasicDetailsTab - main event info with recurrence options properly positioned
  * AdvancedTab - status, privacy, priority
  * PeopleTab - organizer and attendees
  * CategoriesTab - event categories
  * LocationTab - location information
  * RemindersTab - reminder settings
- Added shared types and data structures
- Created new CreateEventModalV2 using modular architecture
- Recurrence options now positioned directly after repeat/reminder pickers

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 12:45:42 -04:00
Connor JohnstoneandClaude 322c88612a Add API proxy configuration and large favicon
- Configure Caddy to proxy /api requests to backend service
- Add favicon_big.png for various icon size needs

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 12:26:50 -04:00
Connor JohnstoneandClaude 4aa53d79e7 Add favicon and remove calendar.db from tracking
- Add favicon.ico as site favicon using Trunk asset pipeline
- Remove calendar.db from git tracking (already in .gitignore)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 12:25:41 -04:00
Connor JohnstoneandClaude 3464754489 Remove debug logging from all-day event detection
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 12:22:34 -04:00
Connor JohnstoneandClaude e56253b9c2 Fix all-day recurring events RFC-5545 compliance
- Set all_day flag properly when creating VEvent in series handler
- Improve all-day event detection using VALUE=DATE parameter
- Add RFC-5545 compliance for exclusive end dates (backend adds 1 day)
- Fix end date display in event modal (frontend subtracts 1 day for display)
- Fix recurring all-day event expansion to maintain proper end date pattern

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 12:21:46 -04:00
Connor JohnstoneandClaude cb8cc7258c Implement smart context menu positioning
Added intelligent viewport boundary detection that repositions context
menus when they would appear outside the screen:

- Detects right/bottom edge overflow and repositions menus accordingly
- Uses accurate size estimates based on actual menu content
- Event menus: 280×200px (recurring) / 180×100px (non-recurring)
- Calendar/generic menus: 180×60px for single items
- Maintains 5px minimum margins from screen edges
- Graceful fallback to original positioning if viewport detection fails

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 11:47:48 -04:00
Connor JohnstoneandClaude b576cd8c4a Add context menus to all-day event boxes
All-day events now have the same right-click context menu functionality
as regular timed events, allowing users to edit, delete, and perform
other actions on all-day events.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 11:37:36 -04:00
Connor JohnstoneandClaude a773159016 Fix recurring event filtering for month view
Previously filtered events by start date only, which excluded recurring
events that started in previous months/years but have instances in the
current month.

New logic:
- Non-recurring events: filter by exact month match (unchanged)
- Recurring events: include if they could have instances in requested month
- Check event start date is before/during month
- Parse RRULE UNTIL date to exclude expired recurring events
- Let frontend handle proper RRULE expansion

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 11:36:28 -04:00
Connor Johnstone a9521ad536 Convenience and fixes
Build and Push Docker Image / docker (push) Successful in 2m11s
2025-09-02 16:07:40 -04:00
Connor Johnstone 5456d7140c Manual updates to fix some deployment steps
Build and Push Docker Image / docker (push) Failing after 21s
2025-09-02 16:03:11 -04:00
Connor Johnstone 62cc910e1a Removing Cargo.lock
Build and Push Docker Image / docker (push) Successful in 7m49s
2025-09-02 12:44:01 -04:00
Connor Johnstone 6ec7bb5422 variables > vars
Build and Push Docker Image / docker (push) Failing after 24s
2025-09-02 12:39:51 -04:00
Connor Johnstone ce74750d85 Trying another approach
Build and Push Docker Image / docker (push) Failing after 20s
2025-09-02 12:38:08 -04:00
Connor Johnstone d089f1545b Fixing the gitea error
Build and Push Docker Image / docker (push) Failing after 22s
2025-09-02 12:34:47 -04:00
Connor Johnstone 7b06fef6c3 Revert "Fix Gitea action Docker build tag error"
This reverts commit 7be9f5a869.
2025-09-02 12:33:17 -04:00
Connor JohnstoneandClaude 7be9f5a869 Fix Gitea action Docker build tag error
- Add fallback registry to prevent invalid tag format
- Make Docker login conditional on secrets being present
- Make push conditional on registry being configured
- Rename Docker image from calendar to runway

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-02 12:32:34 -04:00
Connor JohnstoneandClaude a7ebbe0635 Add application screenshot to README
Shows Runway's week view with events, all-day events, and dark theme

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-02 11:23:13 -04:00