first commit

This commit is contained in:
2024-02-28 16:03:19 -05:00
commit 54ee44ba66
84 changed files with 15919 additions and 0 deletions

View File

@@ -0,0 +1,400 @@
<template>
<Header />
<div class="flex">
<div class="">
<SideBar />
</div>
<div class=" w-full px-10">
<div class="text-sm breadcrumbs">
<ul>
<li>
<router-link :to="{ name: 'home' }">
Home
</router-link>
</li>
<li>
<router-link :to="{ name: 'customer' }">
Customers
</router-link>
</li>
</ul>
</div>
<div class="grid grid-cols-1 rounded-md p-6 ">
<div class="grid grid-cols-12">
<div class="col-span-6 bg-neutral p-5">
<div class="grid grid-cols-12">
<div class="col-span-12 font-bold flex pb-5 text-lg">{{customer.account_number}}</div>
<div class="col-span-12 font-bold flex">
{{ customer.customer_first_name }}
{{ customer.customer_last_name }}
</div>
<div class="col-span-12 font-bold flex">
<div class="pr-2">
{{ customer.customer_town }},
</div>
<div class="pr-2">
<div v-if="customer.customer_state == 0">Massachusetts</div>
<div v-else-if="customer.customer_state == 1">Rhode Island</div>
<div v-else-if="customer.customer_state == 2">New Hampshire</div>
<div v-else-if="customer.customer_state == 3">Maine</div>
<div v-else-if="customer.customer_state == 4">Vermont</div>
<div v-else-if="customer.customer_state == 5">Maine</div>
<div v-else-if="customer.customer_state == 6">New York</div>
<div v-else>Unknown state</div>
</div>
<div class="pr-2">
{{ customer.customer_zip }}
</div>
</div>
<div class="col-span-12 font-bold flex" v-if="customer.customer_apt !== 'None'">
{{ customer.customer_apt }}
</div>
<div class="col-span-12 font-bold flex">
<div v-if="customer.customer_home_type == 0">Residential</div>
<div v-else-if="customer.customer_home_type == 1">apartment</div>
<div v-else-if="customer.customer_home_type == 2">condo</div>
<div v-else-if="customer.customer_home_type == 3">commercial</div>
<div v-else-if="customer.customer_home_type == 4">business</div>
<div v-else-if="customer.customer_home_type == 5">construction</div>
<div v-else-if="customer.customer_home_type == 6">container</div>
</div>
<div class="col-span-12 font-bold flex">
{{ customer.customer_phone_number }}
</div>
</div>
</div>
</div>
<form class="rounded-md px-8 pt-6 pb-8 mb-4 w-full" enctype="multipart/form-data" @submit.prevent="onSubmit">
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0">
<div class="flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Service Category</label>
<select class="select select-bordered w-full max-w-xs" aria-label="Default select example"
id="customer_state" v-model="CreateServiceOrderForm.basicInfo.type_of_service">
<option class="text-white" v-for="(cat, index) in serviceList" :key="index" :value="cat['value']">
{{ cat['text'] }}
</option>
</select>
<span v-if="v$.CreateServiceOrderForm.basicInfo.type_of_service.$error" class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.type_of_service.$errors[0].$message }}
</span>
</div>
<label class="form-control w-full max-w-xs">
<div class="label">
<span class="label-text">Subject</span>
</div>
<input type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs"
v-model="CreateServiceOrderForm.basicInfo.dispatcher_subject_taken" />
</label>
<span v-if="v$.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken.$error"
class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken.$errors[0].$message }}
</span>
</div>
<div class="mb-4">
<label class="form-control">
<div class="label">
<span class="label-text">What is the issue</span>
</div>
<textarea class="textarea textarea-bordered h-24" placeholder="Describe the issue for the service tech .."
v-model="CreateServiceOrderForm.basicInfo.dispatcher_notes_taken"></textarea>
</label>
<span v-if="v$.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken.$error"
class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken.$errors[0].$message }}
</span>
</div>
<div class="mb-4">
<label class="block text-white text-sm font-bold mb-2">Expected Service Date </label>
<input v-model="CreateServiceOrderForm.basicInfo.date_scheduled" class="input input-bordered w-full max-w-xs"
id="title" type="date" min="2023-01-01" max="2030-01-01" />
<span v-if="v$.CreateServiceOrderForm.basicInfo.date_scheduled.$error" class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.date_scheduled.$errors[0].$message }}
</span>
</div>
<div class="flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Service Tech</label>
<select class="select select-bordered w-full max-w-xs" aria-label="Default select example" id="customer_state"
v-model="CreateServiceOrderForm.basicInfo.service_tech">
<option class="text-white" v-for="(tech, index) in serviceTechsList" :key="index" :value="tech['id']">
{{ tech['employee_last_name'] }}
</option>
</select>
<span v-if="v$.CreateServiceOrderForm.basicInfo.service_tech.$error" class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.service_tech.$errors[0].$message }}
</span>
</div>
<div class="bg-neutral">
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0 gap-10">
<label class="block text-white text-sm font-bold cursor-pointer label">Cash</label>
<input v-model="CreateServiceOrderForm.basicInfo.cash"
class="checkbox"
id="cash"
type="checkbox"/>
</div>
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0 gap-10">
<label class="block text-white text-sm font-bold cursor-pointer label">Credit </label>
<input v-model="CreateServiceOrderForm.basicInfo.credit"
class="checkbox"
id="Credit"
type="checkbox"/>
</div>
<div class="flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Customer Cards Payment</label>
<select
class="select select-bordered w-full max-w-xs"
aria-label="Default select example" id="userCards"
v-model="CreateServiceOrderForm.basicInfo.userCards">
<option class="text-white" v-for="(card, index) in userCards"
:key="index"
:value="card['id']">
{{ card['type_of_card'] }} {{ card['card_number'] }}
</option>
</select>
</div>
</div>
<div class="col-span-12 md:col-span-12 flex mt-5 mb-5">
<button class="btn">
Create Service Call
</button>
</div>
</form>
</div>
</div>
</div>
<Footer />
</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 useValidate from "@vuelidate/core";
import {notify} from "@kyvg/vue3-notification"
import {minLength, required} from "@vuelidate/validators";
export default defineComponent({
name: 'ServiceCreate',
components: {
Header,
SideBar,
Footer,
},
data() {
return {
v$: useValidate(),
user: {
id: 0,
user_id: 0,
},
serviceList: [],
serviceTechsList: [],
userCards: [],
service_id: 0,
CreateServiceOrderForm: {
basicInfo: {
type_of_service: '',
dispatcher_notes_taken: '',
dispatcher_subject_taken: '',
date_scheduled: '',
service_tech: '',
userCards: [],
credit: false,
cash: false,
credit_card_id: 0,
},
},
customer: {
id: 0,
user_id: 0,
customer_first_name: '',
customer_last_name: '',
customer_town: '',
customer_state: 0,
customer_zip: '',
customer_apt: '',
customer_home_type: 0,
customer_phone_number: '',
account_number: '',
},
}
},
validations() {
return {
CreateServiceOrderForm: {
basicInfo: {
type_of_service: {required},
dispatcher_notes_taken: {required, minLength: minLength(10)},
dispatcher_subject_taken: {required, minLength: minLength(10)},
date_scheduled: {required},
service_tech: {required},
},
},
};
},
created() {
this.userStatus()
this.getServiceTypeList()
this.getServiceTechsList()
},
watch: {
$route() {
this.getCustomer(this.$route.params.id);
this.getPaymentCards(this.$route.params.id);
},
},
mounted() {
this.getCustomer(this.$route.params.id)
this.getPaymentCards(this.$route.params.id);
},
methods: {
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;
}
})
},
getCustomer(user_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/customer/" + user_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.customer = response.data;
console.log(this.customer)
})
.catch(() => {
notify({
title: "Error",
text: "Could not find customer",
type: "error",
});
});
},
getPaymentCards(user_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/payment/cards/"+ user_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.userCards = response.data;
})
.catch(() => {
});
},
CreateServiceOrder(payload: {
dispatcher_notes_taken: string,
dispatcher_subject_taken: string,
date_scheduled: string,
type_of_service: string,
dispatcher_id: number,
cash: boolean,
credit: boolean,
credit_card_id: any,
}) {
let path = import.meta.env.VITE_BASE_URL + "/service/create/" + this.customer.id;
axios({
method: "post",
url: path,
data: payload,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data.ok) {
this.service_id = response.data.service_id
this.$router.push({name: "payService", params: { id: this.service_id }});
}
if (response.data.error) {
}
})
},
onSubmit() {
let payload = {
dispatcher_notes_taken: this.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken,
dispatcher_subject_taken: this.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken,
date_scheduled: this.CreateServiceOrderForm.basicInfo.date_scheduled,
type_of_service: this.CreateServiceOrderForm.basicInfo.type_of_service,
dispatcher_id: this.user.user_id,
cash: this.CreateServiceOrderForm.basicInfo.cash,
credit: this.CreateServiceOrderForm.basicInfo.credit,
credit_card_id: this.CreateServiceOrderForm.basicInfo.userCards,
};
this.CreateServiceOrder(payload);
},
getServiceTypeList() {
let path = import.meta.env.VITE_BASE_URL + "/query/servicetype";
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
this.serviceList = response.data;
})
.catch(() => {});
},
getServiceTechsList() {
let path = import.meta.env.VITE_BASE_URL + "/employee/techs";
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
this.serviceTechsList = response.data;
})
.catch(() => {
});
},
},
})
</script>
<style scoped></style>

