user auth, settings, profile
This commit is contained in:
@@ -3,4 +3,4 @@
|
||||
*/
|
||||
|
||||
export { useClipboard } from './useClipboard'
|
||||
export { usePreferences } from './usePreferences'
|
||||
export { useUser } from './useUser'
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
86
core/src/composables/useUser.ts
Normal file
86
core/src/composables/useUser.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user