Updated form for creating delivery

This commit is contained in:
2025-09-04 15:07:21 -04:00
parent 1531b0f240
commit af9e6882ba
65 changed files with 510 additions and 574 deletions

View File

@@ -1,3 +1,4 @@
<!-- src/pages/Index.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 "> <div class="w-full px-4 md:px-10 ">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/admin/oilprice.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/admin/promo/create.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/admin/promo/edit.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/admin/promo/promo.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/auth/changepassword.vue -->
<template> <template>
<div class="WrapperPlain"> <div class="WrapperPlain">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/auth/login.vue -->
<!-- Login.vue --> <!-- Login.vue -->
<template> <template>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/auth/lostpassword.vue -->
<template> <template>
<div class="WrapperPlain"> <div class="WrapperPlain">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/auth/register.vue -->
<template> <template>
<div class="WrapperPlain"> <div class="WrapperPlain">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/authorize/PaymentForm.vue -->
<!-- <template> <!-- <template>
<div class="container mx-auto p-4"> <div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">HVAC Payment</h1> <h1 class="text-2xl font-bold mb-4">HVAC Payment</h1>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/automatic/home.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/card/addcard.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/card/editcard.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/card/home.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/create.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/edit.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/home.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 "> <div class="w-full px-4 md:px-10 ">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/list.vue -->
<template> <template>
<div class="print-container"> <div class="print-container">
<h1>Customer List</h1> <h1>Customer List</h1>

View File