501
src/pages/service/edit.vue Normal file
View File

@@ -0,0 +1,501 @@
<template>
<Header/>
<div class="flex">
<div class="">
<SideBar/>
</div>
<div class=" w-full px-10">
<div class="text-sm breadcrumbs">
<ul>
<li>
<router-link :to="{ name: 'home' }">
Home
</router-link>
</li>
<li>
<router-link :to="{ name: 'customer' }">
Customers
</router-link>
</li>
</ul>
</div>
<div class="grid grid-cols-1 rounded-md p-6 ">
<div class="text-[24px]">Edit Service Call
</div>
<div class="grid grid-cols-12">
<div class="col-span-6 bg-neutral p-5">
<div class="grid grid-cols-12">
<div class="col-span-12 font-bold flex">
{{ customer.customer_first_name }}
{{ customer.customer_last_name }}
</div>
<div class="col-span-12
font-bold flex">
<div class="pr-2">
{{ customer.customer_town }},
</div>
<div class="pr-2">
<div v-if="customer.customer_state == 0">Massachusetts</div>
<div v-else-if="customer.customer_state == 1">Rhode Island</div>
<div v-else-if="customer.customer_state == 2">New Hampshire</div>
<div v-else-if="customer.customer_state == 3">Maine</div>
<div v-else-if="customer.customer_state == 4">Vermont</div>
<div v-else-if="customer.customer_state == 5">Maine</div>
<div v-else-if="customer.customer_state == 6">New York</div>
<div v-else>Unknown state</div>
</div>
<div class="pr-2">
{{ customer.customer_zip }}
</div>
</div>
<div class="col-span-12 font-bold flex" v-if="customer.customer_apt !== 'None'">
{{ customer.customer_apt }}
</div>
<div class="col-span-12 font-bold flex">
<div v-if="customer.customer_home_type == 0">Residential</div>
<div v-else-if="customer.customer_home_type == 1">apartment</div>
<div v-else-if="customer.customer_home_type == 2">condo</div>
<div v-else-if="customer.customer_home_type == 3">commercial</div>
<div v-else-if="customer.customer_home_type == 4">business</div>
<div v-else-if="customer.customer_home_type == 5">construction</div>
<div v-else-if="customer.customer_home_type == 6">container</div>
</div>
<div class="col-span-12 font-bold flex">
{{ customer.customer_phone_number }}
</div>
</div>
</div>
</div>
<form class="rounded-md px-8 pt-6 pb-8 mb-4 w-full" enctype="multipart/form-data" @submit.prevent="onSubmit">
<div class="bg-neutral">
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0 gap-10">
<label class="block text-white text-sm font-bold cursor-pointer label">Cash</label>
<input v-model="CreateServiceOrderForm.basicInfo.cash"
class="checkbox"
id="cash"
type="checkbox"/>
</div>
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0 gap-10">
<label class="block text-white text-sm font-bold cursor-pointer label">Credit </label>
<input v-model="CreateServiceOrderForm.basicInfo.card"
class="checkbox"
id="Credit"
type="checkbox"/>
</div>
<div class="flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Customer Cards Payment</label>
<select
class="select select-bordered w-full max-w-xs"
aria-label="Default select example" id="userCards"
v-model="CreateServiceOrderForm.basicInfo.userCards">
<option class="text-white" v-for="(card, index) in userCards"
:key="index"
:value="card['id']">
{{ card['type_of_card'] }} {{ card['card_number'] }}
</option>
</select>
</div>
</div>
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0">
<div class="flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Service Category</label>
<select class="select select-bordered w-full max-w-xs" aria-label="Default select example"
id="customer_state" v-model="CreateServiceOrderForm.basicInfo.type_of_service">
<option class="text-white" v-for="(cat, index) in serviceList" :key="index" :value="cat['value']">
{{ cat['text'] }}
</option>
</select>
<span v-if="v$.CreateServiceOrderForm.basicInfo.type_of_service.$error" class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.type_of_service.$errors[0].$message }}
</span>
</div>
<label class="form-control w-full max-w-xs">
<div class="label">
<span class="label-text">Subject</span>
</div>
<input type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs"
v-model="CreateServiceOrderForm.basicInfo.dispatcher_subject_taken"/>
</label>
<span v-if="v$.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken.$error"
class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken.$errors[0].$message }}
</span>
</div>
<div class="mb-4">
<label class="form-control">
<div class="label">
<span class="label-text">What is the issue</span>
</div>
<textarea class="textarea textarea-bordered h-24" placeholder="Describe the issue for the service tech .."
v-model="CreateServiceOrderForm.basicInfo.dispatcher_notes_taken"></textarea>
</label>
<span v-if="v$.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken.$error"
class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken.$errors[0].$message }}
</span>
</div>
<div class="mb-4">
<label class="block text-white text-sm font-bold mb-2">Expected Service Date </label>
<input v-model="CreateServiceOrderForm.basicInfo.date_scheduled"
class="input input-bordered w-full max-w-xs"
id="title" type="date" min="2023-01-01" max="2030-01-01"/>
<span v-if="v$.CreateServiceOrderForm.basicInfo.date_scheduled.$error" class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.date_scheduled.$errors[0].$message }}
</span>
</div>
<div class="flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Service Tech</label>
<select class="select select-bordered w-full max-w-xs" aria-label="Default select example"
id="customer_state"
v-model="CreateServiceOrderForm.basicInfo.service_tech_id">
<option class="text-white" v-for="(tech, index) in serviceTechsList" :key="index" :value="tech['id']">
{{ tech['employee_last_name'] }}
</option>
</select>
<span v-if="v$.CreateServiceOrderForm.basicInfo.service_tech_id.$error" class="text-red-600 text-center">
{{ v$.CreateServiceOrderForm.basicInfo.type_of_service.$errors[0].$message }}
</span>
</div>
<div class="col-span-12 md:col-span-12 flex mt-5 mb-5">
<button class="btn">
Edit Service Call
</button>
</div>
</form>
</div>
</div>
</div>
<Footer/>
</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 useValidate from "@vuelidate/core";
import {notify} from "@kyvg/vue3-notification"
import {minLength, required} from "@vuelidate/validators";
export default defineComponent({
name: 'ServiceEdit',
components: {
Header,
SideBar,
Footer,
},
data() {
return {
v$: useValidate(),
user: {
id: 0
},
serviceList: [],
serviceTechsList: [],
userCards: [],
userCard: {
date_added: '',
user_id: '',
card_number: '',
last_four_digits: '',
name_on_card: '',
expiration_month: '',
expiration_year: '',
type_of_card: '',
security_number: '',
accepted_or_declined: '',
main_card: '',
},
customer: {
id: 0,
user_id: 0,
customer_first_name: '',
customer_last_name: '',
customer_town: '',
customer_state: 0,
customer_zip: '',
customer_apt: '',
customer_home_type: 0,
customer_phone_number: '',
},
serviceCall: {
id: 0,
tech_id: 0,
customer_id: 0,
type_of_service: 0,
dispatcher_notes_taken: '',
dispatcher_subject_taken: '',
date_scheduled: '',
payment_type: 0,
payment_card_id: 0,
same_day: 0,
},
CreateServiceOrderForm: {
basicInfo: {
type_of_service: '',
dispatcher_notes_taken: '',
dispatcher_subject_taken: '',
date_scheduled: '',
service_tech_id: '',
userCards: [],
credit_card_id: 0,
cash: false,
card: false,
},
},
}
},
validations() {
return {
CreateServiceOrderForm: {
basicInfo: {
type_of_service: {required},
dispatcher_notes_taken: {required, minLength: minLength(10)},
dispatcher_subject_taken: {required, minLength: minLength(10)},
date_scheduled: {required},
service_tech_id: {required},
},
},
};
},
created() {
this.userStatus()
this.getServiceTypeList()
this.getServiceTechsList()
},
watch: {
$route() {
this.getServiceCall(this.$route.params.id);
this.getServiceCallNotes(this.$route.params.id)
},
},
mounted() {
this.getServiceCall(this.$route.params.id)
this.getServiceCallNotes(this.$route.params.id)
this.getServiceTechsList()
},
methods: {
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;
this.user.id = response.data.user_id;
}
})
},
getCustomer(user_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/customer/" + user_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.customer = response.data;
this.getPaymentCards(this.serviceCall.customer_id);
if (this.serviceCall.payment_type == 1) {
this.getPaymentCard(this.serviceCall.payment_card_id)
}
if (this.serviceCall.payment_type == 2) {
this.getPaymentCard(this.serviceCall.payment_card_id)
}
})
.catch(() => {
notify({
title: "Error",
text: "Could not find customer",
type: "error",
});
});
},
getPaymentCard(card_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/payment/card/" + card_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.userCard = response.data;
this.CreateServiceOrderForm.basicInfo.userCards = response.data.id
})
.catch(() => {
});
},
getPaymentCards(user_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/payment/cards/" + user_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.userCards = response.data;
})
.catch(() => {
});
},
// gets the item from paramater router
getServiceCall(serviceid: any) {
let path = import.meta.env.VITE_BASE_URL + "/service/" + serviceid;
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data) {
this.CreateServiceOrderForm.basicInfo.type_of_service = response.data.service_type;
this.CreateServiceOrderForm.basicInfo.date_scheduled = response.data.scheduled_date;
this.CreateServiceOrderForm.basicInfo.service_tech_id = response.data.tech_id;
this.CreateServiceOrderForm.basicInfo.date_scheduled = response.data.scheduled_date;
this.serviceCall = response.data
if (response.data.payment_type == 0) {
this.CreateServiceOrderForm.basicInfo.card = false
this.CreateServiceOrderForm.basicInfo.cash = true
}
if (response.data.payment_type == 1) {
this.CreateServiceOrderForm.basicInfo.card = true
this.CreateServiceOrderForm.basicInfo.cash = false
}
if (response.data.payment_type == 2) {
this.CreateServiceOrderForm.basicInfo.card = true
this.CreateServiceOrderForm.basicInfo.cash = true
}
this.getCustomer(this.serviceCall.customer_id);
}
})
},
getServiceCallNotes(serviceid: any) {
let path = import.meta.env.VITE_BASE_URL + "/service/call/notes/" + serviceid;
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data) {
this.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken = response.data.dispatcher_notes;
this.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken = response.data.dispatcher_subject;
}
})
},
EditServiceOrder(payload: {
dispatcher_notes_taken: string;
dispatcher_subject_taken: string;
date_scheduled: string;
type_of_service: string,
tech_id: number,
cash: boolean,
credit: boolean,
credit_card_id: any,
}) {
let path = import.meta.env.VITE_BASE_URL + "/service/edit/" + this.serviceCall.id;
axios({
method: "put",
url: path,
data: payload,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data.ok) {
this.$router.push({name: "serviceCall", params: { id: this.serviceCall.id }});
}
if (response.data.error) {
this.$router.push("/");
}
})
},
onSubmit() {
let payload = {
dispatcher_notes_taken: this.CreateServiceOrderForm.basicInfo.dispatcher_notes_taken,
dispatcher_subject_taken: this.CreateServiceOrderForm.basicInfo.dispatcher_subject_taken,
date_scheduled: this.CreateServiceOrderForm.basicInfo.date_scheduled,
type_of_service: this.CreateServiceOrderForm.basicInfo.type_of_service,
tech_id: this.serviceCall.tech_id,
cash: this.CreateServiceOrderForm.basicInfo.cash,
credit: this.CreateServiceOrderForm.basicInfo.card,
credit_card_id: this.CreateServiceOrderForm.basicInfo.userCards,
};
this.EditServiceOrder(payload);
},
getServiceTypeList() {
let path = import.meta.env.VITE_BASE_URL + "/query/servicetype";
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
this.serviceList = response.data;
})
.catch(() => {
});
},
getServiceTechsList() {
let path = import.meta.env.VITE_BASE_URL + "/employee/techs";
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
this.serviceTechsList = response.data;
})
.catch(() => {
});
},
},
})
</script>
<style scoped></style>

