impement and fix user settings

This commit is contained in:
root
2025-12-22 18:26:40 -05:00
parent d19bd16210
commit 116f664e7e
7 changed files with 69 additions and 32 deletions

View File

@@ -36,24 +36,26 @@ class UserProfileController extends ControllerAbstract
* Update user profile fields
* Only editable fields can be updated. Provider-managed fields are automatically filtered out.
*
* @param array $profile Key-value pairs of profile fields to update
* @param array $data Key-value pairs of profile fields to update
*
* @example request body:
* {
* "data": {
* "name_given": "John",
* "name_family": "Doe",
* "phone": "+1234567890"
* }
* }
*
* @return JsonResponse Updated profile data
*/
#[AuthenticatedRoute('/user/profile', name: 'user.profile.update', methods: ['PUT', 'PATCH'])]
public function update(array $profile = []): JsonResponse
public function update(array $data): JsonResponse
{
$userId = $this->userIdentity->identifier();
// storeProfile automatically filters out provider-managed fields
$this->userService->storeProfile($userId, $profile);
$this->userService->storeProfile($userId, $data);
// Return updated profile
$updatedProfile = $this->userService->fetchProfile($userId);

View File

@@ -26,8 +26,8 @@ class UserSettingsController extends ControllerAbstract
#[AuthenticatedRoute('/user/settings', name: 'user.settings.read', methods: ['GET'])]
public function read(): JsonResponse
{
// Fetch all settings
$settings = $this->userService->fetchSettings([]);
// Fetch all settings (no filter)
$settings = $this->userService->fetchSettings();
return new JsonResponse($settings, JsonResponse::HTTP_OK);
}
@@ -35,24 +35,26 @@ class UserSettingsController extends ControllerAbstract
/**
* Update user settings
*
* @param array $settings Key-value pairs of settings to update
* @param array $data Key-value pairs of settings to update
*
* @example request body:
* {
* "data": {
* "theme": "dark",
* "language": "en",
* "notifications": true
* }
* }
*
* @return JsonResponse Updated settings data
*/
#[AuthenticatedRoute('/user/settings', name: 'user.settings.update', methods: ['PUT', 'PATCH'])]
public function update(array $settings = []): JsonResponse
public function update(array $data): JsonResponse
{
$this->userService->storeSettings($settings);
$this->userService->storeSettings($data);
// Return updated settings
$updatedSettings = $this->userService->fetchSettings(array_keys($settings));
$updatedSettings = $this->userService->fetchSettings(array_keys($data));
return new JsonResponse($updatedSettings, JsonResponse::HTTP_OK);
}

View File

@@ -197,7 +197,8 @@ class UserStore
['$set' => $updates]
);
return $result->getModifiedCount() > 0;
// Return true if document was matched (exists), even if not modified
return $result->getMatchedCount() > 0;
}
}

View File

@@ -4,4 +4,17 @@
<script setup lang="ts">
import { RouterView } from 'vue-router';
import { onMounted } from 'vue';
import { useTheme } from 'vuetify';
import { useLayoutStore } from '@KTXC/stores/layoutStore';
const theme = useTheme();
const layoutStore = useLayoutStore();
// Apply saved theme on mount
onMounted(() => {
if (layoutStore.theme) {
theme.global.name.value = layoutStore.theme;
}
});
</script>

View File

