parent
f6df79d83f
commit
3aeefee5a4
1 changed files with 248 additions and 247 deletions
|
@ -1,247 +1,248 @@
|
||||||
<template>
|
<template>
|
||||||
<q-layout view="hHh Lpr lFf">
|
<q-layout view="hHh Lpr lFf">
|
||||||
<q-drawer
|
<q-drawer
|
||||||
:mini="!leftDrawerOpen"
|
:mini="!leftDrawerOpen"
|
||||||
bordered
|
bordered
|
||||||
persistent
|
persistent
|
||||||
:model-value="true"
|
:model-value="true"
|
||||||
>
|
>
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item
|
<q-item
|
||||||
clickable
|
clickable
|
||||||
v-ripple
|
v-ripple
|
||||||
@click="toggleLeftDrawer"
|
@click="toggleLeftDrawer"
|
||||||
>
|
>
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<q-icon name="menu" />
|
<q-icon name="menu" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label class="text-h6">
|
<q-item-label class="text-h6">
|
||||||
StylePoint
|
StylePoint
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
<!-- Dynamic Navigation Items -->
|
<!-- Dynamic Navigation Items -->
|
||||||
<q-item
|
<q-item
|
||||||
v-for="item in navItems"
|
v-for="item in navItems"
|
||||||
:key="item.name"
|
:key="item.name"
|
||||||
clickable
|
clickable
|
||||||
v-ripple
|
v-ripple
|
||||||
:to="{ name: item.name }"
|
:to="{ name: item.name }"
|
||||||
exact
|
exact
|
||||||
>
|
>
|
||||||
<q-tooltip
|
<q-tooltip
|
||||||
anchor="center right"
|
anchor="center right"
|
||||||
self="center left"
|
self="center left"
|
||||||
>
|
>
|
||||||
<span>{{ item.meta.title }}</span>
|
<span>{{ item.meta.title }}</span>
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<q-icon :name="item.meta.icon" />
|
<q-icon :name="item.meta.icon" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>{{ item.meta.title }}</q-item-label>
|
<q-item-label>{{ item.meta.title }}</q-item-label>
|
||||||
<q-item-label caption>
|
<q-item-label caption>
|
||||||
{{ item.meta.caption }}
|
{{ item.meta.caption }}
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
<!-- Logout Button (Conditional) -->
|
<!-- Logout Button (Conditional) -->
|
||||||
<q-item
|
<q-item
|
||||||
v-if="authStore.isAuthenticated"
|
v-if="authStore.isAuthenticated"
|
||||||
clickable
|
clickable
|
||||||
v-ripple
|
v-ripple
|
||||||
@click="logout"
|
@click="logout"
|
||||||
>
|
>
|
||||||
<q-tooltip
|
<q-tooltip
|
||||||
anchor="center right"
|
anchor="center right"
|
||||||
self="center left"
|
self="center left"
|
||||||
>
|
>
|
||||||
<span>Logout</span>
|
<span>Logout</span>
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
<q-item-section avatar>
|
<q-item-section avatar>
|
||||||
<q-icon name="logout" />
|
<q-icon name="logout" />
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>Logout</q-item-label>
|
<q-item-label>Logout</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
|
|
||||||
<q-page-container>
|
<q-page-container>
|
||||||
<router-view />
|
<router-view />
|
||||||
</q-page-container>
|
</q-page-container>
|
||||||
|
|
||||||
<!-- Chat FAB -->
|
<!-- Chat FAB -->
|
||||||
<q-page-sticky
|
<q-page-sticky
|
||||||
v-if="isAuthenticated"
|
v-if="isAuthenticated"
|
||||||
position="bottom-right"
|
position="bottom-right"
|
||||||
:offset="[18, 18]"
|
:offset="[18, 18]"
|
||||||
>
|
>
|
||||||
<q-fab
|
<q-fab
|
||||||
v-model="fabOpen"
|
v-model="fabOpen"
|
||||||
icon="chat"
|
icon="chat"
|
||||||
color="accent"
|
color="accent"
|
||||||
direction="up"
|
direction="up"
|
||||||
padding="sm"
|
padding="sm"
|
||||||
@click="toggleChat"
|
@click="toggleChat"
|
||||||
/>
|
/>
|
||||||
</q-page-sticky>
|
</q-page-sticky>
|
||||||
|
|
||||||
<!-- Chat Window Dialog -->
|
<!-- Chat Window Dialog -->
|
||||||
<q-dialog
|
<q-dialog
|
||||||
v-model="isChatVisible"
|
v-model="isChatVisible"
|
||||||
:maximized="$q.screen.lt.sm"
|
:maximized="$q.screen.lt.sm"
|
||||||
fixed
|
fixed
|
||||||
persistent
|
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;">
|
||||||
<q-bar class="bg-primary text-white">
|
<q-bar class="bg-primary text-white">
|
||||||
<div>Chat</div>
|
<div>Chat</div>
|
||||||
<q-space />
|
<q-space />
|
||||||
<q-btn
|
<q-btn
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
icon="close"
|
icon="close"
|
||||||
@click="toggleChat"
|
@click="toggleChat"
|
||||||
/>
|
/>
|
||||||
</q-bar>
|
</q-bar>
|
||||||
|
|
||||||
<q-card-section
|
<q-card-section
|
||||||
class="q-pa-none"
|
class="q-pa-none"
|
||||||
style="height: calc(100% - 50px);"
|
style="height: calc(100% - 50px);"
|
||||||
>
|
>
|
||||||
<ChatInterface
|
<ChatInterface
|
||||||
:messages="chatMessages"
|
:messages="chatMessages"
|
||||||
@send-message="handleSendMessage"
|
@send-message="handleSendMessage"
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-inner-loading :showing="isLoading">
|
<q-inner-loading :showing="isLoading">
|
||||||
<q-spinner-gears
|
<q-spinner-gears
|
||||||
size="50px"
|
size="50px"
|
||||||
color="primary"
|
color="primary"
|
||||||
/>
|
/>
|
||||||
</q-inner-loading>
|
</q-inner-loading>
|
||||||
<q-banner
|
<q-banner
|
||||||
v-if="chatError"
|
v-if="chatError"
|
||||||
inline-actions
|
inline-actions
|
||||||
class="text-white bg-red"
|
class="text-white bg-red"
|
||||||
>
|
>
|
||||||
{{ chatError }}
|
{{ chatError }}
|
||||||
<template #action>
|
<template #action>
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
color="white"
|
color="white"
|
||||||
label="Dismiss"
|
label="Dismiss"
|
||||||
@click="clearError"
|
@click="clearError"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</q-banner>
|
</q-banner>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
</q-layout>
|
</q-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'boot/axios';
|
import axios from 'boot/axios';
|
||||||
import { ref, computed } from 'vue'; // Import computed
|
import { ref, computed } from 'vue'; // Import computed
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useAuthStore } from 'stores/auth'; // Import the auth store
|
import { useAuthStore } from 'stores/auth'; // Import the auth store
|
||||||
import { useChatStore } from 'stores/chat'; // Adjust path as needed
|
import { useChatStore } from 'stores/chat'; // Adjust path as needed
|
||||||
import ChatInterface from 'components/ChatInterface.vue'; // Adjust path as needed
|
import ChatInterface from 'components/ChatInterface.vue'; // Adjust path as needed
|
||||||
import routes from '../router/routes'; // Import routes
|
import routes from '../router/routes'; // Import routes
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const leftDrawerOpen = ref(false);
|
const leftDrawerOpen = ref(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const authStore = useAuthStore(); // Use the auth store
|
const authStore = useAuthStore(); // Use the auth store
|
||||||
const chatStore = useChatStore();
|
const chatStore = useChatStore();
|
||||||
|
|
||||||
const fabOpen = ref(false); // Local state for FAB animation, not chat visibility
|
const fabOpen = ref(false); // Local state for FAB animation, not chat visibility
|
||||||
|
|
||||||
// Computed properties to get state from the store
|
// Computed properties to get state from the store
|
||||||
const isChatVisible = computed(() => chatStore.isChatVisible);
|
const isChatVisible = computed(() => chatStore.isChatVisible);
|
||||||
const chatMessages = computed(() => chatStore.chatMessages);
|
const chatMessages = computed(() => chatStore.chatMessages);
|
||||||
const isLoading = computed(() => chatStore.isLoading);
|
const isLoading = computed(() => chatStore.isLoading);
|
||||||
const chatError = computed(() => chatStore.error);
|
const chatError = computed(() => chatStore.error);
|
||||||
const isAuthenticated = computed(() => authStore.isAuthenticated); // Get auth state
|
const isAuthenticated = computed(() => authStore.isAuthenticated); // Get auth state
|
||||||
|
|
||||||
// Get the child routes of the main layout
|
// Get the child routes of the main layout
|
||||||
const mainLayoutRoutes = routes.find(r => r.path === '/')?.children || [];
|
const mainLayoutRoutes = routes.find(r => r.path === '/')?.children || [];
|
||||||
|
|
||||||
// Compute navigation items based on auth state and route meta
|
// Compute navigation items based on auth state and route meta
|
||||||
const navItems = computed(() =>
|
const navItems = computed(() =>
|
||||||
{
|
{
|
||||||
return mainLayoutRoutes.filter(route =>
|
return mainLayoutRoutes.filter(route =>
|
||||||
{
|
{
|
||||||
const navGroup = route.meta?.navGroup;
|
const navGroup = route.meta?.navGroup;
|
||||||
if (!navGroup) return false; // Only include routes with navGroup defined
|
if (!navGroup) return false; // Only include routes with navGroup defined
|
||||||
|
|
||||||
if (navGroup === 'always') return true;
|
if (navGroup === 'always') return true;
|
||||||
if (navGroup === 'auth' && isAuthenticated.value) return true;
|
if (navGroup === 'auth' && isAuthenticated.value) return true;
|
||||||
if (navGroup === 'noAuth' && !isAuthenticated.value) return true;
|
if (navGroup === 'noAuth' && !isAuthenticated.value) return true;
|
||||||
|
|
||||||
return false; // Exclude otherwise
|
return false; // Exclude otherwise
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Method to toggle chat visibility via the store action
|
// Method to toggle chat visibility via the store action
|
||||||
const toggleChat = () =>
|
const toggleChat = () =>
|
||||||
{
|
{
|
||||||
// Optional: Add an extra check here if needed, though hiding the button is primary
|
// Optional: Add an extra check here if needed, though hiding the button is primary
|
||||||
if (isAuthenticated.value)
|
if (isAuthenticated.value)
|
||||||
{
|
{
|
||||||
chatStore.toggleChat();
|
chatStore.toggleChat();
|
||||||
}
|
fabOpen.value = chatStore.isChatVisible;
|
||||||
};
|
}
|
||||||
|
};
|
||||||
// Method to send a message via the store action
|
|
||||||
const handleSendMessage = (messageContent) =>
|
// Method to send a message via the store action
|
||||||
{
|
const handleSendMessage = (messageContent) =>
|
||||||
chatStore.sendMessage(messageContent);
|
{
|
||||||
};
|
chatStore.sendMessage(messageContent);
|
||||||
|
};
|
||||||
// Method to clear errors in the store (optional)
|
|
||||||
const clearError = () =>
|
// Method to clear errors in the store (optional)
|
||||||
{
|
const clearError = () =>
|
||||||
chatStore.error = null; // Directly setting ref or add an action in store
|
{
|
||||||
};
|
chatStore.error = null; // Directly setting ref or add an action in store
|
||||||
function toggleLeftDrawer()
|
};
|
||||||
{
|
function toggleLeftDrawer()
|
||||||
leftDrawerOpen.value = !leftDrawerOpen.value;
|
{
|
||||||
}
|
leftDrawerOpen.value = !leftDrawerOpen.value;
|
||||||
|
}
|
||||||
async function logout()
|
|
||||||
{
|
async function logout()
|
||||||
try
|
{
|
||||||
{
|
try
|
||||||
await axios.post('/api/auth/logout');
|
{
|
||||||
authStore.logout(); // Use the store action to update state
|
await axios.post('/api/auth/logout');
|
||||||
// No need to manually push, router guard should redirect
|
authStore.logout(); // Use the store action to update state
|
||||||
// router.push({ name: 'login' });
|
// No need to manually push, router guard should redirect
|
||||||
}
|
// router.push({ name: 'login' });
|
||||||
catch (error)
|
}
|
||||||
{
|
catch (error)
|
||||||
console.error('Logout failed:', error);
|
{
|
||||||
|
console.error('Logout failed:', error);
|
||||||
$q.notify({
|
|
||||||
color: 'negative',
|
$q.notify({
|
||||||
message: 'Logout failed. Please try again.',
|
color: 'negative',
|
||||||
icon: 'report_problem'
|
message: 'Logout failed. Please try again.',
|
||||||
});
|
icon: 'report_problem'
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
<style scoped>
|
|
||||||
/* Add any specific styles for the layout or chat window here */
|
<style scoped>
|
||||||
.q-dialog .q-card {
|
/* Add any specific styles for the layout or chat window here */
|
||||||
overflow: hidden; /* Prevent scrollbars on the card itself */
|
.q-dialog .q-card {
|
||||||
}
|
overflow: hidden; /* Prevent scrollbars on the card itself */
|
||||||
</style>
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue