user auth, settings, profile

This commit is contained in:
root
2025-12-22 18:01:26 -05:00
parent 81822498c8
commit d19bd16210
19 changed files with 711 additions and 467 deletions

View File

@@ -3,4 +3,4 @@
*/
export { useClipboard } from './useClipboard'
export { usePreferences } from './usePreferences'
export { useUser } from './useUser'

View File

@@ -1,208 +0,0 @@
import { computed, ref } from 'vue';
import { usePreferencesStore, type PreferencesState } from '@KTXC/stores/preferencesStore';
import { preferenceService } from '@KTXC/services/preferenceService';
/**
* Composable for managing user preferences
* Provides reactive access to preferences with automatic sync to server
*/
export function usePreferences() {
const store = usePreferencesStore();
const saving = ref(false);
const error = ref<string | null>(null);
/**
* Get all preferences
*/
const preferences = computed(() => store.preferences);
/**
* Get locked preference keys
*/
const locks = computed(() => store.locks);
/**
* Check if a preference is locked by tenant admin
*/
const isLocked = (key: keyof PreferencesState): boolean => {
return store.isLocked(key);
};
/**
* Get a single preference value
*/
const get = <K extends keyof PreferencesState>(key: K): PreferencesState[K] => {
return store.getPreference(key);
};
/**
* Set a single preference and sync to server
*/
const set = async <K extends keyof PreferencesState>(
key: K,
value: PreferencesState[K],
syncToServer = true
): Promise<boolean> => {
error.value = null;
// Update local state first
const success = store.setPreference(key, value);
if (!success) {
error.value = `Preference "${key}" is locked by administrator`;
return false;
}
// Sync to server if requested
if (syncToServer) {
saving.value = true;
try {
const response = await preferenceService.setPreference(key, value);
// Update store with server response to ensure consistency
store.setPreferences(response.effective);
store.setLocks(response.locks);
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to save preference';
return false;
} finally {
saving.value = false;
}
}
return true;
};
/**
* Update multiple preferences and sync to server
*/
const update = async (
prefs: Partial<PreferencesState>,
syncToServer = true
): Promise<{ success: boolean; rejected: string[] }> => {
error.value = null;
// Update local state
store.setPreferences(prefs);
if (syncToServer) {
saving.value = true;
try {
const response = await preferenceService.updatePreferences(prefs);
store.setPreferences(response.effective);
store.setLocks(response.locks);
return {
success: true,
rejected: response.rejectedKeys ?? [],
};
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to save preferences';
return { success: false, rejected: [] };
} finally {
saving.value = false;
}
}
return { success: true, rejected: [] };
};
/**
* Reset preferences to tenant defaults
*/
const reset = async (): Promise<boolean> => {
error.value = null;
saving.value = true;
try {
const response = await preferenceService.resetPreferences();
store.setPreferences(response.effective);
store.setLocks(response.locks);
return true;
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to reset preferences';
return false;
} finally {
saving.value = false;
}
};
/**
* Refresh preferences from server
*/
const refresh = async (): Promise<boolean> => {
error.value = null;
store.setLoading(true);
try {
const response = await preferenceService.getPreferences();
store.setPreferences(response.effective);
store.setLocks(response.locks);
return true;
} catch (err) {
error.value = err instanceof Error ? err.message : 'Failed to load preferences';
return false;
} finally {
store.setLoading(false);
}
};
// Individual preference computed refs for convenience
const theme = computed({
get: () => store.preferences.theme,
set: (value: string) => set('theme', value),
});
const language = computed({
get: () => store.preferences.language,
set: (value: string) => set('language', value),
});
const timezone = computed({
get: () => store.preferences.timezone,
set: (value: string) => set('timezone', value),
});
const dateFormat = computed({
get: () => store.preferences.date_format,
set: (value: string) => set('date_format', value),
});
const timeFormat = computed({
get: () => store.preferences.time_format,
set: (value: string) => set('time_format', value),
});
const weekStart = computed({
get: () => store.preferences.week_start,
set: (value: string) => set('week_start', value),
});
const defaultModule = computed({
get: () => store.preferences.default_module ?? '',
set: (value: string) => set('default_module', value),
});
return {
// State
preferences,
locks,
saving,
error,
loading: computed(() => store.loading),
// Methods
get,
set,
update,
reset,
refresh,
isLocked,
// Individual preference refs
theme,
language,
timezone,
dateFormat,
timeFormat,
weekStart,
defaultModule,
};
}

View File

@@ -0,0 +1,86 @@
import { computed } from 'vue';
import { useUserStore } from '@KTXC/stores/userStore';
/**
* Composable for accessing user authentication, profile, and settings
* Provides a clean API for modules to access user data
*/
export function useUser() {
const store = useUserStore();
// =========================================================================
// Authentication
// =========================================================================
const isAuthenticated = computed(() => store.isAuthenticated);
const identifier = computed(() => store.identifier);
const identity = computed(() => store.identity);
const label = computed(() => store.label);
const permissions = computed(() => store.permissions);
const hasPermission = (permission: string): boolean => {
return store.permissions.includes(permission);
};
const logout = async (): Promise<void> => {
await store.logout();
};
// =========================================================================
// Profile
// =========================================================================
const profile = computed(() => store.profileFields);
const editableProfile = computed(() => store.editableProfileFields);
const managedProfile = computed(() => store.managedProfileFields);
const getProfile = (key: string): any => {
return store.getProfileField(key);
};
const setProfile = (key: string, value: any): boolean => {
return store.setProfileField(key, value);
};
const isProfileEditable = (key: string): boolean => {
return store.isProfileFieldEditable(key);
};
// =========================================================================
// Settings
// =========================================================================
const settings = computed(() => store.settings);
const getSetting = (key: string): any => {
return store.getSetting(key);
};
const setSetting = (key: string, value: any): void => {
store.setSetting(key, value);
};
return {
// Auth
isAuthenticated,
identifier,
identity,
label,
permissions,
hasPermission,
logout,
// Profile
profile,
editableProfile,
managedProfile,
getProfile,
setProfile,
isProfileEditable,
// Settings
settings,
getSetting,
setSetting,
};
}