- Add timezone configuration per space with fallback to system default - Implement timezone-aware datetime display and editing across frontend - Add migration for per_space_settings table - Update booking service to handle timezone conversions properly - Improve .gitignore to exclude build artifacts - Add comprehensive testing documentation Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
5.0 KiB
Implementation Summary: Timezone Fix + Per-Space Settings
Overview
Fixed timezone display issues and added per-space scheduling settings to the space booking system.
Changes Implemented
Part A: Frontend Timezone Fix ✅
File: frontend/src/utils/datetime.ts
- Added
ensureUTC()function to handle naive datetime strings from backend - Applied
ensureUTC()to allnew Date()calls in:formatDateTime()formatTime()formatDateTimeWithTZ()isoToLocalDateTime()
File: frontend/src/views/Dashboard.vue
- Imported
ensureUTCfrom utils - Applied to booking date comparisons in
upcomingBookingscomputed property
Impact: MyBookings now correctly shows times in user's timezone (e.g., 10:00-17:00 Bucharest instead of 08:00-15:00 UTC).
Part B: Per-Space Scheduling Settings (Database) ✅
File: backend/app/models/space.py
- Added 4 nullable columns:
working_hours_start(Integer)working_hours_end(Integer)min_duration_minutes(Integer)max_duration_minutes(Integer)
File: backend/app/schemas/space.py
- Added 4 optional fields to
SpaceBaseandSpaceResponse
File: backend/migrations/004_add_per_space_settings.sql
- Created migration (already applied to database)
Impact: Spaces can now override global settings. NULL = use global default.
Part C: Timezone-Aware Validation ✅
File: backend/app/services/booking_service.py
- Imported
Spacemodel and timezone utilities - Added
user_timezoneparameter tovalidate_booking_rules() - Load per-space settings with fallback to global
- Convert UTC times to user timezone for working hours validation
- Fix max bookings per day to use local date boundaries
File: backend/app/api/bookings.py
Updated 6 endpoints to pass user_timezone:
- POST /bookings (create) - Line ~251
- POST /bookings/recurring - Line ~376
- Also fixed: Now converts local times to UTC before storage
- PUT /bookings/{id} (update) - Line ~503
- PUT /admin/.../approve - Line ~682
- Uses booking owner's timezone
- PUT /admin/.../update - Line ~865
- Uses booking owner's timezone
- PUT /admin/.../reschedule - Line ~1013
- Uses booking owner's timezone
Impact:
- Working hours validation now uses user's local time (9:00 Bucharest is valid, not rejected as 7:00 UTC)
- Per-space settings are respected
- Recurring bookings now store correct UTC times
Part D: Admin UI for Per-Space Settings ✅
File: frontend/src/views/Admin.vue
- Added form section "Per-Space Scheduling Settings"
- Added 4 input fields with placeholders indicating global defaults
- Updated
formDatareactive object - Updated
startEdit()to load space settings - Updated
resetForm()to clear settings - Added CSS for form-section-header, form-row, and help-text
File: frontend/src/types/index.ts
- Extended
Spaceinterface with 4 optional fields
Impact: Admins can now configure per-space scheduling rules via UI.
Testing Checklist
Timezone Display
- User with
Europe/Bucharesttimezone sees correct local times in MyBookings - Booking created at 09:00 Bucharest shows as 09:00 (not 07:00)
Working Hours Validation
- Booking at 09:00 Bucharest (07:00 UTC) is accepted (not rejected by 8-20 rule)
- User sees error message with correct timezone-aware hours
Per-Space Settings
- Create space with custom working hours (e.g., 10-18)
- Booking outside custom hours is rejected
- Space without settings uses global defaults
- Admin UI displays and saves per-space settings correctly
Recurring Bookings
- Recurring bookings now store correct UTC times
- Bookings created for multiple occurrences have consistent timezone handling
Files Modified
| # | File | Changes |
|---|---|---|
| 1 | frontend/src/utils/datetime.ts |
Added ensureUTC() + applied to 4 functions |
| 2 | frontend/src/views/Dashboard.vue |
Import and use ensureUTC |
| 3 | backend/app/models/space.py |
Added 4 nullable columns |
| 4 | backend/app/schemas/space.py |
Added 4 optional fields |
| 5 | backend/migrations/004_add_per_space_settings.sql |
DB migration (applied) |
| 6 | backend/app/services/booking_service.py |
Timezone-aware validation |
| 7 | backend/app/api/bookings.py |
Updated 6 callers + recurring fix |
| 8 | frontend/src/views/Admin.vue |
Admin UI for per-space settings |
| 9 | frontend/src/types/index.ts |
Extended Space interface |
Known Limitations
- SQLite: COMMENT ON COLUMN not supported (documented in migration file)
- Backward Compatibility: Existing bookings created before fix may have incorrect times (data migration not included)
Next Steps
- Run frontend ESLint:
cd frontend && npx eslint src/utils/datetime.ts src/views/Dashboard.vue src/views/Admin.vue - Run backend tests:
cd backend && pytest(if tests exist) - Manual testing per checklist above
- Consider data migration for existing bookings if needed