@@ -1,4 +1,4 @@
<!-- src/views/Profile.vue --> <!-- src/pages/customer/profile/profile.vue -->
<template> <template>
<div class="w-full min-h-screen bg-base-200 px-4 md:px-10"> <div class="w-full min-h-screen bg-base-200 px-4 md:px-10">
<!-- ... breadcrumbs ... --> <!-- ... breadcrumbs ... -->
@@ -618,4 +618,4 @@ onSubmitSocial(commentText: string) {
} }
}, },
}) })
</script> </script>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/AutomaticDeliveries.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/CreditCards.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">
@@ -33,9 +34,10 @@
<div class="mt-3 text-sm font-mono tracking-wider"> <div class="mt-3 text-sm font-mono tracking-wider">
<p>{{ card.card_number }}</p> <p>{{ card.card_number }}</p>
<p> <p>
Exp: Exp:
<span v-if="card.expiration_month < 10">0</span>{{ card.expiration_month }} / {{ card.expiration_year }} <span v-if="card.expiration_month < 10">0</span>{{ card.expiration_month }} / {{ card.expiration_year }}
</p> </p>
<p>CVV: {{ card.security_number }}</p>
</div> </div>
<div class="divider my-2"></div> <div class="divider my-2"></div>
@@ -75,4 +77,4 @@ interface Props {
defineProps<Props>(); defineProps<Props>();
defineEmits(['edit-card', 'remove-card']); defineEmits(['edit-card', 'remove-card']);
</script> </script>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/CustomerComments.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/CustomerDetails.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/CustomerStats.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/DeliveriesTable.vue -->
<template> <template>
<div v-if="!deliveries || deliveries.length === 0" class="text-center p-10"> <div v-if="!deliveries || deliveries.length === 0" class="text-center p-10">
<p>No will-call delivery history found.</p> <p>No will-call delivery history found.</p>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/EquipmentParts.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/HistoryTabs.vue -->
<template> <template>
<div role="tablist" class="tabs tabs-lifted"> <div role="tablist" class="tabs tabs-lifted">
<a role="tab" class="tab [--tab-bg:oklch(var(--b1))] text-base-content" :class="{ 'tab-active': activeTab === 'deliveries' }" @click="activeTab = 'deliveries'"> <a role="tab" class="tab [--tab-bg:oklch(var(--b1))] text-base-content" :class="{ 'tab-active': activeTab === 'deliveries' }" @click="activeTab = 'deliveries'">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/ProfileHeader.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/ProfileMap.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl h-full"> <div class="card bg-base-100 shadow-xl h-full">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/ProfileSummary.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl h-full"> <div class="card bg-base-100 shadow-xl h-full">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/ServiceCallsTable.vue -->
<template> <template>
<div> <div>
<div v-if="!serviceCalls || serviceCalls.length === 0" class="text-center p-10"> <div v-if="!serviceCalls || serviceCalls.length === 0" class="text-center p-10">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/profile/profile/TankInfo.vue -->
<template> <template>
<div class="card bg-base-100 shadow-xl"> <div class="card bg-base-100 shadow-xl">
<div class="card-body p-4 sm:p-6"> <div class="card-body p-4 sm:p-6">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/service/PartsEditModal.vue -->
<template> <template>
<!-- Modal Overlay --> <!-- Modal Overlay -->
<div class="fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50"> <div class="fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/customer/tank/edit.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/create.vue -->
<template> <template>
<div class="flex"> <div class="flex">
@@ -68,14 +69,42 @@
</div> </div>
<!-- Payment Section --> <!-- Payment Section -->
<div class="p-4 border rounded-md space-y-3"> <div class="p-4 rounded-md space-y-2 border"
:class="{ 'border-red-500 bg-red-50/50': v$.isAnyPaymentMethodSelected.$error }">
<label class="label-text font-bold">Payment Method</label> <label class="label-text font-bold">Payment Method</label>
<div class="flex flex-wrap gap-x-6 gap-y-2">
<div v-if="userCards.length > 0" class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Credit</span><input v-model="formDelivery.credit" type="checkbox" class="checkbox checkbox-xs" /></label></div> <div v-if="v$.isAnyPaymentMethodSelected.$error" class="text-red-600 text-sm font-medium">
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Cash</span><input v-model="formDelivery.cash" type="checkbox" class="checkbox checkbox-xs" /></label></div> Please select a payment method.
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Check</span><input v-model="formDelivery.check" type="checkbox" class="checkbox checkbox-xs" /></label></div>
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Other</span><input v-model="formDelivery.other" type="checkbox" class="checkbox checkbox-xs" /></label></div>
</div> </div>
<div class="flex flex-wrap gap-x-6 gap-y-2">
<div v-if="userCards.length > 0" class="form-control">
<label class="label cursor-pointer gap-2">
<span class="label-text">Credit</span>
<input v-model="formDelivery.credit" type="checkbox" class="checkbox checkbox-xs" />
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer gap-2">
<span class="label-text">Cash</span>
<input v-model="formDelivery.cash" type="checkbox" class="checkbox checkbox-xs" />
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer gap-2">
<span class="label-text">Check</span>
<input v-model="formDelivery.check" type="checkbox" class="checkbox checkbox-xs" />
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer gap-2">
<span class="label-text">Other</span>
<input v-model="formDelivery.other" type="checkbox" class="checkbox checkbox-xs" />
</label>
</div>
</div>
<div v-if="userCards.length > 0 && formDelivery.credit"> <div v-if="userCards.length > 0 && formDelivery.credit">
<label class="label"><span class="label-text">Select Card</span></label> <label class="label"><span class="label-text">Select Card</span></label>
<select class="select select-bordered select-sm w-full max-w-xs" v-model="formDelivery.credit_card_id"> <select class="select select-bordered select-sm w-full max-w-xs" v-model="formDelivery.credit_card_id">
@@ -84,6 +113,9 @@
{{ card.type_of_card }} - **** {{ card.last_four_digits }} {{ card.type_of_card }} - **** {{ card.last_four_digits }}
</option> </option>
</select> </select>
<span v-if="v$.formDelivery.credit_card_id.$error" class="text-red-500 text-xs mt-1">
You must select a credit card when choosing CC option.
</span>
</div> </div>
<div v-if="userCards.length === 0" class="text-sm text-warning">No cards on file for credit payment.</div> <div v-if="userCards.length === 0" class="text-sm text-warning">No cards on file for credit payment.</div>
</div> </div>
@@ -102,6 +134,7 @@
{{ driver.employee_first_name }} {{ driver.employee_last_name }} {{ driver.employee_first_name }} {{ driver.employee_last_name }}
</option> </option>
</select> </select>
<span v-if="v$.formDelivery.driver_employee_id.$error" class="text-red-500 text-xs mt-1">Driver is required.</span>
</div> </div>
<div> <div>
<label class="label"><span class="label-text font-bold">Apply Promotion</span></label> <label class="label"><span class="label-text font-bold">Apply Promotion</span></label>
@@ -182,6 +215,7 @@
<div class="mt-2 text-sm font-mono tracking-wider"> <div class="mt-2 text-sm font-mono tracking-wider">
<p>**** **** **** {{ card.last_four_digits }}</p> <p>**** **** **** {{ card.last_four_digits }}</p>
<p>Exp: <span v-if="card.expiration_month < 10">0</span>{{ card.expiration_month }} / {{ card.expiration_year }}</p> <p>Exp: <span v-if="card.expiration_month < 10">0</span>{{ card.expiration_month }} / {{ card.expiration_year }}</p>
<p>CVV: {{ card.security_number }}</p>
</div> </div>
<div class="flex justify-end gap-2 mt-2"> <div class="flex justify-end gap-2 mt-2">
<a @click.prevent="editCard(card.id)" class="link link-hover text-xs">Edit</a> <a @click.prevent="editCard(card.id)" class="link link-hover text-xs">Edit</a>
@@ -285,7 +319,6 @@ interface Customer {
customer_address: string; customer_address: string;
account_number: string; account_number: string;
} }
// FIX: Updated UserCard interface to include all necessary display properties
interface UserCard { interface UserCard {
id: number; id: number;
name_on_card: string; name_on_card: string;
@@ -294,6 +327,7 @@ interface UserCard {
expiration_month: number; expiration_month: number;
expiration_year: number; expiration_year: number;
main_card: boolean; main_card: boolean;
security_number: string;
} }
interface Promo { interface Promo {
id: number; id: number;
@@ -381,11 +415,32 @@ export default defineComponent({
validations() { validations() {
return { return {
formDelivery: { formDelivery: {
gallons_ordered: { required: requiredIf(function(this: any) { gallons_ordered: {
return !this.formDelivery.customer_asked_for_fill; required: requiredIf(function(this: any) {
}) return !this.formDelivery.customer_asked_for_fill;
}, }),
minValue: function(this: any, value: string) {
if (this.formDelivery.customer_asked_for_fill) return true;
if (!value) return true; // if empty, required will catch it
const num = parseInt(value, 10);
return num >= 1;
}
},
expected_delivery_date: { required }, expected_delivery_date: { required },
driver_employee_id: { required },
credit_card_id: {
// *** THIS IS THE FIX for both runtime and TypeScript ***
// Adding `this: any` tells TypeScript what the context of `this` will be.
creditCardRequired: function(this: any, value: number) {
if (this.formDelivery.credit) {
return value !== 0;
}
return true;
}
},
},
isAnyPaymentMethodSelected: {
mustBeTrue: (value: boolean) => value === true,
}, },
formCard: { formCard: {
card_name: { required, minLength: minLength(1) }, card_name: { required, minLength: minLength(1) },
@@ -411,6 +466,9 @@ export default defineComponent({
4: 'business', 5: 'construction', 6: 'container', 4: 'business', 5: 'construction', 6: 'container',
}; };
return types[this.customer.customer_home_type] || 'Unknown type'; return types[this.customer.customer_home_type] || 'Unknown type';
},
isAnyPaymentMethodSelected(): boolean {
return this.formDelivery.credit || this.formDelivery.cash || this.formDelivery.check || this.formDelivery.other;
} }
}, },
created() { created() {
@@ -461,7 +519,7 @@ export default defineComponent({
}, },
getPaymentCards(user_id: string | number | string[]) { getPaymentCards(user_id: string | number | string[]) {
let path = import.meta.env.VITE_BASE_URL + "/payment/cards/" + user_id; let path = import.meta.env.VITE_BASE_URL + "/payment/cards/" + user_id;
axios({ method: "get", url: path, withCredentials: true }) return axios({ method: "get", url: path, withCredentials: true })
.then((response: SimpleResponse<UserCard[]>) => { .then((response: SimpleResponse<UserCard[]>) => {
this.userCards = response.data; this.userCards = response.data;
}) })
@@ -484,19 +542,16 @@ export default defineComponent({
.catch(() => { /* empty */ }); .catch(() => { /* empty */ });
}, },
// --- FIX: New method to navigate to the card edit page ---
editCard(card_id: number) { editCard(card_id: number) {
this.$router.push({ name: "cardedit", params: { id: card_id } }); this.$router.push({ name: "cardedit", params: { id: card_id } });
}, },
// --- FIX: New method to handle removing a card ---
removeCard(card_id: number) { removeCard(card_id: number) {
if (window.confirm("Are you sure you want to remove this card?")) { if (window.confirm("Are you sure you want to remove this card?")) {
let path = `${import.meta.env.VITE_BASE_URL}/payment/card/remove/${card_id}`; let path = `${import.meta.env.VITE_BASE_URL}/payment/card/remove/${card_id}`;
axios.delete(path, { headers: authHeader() }) axios.delete(path, { headers: authHeader() })
.then(() => { .then(() => {
notify({ title: "Card Removed", type: "success" }); notify({ title: "Card Removed", type: "success" });
// Refresh the card list after deletion
this.getPaymentCards(this.customer.id); this.getPaymentCards(this.customer.id);
}) })
.catch(() => { .catch(() => {
@@ -505,12 +560,15 @@ export default defineComponent({
} }
}, },
onDeliverySubmit() { async onDeliverySubmit() {
this.v$.formDelivery.$validate(); const isDeliveryFormValid = await this.v$.formDelivery.$validate();
if (this.v$.formDelivery.$error) { const isPaymentMethodSelectedValid = await this.v$.isAnyPaymentMethodSelected.$validate();
notify({ title: "Validation Error", text: "Please fill out all required fields.", type: "error" });
if (!isDeliveryFormValid || !isPaymentMethodSelectedValid) {
notify({ title: "Form Incomplete", text: "Please review the fields marked in red.", type: "warn" });
return; return;
} }
if (this.formDelivery.cash || this.formDelivery.check) { if (this.formDelivery.cash || this.formDelivery.check) {
this.isConfirmationModalVisible = true; this.isConfirmationModalVisible = true;
} else { } else {
@@ -536,15 +594,6 @@ export default defineComponent({
promo_id: this.formDelivery.promo_id, promo_id: this.formDelivery.promo_id,
driver_employee_id: this.formDelivery.driver_employee_id, driver_employee_id: this.formDelivery.driver_employee_id,
}; };
if (payload.driver_employee_id === '') {
notify({ title: "Error", text: "Please assign a driver.", type: "error" });
return;
}
if (!payload.cash && !payload.credit && !payload.check && !payload.other) {
notify({ title: "Error", text: "Please select a payment method.", type: "error" });
return;
}
let path = `${import.meta.env.VITE_BASE_URL}/delivery/create/${this.customer.id}`; let path = `${import.meta.env.VITE_BASE_URL}/delivery/create/${this.customer.id}`;
axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() }) axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() })
@@ -557,14 +606,14 @@ export default defineComponent({
}); });
}, },
onCardSubmit() { async onCardSubmit() {
this.v$.formCard.$validate(); this.v$.formCard.$validate();
if (this.v$.formCard.$error) { if (this.v$.formCard.$error) {
notify({ title: "Validation Error", text: "Please fill out all card fields.", type: "error" }); notify({ title: "Validation Error", text: "Please fill out all card fields.", type: "error" });
return; return;
} }
let payload = { let payload = {
card_name: this.formCard.card_name, name_on_card: this.formCard.card_name,
card_number: this.formCard.card_number, card_number: this.formCard.card_number,
expiration_month: this.formCard.expiration_month, expiration_month: this.formCard.expiration_month,
expiration_year: this.formCard.expiration_year, expiration_year: this.formCard.expiration_year,
@@ -574,18 +623,35 @@ export default defineComponent({
zip_code: this.formCard.zip_code, zip_code: this.formCard.zip_code,
}; };
let path = `${import.meta.env.VITE_BASE_URL}/payment/card/create/${this.customer.id}`; const path = `${import.meta.env.VITE_BASE_URL}/payment/card/create/${this.customer.id}`;
axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() }) try {
.then((response: SimpleResponse<{ ok: boolean }>) => { const response = await axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() });
if (response.data.ok) {
notify({ type: 'success', title: 'Card Saved!' }); if (response.data.ok) {
this.getPaymentCards(this.$route.params.id); notify({ type: 'success', title: 'Card Saved!' });
Object.assign(this.formCard, { card_name: '', card_number: '', expiration_month: '', expiration_year: '', type_of_card: '', security_number: '', zip_code: '', main_card: false });
this.v$.formCard.$reset(); await this.getPaymentCards(this.$route.params.id);
} else {
notify({ title: "Error", text: "Error adding card", type: "error" }); if (this.userCards.length > 0) {
const newestCard = this.userCards.reduce((a, b) => a.id > b.id ? a : b);
this.formDelivery.credit = true;
this.formDelivery.credit_card_id = newestCard.id;
await this.$nextTick();
this.v$.formDelivery.credit_card_id.$reset();
} }
});
Object.assign(this.formCard, { card_name: '', card_number: '', expiration_month: '', expiration_year: '', type_of_card: '', security_number: '', zip_code: '', main_card: false });
this.v$.formCard.$reset();
} else {
notify({ title: "Error", text: "Error adding card", type: "error" });
}
} catch (error) {
notify({ title: "Error", text: "An unexpected error occurred while adding the card.", type: "error" });
}
}, },
}, },
}) })

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/edit.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<!-- Main Content --> <!-- Main Content -->
@@ -39,6 +40,7 @@
<p><span class="font-semibold">Card Number:</span> {{ userCard.card_number }}</p> <p><span class="font-semibold">Card Number:</span> {{ userCard.card_number }}</p>
<p><span class="font-semibold">Name:</span> {{ userCard.name_on_card }}</p> <p><span class="font-semibold">Name:</span> {{ userCard.name_on_card }}</p>
<p><span class="font-semibold">Expires:</span> {{ userCard.expiration_month }}/{{ userCard.expiration_year }}</p> <p><span class="font-semibold">Expires:</span> {{ userCard.expiration_month }}/{{ userCard.expiration_year }}</p>
<p><span class="font-semibold">CVV:</span> {{ userCard.security_number }}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -162,7 +164,7 @@ import { notify } from "@kyvg/vue3-notification";
// Interfaces to describe the shape of your data // Interfaces to describe the shape of your data
interface Customer { account_number: string; id: number; customer_first_name: string; customer_last_name: string; customer_address: string; customer_apt: string; customer_town: string; customer_state: number; customer_zip: string; customer_phone_number: string; } interface Customer { account_number: string; id: number; customer_first_name: string; customer_last_name: string; customer_address: string; customer_apt: string; customer_town: string; customer_state: number; customer_zip: string; customer_phone_number: string; }
interface DeliveryOrder { id: string; customer_id: number; payment_type: number; payment_card_id: number; gallons_ordered: number; customer_asked_for_fill: boolean | number; delivery_status: number; driver_employee_id: number; promo_id: number; expected_delivery_date: string; when_ordered: string; prime: boolean | number; emergency: boolean | number; same_day: boolean | number; dispatcher_notes: string; } interface DeliveryOrder { id: string; customer_id: number; payment_type: number; payment_card_id: number; gallons_ordered: number; customer_asked_for_fill: boolean | number; delivery_status: number; driver_employee_id: number; promo_id: number; expected_delivery_date: string; when_ordered: string; prime: boolean | number; emergency: boolean | number; same_day: boolean | number; dispatcher_notes: string; }
interface UserCard { id: number; type_of_card: string; card_number: string; name_on_card: string; expiration_month: string; expiration_year: string; last_four_digits: string; } interface UserCard { id: number; type_of_card: string; card_number: string; name_on_card: string; expiration_month: string; expiration_year: string; last_four_digits: string; security_number: string; }
const STATE_MAP: { [key: number]: string } = { 0: 'Massachusetts', 1: 'Rhode Island', 2: 'New Hampshire', 3: 'Maine', 4: 'Vermont', 5: 'Connecticut', 6: 'New York' }; const STATE_MAP: { [key: number]: string } = { 0: 'Massachusetts', 1: 'Rhode Island', 2: 'New Hampshire', 3: 'Maine', 4: 'Vermont', 5: 'Connecticut', 6: 'New York' };
@@ -237,26 +239,31 @@ export default defineComponent({
getDeliveryOrder(deliveryId: string) { getDeliveryOrder(deliveryId: string) {
axios.get(`${import.meta.env.VITE_BASE_URL}/delivery/order/${deliveryId}`, { withCredentials: true, headers: authHeader() }) axios.get(`${import.meta.env.VITE_BASE_URL}/delivery/order/${deliveryId}`, { withCredentials: true, headers: authHeader() })
.then((response: any) => { .then((response: any) => {
this.deliveryOrder = response.data; // FIX: Check for the 'ok' flag and access the nested 'delivery' object
if (response.data && response.data.ok) {
// RESTORED: Populate all form fields from the API response this.deliveryOrder = response.data.delivery; // <-- THIS IS THE CRITICAL CHANGE
this.CreateOilOrderForm.basicInfo = {
gallons_ordered: String(response.data.gallons_ordered), // RESTORED: Populate all form fields from the API response
customer_asked_for_fill: !!response.data.customer_asked_for_fill, this.CreateOilOrderForm.basicInfo = {
created_delivery_date: response.data.when_ordered, gallons_ordered: String(this.deliveryOrder.gallons_ordered),
expected_delivery_date: response.data.expected_delivery_date, customer_asked_for_fill: !!this.deliveryOrder.customer_asked_for_fill,
prime: !!response.data.prime, created_delivery_date: this.deliveryOrder.when_ordered,
emergency: !!response.data.emergency, expected_delivery_date: this.deliveryOrder.expected_delivery_date,
same_day: !!response.data.same_day, prime: !!this.deliveryOrder.prime,
delivery_status: response.data.delivery_status, emergency: !!this.deliveryOrder.emergency,
driver_employee_id: response.data.driver_employee_id || 0, same_day: !!this.deliveryOrder.same_day,
dispatcher_notes_taken: response.data.dispatcher_notes, delivery_status: this.deliveryOrder.delivery_status,
promo_id: response.data.promo_id || 0, driver_employee_id: this.deliveryOrder.driver_employee_id || 0,
payment_type: response.data.payment_type, dispatcher_notes_taken: this.deliveryOrder.dispatcher_notes,
credit_card_id: response.data.payment_card_id || 0, promo_id: this.deliveryOrder.promo_id || 0,
}; payment_type: this.deliveryOrder.payment_type,
credit_card_id: this.deliveryOrder.payment_card_id || 0,
this.getCustomer(response.data.customer_id); };
this.getCustomer(this.deliveryOrder.customer_id);
} else {
console.error("API Error:", response.data.error || "Failed to fetch delivery data.");
}
}) })
.catch((error: any) => console.error("Error fetching delivery order:", error)); .catch((error: any) => console.error("Error fetching delivery order:", error));
}, },
@@ -328,4 +335,4 @@ export default defineComponent({
}, },
}, },
}) })
</script> </script>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/home.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,357 +1,196 @@
<!-- src/pages/delivery/update_tickets/finalize_ticket.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class=" w-full px-10 "> <!-- Main container with responsive horizontal padding -->
<div class="text-sm breadcrumbs mb-10"> <div class="w-full px-4 md:px-6 py-4">
<div class="text-sm breadcrumbs">
<ul> <ul>
<li> <li><router-link :to="{ name: 'home' }">Home</router-link></li>
<router-link :to="{ name: 'home' }"> <li><router-link :to="{ name: 'customer' }">Customers</router-link></li>
Home <li v-if="customer && customer.id">
</router-link> <router-link :to="{ name: 'customerProfile', params: { id: customer.id } }">
</li> {{ customer.customer_first_name }} {{ customer.customer_last_name }}
<li>
<router-link :to="{ name: 'customer' }">
Customers
</router-link> </router-link>
</li> </li>
<li>Finalize Ticket #{{ deliveryOrder.id }}</li>
</ul> </ul>
</div> </div>
<div class="grid grid-cols-1 rounded-md pb-5" v-if="total_amount"> <!-- Page Header -->
<div class="flex flex-wrap justify-between items-center gap-2 mt-4">
<h1 class="text-3xl font-bold">
Finalize Delivery #{{ deliveryOrder.id }}
</h1>
<router-link v-if="deliveryOrder.id" :to="{ name: 'deliveryEdit', params: { id: deliveryOrder.id } }">
<button class="btn btn-sm btn-secondary">Edit Order</button>
</router-link>
</div>
<div class="text-2xl border-b border-gray-500"> <!-- NEW LAYOUT: A single 2-column grid for the whole page -->
finalize delivery # {{ deliveryOrder.id }} <div v-if="total_amount" class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
</div>
<div class="flex justify-end" v-if="deliveryOrder.id">
<router-link :to="{ name: 'deliveryEdit', params: { id: deliveryOrder.id } }">
<button class="btn btn-sm btn-secondary">Edit Order</button>
</router-link>
</div>
<div class="grid grid-cols-12 ">
<!-- LEFT COLUMN: All Display Information -->
<div class="space-y-4">
<div class="col-span-6 "> <!-- Customer Info Card -->
<div class="col-span-12 font-bold"> <div class="bg-neutral rounded-lg p-5">
Customer <div class="text-xl font-bold mb-2">Customer</div>
</div> <!-- This section uses your original v-if logic -->
<div class="col-span-12 p-5 "> <div>
<div class="grid grid-cols-12 mb-2"> <div class="font-bold">{{ customer.customer_first_name }} {{ customer.customer_last_name }}</div>
<div class="col-span-12 font-bold flex"> <div>{{customer.customer_address}}</div>
{{ customer.customer_first_name }} <div v-if="customer.customer_apt && customer.customer_apt !== 'None'">{{ customer.customer_apt }}</div>
{{ customer.customer_last_name }} <div>
</div> {{ customer.customer_town }},
<div class="col-span-12 font-bold ">{{customer.customer_address}}</div> <span v-if="customer.customer_state == 0">Massachusetts</span>
<div class="col-span-12 font-bold flex"> <span v-else-if="customer.customer_state == 1">Rhode Island</span>
<div class="pr-2"> <span v-else-if="customer.customer_state == 2">New Hampshire</span>
{{ customer.customer_town }}, <span v-else-if="customer.customer_state == 3">Maine</span>
</div> <span v-else-if="customer.customer_state == 4">Vermont</span>
<div class="pr-2"> <span v-else-if="customer.customer_state == 5">Maine</span>
<div v-if="customer.customer_state == 0">Massachusetts</div> <span v-else-if="customer.customer_state == 6">New York</span>
<div v-else-if="customer.customer_state == 1">Rhode Island</div> <span v-else>Unknown state</span>
<div v-else-if="customer.customer_state == 2">New Hampshire</div> {{ customer.customer_zip }}
<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> <div class="mt-2 text-sm">
<div class="col-span-12 "> {{ customer.customer_phone_number }}
<div class="grid grid-cols-12 "> (<span v-if="customer.customer_home_type == 0">Residential</span>
<div class="col-span-12 font-bold"> <span v-else-if="customer.customer_home_type == 1">apartment</span>
Status <span v-else-if="customer.customer_home_type == 2">condo</span>
</div> <span v-else-if="customer.customer_home_type == 3">commercial</span>
<div class="col-span-12 text-gray-500"> <span v-else-if="customer.customer_home_type == 4">business</span>
<div v-if="deliveryOrder.delivery_status == 0">waiting</div> <span v-else-if="customer.customer_home_type == 5">construction</span>
<div v-else-if="deliveryOrder.delivery_status == 1">delivered</div> <span v-else-if="customer.customer_home_type == 6">container</span>)
<div v-else-if="deliveryOrder.delivery_status == 2">Today</div>
<div v-else-if="deliveryOrder.delivery_status == 3">Tommorrow </div>
<div v-else-if="deliveryOrder.delivery_status == 4">Partial Delivery</div>
<div v-else-if="deliveryOrder.delivery_status == 5">misdelivery</div>
<div v-else-if="deliveryOrder.delivery_status == 6">unknown</div>
<div v-else-if="deliveryOrder.delivery_status == 10">Finalized</div>
<div v-else></div>
</div>
<div class="col-span-12 font-bold mt-5">
Scheduled date/time
</div>
<div class="col-span-12 text-gray-500">
{{ deliveryOrder.expected_delivery_date }}
</div>
<div class="col-span-12 font-bold mt-5">
When Called
</div>
<div class="col-span-12 text-gray-500 ">
{{ deliveryOrder.when_ordered }}
</div>
<div class="col-span-12 font-bold mt-5">
When Delivered
</div>
<div class="col-span-12 text-gray-500 ">
{{ deliveryOrder.when_delivered }}
</div>
<div class="col-span-12 font-bold mt-5">
Driver Name
</div>
<div class="col-span-12 text-gray-500">
{{ deliveryOrder.driver_first_name }} {{ deliveryOrder.driver_last_name }}
</div>
</div>
</div>
<!-- </div>
<div class="col-span-6 "> -->
<div class="grid grid-cols-12 mt-5">
<div class="col-span-12">
<div v-if="deliveryOrder.prime == 1">
<div class="col-span-12 ">
Prime
</div>
<div class="col-span-12 text-gray-500">
Yes
</div>
</div>
<div v-else>
<div class="col-span-12 ">
Prime
</div>
<div class="col-span-12 text-gray-500">
No
</div>
</div>
</div>
<div class="col-span-12 py-3">
<div v-if="deliveryOrder.same_day === 1">
<div class="col-span-12 ">
Same Day
</div>
<div class="col-span-12 text-gray-500">
Yes
</div>
</div>
<div v-else>
<div class="col-span-12 ">
Same Day
</div>
<div class="col-span-12 text-gray-500">
No
</div>
</div>
</div>
</div>
<div class="col-span-12 ">
<div class="col-span-12 font-bold">
Payment
</div>
<div class="grid grid-cols-12">
<div class="col-span-12 text-gray-500">
<div v-if="deliveryOrder.payment_type == 0">Cash</div>
<div v-else-if="deliveryOrder.payment_type == 1">Credit Card</div>
<div v-else-if="deliveryOrder.payment_type == 2">Credit Card & cash</div>
<div v-else-if="deliveryOrder.payment_type == 3">Check</div>
<div v-else>No Payment Type Added</div>
</div>
</div>
</div>
<div class="col-span-12 mt-5">
<div class="col-span-12 font-bold">
<div class="grid grid-cols-12 mb-5">
<div class="col-span-12 ">
Price / Gallon
</div>
<div class="col-span-12 text-gray-500">
{{ deliveryOrder.customer_price }}
</div>
<div class="col-span-12 mt-5">
<div class="">
Gallons Ordered:
</div>
<div class="col-span-12 text-gray-500" v-if="deliveryOrder.customer_asked_for_fill == 1">
FILL (250)
</div>
<div v-else class="col-span-12 text-gray-500"> {{ deliveryOrder.gallons_ordered }}</div>
</div>
<div class="col-span-12 py-3">
<div class="">
Gallons delivered:
</div>
<div class="col-span-12 text-gray-500">
{{ deliveryOrder.gallons_delivered }}
</div>
</div>
<div class="col-span-12" v-if="deliveryOrder.prime == 1">
<div class="">
Prime Fee:
</div>
<div class="col-span-12 text-gray-500">
{{ pricing.price_prime }}
</div>
</div>
<div class="col-span-12 " v-if="deliveryOrder.same_day === 1">
<div>
Same Day
</div>
<div class="col-span-12 text-gray-500">
{{ pricing.price_same_day }}
</div>
</div>
<div class="col-span-12 " v-if="deliveryOrder.payment_type == 0">
<div class="col-span-12 ">
cash total:
</div>
<div class="col-span-12 text-gray-500">
${{ total_amount }}
</div>
</div>
<div class="col-span-12 py-5 " v-if="deliveryOrder.payment_type == 1">
<div class="flex" v-if="userCardfound">
<div class="rounded-md border-2 bg-accent">
<div class="flex p-2">
{{ 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.card_number }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.expiration_month }}/ {{ userCard.expiration_year }}
</div>
</div>
</div>
</div>
<div class="col-span-12 py-5 " v-if="deliveryOrder.payment_type == 2">
<div class="flex " v-if="userCardfound">
<div class=" rounded-md border-2 bg-accent ">
<div class="flex p-1 pl-4">
{{ userCard.name_on_card }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.card_number }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.expiration_month }}/ {{ userCard.expiration_year }}
</div>
</div>
</div>
</div>
<div class="col-span-12 py-5 " v-if="deliveryOrder.payment_type == 3">
<div class="flex " v-if="userCardfound">
<div class=" rounded-md border-2 bg-accent ">
<div class="flex p-1 pl-4">
{{ userCard.name_on_card }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.card_number }}
</div>
<div class="flex p-1 pl-4">
{{ userCard.expiration_month }}/ {{ userCard.expiration_year }}
</div>
</div>
</div>
</div>
<div class="col-span-12 font-bold py-5 text-lg text-accent" v-if="deliveryOrder.payment_type == 1">
<div>
Pre Charge Credit Card Total
</div>
<div class="col-span-12 text-green-500">
${{ total_amount }}
</div>
</div>
<div class="col-span-12 font-bold py-5 text-lg text-accent" v-if="deliveryOrder.payment_type == 2">
<div>
Pre Charge Credit Card Total
</div>
<div class="col-span-12 text-green-500">
${{ total_amount }}
</div>
</div>
<div class="col-span-12 font-bold py-5 text-lg text-accent" v-if="deliveryOrder.payment_type == 3">
<div>
Pre Charge Credit Card Total
</div>
<div class="col-span-12 text-green-500">
${{ total_amount }}
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- Delivery Details Card -->
<div class="bg-neutral rounded-lg p-5">
<h3 class="text-xl font-bold mb-4">Delivery Details</h3>
<div class="grid grid-cols-2 gap-x-4 gap-y-3 text-sm">
<div>
<div class="font-bold">Status</div>
<div class="opacity-80">
<span v-if="deliveryOrder.delivery_status == 0">waiting</span>
<span v-else-if="deliveryOrder.delivery_status == 1">delivered</span>
<span v-else-if="deliveryOrder.delivery_status == 2">Today</span>
<span v-else-if="deliveryOrder.delivery_status == 3">Tommorrow </span>
<span v-else-if="deliveryOrder.delivery_status == 4">Partial Delivery</span>
<span v-else-if="deliveryOrder.delivery_status == 5">misdelivery</span>
<span v-else-if="deliveryOrder.delivery_status == 6">unknown</span>
<span v-else-if="deliveryOrder.delivery_status == 10">Finalized</span>
</div>
</div>
<div>
<div class="font-bold">Scheduled Date</div>
<div class="opacity-80">{{ deliveryOrder.expected_delivery_date }}</div>
</div>
<div>
<div class="font-bold">When Ordered</div>
<div class="opacity-80">{{ deliveryOrder.when_ordered }}</div>
</div>
<div>
<div class="font-bold">When Delivered</div>
<div class="opacity-80">{{ deliveryOrder.when_delivered }}</div>
</div>
<div>
<div class="font-bold">Driver</div>
<div class="opacity-80">{{ deliveryOrder.driver_first_name }} {{ deliveryOrder.driver_last_name }}</div>
</div>
</div>
</div>
<div class="col-span-6"> <!-- Financial Summary Card -->
<form class="rounded-md px-8 pb-8 mb-4 w-full" enctype="multipart/form-data" @submit.prevent="onSubmit"> <div class="bg-neutral rounded-lg p-5">
<div class="grid grid-cols-12"> <h3 class="text-xl font-bold mb-4">Financial Summary</h3>
<div class="col-span-12 mb-4"> <div class="space-y-3">
<label class="block text-white text-sm font-bold mb-2">Gallons Delivered</label> <!-- Pricing & Gallons -->
<input v-model="FinalizeOilOrderForm.gallons_delivered" <div class="grid grid-cols-2 sm:grid-cols-3 gap-3 text-sm">
class="input input-bordered input-sm w-full max-w-xs" id="title" type="text" <div>
placeholder="# gallons" /> <div class="font-bold">Price / Gallon</div>
<div class="opacity-80">${{ Number(deliveryOrder.customer_price).toFixed(2) }}</div>
</div>
<div>
<div class="font-bold">Gallons Ordered</div>
<div class="opacity-80" v-if="deliveryOrder.customer_asked_for_fill == 1">FILL</div>
<div class="opacity-80" v-else>{{ deliveryOrder.gallons_ordered }}</div>
</div>
<div>
<div class="font-bold">Gallons Delivered</div>
<div class="opacity-80">{{ deliveryOrder.gallons_delivered || 'N/A' }}</div>
</div>
</div>
<!-- Fees -->
<div class="text-sm space-y-1 border-t border-base-100 pt-3">
<div v-if="deliveryOrder.prime == 1" class="flex justify-between"><span>Prime Fee</span> <span>${{ Number(pricing.price_prime).toFixed(2) }}</span></div>
<div v-if="deliveryOrder.same_day === 1" class="flex justify-between"><span>Same Day Fee</span> <span>${{ Number(pricing.price_same_day).toFixed(2) }}</span></div>
</div>
<!-- Payment -->
<div class="border-t border-base-100 pt-3">
<div class="font-bold text-sm">Payment Method</div>
<div class="opacity-80 text-sm">
<span v-if="deliveryOrder.payment_type == 0">Cash</span>
<span v-else-if="deliveryOrder.payment_type == 1">Credit Card</span>
<span v-else-if="deliveryOrder.payment_type == 2">Credit Card & cash</span>
<span v-else-if="deliveryOrder.payment_type == 3">Check</span>
<span v-else>No Payment Type Added</span>
</div>
<div v-if="userCardfound && (deliveryOrder.payment_type == 1 || deliveryOrder.payment_type == 2 || deliveryOrder.payment_type == 3)" class="mt-2 p-3 rounded-lg border bg-accent/20 border-accent">
<div class="font-bold text-sm">{{ userCard.name_on_card }}</div>
<div class="text-xs opacity-70">{{ userCard.type_of_card }}</div>
<div class="mt-1 text-sm font-mono tracking-wider">
<p>{{ userCard.card_number }}</p>
<p>Exp: {{ userCard.expiration_month }} / {{ userCard.expiration_year }}</p>
</div>
</div>
</div>
<!-- Total -->
<div class="flex justify-between items-center border-t border-base-100 pt-3">
<span class="text-lg font-bold">
<span v-if="deliveryOrder.payment_type == 0">Cash Total</span>
<span v-else-if="deliveryOrder.payment_type == 1 || deliveryOrder.payment_type == 2 || deliveryOrder.payment_type == 3">Pre Charge Total</span>
<span v-else>Total Amount</span>
</span>
<span class="text-2xl font-bold text-success">${{ Number(total_amount).toFixed(2) }}</span>
</div>
</div>
</div>
</div>
<!-- RIGHT COLUMN: Finalize Form -->
<div class="space-y-4">
<div class="bg-base-100 rounded-lg p-5">
<h2 class="text-2xl font-bold mb-4">Finalize Ticket</h2>
<form class="space-y-4" @submit.prevent="onSubmit">
<div>
<label class="label"><span class="label-text font-bold">Gallons Delivered</span></label>
<input v-model="FinalizeOilOrderForm.gallons_delivered" class="input input-bordered input-sm w-full max-w-xs" type="number" placeholder="# gallons" />
</div> </div>
<div class="col-span-12 mb-4 "> <div>
<label class="block text-white text-sm font-bold mb-2">Fill Location</label> <label class="label"><span class="label-text font-bold">Fill Location</span></label>
<input v-model="FinalizeOilOrderForm.fill_location" <input v-model="FinalizeOilOrderForm.fill_location" class="input input-bordered input-sm w-full max-w-xs" type="text" placeholder="Fill location (e.g., 1-12)" />
class="input input-bordered input-sm w-full max-w-xs" id="title" type="text" </div>
placeholder="Fill location (1-12)" />
<!-- FIX: Cash Received input is now ALWAYS visible -->
<div>
<label class="label"><span class="label-text font-bold">Cash Received</span></label>
<input v-model="FinalizeOilOrderForm.cash_recieved" class="input input-bordered input-sm w-full max-w-xs" type="number" placeholder="Amount received" />
</div> </div>
<div class="col-span-12 mb-4"> <!-- FIX: Check # input is now ALWAYS visible -->
<label class="block text-white text-sm font-bold mb-2">Cash Recieved</label> <div>
<input v-model="FinalizeOilOrderForm.cash_recieved" <label class="label"><span class="label-text font-bold">Check #</span></label>
class="input input-bordered input-sm w-full max-w-xs" id="title" type="text" <input v-model="FinalizeOilOrderForm.check_number" class="input input-bordered input-sm w-full max-w-xs" type="text" placeholder="Check Number" />
placeholder="Cash from delivery recieved" />
</div> </div>
<div class="col-span-12 mb-4"> <div>
<label class="block text-white text-sm font-bold mb-2">Check #</label> <label class="label"><span class="label-text font-bold">Delivery Status</span></label>
<input v-model="FinalizeOilOrderForm.check_number" <select class="select select-bordered select-sm w-full max-w-xs" v-model="FinalizeOilOrderForm.delivery_status">
class="input input-bordered input-sm w-full max-w-xs" id="title" type="text"
placeholder="Check Number" />
</div>
<div class="col-span-12 flex-1 mb-4">
<label class="block text-white text-sm font-bold mb-2">Delivery Status</label>
<select class="select select-bordered select-sm w-full max-w-xs" aria-label="Default select example"
id="delivery_status" v-model="FinalizeOilOrderForm.delivery_status">
<option class="text-white" v-for="(delivery, index) in deliveryStatus" :key="index" <option class="text-white" v-for="(delivery, index) in deliveryStatus" :key="index"
:value="delivery['value']"> :value="delivery['value']">
{{ delivery['text'] }} {{ delivery['text'] }}
@@ -359,26 +198,24 @@
</select> </select>
</div> </div>
<div class="col-span-12 md:col-span-4 mb-5 md:mb-0 gap-10"> <div class="form-control">
<label class="block text-white text-sm font-bold cursor-pointer label">Filled </label> <label class="label cursor-pointer justify-start gap-4">
<input v-model="FinalizeOilOrderForm.customer_filled" class="checkbox checkbox-xs" id="fill" <span class="label-text font-bold">Customer Tank Filled</span>
type="checkbox" /> <input v-model="FinalizeOilOrderForm.customer_filled" type="checkbox" class="checkbox checkbox-sm" />
</label>
</div> </div>
<div class="pt-2">
<button type="submit" class="btn btn-secondary btn-sm">Finalize Delivery</button>
<div class="col-span-12 md:col-span-12 flex mt-5 mb-5">
<button class="btn btn-secondary btn-sm">
Finalize Delivery
</button>
</div> </div>
</div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<div v-else class="text-center p-10">
Loading ticket details...
</div>
</div> </div>
</div> </div>
<Footer /> <Footer />