216
src/pages/service/home.vue Normal file
View File

@@ -0,0 +1,216 @@
<template>
<Header/>
<div class="flex">
<div class="">
<SideBar/>
</div>
<div class=" w-full px-10 ">
<div class="text-sm breadcrumbs">
<ul>
<li>
<router-link :to="{ name: 'home' }">
Home
</router-link>
</li>
</ul>
</div>
<div class="flex justify-end">
</div>
<div class="overflow-x-auto">
<div class="flex start">Service Calls</div>
<table class="table">
<!-- head -->
<thead>
<tr>
<th>Customer Name</th>
<th>Scheduled Date</th>
<th>Status</th>
<th>Town</th>
<th>Service Type</th>
<th>Initial Call</th>
<th>Tech Name</th>
<th>Payment Type</th>
</tr>
</thead>
<tbody>
<!-- row 1 -->
<tr v-for="service in service_calls" :key="service['id']">
<td>
<router-link :to="{ name: 'customerProfile', params: { id: person['id'] } }">
{{ person['customer_first_name'] }} {{ person['customer_last_name'] }}
</router-link>
</td>
<td>
{{ service['scheduled_date'] }}
</td>
<td>
<div v-if="service['status'] == 0">Waiting/not paid</div>
<div v-else-if="service['status'] == 1">Paid /waiting</div>
<div v-else-if="service['status'] == 2">Scheduled Today</div>
<div v-else-if="service['status'] == 3">Completed/Unpaid</div>
<div v-else-if="service['status'] == 4">Completed/Paid</div>
<div v-else></div>
</td>
<td>
{{ service['customer_town'] }}
</td>
<td>
<div v-if="service['service_type'] == 0">General</div>
<div v-else-if="service['service_type'] == 1">Cleaning / Tuneup</div>
<div v-else-if="service['service_type'] == 2">No Heat</div>
<div v-else-if="service['service_type'] == 3">Install</div>
<div v-else-if="service['service_type'] == 4">Call Back</div>
<div v-else-if="service['service_type'] == 5">Quote</div>
<div v-else-if="service['service_type'] == 6" class="text-red-700 font-bold">Emergency</div>
<div v-else></div>
</td>
<td>
{{ service['when_called'] }}
</td>
<td>
{{ service['tech_first_name'] }} {{ service['tech_last_name'] }}
</td>
<td>
<div v-if="service['payment_type'] == 0">Cash C.O.D</div>
<div v-else-if="service['payment_type'] == 1">Credit</div>
<div v-else-if="service['payment_type'] == 2">Stripe</div>
<div v-else-if="service['payment_type'] == 3">Cash/Credit</div>
<div v-else></div>
</td>
<td class="flex gap-5">
<router-link :to="{ name: 'serviceCall', params: { id: service['id'] } }">
<button class="btn">View</button>
</router-link>
<router-link :to="{ name: 'serviceEdit', params: { id: service['id'] } }">
<button class="btn">Edit</button>
</router-link>
<button @click.prevent="deleteCall(service['id'])" class="btn">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="flex justify-center" v-if="recordsLength > 9">
<pagination @paginate="getPage" :records="recordsLength" v-model="page" :per-page="perPage" :options="options">
</pagination>
<div class="flex justify-center mb-10"> {{ recordsLength }} items Found</div>
</div>
</div>
</div>
<Footer/>
</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 PaginationComp from '../../components/pagination.vue'
import SideBar from '../../layouts/sidebar/sidebar.vue'
import Footer from '../../layouts/footers/footer.vue'
import {notify} from "@kyvg/vue3-notification";
export default defineComponent({
name: 'ServiceCall',
components: {
Header,
SideBar,
Footer,
},
data() {
return {
token: null,
user: null,
service_calls: [],
page: 1,
perPage: 50,
recordsLength: 0,
options: {
edgeNavigation: false,
format: false,
template: PaginationComp
}
}
},
created() {
this.userStatus()
},
mounted() {
this.getPage(this.page)
},
methods: {
getPage: function (page: any) {
// we simulate an api call that fetch the records from a backend
this.service_calls = [];
this.get_service_call(page)
},
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
})
},
get_service_call(page: any) {
let path = import.meta.env.VITE_BASE_URL + '/service/all/' + page;
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.service_calls = response.data
})
},
deleteCall(service_id: any) {
let path = import.meta.env.VITE_BASE_URL + '/service/delete/' + service_id;
axios({
method: 'delete',
url: path,
headers: authHeader(),
}).then((response: any) => {
if (response.data.ok) {
notify({
title: "Success",
text: "deleted service order",
type: "success",
});
this.getPage(this.page)
} else {
notify({
title: "Failure",
text: "error deleting service order",
type: "success",
});
}
})
},
},
})
</script>
<style scoped></style>

