# User Preferences API Documentation ## Overview The User Preferences API allows users to customize their experience in the SwiftOps platform, including favorite apps in the navigation bar, UI theme, language, notification settings, and dashboard layout. **Key Features:** - Role-based default preferences - Maximum 6 favorite apps (database constraint) - Automatic preference creation on first access - Full CRUD operations with audit logging - Context-aware app availability based on user role --- ## Table of Contents 1. [Authentication](#authentication) 2. [Endpoints](#endpoints) 3. [Data Models](#data-models) 4. [Role-Based Defaults](#role-based-defaults) 5. [Frontend Integration Guide](#frontend-integration-guide) 6. [Common Use Cases](#common-use-cases) 7. [Error Handling](#error-handling) 8. [Best Practices](#best-practices) --- ## Authentication All endpoints require authentication via JWT token in the Authorization header: ``` Authorization: Bearer ``` --- ## Endpoints ### 1. Get Current User's Preferences **Endpoint:** `GET /api/v1/auth/me/preferences` **Description:** Retrieves the current user's preferences. If no preferences exist yet, they are automatically created with role-based defaults. **Response:** Returns full preference object including: - Favorite apps array (max 6 items) - UI theme (light/dark/auto) - Language preference - Notification settings (email, push, SMS) - Dashboard widget configuration - Table/list preferences (view type, pagination, sorting) - Map preferences (zoom level, center coordinates) - Additional custom settings **Use Cases:** - Load user preferences on application startup - Populate settings page - Configure UI based on user theme preference - Display favorite apps in navigation bar --- ### 2. Update User Preferences **Endpoint:** `PUT /api/v1/auth/me/preferences` **Description:** Updates one or more preference fields. Only send fields you want to update - all fields are optional. **Request Body Fields:** - `favorite_apps` - Array of app codes (max 6, validated against role) - `theme` - One of: `light`, `dark`, `auto` - `language` - Language code (e.g., `en`, `sw`) - `email_notifications` - Boolean - `push_notifications` - Boolean - `sms_notifications` - Boolean - `dashboard_widgets` - Array of widget codes - `default_tickets_view` - One of: `list`, `kanban`, `calendar` - `tickets_per_page` - Integer between 10-100 - `default_sort_field` - String (field name for default sorting) - `default_sort_order` - One of: `asc`, `desc` - `default_map_zoom` - Integer (map zoom level) - `default_map_center_lat` - Float (latitude) - `default_map_center_lng` - Float (longitude) - `additional_settings` - Object (free-form custom settings) **Validation Rules:** - Maximum 6 favorite apps - Favorite apps must be from the role's available apps list - Theme must be one of the valid options - Tickets per page must be between 10-100 **Response:** Returns updated preference object **Use Cases:** - Save settings from user preferences page - Update theme when user toggles dark mode - Reorder favorite apps in navigation - Change language preference - Toggle notification preferences --- ### 3. Get Available Apps for Role **Endpoint:** `GET /api/v1/auth/me/preferences/available-apps` **Description:** Returns the list of apps available for the user to favorite based on their role, along with current favorites and defaults. **Response Fields:** - `role` - User's current role - `current_favorites` - Array of currently favorited app codes - `available_apps` - Array of all apps user can choose from - `default_favorites` - Array of role's default favorite apps - `max_favorites` - Maximum number allowed (always 6) **Use Cases:** - Populate app picker in settings UI - Show which apps can be added/removed - Display role-appropriate app options - Validate favorite apps client-side before submission --- ## Data Models ### UserPreferencesResponse Full preference object returned by GET and PUT endpoints: **Core Fields:** - `id` - UUID of preference record - `user_id` - UUID of user who owns these preferences **App & Navigation:** - `favorite_apps` - Array of app codes (e.g., `["dashboard", "users", "tickets"]`) **UI Preferences:** - `theme` - `"light"`, `"dark"`, or `"auto"` - `language` - Language code (default: `"en"`) **Notifications:** - `email_notifications` - Boolean (default: `true`) - `push_notifications` - Boolean (default: `true`) - `sms_notifications` - Boolean (default: `false`) **Dashboard:** - `dashboard_widgets` - Array of widget codes (e.g., `["recent_tickets", "team_performance"]`) **Table/List Preferences:** - `default_tickets_view` - View type (default: `"list"`) - `tickets_per_page` - Pagination size (default: `25`) - `default_sort_field` - Default sort field (default: `"created_at"`) - `default_sort_order` - Sort direction (default: `"desc"`) **Map Preferences:** - `default_map_zoom` - Zoom level (default: `12`) - `default_map_center_lat` - Latitude (nullable) - `default_map_center_lng` - Longitude (nullable) **Flexible Storage:** - `additional_settings` - Object for custom settings --- ## Role-Based Defaults Each role gets context-appropriate default preferences: ### Platform Admin **Favorite Apps:** `dashboard`, `organizations`, `users`, `activity` **Available Apps:** Core apps (dashboard, organizations, users, activity) + Management apps (settings, billing, notifications, help) **Dashboard Widgets:** Recent tickets, team performance, SLA metrics, organizations overview ### Client Admin **Favorite Apps:** `dashboard`, `projects`, `tickets`, `team` **Available Apps:** Dashboard, projects, tickets, team, sales orders, customers, contractors, reports, settings, help **Dashboard Widgets:** Recent tickets, team performance, SLA metrics, project status ### Contractor Admin **Favorite Apps:** `dashboard`, `projects`, `tickets`, `team` **Available Apps:** Dashboard, projects, tickets, team, timesheets, payroll, reports, settings, help **Dashboard Widgets:** Recent tickets, team performance, payroll summary, project status ### Sales Manager **Favorite Apps:** `dashboard`, `sales_orders`, `customers`, `reports` **Available Apps:** Dashboard, sales orders, customers, reports, team, maps, settings, help **Dashboard Widgets:** Sales pipeline, revenue metrics, team performance, conversion rates ### Project Manager **Favorite Apps:** `dashboard`, `projects`, `tickets`, `team` **Available Apps:** Dashboard, projects, tickets, team, reports, maps, settings, help **Dashboard Widgets:** Project status, team performance, SLA metrics, map view ### Dispatcher **Favorite Apps:** `dashboard`, `tickets`, `maps`, `team` **Available Apps:** Dashboard, tickets, maps, team, projects, reports, settings, help **Dashboard Widgets:** Recent tickets, map view, team availability, SLA metrics ### Field Agent **Favorite Apps:** `tickets`, `maps`, `timesheets`, `profile` **Available Apps:** Tickets, maps, timesheets, profile, expenses, documents, help **Dashboard Widgets:** My tickets, earnings summary, attendance summary ### Sales Agent **Favorite Apps:** `dashboard`, `sales_orders`, `customers`, `maps` **Available Apps:** Dashboard, sales orders, customers, maps, profile, reports, help **Dashboard Widgets:** My sales, customer pipeline, earnings summary --- ## Frontend Integration Guide ### Application Startup Flow 1. **After successful login**, fetch user preferences: - Call `GET /api/v1/auth/me/preferences` - Store preferences in global state (Redux, Vuex, Context, etc.) - If preferences don't exist, backend automatically creates them with role defaults 2. **Apply preferences to UI:** - Set theme based on `theme` field (light/dark/auto) - Configure language/i18n based on `language` field - Render favorite apps in top navigation bar - Configure dashboard widgets - Set default table views and pagination sizes 3. **Cache preferences locally:** - Store in localStorage/sessionStorage for quick access - Sync with backend on changes - Handle offline scenarios gracefully ### Settings Page Implementation **Favorite Apps Section:** - Display current favorite apps with drag-to-reorder functionality - Show "Add App" button that opens modal with available apps - Validate max 6 apps client-side - Allow removal of favorites - Show role-appropriate apps only (fetch from `/available-apps` endpoint) **Theme Selector:** - Radio buttons or dropdown for Light/Dark/Auto - Apply theme immediately on change (optimistic UI) - Save to backend in background **Notification Preferences:** - Toggle switches for each notification type - Group by delivery method (Email, Push, SMS) - Show current state from backend - Update backend on toggle **Dashboard Customization:** - Widget picker showing available widgets for role - Drag-and-drop to reorder widgets - Toggle widget visibility - Save layout to `dashboard_widgets` field **Table Preferences:** - Dropdown for default view (List/Kanban/Calendar) - Number input for pagination size (10-100) - Dropdowns for sort field and order ### Navigation Bar Integration **Rendering Favorite Apps:** - Fetch `favorite_apps` array from preferences - Map app codes to app metadata (icons, names, routes) - Render in top navigation or app drawer - Maintain order from array - Show all available apps in "All Apps" menu or 9-dot launcher **App Code to Route Mapping:** ``` dashboard -> /dashboard organizations -> /organizations users -> /users tickets -> /tickets projects -> /projects sales_orders -> /sales-orders customers -> /customers maps -> /map team -> /team reports -> /reports timesheets -> /timesheets payroll -> /payroll profile -> /profile expenses -> /expenses documents -> /documents settings -> /settings billing -> /billing notifications -> /notifications help -> /help ``` ### Theme Management **Auto Theme Implementation:** - When `theme: "auto"`, detect system preference - Listen for system theme changes - Update UI dynamically without backend call - Only `light` and `dark` are stored in backend, `auto` uses system detection **Theme Application:** - Set CSS variables or toggle theme classes - Persist across page refreshes - Apply before first paint to avoid flash ### Optimistic Updates For better UX, update UI immediately before backend confirmation: 1. User changes preference in UI 2. Update local state/UI immediately 3. Call PUT endpoint in background 4. On success: Keep UI as is 5. On error: Revert UI to previous state and show error message --- ## Common Use Cases ### Use Case 1: Customizing Favorite Apps **User Story:** As a platform admin, I want to add "Billing" to my favorite apps. **Implementation Steps:** 1. User opens Settings → Favorite Apps 2. Frontend calls `GET /api/v1/auth/me/preferences/available-apps` to get available apps 3. Display current favorites (4 apps) and available apps (8 apps) 4. User clicks "Add App" → Modal shows available apps not already favorited 5. User selects "billing" → Add to favorites array 6. Frontend calls `PUT /api/v1/auth/me/preferences` with `{"favorite_apps": ["dashboard", "organizations", "users", "activity", "billing"]}` 7. Backend validates (max 6, role-appropriate) and saves 8. Frontend updates navigation bar with new favorite ### Use Case 2: Toggling Dark Mode **User Story:** As a user, I want to switch to dark mode. **Implementation Steps:** 1. User clicks theme toggle in header/settings 2. Frontend immediately applies dark theme to UI (optimistic update) 3. Frontend calls `PUT /api/v1/auth/me/preferences` with `{"theme": "dark"}` 4. Backend saves preference 5. On next login, dark theme is automatically applied ### Use Case 3: Reordering Favorite Apps **User Story:** As a dispatcher, I want "maps" to be my first favorite app. **Implementation Steps:** 1. User drags "maps" to first position in favorites list 2. Frontend updates array order: `["maps", "dashboard", "tickets", "team"]` 3. UI updates immediately (optimistic) 4. Frontend calls `PUT /api/v1/auth/me/preferences` with new array 5. Backend saves new order 6. Navigation bar reflects new order ### Use Case 4: Setting Default Map Center **User Story:** As a field agent, I want the map to always center on my region. **Implementation Steps:** 1. User navigates map to preferred location 2. User clicks "Set as default center" button 3. Frontend captures current map center coordinates 4. Frontend calls `PUT /api/v1/auth/me/preferences` with `{"default_map_center_lat": -1.2921, "default_map_center_lng": 36.8219, "default_map_zoom": 13}` 5. Backend saves preferences 6. On next map load, map centers at saved coordinates with saved zoom level ### Use Case 5: Customizing Dashboard **User Story:** As a sales manager, I want to see "Conversion Rates" widget on my dashboard. **Implementation Steps:** 1. User opens Dashboard Settings 2. Frontend shows available widgets for sales_manager role 3. User toggles "conversion_rates" widget on 4. Frontend updates `dashboard_widgets` array 5. Frontend calls `PUT /api/v1/auth/me/preferences` with updated widget list 6. Dashboard re-renders with new widget --- ## Error Handling ### Common Errors **400 Bad Request - Invalid App for Role:** ```json { "detail": "Invalid apps for dispatcher: billing, organizations. Available apps: dashboard, tickets, maps, team, projects, reports, settings, help" } ``` **Action:** Show user which apps are invalid and provide picker with valid apps only. **400 Bad Request - Too Many Favorites:** ```json { "detail": "Maximum 6 favorite apps allowed" } ``` **Action:** Disable "Add" button when 6 apps are already favorited, show count (e.g., "5/6 favorites"). **400 Bad Request - Invalid Theme:** ```json { "detail": "Theme must be one of: light, dark, auto" } ``` **Action:** Use dropdown/radio buttons to prevent invalid values client-side. **401 Unauthorized:** ```json { "detail": "Could not validate credentials" } ``` **Action:** Token expired or invalid - redirect to login page. ### Error Handling Strategy 1. **Validate client-side first** - Prevent invalid requests before sending 2. **Show specific error messages** - Extract `detail` field from error response 3. **Revert optimistic updates** - Roll back UI changes if API call fails 4. **Retry on network errors** - Implement exponential backoff for transient failures 5. **Log errors** - Track preference update failures for debugging --- ## Best Practices ### Performance 1. **Cache preferences locally** - Fetch once on login, update on changes 2. **Debounce rapid updates** - If user changes multiple settings quickly, batch into single API call 3. **Use optimistic updates** - Update UI immediately, sync with backend asynchronously 4. **Lazy load available apps** - Only fetch when user opens app picker modal ### User Experience 1. **Show loading states** - Display skeleton or spinner during fetch 2. **Provide immediate feedback** - Visual confirmation when settings save 3. **Persist across sessions** - Store preferences in localStorage as backup 4. **Handle offline gracefully** - Queue preference updates if offline, sync when online 5. **Validate before submission** - Check constraints client-side (max 6 apps, valid values) ### Security 1. **Never cache sensitive data** - Clear preferences on logout 2. **Validate all inputs** - Don't trust client-side validation alone 3. **Use HTTPS** - Ensure all API calls are over secure connection 4. **Handle token expiration** - Refresh token or redirect to login gracefully ### Accessibility 1. **Keyboard navigation** - Allow keyboard control of app picker and settings 2. **Screen reader support** - Announce preference changes 3. **High contrast mode** - Respect system high contrast preferences 4. **Focus management** - Return focus appropriately after modal closes ### State Management 1. **Single source of truth** - Store preferences in global state manager 2. **Sync with backend** - Keep local state in sync with server 3. **Handle race conditions** - Use timestamps or version numbers to resolve conflicts 4. **Broadcast changes** - Notify all components when preferences update --- ## Example Implementation Flows ### Complete Settings Page Flow **Initial Load:** 1. Component mounts → Check if preferences in state 2. If not in state → Call `GET /api/v1/auth/me/preferences` 3. Store in state and render current preferences 4. Enable editing **User Makes Change:** 1. User modifies setting (e.g., toggles notification) 2. Update local state immediately (optimistic) 3. Debounce API call (500ms wait for more changes) 4. Call `PUT /api/v1/auth/me/preferences` with changed fields only 5. On success: Keep optimistic update 6. On error: Revert to previous value, show error toast **Adding Favorite App:** 1. User clicks "Add Favorite App" button 2. If favorites.length === 6 → Show "Maximum reached" message 3. Else → Call `GET /api/v1/auth/me/preferences/available-apps` 4. Filter out already favorited apps 5. Show modal with available apps 6. User selects app → Add to favorites array 7. Update UI immediately 8. Call `PUT` endpoint with new array 9. On success: Close modal 10. On error: Remove app from array, show error ### Theme Toggle Implementation **Toggle Component:** 1. Read current theme from preferences state 2. Render toggle switch (Light/Dark) or three-way selector (Light/Dark/Auto) 3. On click: - Update UI theme immediately - Call `PUT /api/v1/auth/me/preferences` with `{"theme": newTheme}` - Show loading indicator on toggle - On success: Remove loading indicator - On error: Revert theme, show error **Auto Theme Handling:** 1. If theme is "auto", detect system preference: ```javascript const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' ``` 2. Apply system theme to UI 3. Listen for changes: ```javascript window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { if (preferences.theme === 'auto') { applyTheme(e.matches ? 'dark' : 'light') } }) ``` --- ## Testing Recommendations ### Unit Tests - Test preference state management (Redux/Vuex actions) - Test validation logic (max 6 apps, valid values) - Test app code to route mapping - Test theme application logic ### Integration Tests - Test full settings page flow (fetch → edit → save) - Test favorite app picker flow - Test theme toggle with API calls - Test error handling and rollback ### E2E Tests - Test complete user journey: Login → Change preferences → Logout → Login (preferences persisted) - Test preference changes reflect across multiple tabs - Test offline handling and sync on reconnect --- ## Migration Guide If your app currently stores preferences differently: 1. **Phase 1: Dual Read** - Read from old storage, fallback to new API 2. **Phase 2: Migrate Data** - Background job to copy old preferences to new system 3. **Phase 3: Dual Write** - Write to both old and new storage 4. **Phase 4: Cut Over** - Stop reading from old storage, read from API only 5. **Phase 5: Cleanup** - Remove old preference storage code --- ## Support & Troubleshooting ### Common Issues **Issue:** Preferences not saving **Solution:** Check network tab for API errors, verify authentication token is valid **Issue:** Default preferences not created **Solution:** Preferences are auto-created on first GET request, ensure user is authenticated **Issue:** Theme not applying **Solution:** Ensure theme CSS classes/variables are correctly wired to preference value **Issue:** Favorite apps showing wrong apps for role **Solution:** Fetch available apps from API, don't hardcode app lists in frontend ### Debug Checklist - [ ] User is authenticated (valid token) - [ ] API endpoint returns 200 status - [ ] Response data structure matches expected format - [ ] Preferences are stored in state manager - [ ] UI components read from state correctly - [ ] Optimistic updates revert on error - [ ] Error messages are displayed to user --- ## API Versioning Current Version: **v1** All endpoints are under `/api/v1/auth/me/preferences` Breaking changes will be introduced in new API versions (v2, v3, etc.) with deprecation notices. --- ## Changelog **Version 1.0** (Current) - Initial release - Support for favorite apps, theme, notifications, dashboard widgets - Role-based defaults and validation - Maximum 6 favorite apps constraint --- ## Additional Resources - **User Management API:** See general user profile endpoints - **Authentication API:** Token management and session handling - **Role Definitions:** Complete list of roles and permissions --- **Last Updated:** November 18, 2025 **Maintained By:** SwiftOps Backend Team