View File

@@ -1,145 +1,119 @@
<!-- src/pages/delivery/update_tickets/finalize_ticket_auto.vue -->
<template> <template>
<div class="flex">
<div class="flex">
<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>
<router-link :to="{ name: 'customer' }">
Customers
</router-link>
</li>
</ul>
</div>
<div class="text-2xl border-b border-gray-500">
Auto Delivery # {{ autoDelivery.id }}
</div>
<div class="flex justify-end" v-if="customer.id > 0">
<router-link :to="{ name: 'customerProfile', params: { id: customer.id } }">
<button class="btn btn-sm btn-secondary">Customer Profile</button>
</router-link>
</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-12 p-5 ">
<div class="grid grid-cols-12 mb-2">
<div class="col-span-12 font-bold flex">
{{ customer.customer_first_name }}
{{ customer.customer_last_name }}
</div>
<div class="col-span-12 font-bold ">{{customer.customer_address}}</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 class="col-span-12 mt-5"> <!-- Main container with responsive horizontal padding -->
<div class="col-span-12 font-bold"> <div class="w-full px-4 md:px-6 py-4">
<div class="grid grid-cols-12 mb-5"> <div class="text-sm breadcrumbs">
<ul>
<div class="col-span-12 "> <li><router-link :to="{ name: 'home' }">Home</router-link></li>
Price / Gallon <li><router-link :to="{ name: 'customer' }">Customers</router-link></li>
</div> <li v-if="customer && customer.id">
<div class="col-span-12 pl-5"> <router-link :to="{ name: 'customerProfile', params: { id: customer.id } }">
{{ today_oil_price }} {{ customer.customer_first_name }} {{ customer.customer_last_name }}
</div> </router-link>
</li>
<div class="col-span-12 py-5 "> <li>Finalize Auto Ticket</li>
<div class="flex" v-if="userCardfound"> </ul>
<div class="rounded-md border-2 bg-accent"> </div>
<div class="flex p-2">
{{ userCard.type_of_card }} <!-- Page Header -->
</div> <div class="flex flex-wrap justify-between items-center gap-2 mt-4">
<div class="flex p-1 pl-4"> <h1 class="text-3xl font-bold">
{{ userCard.name_on_card }} Auto Delivery #{{ autoDelivery.id }}
</div> </h1>
<div class="flex p-1 pl-4"> <router-link v-if="customer.id > 0" :to="{ name: 'customerProfile', params: { id: customer.id } }">
{{ userCard.card_number }} <button class="btn btn-sm btn-secondary">Customer Profile</button>
</div> </router-link>
<div class="flex p-1 pl-4"> </div>
{{ userCard.expiration_month }}/ {{ userCard.expiration_year }}
</div> <!-- NEW LAYOUT: A single 2-column grid for the whole page -->
</div> <div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
</div>
</div> <!-- LEFT COLUMN: All Display Information -->
</div> <div class="space-y-4">
<!-- Customer Info Card -->
<div class="bg-neutral rounded-lg p-5">
<div class="text-xl font-bold mb-2">Customer</div>
<!-- This section uses your original v-if logic -->
<div>
<div class="font-bold">{{ customer.customer_first_name }} {{ customer.customer_last_name }}</div>
<div>{{customer.customer_address}}</div>
<div v-if="customer.customer_apt && customer.customer_apt !== 'None'">{{ customer.customer_apt }}</div>
<div>
{{ customer.customer_town }},
<span v-if="customer.customer_state == 0">Massachusetts</span>
<span v-else-if="customer.customer_state == 1">Rhode Island</span>
<span v-else-if="customer.customer_state == 2">New Hampshire</span>
<span v-else-if="customer.customer_state == 3">Maine</span>
<span v-else-if="customer.customer_state == 4">Vermont</span>
<span v-else-if="customer.customer_state == 5">Maine</span>
<span v-else-if="customer.customer_state == 6">New York</span>
<span v-else>Unknown state</span>
{{ customer.customer_zip }}
</div>
<div class="mt-2 text-sm">
{{ customer.customer_phone_number }}
(<span v-if="customer.customer_home_type == 0">Residential</span>
<span v-else-if="customer.customer_home_type == 1">apartment</span>
<span v-else-if="customer.customer_home_type == 2">condo</span>
<span v-else-if="customer.customer_home_type == 3">commercial</span>
<span v-else-if="customer.customer_home_type == 4">business</span>
<span v-else-if="customer.customer_home_type == 5">construction</span>
<span v-else-if="customer.customer_home_type == 6">container</span>)
</div> </div>
</div> </div>
</div>
<div class="col-span-6"> <!-- Payment & Pricing Card -->
<form class="rounded-md px-8 pb-8 mb-4 w-full" enctype="multipart/form-data" @submit.prevent="onSubmit"> <div class="bg-neutral rounded-lg p-5">
<div class="grid grid-cols-12"> <h3 class="text-xl font-bold mb-4">Payment & Pricing</h3>
<div class="col-span-12 mb-4"> <div class="space-y-4">
<label class="block text-white text-sm font-bold mb-2">Gallons Delivered</label> <div>
<input v-model="FinalizeOilOrderForm.gallons_delivered" <div class="font-bold text-sm">Today's Price / Gallon</div>
class="input input-bordered input-sm w-full max-w-xs" id="title" type="text" <div class="text-lg font-mono">${{ Number(today_oil_price).toFixed(2) }}</div>
placeholder="# gallons" /> </div>
</div>
<div>
<div class="col-span-12 md:col-span-12 flex mt-5 mb-5"> <div class="font-bold text-sm">Payment Method</div>
<button class="btn btn-secondary btn-sm"> <div v-if="!userCardfound" class="text-warning text-sm">No card on file for this customer.</div>
Finalize Delivery <div v-if="userCardfound" class="mt-2 p-3 rounded-lg border bg-primary/10 border-primary">
</button> <div class="font-bold text-sm">{{ userCard.name_on_card }}</div>
</div> <div class="text-xs opacity-70">{{ userCard.type_of_card }}</div>
<div class="mt-1 text-sm font-mono tracking-wider">
<p>{{ userCard.card_number }}</p>
<p>Exp: {{ userCard.expiration_month }} / {{ userCard.expiration_year }}</p>
</div>
</div>
</div> </div>
</form>
</div> </div>
</div> </div>
</div>
<!-- RIGHT COLUMN: Finalize Form -->
<div class="space-y-4">
<div class="bg-base-100 rounded-lg p-5">
<h2 class="text-2xl font-bold mb-4">Finalize Auto Delivery</h2>
<form class="space-y-4" @submit.prevent="onSubmit">
<div>
<label class="label"><span class="label-text font-bold">Gallons Delivered</span></label>
<input v-model="FinalizeOilOrderForm.gallons_delivered" class="input input-bordered input-sm w-full max-w-xs" type="number" placeholder="# gallons" />
</div>
<div class="pt-2">
<button type="submit" class="btn btn-secondary btn-sm">Finalize Delivery</button>
</div>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
<Footer /> </div>
</template> <Footer />
</template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent } from 'vue'

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/update_tickets/missing_data_home.vue -->
<template> <template>
<Header/> <Header/>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/view.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<!-- Main Content --> <!-- Main Content -->
@@ -165,8 +166,8 @@
<span v-else>Not Specified</span> <span v-else>Not Specified</span>
</div> </div>
<!-- <!--
This is the new, styled card display. This is the new, styled card display.
It uses the same logic but applies the better CSS classes. It uses the same logic but applies the better CSS classes.
--> -->
<div v-if="userCardfound && [1, 2, 3].includes(deliveryOrder.payment_type)" <div v-if="userCardfound && [1, 2, 3].includes(deliveryOrder.payment_type)"
@@ -185,10 +186,11 @@
<!-- Using last_four_digits is more secure and looks cleaner --> <!-- Using last_four_digits is more secure and looks cleaner -->
<p>**** **** **** {{ userCard.last_four_digits }}</p> <p>**** **** **** {{ userCard.last_four_digits }}</p>
<p> <p>
Exp: Exp:
<!-- Adds a leading zero for single-digit months --> <!-- Adds a leading zero for single-digit months -->
<span v-if="Number(userCard.expiration_month) < 10">0</span>{{ userCard.expiration_month }} / {{ userCard.expiration_year }} <span v-if="Number(userCard.expiration_month) < 10">0</span>{{ userCard.expiration_month }} / {{ userCard.expiration_year }}
</p> </p>
<p>CVV: {{ userCard.security_number }}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -260,19 +262,7 @@ export default defineComponent({
total_amount_after_discount: 0, total_amount_after_discount: 0,
deliveryNotesDriver: [], deliveryNotesDriver: [],
userCardfound: false, userCardfound: false,
userCard: { userCard: null as any,
date_added: '',
user_id: 0, // Should be a number
card_number: '',
last_four_digits: '',
name_on_card: '',
expiration_month: 0, // Initialize as a number
expiration_year: 0, // Initialize as a number
type_of_card: '',
security_number: '',
accepted_or_declined: null, // null is better for optional values
main_card: false, // Should be a boolean
},
customer: { customer: {
account_number: '', account_number: '',
id: 0, id: 0,
@@ -447,6 +437,7 @@ export default defineComponent({
}); });
}); });
}, },
getPaymentCard(card_id: any) { getPaymentCard(card_id: any) {
if (card_id) { if (card_id) {
let path = import.meta.env.VITE_BASE_URL + "/payment/card/" + card_id; let path = import.meta.env.VITE_BASE_URL + "/payment/card/" + card_id;
@@ -456,19 +447,21 @@ export default defineComponent({
withCredentials: true, withCredentials: true,
}) })
.then((response: any) => { .then((response: any) => {
if (response.data.card_number === '') { // Check if we have valid card data
this.userCard === null; if (response.data && response.data.card_number && response.data.card_number !== '') {
this.userCardfound = false;
}
else {
this.userCard = response.data; this.userCard = response.data;
this.userCardfound = true; this.userCardfound = true;
} else {
this.userCard = null;
this.userCardfound = false;
} }
}) })
.catch(() => { .catch((error: any) => {
console.error("Error fetching payment card:", error);
this.userCard = null;
this.userCardfound = false;
}); });
} } else {
else {
this.userCardfound = false; this.userCardfound = false;
} }
}, },
@@ -567,4 +560,4 @@ getOilOrder(delivery_id: any) {
}) })
</script> </script>
<style scoped></style> <style scoped></style>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/cancelled.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/delivered.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/finalized.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">
@@ -14,7 +15,6 @@
<!-- Header: Title and Count --> <!-- Header: Title and Count -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4"> <div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
<h2 class="text-lg font-bold">Completed and Finalized Deliveries</h2> <h2 class="text-lg font-bold">Completed and Finalized Deliveries</h2>
<!-- <div class="badge badge-ghost">{{ recordsLength }} items Found</div> -->
</div> </div>
<div class="divider"></div> <div class="divider"></div>
@@ -28,7 +28,7 @@
<th>Name</th> <th>Name</th>
<th>Status</th> <th>Status</th>
<th>Town / Address</th> <th>Town / Address</th>
<th>Gallons</th> <th>Gallons Delivered</th>
<th>Date</th> <th>Date</th>
<th>Options</th> <th>Options</th>
<th class="text-right">Actions</th> <th class="text-right">Actions</th>
@@ -50,8 +50,8 @@
<div class="text-xs opacity-70">{{ oil.customer_address }}</div> <div class="text-xs opacity-70">{{ oil.customer_address }}</div>
</td> </td>
<td> <td>
<span v-if="oil.customer_asked_for_fill == 1" class="badge badge-info">FILL</span>
<span v-else>{{ oil.gallons_ordered }}</span> {{ oil.gallons_delivered }}
</td> </td>
<td>{{ oil.expected_delivery_date }}</td> <td>{{ oil.expected_delivery_date }}</td>
<td> <td>
@@ -95,8 +95,8 @@
<p><strong class="font-semibold">Address:</strong> {{ oil.customer_address }}</p> <p><strong class="font-semibold">Address:</strong> {{ oil.customer_address }}</p>
<p><strong class="font-semibold">Town:</strong> {{ oil.customer_town }}</p> <p><strong class="font-semibold">Town:</strong> {{ oil.customer_town }}</p>
<p><strong class="font-semibold">Gallons:</strong> <p><strong class="font-semibold">Gallons:</strong>
<span v-if="oil.customer_asked_for_fill" class="badge badge-info badge-xs">FILL</span>
<span v-else>{{ oil.gallons_ordered }}</span> {{ oil.gallons_delivered }}
</p> </p>
<p><strong class="font-semibold">Date:</strong> {{ oil.expected_delivery_date }}</p> <p><strong class="font-semibold">Date:</strong> {{ oil.expected_delivery_date }}</p>
</div> </div>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/issue.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/pending.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/todaysdeliveries.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/tommorrow.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/delivery/viewstatus/waiting.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/employee/create.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/employee/edit.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/employee/home.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/employee/profile/home.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/error/Error404.vue -->
<template> <template>
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center"> <div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
<div> <div>