View File

@@ -0,0 +1,32 @@
import ServiceHome from '../service/home.vue';
import ServiceCreate from '../service/create.vue';
import ServiceEdit from '../service/edit.vue';
import ServiceCall from '../service/view.vue';
const serviceRoutes = [
{
path: '/service',
name: 'service',
component: ServiceHome,
},
{
path: '/service/:id',
name: 'serviceCall',
component: ServiceCall,
},
{
path: '/service/create/:id',
name: 'serviceCreate',
component: ServiceCreate,
},
{
path: '/service/edit/:id',
name: 'serviceEdit',
component: ServiceEdit,
},
]
export default serviceRoutes
//sourceMappingURL=index.ts.map

423
src/pages/service/view.vue Normal file
View File

@@ -0,0 +1,423 @@
<template>
<Header/>
<div class="flex">
<div class="">
<SideBar/>
</div>
<div class=" w-full px-10">
<div class="text-sm breadcrumbs">
<ul>
<li>
<router-link :to="{ name: 'home' }">
Home
</router-link>
</li>
<li>
<router-link :to="{ name: 'service' }">
Service Home
</router-link>
</li>
</ul>
</div>
<div class="grid grid-cols-1 rounded-md pb-5">
<div class="text-[24px]">
View Service Call # {{ serviceCall.id }}
</div>
<div class="grid grid-cols-12">
<div class="col-span-6">
<div class="col-span-12 font-bold">
Customer
</div>
<div class="col-span-6 bg-neutral p-5">
<div class="grid grid-cols-12">
<div class="col-span-12 font-bold flex">
{{ serviceCall.customer_first_name }}
{{ serviceCall.customer_last_name }}
</div>
<div class="col-span-12 font-bold flex">
<div class="pr-2">
{{ customer.customer_town }},
</div>
<div class="pr-2">
<div v-if="customer.customer_state == 0">Massachusetts</div>
<div v-else-if="customer.customer_state == 1">Rhode Island</div>
<div v-else-if="customer.customer_state == 2">New Hampshire</div>
<div v-else-if="customer.customer_state == 3">Maine</div>
<div v-else-if="customer.customer_state == 4">Vermont</div>
<div v-else-if="customer.customer_state == 5">Connecticut</div>
<div v-else-if="customer.customer_state == 6">New York</div>
<div v-else>Unknown state</div>
</div>
<div class="pr-2">
{{ customer.customer_zip }}
</div>
</div>
<div class="col-span-12 font-bold flex" v-if="customer.customer_apt !== 'None'">
{{ customer.customer_apt }}
</div>
<div class="col-span-12 font-bold flex">
<div v-if="customer.customer_home_type == 0">Residential</div>
<div v-else-if="customer.customer_home_type == 1">apartment</div>
<div v-else-if="customer.customer_home_type == 2">condo</div>
<div v-else-if="customer.customer_home_type == 3">commercial</div>
<div v-else-if="customer.customer_home_type == 4">business</div>
<div v-else-if="customer.customer_home_type == 5">construction</div>
<div v-else-if="customer.customer_home_type == 6">container</div>
</div>
<div class="col-span-12 font-bold flex">
{{ customer.customer_phone_number }}
</div>
</div>
</div>
</div>
<div class="col-span-6 ">
<div class="flex justify-end" v-if="serviceCall.id ">
<router-link :to="{ name: 'serviceEdit', params: { id: serviceCall.id } }">
<button class="btn">Edit Service Call</button>
</router-link>
</div>
</div>
</div>
</div>
<div class="col-span-6">
<div class="col-span-12 font-bold">
Service Status
</div>
<div class="grid grid-cols-12 bg-neutral p-5">
<div class="col-span-12 font-bold">
Service Category
</div>
<div class="col-span-12">
<div v-if="serviceCall.service_type == 0">General</div>
<div v-else-if="serviceCall.service_type == 1">Cleaning / Tuneup</div>
<div v-else-if="serviceCall.service_type == 2">No Heat</div>
<div v-else-if="serviceCall.service_type == 3">Install</div>
<div v-else-if="serviceCall.service_type == 4">Call Back</div>
<div v-else-if="serviceCall.service_type == 5">Quote</div>
<div v-else-if="serviceCall.service_type == 6">Emergency</div>
<div v-else></div>
</div>
<div class="col-span-12 font-bold mt-10">
Scheduled date/time
</div>
<div class="col-span-12 ">
{{ serviceCall.scheduled_date }}
</div>
<div class="col-span-12 font-bold mt-10">
Tech Name
</div>
<div class="col-span-12 ">
{{ serviceCall.tech_first_name }} {{ serviceCall.tech_last_name }}
</div>
<div class="col-span-12 font-bold mt-10">
When Called
</div>
<div class="col-span-12 ">
{{ serviceCall.when_called }}
</div>
</div>
</div>
<div class="col-span-6 mt-5">
<div class="col-span-12 font-bold">
Dispatcher Notes
</div>
<div class="grid grid-cols-12 bg-neutral p-5">
<div class="col-span-12 font-bold">
Subject
</div>
<div class="col-span-12">
{{ serviceCallNotes.dispatcher_subject }}
</div>
<div class="col-span-12 font-bold mt-10">
Notes
</div>
<div class="col-span-12 ">
{{ serviceCallNotes.dispatcher_notes }}
</div>
</div>
</div>
<div class="col-span-6 mt-5">
<div class="col-span-12 font-bold">
Amount
</div>
<div class="grid grid-cols-12 bg-neutral p-5">
<div class="col-span-12 font-bold">
<div v-if="serviceCall.customer_asked_for_fill==1">Fill</div>
<div v-else>{{ serviceCall.gallons_ordered }}</div>
</div>
</div>
</div>
<div class="col-span-6 mt-5">
<div class="col-span-12 font-bold">
Payment
</div>
<div class="grid grid-cols-12 bg-neutral p-5">
<div class="col-span-12 font-bold">
<div v-if="serviceCall.payment_type==0">Cash</div>
<div v-else-if="serviceCall.payment_type==1">Credit Card</div>
<div v-else-if="serviceCall.payment_type==2">Credit Card & cash</div>
<div v-else>No Payment Type Added</div>
</div>
<div class="col-span-12" v-if="serviceCall.payment_type==1">
<div class="flex">
<div class="basis-1/3 p-2">
<div class="bg-neutral rounded-md border-2 ">
<div class="flex p-3">
{{ userCard.type_of_card }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.name_on_card }}
</div>
<div class="flex p-1 pl-4">
****-****-****-{{ userCard.last_four_digits }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.expiration_month }}/ {{ userCard.expiration_year }}
</div>
</div>
</div>
</div>
</div>
<div class="col-span-12" v-if="serviceCall.payment_type==2">
<div class="flex">
<div class="basis-1/3 p-2">
<div class="bg-neutral rounded-md border-2 ">
<div class="flex p-3">
{{ userCard.type_of_card }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.name_on_card }}
</div>
<div class="flex p-1 pl-4">
****-****-****-{{ userCard.last_four_digits }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.expiration_month }}/ {{ userCard.expiration_year }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<Footer/>
</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 useValidate from "@vuelidate/core";
import {notify} from "@kyvg/vue3-notification"
import {minLength, required} from "@vuelidate/validators";
export default defineComponent({
name: 'serviceCall',
components: {
Header,
SideBar,
Footer,
},
data() {
return {
v$: useValidate(),
user: {
id: 0
},
serviceTech: [],
userCard: {
date_added: '',
user_id: '',
card_number: '',
last_four_digits: '',
name_on_card: '',
expiration_month: '',
expiration_year: '',
type_of_card: '',
security_number: '',
accepted_or_declined: '',
main_card: '',
},
customer: {
id: 0,
user_id: 0,
customer_first_name: '',
customer_last_name: '',
customer_town: '',
customer_state: 0,
customer_zip: '',
customer_apt: '',
customer_home_type: 0,
customer_phone_number: '',
},
serviceCallNotes: {
service_call_id: '',
dispatcher_notes: '',
dispatcher_subject: '',
time_added: '',
dispatcher_id: '',
dispatcher_name: '',
},
serviceCall: {
id: 0,
customer_id: 0,
customer_last_name: '',
customer_first_name: '',
customer_town: '',
customer_state: 0,
customer_zip: '',
customer_apt: '',
customer_address: '',
status: 0,
service_type: 0,
when_called: '',
scheduled_date: '',
scheduled_time: '',
when_serviced: '',
completed: 0,
tech_id: 0,
tech_first_name: '',
tech_last_name: '',
payment_type: 0,
payment_card_id: 0,
},
}
},
validations() {
return {
CreateServiceOrderForm: {
basicInfo: {
type_of_service: {required},
dispatcher_notes_taken: {required, minLength: minLength(10)},
dispatcher_subject_taken: {required, minLength: minLength(10)},
date_scheduled: {required},
service_tech_id: {required},
},
},
};
},
created() {
this.userStatus()
},
watch: {
$route() {
this.getServiceCall(this.$route.params.id);
this.getServiceCallNotes(this.$route.params.id);
},
},
mounted() {
this.getServiceCall(this.$route.params.id);
this.getServiceCallNotes(this.$route.params.id);
},
methods: {
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;
this.user.id = response.data.user_id;
}
})
},
getCustomer(user_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/customer/" + user_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.customer = response.data;
})
.catch(() => {
notify({
title: "Error",
text: "Could not find customer",
type: "error",
});
});
},
getPaymentCard(card_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/payment/card/" + card_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
this.userCard = response.data;
})
.catch(() => {
});
},
getServiceCall(service_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/service/call/" + service_id;
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data) {
this.serviceCall = response.data
this.getCustomer(this.serviceCall.customer_id)
if (this.serviceCall.payment_type != null) {
this.getPaymentCard(this.serviceCall.payment_card_id);
}
}
})
},
getServiceCallNotes(service_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/service/call/notes/" + service_id;
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data) {
this.serviceCallNotes = response.data
}
})
},
},
})
</script>
<style scoped></style>