Added calender
This commit is contained in:
205
src/pages/service/ServiceHome.vue
Normal file
205
src/pages/service/ServiceHome.vue
Normal file
@@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<Header />
|
||||
<div class="flex">
|
||||
<div class="">
|
||||
<SideBar />
|
||||
</div>
|
||||
<div class=" w-full px-10 ">
|
||||
<div class="text-sm breadcrumbs mb-10">
|
||||
<ul>
|
||||
<li><router-link :to="{ name: 'home' }">Home</router-link></li>
|
||||
<li>Service Calls</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="flex text-2xl mb-5 font-bold">
|
||||
Upcoming Service Calls
|
||||
</div>
|
||||
|
||||
<div v-if="isLoading" class="text-center p-10">
|
||||
<p>Loading upcoming service calls...</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="services.length === 0" class="text-center p-10 bg-gray-100 rounded-md">
|
||||
<p>No upcoming service calls found.</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class=" bg-neutral">
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Scheduled Date</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Customer Name</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Address</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Service Type</th>
|
||||
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class=" divide-y bg-neutral">
|
||||
<tr v-for="service in services" :key="service.id" @click="openEditModal(service)" class="hover:bg-blue-600 hover:text-black cursor-pointer">
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ formatDate(service.scheduled_date) }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ service.customer_name }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ service.customer_address }}, {{ service.customer_town }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap font-medium" :style="{ color: getServiceTypeColor(service.type_service_call) }">
|
||||
{{ getServiceTypeName(service.type_service_call) }}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-normal text-sm text-gray-500">{{ service.description }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
|
||||
<ServiceEditModal
|
||||
v-if="selectedServiceForEdit"
|
||||
:service="selectedServiceForEdit"
|
||||
@close-modal="closeEditModal"
|
||||
@save-changes="handleSaveChanges"
|
||||
@delete-service="handleDeleteService"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import axios from 'axios';
|
||||
import authHeader from '../../services/auth.header';
|
||||
import Header from '../../layouts/headers/headerauth.vue';
|
||||
import SideBar from '../../layouts/sidebar/sidebar.vue';
|
||||
import Footer from '../../layouts/footers/footer.vue';
|
||||
import ServiceEditModal from './ServiceEditModal.vue';
|
||||
|
||||
interface ServiceCall {
|
||||
id: number;
|
||||
scheduled_date: string;
|
||||
customer_name: string;
|
||||
customer_address: string;
|
||||
customer_town: string;
|
||||
type_service_call: number;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ServiceHome',
|
||||
components: { Header, SideBar, Footer, ServiceEditModal },
|
||||
data() {
|
||||
return {
|
||||
user: null,
|
||||
services: [] as ServiceCall[],
|
||||
isLoading: true,
|
||||
selectedServiceForEdit: null as ServiceCall | null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.userStatus();
|
||||
this.fetchUpcomingServices();
|
||||
},
|
||||
methods: {
|
||||
async fetchUpcomingServices(): Promise<void> {
|
||||
this.isLoading = true;
|
||||
try {
|
||||
const path = import.meta.env.VITE_BASE_URL + '/service/upcoming';
|
||||
const response = await axios.get(path, {
|
||||
headers: authHeader(),
|
||||
withCredentials: true,
|
||||
});
|
||||
this.services = response.data;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch upcoming service calls:", error);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
userStatus() {
|
||||
let path = import.meta.env.VITE_BASE_URL + '/auth/whoami';
|
||||
axios({
|
||||
method: 'get',
|
||||
url: path,
|
||||
withCredentials: true,
|
||||
headers: authHeader(),
|
||||
})
|
||||
.then((response: any) => {
|
||||
if (response.data.ok) {
|
||||
this.user = response.data.user;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.user = null
|
||||
})
|
||||
},
|
||||
|
||||
// --- HELPER METHODS WITH IMPLEMENTATIONS RESTORED ---
|
||||
|
||||
formatDate(dateString: string): string {
|
||||
const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric' };
|
||||
// Adding a timeZone option helps prevent off-by-one-day errors
|
||||
return new Date(dateString).toLocaleDateString(undefined, { ...options, timeZone: 'UTC' });
|
||||
},
|
||||
|
||||
getServiceTypeName(typeId: number): string {
|
||||
const typeMap: { [key: number]: string } = {
|
||||
0: 'Tune-up',
|
||||
1: 'No Heat',
|
||||
2: 'Fix',
|
||||
3: 'Tank Install',
|
||||
4: 'Other',
|
||||
};
|
||||
return typeMap[typeId] || 'Unknown Service';
|
||||
},
|
||||
|
||||
getServiceTypeColor(typeId: number): string {
|
||||
const colorMap: { [key: number]: string } = {
|
||||
0: 'blue',
|
||||
1: 'red',
|
||||
2: 'green',
|
||||
3: '#B58900', // A darker yellow for text
|
||||
4: 'black',
|
||||
};
|
||||
return colorMap[typeId] || 'gray';
|
||||
},
|
||||
|
||||
// --- MODAL MANAGEMENT METHODS ---
|
||||
|
||||
openEditModal(service: ServiceCall) {
|
||||
this.selectedServiceForEdit = service;
|
||||
},
|
||||
closeEditModal() {
|
||||
this.selectedServiceForEdit = null;
|
||||
},
|
||||
async handleSaveChanges(updatedService: ServiceCall) {
|
||||
try {
|
||||
const path = `${import.meta.env.VITE_BASE_URL}/service/update/${updatedService.id}`;
|
||||
const response = await axios.put(path, updatedService, { headers: authHeader(), withCredentials: true });
|
||||
|
||||
if (response.data.ok) {
|
||||
const index = this.services.findIndex(s => s.id === updatedService.id);
|
||||
if (index !== -1) {
|
||||
this.services[index] = response.data.service;
|
||||
}
|
||||
this.closeEditModal();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to save changes:", error);
|
||||
alert("An error occurred while saving. Please check the console.");
|
||||
}
|
||||
},
|
||||
async handleDeleteService(serviceId: number) {
|
||||
try {
|
||||
const path = `${import.meta.env.VITE_BASE_URL}/service/delete/${serviceId}`;
|
||||
const response = await axios.delete(path, { headers: authHeader(), withCredentials: true });
|
||||
|
||||
if (response.data.ok) {
|
||||
this.services = this.services.filter(s => s.id !== serviceId);
|
||||
this.closeEditModal();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to delete service call:", error);
|
||||
alert("An error occurred while deleting. Please check the console.");
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user