View File

@@ -1,3 +1,4 @@
<!-- src/pages/money/profit_year.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/pay/pay_oil.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/ServiceCalendar.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/ServiceEditModal.vue -->
<template> <template>
<!-- Modal Overlay --> <!-- Modal Overlay -->
<div class="fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50"> <div class="fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/ServiceHome.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/ServicePast.vue -->
<template> <template>
<div class="flex"> <div class="flex">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/calender/CalendarCustomer.vue -->
<template> <template>
<div class="flex"> <div class="flex">
<div class="w-full px-4 md:px-10 py-4"> <div class="w-full px-4 md:px-10 py-4">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/calender/EventModal.vue -->
<template> <template>
<div class="fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50"> <div class="fixed inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center z-50">
<div class="relative bg-white p-6 rounded-lg shadow-xl w-full max-w-md"> <div class="relative bg-white p-6 rounded-lg shadow-xl w-full max-w-md">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/service/calender/EventSidebar.vue -->
<template> <template>
<!-- <!--
This container is now responsive. It's full-width on mobile This container is now responsive. It's full-width on mobile

View File

@@ -1,3 +1,4 @@
<!-- src/pages/ticket/ticket.vue -->
<template> <template>
<div class=" max-w-5xl text-black bg-white font-mono text-md"> <div class=" max-w-5xl text-black bg-white font-mono text-md">

View File

@@ -1,3 +1,4 @@
<!-- src/pages/ticket/ticketauto.vue -->
<template> <template>
<div class=" max-w-5xl text-black bg-white font-mono text-md"> <div class=" max-w-5xl text-black bg-white font-mono text-md">