{{ authStore.user.username }}
@@ -54,6 +80,50 @@
class="menu-list"
v-else
>
+
+
+ Passkey Management
+
+
+
+
+
+
+ Passkey Management
+
+
+
+
+
+ User Preferences
+
+
+
+
+
+
+ User Preferences
+
+
+
chatStore.isChatVisible);
const chatMessages = computed(() => chatStore.chatMessages);
diff --git a/src/pages/FormListPage.vue b/src/pages/FormListPage.vue
index aefc2b9..6bab285 100644
--- a/src/pages/FormListPage.vue
+++ b/src/pages/FormListPage.vue
@@ -1,96 +1,100 @@
-
-
-
-
-
- {{ form.title }}
-
- {{ form.description || 'No description' }}
-
-
- Created: {{ formatDate(form.createdAt) }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ Forms
+
+
-
- No forms created yet. Click the button above to create your first form.
-
+
-
-
-
+
+
+
+ {{ form.title }}
+
+ {{ form.description || 'No description' }}
+
+
+ Created: {{ formatDate(form.createdAt) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No forms created yet. Click the button above to create your first form.
+
+
+
+
+
+
diff --git a/src/pages/LandingPage.vue b/src/pages/LandingPage.vue
index cbc8f61..e355008 100644
--- a/src/pages/LandingPage.vue
+++ b/src/pages/LandingPage.vue
@@ -45,7 +45,7 @@ const $q = useQuasar();
const currentYear = ref(new Date().getFullYear());
const features = ref([
- 'Auatomated Daily Reports',
+ 'Automated Daily Reports',
'Deep Mantis Integration',
'Easy Authentication',
'And more..?'
diff --git a/src/pages/LoginPage.vue b/src/pages/LoginPage.vue
index 5d863de..9af9a9d 100644
--- a/src/pages/LoginPage.vue
+++ b/src/pages/LoginPage.vue
@@ -80,12 +80,10 @@ async function handleLogin()
if (verificationRes.data.verified)
{
- // Update the auth store on successful login
authStore.isAuthenticated = true;
authStore.user = verificationRes.data.user;
- authStore.error = null; // Clear any previous errors
- console.log('Login successful:', verificationRes.data.user);
- router.push('/'); // Redirect to home page
+ authStore.error = null;
+ router.push('/');
}
else
{
diff --git a/src/pages/MantisSummariesPage.vue b/src/pages/MantisSummariesPage.vue
index fdc0e16..f91ff8d 100644
--- a/src/pages/MantisSummariesPage.vue
+++ b/src/pages/MantisSummariesPage.vue
@@ -5,7 +5,7 @@
bordered
>
-
+
Mantis Summaries
-
-
- Passkey Management
-
-
-
-
-
-
+
+
+
+ Passkey Management
+
+
+
+
+
+
-
-
- Your Registered Passkeys
-
-
-
- {{ registerSuccessMessage }}
-
-
- {{ registerErrorMessage }}
-
-
-
+
+
+
+ Registered Passkeys
+
+
+
+
-
- Passkey ID: {{ passkey.credentialID }}
-
- Verified just now!
-
-
-
+ {{ registerSuccessMessage }}
+
+
+ {{ registerErrorMessage }}
+
-
+
+
-
-
-
-
-
-
- Loading passkeys...
-
-
- You have no passkeys registered yet.
-
+ :class="{ 'bg-info': identifiedPasskeyId === passkey.credentialID }"
+ >
+
+
+ Passkey ID:
+ {{ passkey.credentialID }}
+
+
+ {{ passkey.credentialID }}
+
+
+ Verified just now!
+
+
-
- {{ fetchErrorMessage }}
-
-
- {{ deleteSuccessMessage }}
-
-
- {{ deleteErrorMessage }}
-
-
- {{ identifyErrorMessage }}
-
-
+
+
+
+
+ Delete Passkey
+
+
+
+
+
+
+ Loading passkeys...
+
+
+ You have no passkeys registered yet.
+
+
+
+ {{ fetchErrorMessage }}
+
+
+ {{ deleteSuccessMessage }}
+
+
+ {{ deleteErrorMessage }}
+
+
+ {{ identifyErrorMessage }}
+
+
+
-
-
diff --git a/src/pages/UserPreferencesPage.vue b/src/pages/UserPreferencesPage.vue
new file mode 100644
index 0000000..a858369
--- /dev/null
+++ b/src/pages/UserPreferencesPage.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+ User Preferences
+
+
+
+
+ Loading preferences...
+
+
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+ {{ groupName.replaceAll('_', ' ') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/router/routes.js b/src/router/routes.js
index 5df8272..875e221 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -40,7 +40,6 @@ const routes = [
component: () => import('pages/PasskeyManagementPage.vue'), // Assuming this page exists or will be created
meta: {
requiresAuth: true,
- navGroup: 'auth', // Show only when logged in
icon: 'key',
title: 'Passkeys',
caption: 'Manage your passkeys'
@@ -85,6 +84,14 @@ const routes = [
title: 'Settings',
caption: 'Manage application settings'
}
+ },
+ {
+ path: 'user-preferences',
+ name: 'userPreferences',
+ component: () => import('pages/UserPreferencesPage.vue'),
+ meta: {
+ requiresAuth: true
+ }
}
]
},
diff --git a/src/stores/preferences.js b/src/stores/preferences.js
new file mode 100644
index 0000000..1e16532
--- /dev/null
+++ b/src/stores/preferences.js
@@ -0,0 +1,115 @@
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
+import axios from 'boot/axios';
+import { Dark } from 'quasar';
+
+export const usePreferencesStore = defineStore('preferences', () =>
+{
+ // Grouped user preferences structure (can be imported/shared if needed)
+ const preferences = ref({
+ UI: [
+ {
+ name: 'Theme',
+ key: 'theme',
+ type: 'text',
+ options: [
+ { label: 'Light', value: 'light' },
+ { label: 'Dark', value: 'dark' },
+ ],
+ },
+ ],
+ API_Tokens: [
+ {
+ name: 'Mantis API Key',
+ key: 'MANTIS_API_KEY',
+ type: 'text',
+ }
+ ]
+ });
+
+ const values = ref({});
+ const loading = ref(false);
+ const saving = ref(false);
+ const error = ref(null);
+
+ async function loadPreferences()
+ {
+ loading.value = true;
+ error.value = null;
+ values.value = {};
+ const allKeys = Object.values(preferences.value).flat().map(p => p.key);
+ try
+ {
+ const responses = await Promise.all(
+ allKeys.map(key =>
+ axios.get(`/api/user-preferences/${key}`, {
+ validateStatus: status => status === 200 || status === 404,
+ })
+ )
+ );
+ responses.forEach((response, idx) =>
+ {
+ const key = allKeys[idx];
+ if (response.status === 404)
+ {
+ values.value[key] = '';
+ }
+ else
+ {
+ values.value[key] = response.data.value;
+ }
+ });
+ }
+ catch (err)
+ {
+ error.value = err.response?.data?.error || 'Failed to load preferences.';
+ }
+ finally
+ {
+ loading.value = false;
+ }
+
+ //If we have a "theme" preference, change it in Quasar
+ if (values.value.theme)
+ {
+ Dark.set(values.value.theme === 'dark');
+ }
+ }
+
+ async function savePreferences()
+ {
+ saving.value = true;
+ error.value = null;
+ const allKeys = Object.keys(values.value);
+ const requests = allKeys.map(key =>
+ axios.put(`/api/user-preferences/${key}`, { value: values.value[key] })
+ );
+ try
+ {
+ await Promise.all(requests);
+ }
+ catch (err)
+ {
+ error.value = err.response?.data?.error || 'Failed to save preferences.';
+ }
+ finally
+ {
+ saving.value = false;
+ }
+
+ if (values.value.theme)
+ {
+ Dark.set(values.value.theme === 'dark');
+ }
+ }
+
+ return {
+ preferences,
+ values,
+ loading,
+ saving,
+ error,
+ loadPreferences,
+ savePreferences,
+ };
+});