Skip to main content

User Preferences

User preferences allow users to customize their display and UI settings. Each user has their own preferences that are automatically created on first access.

Overview

User preferences store personalization settings such as:

  • Date Format: How dates are displayed
  • Time Format: 12-hour or 24-hour time
  • Timezone: User's preferred timezone
  • Theme: Light or dark mode
  • Widget Configuration: Dashboard and UI customization
Auto-Creation

Preferences are automatically created with default values when a user first accesses them. No manual setup required!

Endpoints

Get User Preferences

Retrieve the current user's preferences. Auto-creates with defaults if not exists.

curl -X GET https://your-site.taruvi.cloud/api/users/me/preferences/ \
-H "Authorization: Bearer YOUR_TOKEN"

Response:

{
"success": true,
"message": "Preferences retrieved successfully",
"data": {
"date_format": "YYYY-MM-DD",
"time_format": "24h",
"timezone": "UTC",
"theme": "light",
"widget_config": {}
}
}

Create or Update Preferences

Create or update the current user's preferences. Both POST and PUT work identically (upsert).

curl -X POST https://your-site.taruvi.cloud/api/users/me/preferences/ \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"date_format": "DD/MM/YYYY",
"time_format": "12h",
"timezone": "Asia/Kolkata",
"theme": "dark",
"widget_config": {
"sidebar_collapsed": true,
"default_page_size": 25,
"show_tooltips": false
}
}'

Response:

{
"success": true,
"message": "Preferences updated successfully",
"data": {
"date_format": "DD/MM/YYYY",
"time_format": "12h",
"timezone": "Asia/Kolkata",
"theme": "dark",
"widget_config": {
"sidebar_collapsed": true,
"default_page_size": 25,
"show_tooltips": false
}
}
}

Field Reference

Date Format

Controls how dates are displayed in the UI.

Type: string Required: Yes Choices:

  • YYYY-MM-DD - ISO format (2024-01-15)
  • DD/MM/YYYY - European format (15/01/2024)
  • MM/DD/YYYY - US format (01/15/2024)
  • DD-MMM-YYYY - Readable format (15-Jan-2024)

Default: YYYY-MM-DD

Example:

{
"date_format": "DD/MM/YYYY"
}

Time Format

Controls whether time is displayed in 12-hour or 24-hour format.

Type: string Required: Yes Choices:

  • 24h - 24-hour format (14:30)
  • 12h - 12-hour format (2:30 PM)

Default: 24h

Example:

{
"time_format": "12h"
}

Timezone

User's preferred timezone for displaying dates and times.

Type: string Required: Yes Validation: Must be a valid IANA timezone

Default: UTC

Common Values:

  • UTC
  • America/New_York
  • America/Los_Angeles
  • Europe/London
  • Europe/Paris
  • Asia/Kolkata
  • Asia/Tokyo
  • Australia/Sydney

Example:

{
"timezone": "Asia/Kolkata"
}

Theme

UI theme preference for the application.

Type: string Required: Yes Choices:

  • light - Light theme
  • dark - Dark theme

Default: light

Example:

{
"theme": "dark"
}

Widget Config

Flexible JSON field for storing dashboard and widget configurations.

Type: object Required: No Validation: None (completely flexible)

Default: {}

Example:

{
"widget_config": {
"sidebar_collapsed": true,
"default_page_size": 25,
"show_tooltips": false,
"dashboard_layout": "grid",
"widgets": [
{
"id": "stats",
"position": {"x": 0, "y": 0, "w": 6, "h": 2}
},
{
"id": "chart",
"position": {"x": 6, "y": 0, "w": 6, "h": 4}
}
]
}
}

Usage Examples

Format Date Based on Preference

// Format date based on user preference
function formatDate(date, format) {
switch(format) {
case 'YYYY-MM-DD':
return date.toISOString().split('T')[0];
case 'DD/MM/YYYY':
return `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()}`;
case 'MM/DD/YYYY':
return `${date.getMonth()+1}/${date.getDate()}/${date.getFullYear()}`;
case 'DD-MMM-YYYY':
const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
return `${date.getDate()}-${months[date.getMonth()]}-${date.getFullYear()}`;
}
}

Error Responses

Invalid Timezone

{
"success": false,
"errors": {
"timezone": ["Invalid timezone: Invalid/Timezone"]
}
}

Invalid Date Format

{
"success": false,
"errors": {
"date_format": ["\"INVALID_FORMAT\" is not a valid choice."]
}
}

Invalid Theme

{
"success": false,
"errors": {
"theme": ["\"auto\" is not a valid choice."]
}
}

Unauthenticated

{
"detail": "Authentication credentials were not provided."
}

Best Practices

1. Load Preferences on App Initialization

// Load preferences when app starts
useEffect(() => {
async function loadPreferences() {
const prefs = await getPreferences();
// Apply preferences to app
applyTheme(prefs.theme);
setDateFormat(prefs.date_format);
setTimezone(prefs.timezone);
}
loadPreferences();
}, []);

2. Debounce Preference Updates

// Debounce updates to avoid excessive API calls
const debouncedUpdate = debounce(async (preferences) => {
await updatePreferences(preferences);
}, 500);

// Usage
function handleThemeChange(theme) {
debouncedUpdate({ ...currentPrefs, theme });
}

3. Cache Preferences Locally

// Cache in localStorage for faster loads
function cachePreferences(prefs) {
localStorage.setItem('user_preferences', JSON.stringify(prefs));
}

function getCachedPreferences() {
const cached = localStorage.getItem('user_preferences');
return cached ? JSON.parse(cached) : null;
}

4. Validate Before Sending

// Validate preferences before updating
function validatePreferences(prefs) {
const validDateFormats = ['YYYY-MM-DD', 'DD/MM/YYYY', 'MM/DD/YYYY', 'DD-MMM-YYYY'];
const validTimeFormats = ['24h', '12h'];
const validThemes = ['light', 'dark'];

if (!validDateFormats.includes(prefs.date_format)) {
throw new Error('Invalid date format');
}
if (!validTimeFormats.includes(prefs.time_format)) {
throw new Error('Invalid time format');
}
if (!validThemes.includes(prefs.theme)) {
throw new Error('Invalid theme');
}

return true;
}

Common Workflows

Initial Setup

  1. User logs in for the first time
  2. App calls GET /api/users/me/preferences/
  3. Backend auto-creates preferences with defaults
  4. App applies default preferences to UI

Changing Theme

  1. User clicks theme toggle
  2. App updates local state immediately (optimistic update)
  3. App calls POST /api/users/me/preferences/ with new theme
  4. Backend validates and saves
  5. On error, revert to previous theme

Timezone Detection

  1. Detect user's timezone using browser API
  2. Compare with saved preference
  3. If different, prompt user to update
  4. Update preference if user confirms
// Detect browser timezone
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;

// Compare with saved preference
if (browserTimezone !== preferences.timezone) {
// Prompt user to update
const shouldUpdate = confirm(
`Your timezone appears to be ${browserTimezone}. Update preferences?`
);

if (shouldUpdate) {
await updatePreferences({
...preferences,
timezone: browserTimezone
});
}
}

Security Considerations

  • User-Specific: Each user can only access their own preferences
  • Authentication Required: All endpoints require valid authentication
  • No Sensitive Data: Preferences should not contain sensitive information
  • Validation: All fields are validated on the backend
  • Rate Limiting: Standard API rate limits apply

Limitations

  • No Partial Updates: POST/PUT replaces all fields (full update only)
  • No History: Previous preferences are not stored
  • No Sharing: Preferences cannot be shared between users
  • Tenant-Specific: Preferences are stored per tenant (not global)