Working log in/route guard

This commit is contained in:
2025-09-04 08:03:24 -04:00
parent 992a1a217d
commit dc1ee95827
37 changed files with 1283 additions and 1191 deletions

View File

@@ -11,18 +11,23 @@
<!-- Logo -->
<router-link :to="{ name: 'home' }" class="btn btn-ghost normal-case text-xl">
<img src="../../assets/images/1.png" alt="Company Logo" class="h-8 md:h-10 w-auto" />
Auburn Oil
</router-link>
</div>
<!-- Navbar Center Section (Desktop Search Bar) -->
<div class="navbar-center hidden lg:flex">
<!--
THIS IS THE ONLY CHANGE NEEDED ON THIS ENTIRE PAGE.
We are adding the @input event listener to trigger the search.
-->
<input
id="customer-search-input"
type="text"
placeholder="Search Customers..."
class="input input-bordered w-full max-w-xs"
placeholder="Search customers..."
v-model="searchStore.searchTerm"
@input="searchStore.fetchSearchResults"
class="input input-bordered"
@input="searchStore.debouncedSearch"
/>
</div>
@@ -34,8 +39,7 @@
</router-link>
<!-- User Dropdown -->
<!-- v-if="employee.id" only renders this block AFTER the API call is successful and an employee ID exists. -->
<div v-if="employee.id" class="dropdown dropdown-end">
<div v-if="user.user_id" class="dropdown dropdown-end">
<label tabindex="0" class="btn btn-ghost btn-circle avatar">
<div class="w-10 rounded-full bg-neutral text-neutral-content flex items-center justify-center">
<span class="text-lg font-bold">{{ userInitials }}</span>
@@ -45,7 +49,7 @@
<li class="p-2 font-semibold">{{ user.user_name }}</li>
<div class="divider my-0"></div>
<li>
<router-link :to="{ name: 'employeeProfile', params: { id: employee.id } }">
<router-link :to="{ name: 'employeeProfile', params: { id: user.user_id } }">
Profile
</router-link>
</li>
@@ -54,31 +58,29 @@
</div>
<!-- This provides the loading indicator while we wait for the API call to finish. -->
<div v-else class="px-4">
<span class="loading loading-spinner loading-sm"></span>
{{user}}
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import axios from 'axios'
import authHeader from '../../services/auth.header'
import { useSearchStore } from '../../stores/search' // Adjust path if needed
import { useAuthStore } from '../../stores/auth'
// Define the shape of your data for internal type safety
interface User {
user_name: string;
user_id: number;
}
interface Employee {
id: number;
}
export default defineComponent({
data() {
return {
// Initialize with empty objects to prevent template errors
employee: {} as Employee,
user: {} as User,
}
},
@@ -86,6 +88,7 @@ export default defineComponent({
computed: {
searchStore() {
return useSearchStore();
},
userInitials(): string {
if (!this.user || !this.user.user_name) return '';
@@ -97,32 +100,39 @@ export default defineComponent({
},
created() {
this.fetchUserData();
this.userStatus();
},
methods: {
fetchUserData() {
axios.get('/auth/whoami', { headers: authHeader() })
.then((response: any) => {
console.log("User Data Response from API:", response.data);
// This check is now more robust. It only checks for what it truly needs.
if (response.data && response.data.ok && response.data.employee && response.data.employee.id) {
this.user = response.data.user;
this.employee = response.data.employee;
} else {
console.error("API response was successful, but the expected employee data with an ID is missing.");
}
userStatus() {
let path = import.meta.env.VITE_BASE_URL + '/auth/whoami';
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.catch((error: any) => {
console.error("CRITICAL: Failed to fetch user data. The API call itself failed.", error);
});
},
.then((response: any) => {
console.log(this.user)
if (response.data.ok) {
this.user = response.data.user;
} else {
localStorage.removeItem('user');
this.$router.push('/login');
}
})
},
logout() {
console.log("Logging out...");
// Your full logout logic here
// Clear auth data
const authStore = useAuthStore();
authStore.clearAuth();
// Redirect to login
this.$router.push({ name: 'login' });
}
}
});
</script>
</script>

View File

@@ -1,24 +1,15 @@
<!-- sidebar.vue -->
<template>
<!--
The sidebar is now just the menu. The layout logic lives in App.vue.
This is much cleaner and works correctly with the mobile hamburger button.
-->
<ul class="menu p-4 w-80 min-h-full bg-base-100 text-base-content">
<!-- Logo at the top of the sidebar for mobile view -->
<li class="mb-4 lg:hidden">
<router-link :to="{ name: 'home' }">
<img src="../assets/images/1.png" alt="Company Logo" class="h-10 w-auto" />
</router-link>
</li>
<li>
<router-link :to="{ name: 'home' }" exact-active-class="active">
Home
<ul class="menu p-4 w-64 min-h-full bg-base-100 text-base-content">
<li class="mb-4 lg-hidden">
<router-link :to="{ name: 'home' }">
<img src="../../assets/images/1.png" alt="Company Logo" class="h-10 w-auto" />
</router-link>
</li>
<li><router-link :to="{ name: 'home' }" exact-active-class="active">Home</router-link></li>
<!-- Customer Section - Open by default -->
<!-- Customer Section -->
<li>
<details open>
<summary class="font-bold text-lg">Customer</summary>
@@ -28,7 +19,7 @@
</details>
</li>
<!-- Delivery Section - Open by default -->
<!-- Delivery Section -->
<li>
<details open>
<summary class="font-bold text-lg">Delivery</summary>
@@ -37,26 +28,26 @@
<li>
<router-link :to="{ name: 'deliveryOutForDelivery' }" exact-active-class="active">
Todays Deliveries
<span v-if="today_count > 0" class="badge badge-secondary">{{ today_count }}</span>
<span v-if="countsStore.today > 0" class="badge badge-secondary">{{ countsStore.today }}</span>
</router-link>
</li>
<li>
<router-link :to="{ name: 'deliveryTommorrow' }" exact-active-class="active">
Tomorrows Deliveries
<span v-if="tommorrow_count > 0" class="badge badge-secondary">{{ tommorrow_count }}</span>
<span v-if="countsStore.tomorrow > 0" class="badge badge-secondary">{{ countsStore.tomorrow }}</span>
</router-link>
</li>
<li>
<router-link :to="{ name: 'deliveryWaiting' }" exact-active-class="active">
Waiting Deliveries
<span v-if="waiting_count > 0" class="badge badge-info">{{ waiting_count }}</span>
<span v-if="countsStore.waiting > 0" class="badge badge-info">{{ countsStore.waiting }}</span>
</router-link>
</li>
<li><router-link :to="{ name: 'deliveryIssue' }" exact-active-class="active">Issue Tickets</router-link></li>
<li>
<router-link :to="{ name: 'deliveryPending' }" exact-active-class="active">
Pending Payment
<span v-if="pending_count > 0" class="badge badge-warning">{{ pending_count }}</span>
<span v-if="countsStore.pending > 0" class="badge badge-warning">{{ countsStore.pending }}</span>
</router-link>
</li>
<li><router-link :to="{ name: 'deliveryFinalized' }" exact-active-class="active">Finalized Tickets</router-link></li>
@@ -64,7 +55,7 @@
</details>
</li>
<!-- Service Section - Open by default -->
<!-- Service Section -->
<li>
<details open>
<summary class="font-bold text-lg">Service</summary>
@@ -73,7 +64,7 @@
<li>
<router-link :to="{ name: 'ServiceHome' }" exact-active-class="active">
Upcoming Service
<span v-if="upcoming_service_count > 0" class="badge badge-info">{{ upcoming_service_count }}</span>
<span v-if="countsStore.upcoming_service > 0" class="badge badge-info">{{ countsStore.upcoming_service }}</span>
</router-link>
</li>
<li><router-link :to="{ name: 'ServicePast' }" exact-active-class="active">Past Service</router-link></li>
@@ -81,7 +72,7 @@
</details>
</li>
<!-- Automatics Section - Now has its own header -->
<!-- Automatics Section -->
<li>
<details>
<summary class="font-bold text-lg">Automatics</summary>
@@ -89,19 +80,18 @@
<li>
<router-link :to="{ name: 'auto' }" exact-active-class="active">
All Automatics
<span v-if="automatic_count > 0" class="badge badge-info">{{ automatic_count }}</span>
<span v-if="countsStore.automatic > 0" class="badge badge-info">{{ countsStore.automatic }}</span>
</router-link>
</li>
</ul>
</details>
</li>
<!-- Admin Section - Closed by default and contains Employees -->
<!-- Admin Section remains the same -->
<li>
<details>
<summary class="font-bold text-lg">Admin</summary>
<ul>
<!-- Employees is now here -->
<li><router-link :to="{ name: 'employee' }" exact-active-class="active">Employees</router-link></li>
<li><router-link :to="{ name: 'oilprice' }" exact-active-class="active">Oil Pricing</router-link></li>
<li><router-link :to="{ name: 'promo' }" exact-active-class="active">Promos</router-link></li>
@@ -112,132 +102,16 @@
</ul>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import axios from 'axios';
import authHeader from '../../services/auth.header';
<script setup lang="ts">
import { onMounted } from 'vue';
import { useCountsStore } from '../../stores/counts'; // Adjust path if needed
export default defineComponent({
name: "SideBar",
mounted() {
this.getUpcomingServiceCount();
this.getTodayCount();
this.getTommorrowCount();
this.getWaitingCount();
this.getPendingCount();
this.getAutoCount();
this.updatestatus();
this.updateautos();
this.updatetemp();
},
data() {
return {
upcoming_service_count: 0,
waiting_count: 0,
today_count: 0,
tommorrow_count: 0,
pending_count: 0,
automatic_count: 0,
};
},
// Get a reference to our new store
const countsStore = useCountsStore();
methods: {
getUpcomingServiceCount() {
let path = import.meta.env.VITE_BASE_URL + '/service/upcoming/count';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.upcoming_service_count = response.data.count;
}).catch((error: any) => {
console.error("Failed to get upcoming service count:", error);
this.upcoming_service_count = 0;
});
},
updatestatus() {
let path = import.meta.env.VITE_BASE_URL + '/delivery/updatestatus';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
if (response.data.update)
console.log("Updated Status of Deliveries")
}).catch((error: any) => console.error("Update status failed:", error));
},
updatetemp() {
let path = import.meta.env.VITE_AUTO_URL + '/main/temp';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
if (response.data.ok)
console.log("Updated Temp")
}).catch((error: any) => console.error("Update temp failed:", error));
},
updateautos() {
let path = import.meta.env.VITE_AUTO_URL + '/main/update';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
if (response.data.ok)
console.log("Updated Autos")
}).catch((error: any) => console.error("Update autos failed:", error));
},
getAutoCount() {
let path = import.meta.env.VITE_BASE_URL + '/deliverystatus/count/automatic';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.automatic_count = response.data.count
}).catch((error: any) => console.error("Get auto count failed:", error));
},
getTodayCount() {
let path = import.meta.env.VITE_BASE_URL + '/deliverystatus/count/today';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.today_count = response.data.count
}).catch((error: any) => console.error("Get today count failed:", error));
},
getTommorrowCount() {
let path = import.meta.env.VITE_BASE_URL + '/deliverystatus/count/tommorrow';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.tommorrow_count = response.data.count
}).catch((error: any) => console.error("Get tomorrow count failed:", error));
},
getPendingCount() {
let path = import.meta.env.VITE_BASE_URL + '/deliverystatus/count/pending';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.pending_count = response.data.count
}).catch((error: any) => console.error("Get pending count failed:", error));
},
getWaitingCount() {
let path = import.meta.env.VITE_BASE_URL + '/deliverystatus/count/waiting';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.waiting_count = response.data.count
}).catch((error: any) => console.error("Get waiting count failed:", error));
},
},
// When the sidebar is first mounted, fetch all the counts
onMounted(() => {
countsStore.fetchSidebarCounts();
// You can remove your other update functions if their logic is now handled elsewhere
});
</script>