Force line endings and whitespace, and revamp logout via introduction of a new profile component.

This commit is contained in:
Cameron Redmore 2025-04-25 13:56:12 +01:00
parent f6df79d83f
commit 0e491ecabe
31 changed files with 4870 additions and 4797 deletions

View file

@ -13,5 +13,8 @@
"[vue]": { "[vue]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint" "editor.defaultFormatter": "dbaeumer.vscode-eslint"
}, },
"editor.formatOnSave": true "editor.formatOnSave": true,
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
"editor.trimAutoWhitespace": true
} }

View file

@ -75,6 +75,12 @@ export default
//Enforce semicolon //Enforce semicolon
'@stylistic/semi': ['warn', 'always'], '@stylistic/semi': ['warn', 'always'],
'@stylistic/space-before-function-paren': ['warn', 'never'], '@stylistic/space-before-function-paren': ['warn', 'never'],
//Force LF and not CRLF
'@stylistic/linebreak-style': ['warn', 'unix'],
//Force no trailing spaces
'@stylistic/no-trailing-spaces': ['warn', { skipBlankLines: false, ignoreComments: false }]
} }
}, },

View file

@ -23,7 +23,7 @@ export default defineConfig((/* ctx */) =>
// https://github.com/quasarframework/quasar/tree/dev/extras // https://github.com/quasarframework/quasar/tree/dev/extras
extras: [ extras: [
// 'ionicons-v4', // 'ionicons-v4',
// 'mdi-v7', 'mdi-v7',
// 'fontawesome-v6', // 'fontawesome-v6',
// 'eva-icons', // 'eva-icons',
// 'themify', // 'themify',

View file

@ -6,22 +6,83 @@
persistent persistent
:model-value="true" :model-value="true"
> >
<q-list> <q-item
<q-item clickable
clickable v-ripple
v-ripple @click="toggleLeftDrawer"
@click="toggleLeftDrawer" >
<q-item-section avatar>
<q-icon name="menu" />
</q-item-section>
<q-item-section>
<q-item-label class="text-h6">
StylePoint
</q-item-label>
</q-item-section>
</q-item>
<template v-if="authStore.isAuthenticated">
<q-card
v-if="leftDrawerOpen"
bordered
flat
class="q-ma-sm text-center"
> >
<q-item-section avatar> <q-card-section>
<q-icon name="menu" /> <q-avatar
</q-item-section> class="bg-primary cursor-pointer text-white"
<q-item-section> >
<q-item-label class="text-h6"> <q-icon name="mdi-account" />
StylePoint <q-tooltip>
</q-item-label> {{ authStore.user.username }}
</q-item-section> </q-tooltip>
</q-item> </q-avatar>
<div class="text-h6">
{{ authStore.user.username }}
</div>
<q-btn
class="full-width q-mt-sm"
dense
outline
@click="logout"
>
Logout
</q-btn>
</q-card-section>
</q-card>
<q-list
padding
class="menu-list"
v-else
>
<q-item
clickable
v-ripple
dense
@click="logout"
class="q-mb-sm"
>
<q-tooltip
anchor="center right"
self="center left"
>
<span>Logout</span>
</q-tooltip>
<q-item-section avatar>
<q-icon name="logout" />
</q-item-section>
<q-item-section>
<q-item-label class="text-h6">
Logout
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</template>
<q-separator />
<q-list
padding
class="menu-list"
>
<!-- Dynamic Navigation Items --> <!-- Dynamic Navigation Items -->
<q-item <q-item
v-for="item in navItems" v-for="item in navItems"
@ -30,6 +91,7 @@
v-ripple v-ripple
:to="{ name: item.name }" :to="{ name: item.name }"
exact exact
dense
> >
<q-tooltip <q-tooltip
anchor="center right" anchor="center right"
@ -47,27 +109,6 @@
</q-item-label> </q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
<!-- Logout Button (Conditional) -->
<q-item
v-if="authStore.isAuthenticated"
clickable
v-ripple
@click="logout"
>
<q-tooltip
anchor="center right"
self="center left"
>
<span>Logout</span>
</q-tooltip>
<q-item-section avatar>
<q-icon name="logout" />
</q-item-section>
<q-item-section>
<q-item-label>Logout</q-item-label>
</q-item-section>
</q-item>
</q-list> </q-list>
</q-drawer> </q-drawer>
@ -86,7 +127,6 @@
icon="chat" icon="chat"
color="accent" color="accent"
direction="up" direction="up"
padding="sm"
@click="toggleChat" @click="toggleChat"
/> />
</q-page-sticky> </q-page-sticky>
@ -95,8 +135,6 @@
<q-dialog <q-dialog
v-model="isChatVisible" v-model="isChatVisible"
:maximized="$q.screen.lt.sm" :maximized="$q.screen.lt.sm"
fixed
persistent
style="width: max(400px, 25%);" style="width: max(400px, 25%);"
> >
<q-card style="width: max(400px, 25%); height: 600px; max-height: 80vh;"> <q-card style="width: max(400px, 25%); height: 600px; max-height: 80vh;">
@ -216,32 +254,58 @@ function toggleLeftDrawer()
{ {
leftDrawerOpen.value = !leftDrawerOpen.value; leftDrawerOpen.value = !leftDrawerOpen.value;
} }
async function logout() async function logout()
{ {
try $q.dialog({
title: 'Confirm Logout',
message: 'Are you sure you want to logout?',
cancel: true,
persistent: true
}).onOk(async() =>
{ {
await axios.post('/api/auth/logout'); try
authStore.logout(); // Use the store action to update state {
// No need to manually push, router guard should redirect await axios.post('/api/auth/logout');
// router.push({ name: 'login' }); authStore.logout();
}
catch (error)
{
console.error('Logout failed:', error);
$q.notify({ $q.notify({
color: 'negative', color: 'positive',
message: 'Logout failed. Please try again.', message: 'Logout successful.',
icon: 'report_problem' icon: 'check_circle'
}); });
}
router.push({ name: 'login' });
}
catch (error)
{
console.error('Logout failed:', error);
$q.notify({
color: 'negative',
message: 'Logout failed. Please try again.',
icon: 'report_problem'
});
}
});
} }
</script> </script>
<style scoped> <style lang="scss" scoped>
/* Add any specific styles for the layout or chat window here */
.q-dialog .q-card { .q-dialog .q-card {
overflow: hidden; /* Prevent scrollbars on the card itself */ overflow: hidden;
}
.menu-list .q-item {
border-radius: 32px;
margin: 5px 5px;
}
.menu-list .q-item:first-child {
margin-top: 0px;
}
.menu-list .q-router-link--active {
background-color: var(--q-primary);
color: #fff;
} }
</style> </style>