@@ -12,7 +12,7 @@ const userStore = useUserStore();
const integrationStore = useIntegrationStore();
const layoutStore = useLayoutStore();
const identityData = computed(() => userStore.user);
const identityData = computed(() => userStore.auth);
const profileMenuItems = computed(() => integrationStore.getItems('profile_menu'));
// Theme toggle
@@ -20,7 +20,7 @@ const isDarkMode = computed(() => theme.global.name.value === 'dark');
const toggleTheme = () => {
const newTheme = theme.global.name.value === 'light' ? 'dark' : 'light';
theme.global.name.value = newTheme;
localStorage.setItem('theme', newTheme);
layoutStore.setTheme(newTheme);
};
// Navigate to settings
@@ -45,7 +45,7 @@ const goToSettings = () => {
<h6 class="text-h6 mb-0">
{{ identityData?.label || 'User Name' }}
</h6>
<p class="text-caption mb-0">{{ identityData?.email || '' }}</p>
<p class="text-caption mb-0">{{ userStore.getProfileField('email') || '' }}</p>
</div>
</div>
<v-divider />

View File

@@ -36,7 +36,7 @@ export const userService = {
profileUpdateTimer = null;
try {
await fetchWrapper.put('/user/profile', updates);
await fetchWrapper.put('/user/profile', { data: updates });
resolve();
} catch (error) {
reject(error);
@@ -59,7 +59,7 @@ export const userService = {
const updates = { ...pendingProfileUpdates, ...fields };
pendingProfileUpdates = {};
return fetchWrapper.put('/user/profile', updates);
return fetchWrapper.put('/user/profile', { data: updates });
},
/**
@@ -74,7 +74,7 @@ export const userService = {
if (Object.keys(pendingProfileUpdates).length > 0) {
const updates = { ...pendingProfileUpdates };
pendingProfileUpdates = {};
return fetchWrapper.put('/user/profile', updates);
return fetchWrapper.put('/user/profile', { data: updates });
}
},
@@ -99,7 +99,7 @@ export const userService = {
settingsUpdateTimer = null;
try {
await fetchWrapper.put('/user/settings', updates);
await fetchWrapper.put('/user/settings', { data: updates });
resolve();
} catch (error) {
reject(error);
@@ -122,7 +122,7 @@ export const userService = {
const updates = { ...pendingSettingsUpdates, ...settings };
pendingSettingsUpdates = {};
return fetchWrapper.put('/user/settings', updates);
return fetchWrapper.put('/user/settings', { data: updates });
},
/**
@@ -137,7 +137,7 @@ export const userService = {
if (Object.keys(pendingSettingsUpdates).length > 0) {
const updates = { ...pendingSettingsUpdates };
pendingSettingsUpdates = {};
return fetchWrapper.put('/user/settings', updates);
return fetchWrapper.put('/user/settings', { data: updates });
}
},

View File

@@ -1,6 +1,7 @@
import { ref } from 'vue';
import { ref, watch } from 'vue';
import { defineStore } from 'pinia';
import config from '@KTXC/config';
import { useUserStore } from './userStore';
export type MenuMode = 'apps' | 'settings';
@@ -8,14 +9,32 @@ export const useLayoutStore = defineStore('layout', () => {
// Loading state
const isLoading = ref(false);
// Sidebar state
const sidebarDrawer = ref(config.Sidebar_drawer);
const miniSidebar = ref(config.mini_sidebar);
// Sidebar state - initialize from settings or config
const userStore = useUserStore();
const sidebarDrawer = ref(userStore.getSetting('sidebar_drawer') ?? config.Sidebar_drawer);
const miniSidebar = ref(userStore.getSetting('mini_sidebar') ?? config.mini_sidebar);
const menuMode = ref<MenuMode>('apps');
// Theme state
const theme = ref(config.actTheme);
const font = ref(config.fontTheme);
// Theme state - initialize from settings or config
const theme = ref(userStore.getSetting('theme') ?? config.actTheme);
const font = ref(userStore.getSetting('font') ?? config.fontTheme);
// Watch and sync sidebar state to settings
watch(sidebarDrawer, (value) => {
userStore.setSetting('sidebar_drawer', value);
});
watch(miniSidebar, (value) => {
userStore.setSetting('mini_sidebar', value);
});
watch(theme, (value) => {
userStore.setSetting('theme', value);
});
watch(font, (value) => {
userStore.setSetting('font', value);
});
// Actions
function toggleSidebarDrawer() {