Working log in/route guard
This commit is contained in:
@@ -2,210 +2,260 @@
|
||||
|
||||
<div class="flex">
|
||||
|
||||
<div class="w-full px-10">
|
||||
<!-- Main container with reduced horizontal padding -->
|
||||
<div class="w-full px-4 md:px-6 py-4">
|
||||
<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>
|
||||
<li>Create Delivery for {{ customer.customer_first_name }}</li>
|
||||
<li v-if="customer && customer.id">
|
||||
<router-link :to="{ name: 'customerProfile', params: { id: customer.id } }">
|
||||
{{ customer.customer_first_name }} {{ customer.customer_last_name }}
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- TOP SECTION: Customer Info and Pricing Chart -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
<!-- Customer Info Card -->
|
||||
<div class="bg-neutral rounded-lg p-5">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<div>
|
||||
<div class="text-xl font-bold">{{ customer.customer_first_name }} {{ customer.customer_last_name }}</div>
|
||||
<div class="text-sm text-gray-400">Account: {{ customer.account_number }}</div>
|
||||
</div>
|
||||
<router-link :to="{ name: 'customerProfile', params: { id: customer.id } }" class="btn btn-secondary btn-sm">
|
||||
View Profile
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<div>{{ customer.customer_address }}</div>
|
||||
<div v-if="customer.customer_apt && customer.customer_apt !== 'None'">{{ customer.customer_apt }}</div>
|
||||
<div>{{ customer.customer_town }}, {{ customerStateName }} {{ customer.customer_zip }}</div>
|
||||
<div class="text-sm text-gray-400 mt-1">{{ customerHomeTypeName }}</div>
|
||||
<div class="mt-2">{{ customer.customer_phone_number }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
NEW LAYOUT: A single 2-column grid for the whole page.
|
||||
Gaps and spacing are reduced for a more compact feel.
|
||||
-->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4 mt-4">
|
||||
|
||||
<!-- Pricing Chart Card -->
|
||||
<div class="bg-neutral rounded-lg p-5">
|
||||
<h3 class="text-xl font-bold mb-4">Today's Price Per Gallon</h3>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-sm w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Gallons</th>
|
||||
<th>Total Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="tier in pricingTiers" :key="tier.gallons" class="hover">
|
||||
<!-- Access properties of the 'tier' object -->
|
||||
<td>{{ tier.gallons }}</td>
|
||||
<td>${{ parseFloat(tier.price.toString()).toFixed(2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BOTTOM SECTION: Forms -->
|
||||
<div class="grid grid-cols-1 xl:grid-cols-2 gap-6">
|
||||
<!-- Create Delivery Form -->
|
||||
<div class="p-6 ">
|
||||
<h2 class="text-2xl font-bold mb-4">Create Delivery Order</h2>
|
||||
<form class="space-y-4" @submit.prevent="onDeliverySubmit">
|
||||
<!-- Gallons & Fill -->
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Gallons Ordered</span></label>
|
||||
<input v-model="formDelivery.gallons_ordered" :disabled="formDelivery.customer_asked_for_fill"
|
||||
class="input input-bordered input-sm w-full max-w-xs" type="number" placeholder="# gallons" />
|
||||
<span v-if="v$.formDelivery.gallons_ordered.$error" class="text-red-500 text-xs mt-1">
|
||||
Gallons are required unless "Fill" is checked.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-4">
|
||||
<span class="label-text font-bold">Customer Asked for Fill</span>
|
||||
<input v-model="formDelivery.customer_asked_for_fill" type="checkbox" class="checkbox checkbox-sm" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Payment Section -->
|
||||
<div class="p-4 border rounded-md space-y-3">
|
||||
<label class="label-text font-bold">Payment Method</label>
|
||||
<div class="flex flex-wrap gap-x-6 gap-y-2">
|
||||
<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 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">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>
|
||||
<!-- LEFT COLUMN: Primary Information & Actions -->
|
||||
<div class="space-y-4">
|
||||
|
||||
<!-- Customer Info Card -->
|
||||
<div class="bg-neutral rounded-lg p-5">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<div>
|
||||
<div class="text-xl font-bold">{{ customer.customer_first_name }} {{ customer.customer_last_name }}</div>
|
||||
<div class="text-sm text-gray-400">Account: {{ customer.account_number }}</div>
|
||||
</div>
|
||||
<div v-if="userCards.length > 0 && formDelivery.credit">
|
||||
<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">
|
||||
<option disabled :value="0">Select a card</option>
|
||||
<option v-for="card in userCards" :key="card.id" :value="card.id">
|
||||
{{ card.type_of_card }} - **** {{ card.last_four_digits }}
|
||||
</option>
|
||||
<router-link v-if="customer && customer.id" :to="{ name: 'customerProfile', params: { id: customer.id } }" class="btn btn-secondary btn-sm">
|
||||
View Profile
|
||||
</router-link>
|
||||
</div>
|
||||
<div>
|
||||
<div>{{ customer.customer_address }}</div>
|
||||
<div v-if="customer.customer_apt && customer.customer_apt !== 'None'">{{ customer.customer_apt }}</div>
|
||||
<div>{{ customer.customer_town }}, {{ customerStateName }} {{ customer.customer_zip }}</div>
|
||||
<div class="mt-2">{{ customer.customer_phone_number }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create Delivery Form (now in the left column) -->
|
||||
<div class="bg-base-100 rounded-lg p-4">
|
||||
<h2 class="text-2xl font-bold mb-4">Create Delivery Order</h2>
|
||||
<form class="space-y-4" @submit.prevent="onDeliverySubmit">
|
||||
<!-- Gallons & Fill -->
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Gallons Ordered</span></label>
|
||||
<input v-model="formDelivery.gallons_ordered" :disabled="formDelivery.customer_asked_for_fill"
|
||||
class="input input-bordered input-sm w-full max-w-xs" type="number" placeholder="# gallons" />
|
||||
<div class="flex flex-wrap gap-2 mt-2">
|
||||
<button v-for="amount in quickGallonAmounts" :key="amount" @click.prevent="setGallons(amount)" class="btn btn-xs btn-outline">{{ amount }} gal</button>
|
||||
</div>
|
||||
<span v-if="v$.formDelivery.gallons_ordered.$error" class="text-red-500 text-xs mt-1">
|
||||
Required unless "Fill" is checked.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-4">
|
||||
<span class="label-text font-bold">Fill</span>
|
||||
<input v-model="formDelivery.customer_asked_for_fill" type="checkbox" class="checkbox checkbox-sm" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Payment Section -->
|
||||
<div class="p-4 border rounded-md space-y-3">
|
||||
<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 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">
|
||||
<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">
|
||||
<option disabled :value="0">Select a card</option>
|
||||
<option v-for="card in userCards" :key="card.id" :value="card.id">
|
||||
{{ card.type_of_card }} - **** {{ card.last_four_digits }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-if="userCards.length === 0" class="text-sm text-warning">No cards on file for credit payment.</div>
|
||||
</div>
|
||||
|
||||
<!-- Date, Driver, Promo -->
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Expected Delivery Date</span></label>
|
||||
<input v-model="formDelivery.expected_delivery_date" class="input input-bordered input-sm w-full max-w-xs" type="date" />
|
||||
<span v-if="v$.formDelivery.expected_delivery_date.$error" class="text-red-500 text-xs mt-1">Date is required.</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Assigned Driver</span></label>
|
||||
<select class="select select-bordered select-sm w-full max-w-xs" v-model="formDelivery.driver_employee_id">
|
||||
<option disabled value="">Select a driver</option>
|
||||
<option v-for="driver in truckDriversList" :key="driver.id" :value="driver.id">
|
||||
{{ driver.employee_first_name }} {{ driver.employee_last_name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Apply Promotion</span></label>
|
||||
<select class="select select-bordered select-sm w-full max-w-xs" v-model="formDelivery.promo_id">
|
||||
<option :value="0">No Promotion</option>
|
||||
<option v-for="promo in promos" :key="promo.id" :value="promo.id">
|
||||
{{ promo.name_of_promotion }} (${{ promo.money_off_delivery }} off)
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-if="userCards.length === 0" class="text-sm text-warning">No cards on file for credit payment.</div>
|
||||
</div>
|
||||
|
||||
<!-- Date, Driver, Promo -->
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Expected Delivery Date</span></label>
|
||||
<input v-model="formDelivery.expected_delivery_date" class="input input-bordered input-sm w-full max-w-xs" type="date" />
|
||||
<span v-if="v$.formDelivery.expected_delivery_date.$error" class="text-red-500 text-xs mt-1">Date is required.</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Assigned Driver</span></label>
|
||||
<select class="select select-bordered select-sm w-full max-w-xs" v-model="formDelivery.driver_employee_id">
|
||||
<option disabled value="">Select a driver</option>
|
||||
<option v-for="driver in truckDriversList" :key="driver.id" :value="driver.id">
|
||||
{{ driver.employee_first_name }} {{ driver.employee_last_name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Apply Promotion</span></label>
|
||||
<select class="select select-bordered select-sm w-full max-w-xs" v-model="formDelivery.promo_id">
|
||||
<option :value="0">No Promotion</option>
|
||||
<option v-for="promo in promos" :key="promo.id" :value="promo.id">
|
||||
{{ promo.name_of_promotion }} (${{ promo.money_off_delivery }} off)
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- Fees -->
|
||||
<div class="p-4 border rounded-md">
|
||||
<label class="label-text font-bold">Fees & Options</label>
|
||||
<div class="flex flex-wrap gap-x-6 gap-y-2">
|
||||
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Emergency</span><input v-model="formDelivery.emergency" type="checkbox" class="checkbox checkbox-xs" /></label></div>
|
||||
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Prime</span><input v-model="formDelivery.prime" type="checkbox" class="checkbox checkbox-xs" /></label></div>
|
||||
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Same Day</span><input v-model="formDelivery.same_day" type="checkbox" class="checkbox checkbox-xs" /></label></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fees -->
|
||||
<div class="p-4 border rounded-md">
|
||||
<label class="label-text font-bold">Fees & Options</label>
|
||||
<div class="flex flex-wrap gap-x-6 gap-y-2">
|
||||
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Emergency</span><input v-model="formDelivery.emergency" type="checkbox" class="checkbox checkbox-xs" /></label></div>
|
||||
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Prime</span><input v-model="formDelivery.prime" type="checkbox" class="checkbox checkbox-xs" /></label></div>
|
||||
<div class="form-control"><label class="label cursor-pointer gap-2"><span class="label-text">Same Day</span><input v-model="formDelivery.same_day" type="checkbox" class="checkbox checkbox-xs" /></label></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Notes -->
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Dispatcher Notes</span></label>
|
||||
<textarea v-model="formDelivery.dispatcher_notes_taken" rows="3" class="textarea textarea-bordered w-full" placeholder="Notes for the driver..."></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Notes -->
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Dispatcher Notes</span></label>
|
||||
<textarea v-model="formDelivery.dispatcher_notes_taken" rows="3" class="textarea textarea-bordered w-full" placeholder="Notes for the driver..."></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-sm">Create Delivery</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-sm">Create Delivery</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Add Credit Card Form -->
|
||||
<div class="p-6 ">
|
||||
<h2 class="text-2xl font-bold mb-4">Add a Credit Card</h2>
|
||||
<form class="space-y-3" @submit.prevent="onCardSubmit">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<!-- RIGHT COLUMN: Reference Information & Secondary Actions -->
|
||||
<div class="space-y-4">
|
||||
|
||||
<!-- Pricing Chart Card -->
|
||||
<div class="bg-neutral rounded-lg p-5">
|
||||
<h3 class="text-xl font-bold mb-4">Today's Price Per Gallon</h3>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-sm w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Gallons</th>
|
||||
<th>Total Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="tier in pricingTiers" :key="tier.gallons" class="hover">
|
||||
<td>{{ tier.gallons }}</td>
|
||||
<td>${{ Number(tier.price).toFixed(2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Credit Cards Display -->
|
||||
<div v-if="customer && customer.id" class="bg-neutral rounded-lg p-5">
|
||||
<div class="flex justify-between items-center">
|
||||
<h2 class="text-xl font-bold">Credit Cards</h2>
|
||||
<router-link :to="{ name: 'cardadd', params: { id: customer.id } }">
|
||||
<button class="btn btn-xs btn-outline btn-success">Add New</button>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="mt-2 text-sm" v-if="userCards.length === 0">
|
||||
<p class="text-warning font-semibold">No cards on file.</p>
|
||||
</div>
|
||||
<div class="mt-4 space-y-3">
|
||||
<div v-for="card in userCards" :key="card.id" class="p-3 rounded-lg border" :class="card.main_card ? 'bg-primary/10 border-primary' : 'bg-base-200 border-base-300'">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Name on Card</span></label>
|
||||
<input v-model="formCard.card_name" type="text" placeholder="John M. Doe" class="input input-bordered input-sm w-full" />
|
||||
<span v-if="v$.formCard.card_name.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Card Number</span></label>
|
||||
<input v-model="formCard.card_number" type="text" placeholder="4242..." class="input input-bordered input-sm w-full" />
|
||||
<span v-if="v$.formCard.card_number.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Expiration</span></label>
|
||||
<div class="flex gap-2">
|
||||
<select v-model="formCard.expiration_month" class="select select-bordered select-sm w-full">
|
||||
<option disabled value="">MM</option>
|
||||
<option v-for="m in 12" :key="m" :value_count="String(m).padStart(2, '0')">{{ String(m).padStart(2, '0') }}</option>
|
||||
</select>
|
||||
<select v-model="formCard.expiration_year" class="select select-bordered select-sm w-full">
|
||||
<option disabled value="">YYYY</option>
|
||||
<option v-for="y in 10" :key="y" :value_count="(new Date().getFullYear() + y - 1)">{{ new Date().getFullYear() + y - 1 }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<span v-if="v$.formCard.expiration_month.$error || v$.formCard.expiration_year.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">CVC / CVV</span></label>
|
||||
<input v-model="formCard.security_number" type="text" placeholder="123" class="input input-bordered input-sm w-full" />
|
||||
<span v-if="v$.formCard.security_number.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Card Type</span></label>
|
||||
<select v-model="formCard.type_of_card" class="select select-bordered select-sm w-full">
|
||||
<option disabled value="">Select Type</option>
|
||||
<option>Visa</option><option>MasterCard</option><option>Discover</option><option>American Express</option>
|
||||
</select>
|
||||
<span v-if="v$.formCard.type_of_card.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label"><span class="label-text font-bold">Billing Zip Code</span></label>
|
||||
<input v-model="formCard.zip_code" type="text" placeholder="01234" class="input input-bordered input-sm w-full" />
|
||||
<div class="font-bold text-sm">{{ card.name_on_card }}</div>
|
||||
<div class="text-xs opacity-70">{{ card.type_of_card }}</div>
|
||||
</div>
|
||||
<div v-if="card.main_card" class="badge badge-primary badge-sm">Primary</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-4">
|
||||
<span class="label-text font-bold">Set as Main Card</span>
|
||||
<input v-model="formCard.main_card" type="checkbox" class="checkbox checkbox-sm" />
|
||||
</label>
|
||||
<div class="mt-2 text-sm font-mono tracking-wider">
|
||||
<p>**** **** **** {{ card.last_four_digits }}</p>
|
||||
<p>Exp: <span v-if="card.expiration_month < 10">0</span>{{ card.expiration_month }} / {{ card.expiration_year }}</p>
|
||||
</div>
|
||||
<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="removeCard(card.id)" class="link link-hover text-error text-xs">Remove</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Credit Card Form -->
|
||||
<div class="bg-base-100 rounded-lg p-4">
|
||||
<h2 class="text-xl font-bold mb-4">Quick Add Card</h2>
|
||||
<form class="space-y-3" @submit.prevent="onCardSubmit">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="label py-1"><span class="label-text">Name on Card</span></label>
|
||||
<input v-model="formCard.card_name" type="text" class="input input-bordered input-sm w-full" />
|
||||
<span v-if="v$.formCard.card_name.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label py-1"><span class="label-text">Card Number</span></label>
|
||||
<input v-model="formCard.card_number" type="text" class="input input-bordered input-sm w-full" />
|
||||
<span v-if="v$.formCard.card_number.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label py-1"><span class="label-text">Expiration</span></label>
|
||||
<div class="flex gap-2">
|
||||
<select v-model="formCard.expiration_month" class="select select-bordered select-sm w-full"><option disabled value="">MM</option><option v-for="m in 12" :key="m">{{ String(m).padStart(2, '0') }}</option></select>
|
||||
<select v-model="formCard.expiration_year" class="select select-bordered select-sm w-full"><option disabled value="">YYYY</option><option v-for="y in 10" :key="y">{{ new Date().getFullYear() + y - 1 }}</option></select>
|
||||
</div>
|
||||
<span v-if="v$.formCard.expiration_month.$error || v$.formCard.expiration_year.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label py-1"><span class="label-text">CVC</span></label>
|
||||
<input v-model="formCard.security_number" type="text" class="input input-bordered input-sm w-full" />
|
||||
<span v-if="v$.formCard.security_number.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label py-1"><span class="label-text">Card Type</span></label>
|
||||
<select v-model="formCard.type_of_card" class="select select-bordered select-sm w-full"><option disabled value="">Select Type</option><option>Visa</option><option>MasterCard</option><option>Discover</option><option>American Express</option></select>
|
||||
<span v-if="v$.formCard.type_of_card.$error" class="text-red-500 text-xs mt-1">Required</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label py-1"><span class="label-text">Billing Zip</span></label>
|
||||
<input v-model="formCard.zip_code" type="text" class="input input-bordered input-sm w-full" />
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-secondary btn-sm">Save Credit Card</button>
|
||||
</form>
|
||||
<div class="form-control">
|
||||
<label class="label cursor-pointer justify-start gap-4 py-1">
|
||||
<span class="label-text">Set as Main Card</span>
|
||||
<input v-model="formCard.main_card" type="checkbox" class="checkbox checkbox-sm" />
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-secondary btn-sm">Save Card</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" :class="{ 'modal-open': isConfirmationModalVisible }">
|
||||
<div class="modal-box">
|
||||
<h3 class="font-bold text-lg">Confirm Payment Method</h3>
|
||||
<p class="py-4">You have selected a non-standard payment method (Cash or Check). Please confirm you wish to proceed.</p>
|
||||
<div class="modal-action">
|
||||
<button @click="proceedWithSubmission" class="btn btn-primary">Confirm & Create</button>
|
||||
<button @click="isConfirmationModalVisible = false" class="btn">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { defineComponent } from 'vue'
|
||||
@@ -235,10 +285,15 @@ interface Customer {
|
||||
customer_address: string;
|
||||
account_number: string;
|
||||
}
|
||||
// FIX: Updated UserCard interface to include all necessary display properties
|
||||
interface UserCard {
|
||||
id: number;
|
||||
name_on_card: string;
|
||||
type_of_card: string;
|
||||
last_four_digits: string;
|
||||
expiration_month: number;
|
||||
expiration_year: number;
|
||||
main_card: boolean;
|
||||
}
|
||||
interface Promo {
|
||||
id: number;
|
||||
@@ -250,12 +305,10 @@ interface Driver {
|
||||
employee_first_name: string;
|
||||
employee_last_name: string;
|
||||
}
|
||||
interface PricingTier { // <-- CHANGED: New interface for a single tier
|
||||
interface PricingTier {
|
||||
gallons: number | string;
|
||||
price: number | string;
|
||||
}
|
||||
|
||||
// --- Define types for your FLAT form models to match the new template ---
|
||||
interface DeliveryFormData {
|
||||
gallons_ordered: string;
|
||||
customer_asked_for_fill: boolean;
|
||||
@@ -290,12 +343,12 @@ export default defineComponent({
|
||||
return {
|
||||
v$: useValidate(),
|
||||
user: null as any,
|
||||
checked: false,
|
||||
quickGallonAmounts: [100, 125, 150, 200, 220],
|
||||
userCards: [] as UserCard[],
|
||||
promos: [] as Promo[],
|
||||
truckDriversList: [] as Driver[],
|
||||
pricingTiers: [] as PricingTier[],
|
||||
// --- FIX: Use flat form objects that match the template ---
|
||||
pricingTiers: [] as PricingTier[],
|
||||
isConfirmationModalVisible: false,
|
||||
formDelivery: {
|
||||
gallons_ordered: '',
|
||||
customer_asked_for_fill: false,
|
||||
@@ -327,7 +380,6 @@ export default defineComponent({
|
||||
},
|
||||
validations() {
|
||||
return {
|
||||
// --- FIX: Validation targets the new flat form objects ---
|
||||
formDelivery: {
|
||||
gallons_ordered: { required: requiredIf(function(this: any) {
|
||||
return !this.formDelivery.customer_asked_for_fill;
|
||||
@@ -379,13 +431,21 @@ export default defineComponent({
|
||||
this.getPaymentCards(customerId);
|
||||
},
|
||||
methods: {
|
||||
setGallons(amount: number) {
|
||||
this.formDelivery.gallons_ordered = String(amount);
|
||||
this.formDelivery.customer_asked_for_fill = false;
|
||||
},
|
||||
getPricingTiers() {
|
||||
let path = import.meta.env.VITE_BASE_URL + "/info/price/oil/tiers";
|
||||
axios({ method: "get", url: path, withCredentials: true, headers: authHeader() })
|
||||
.then((response: SimpleResponse<PricingTier[]>) => {
|
||||
this.pricingTiers = response.data;
|
||||
.then((response: SimpleResponse<{ [key: string]: string }>) => {
|
||||
const tiersObject = response.data;
|
||||
this.pricingTiers = Object.entries(tiersObject).map(([gallons, price]) => ({
|
||||
gallons: parseInt(gallons, 10),
|
||||
price: price,
|
||||
}));
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
.catch(() => {
|
||||
notify({ title: "Pricing Error", text: "Could not retrieve today's pricing.", type: "error" });
|
||||
});
|
||||
},
|
||||
@@ -395,7 +455,7 @@ export default defineComponent({
|
||||
.then((response: SimpleResponse<Customer>) => {
|
||||
this.customer = response.data;
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
.catch(() => {
|
||||
notify({ title: "Error", text: "Could not find customer", type: "error" });
|
||||
});
|
||||
},
|
||||
@@ -405,7 +465,7 @@ export default defineComponent({
|
||||
.then((response: SimpleResponse<UserCard[]>) => {
|
||||
this.userCards = response.data;
|
||||
})
|
||||
.catch((error: unknown) => { /* empty */ });
|
||||
.catch(() => { /* empty */ });
|
||||
},
|
||||
getPromos() {
|
||||
let path = import.meta.env.VITE_BASE_URL + "/promo/all";
|
||||
@@ -413,7 +473,7 @@ export default defineComponent({
|
||||
.then((response: SimpleResponse<Promo[]>) => {
|
||||
this.promos = response.data;
|
||||
})
|
||||
.catch((error: unknown) => { /* empty */ });
|
||||
.catch(() => { /* empty */ });
|
||||
},
|
||||
getDriversList() {
|
||||
let path = import.meta.env.VITE_BASE_URL + "/employee/drivers";
|
||||
@@ -421,11 +481,45 @@ export default defineComponent({
|
||||
.then((response: SimpleResponse<Driver[]>) => {
|
||||
this.truckDriversList = response.data;
|
||||
})
|
||||
.catch((error: unknown) => { /* empty */ });
|
||||
.catch(() => { /* empty */ });
|
||||
},
|
||||
|
||||
// --- FIX: New method to navigate to the card edit page ---
|
||||
editCard(card_id: number) {
|
||||
this.$router.push({ name: "cardedit", params: { id: card_id } });
|
||||
},
|
||||
|
||||
// --- FIX: New method to handle removing a card ---
|
||||
removeCard(card_id: number) {
|
||||
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}`;
|
||||
axios.delete(path, { headers: authHeader() })
|
||||
.then(() => {
|
||||
notify({ title: "Card Removed", type: "success" });
|
||||
// Refresh the card list after deletion
|
||||
this.getPaymentCards(this.customer.id);
|
||||
})
|
||||
.catch(() => {
|
||||
notify({ title: "Error", text: "Could not remove card.", type: "error" });
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// --- FIX: Renamed to match template's @submit event ---
|
||||
onDeliverySubmit() {
|
||||
this.v$.formDelivery.$validate();
|
||||
if (this.v$.formDelivery.$error) {
|
||||
notify({ title: "Validation Error", text: "Please fill out all required fields.", type: "error" });
|
||||
return;
|
||||
}
|
||||
if (this.formDelivery.cash || this.formDelivery.check) {
|
||||
this.isConfirmationModalVisible = true;
|
||||
} else {
|
||||
this.proceedWithSubmission();
|
||||
}
|
||||
},
|
||||
|
||||
proceedWithSubmission() {
|
||||
this.isConfirmationModalVisible = false;
|
||||
let payload = {
|
||||
gallons_ordered: this.formDelivery.gallons_ordered,
|
||||
customer_asked_for_fill: this.formDelivery.customer_asked_for_fill,
|
||||
@@ -443,30 +537,32 @@ export default defineComponent({
|
||||
driver_employee_id: this.formDelivery.driver_employee_id,
|
||||
};
|
||||
|
||||
let pass = 0;
|
||||
if (payload.driver_employee_id === '') {
|
||||
notify({ title: "Error", text: "Please assign a driver.", type: "error" });
|
||||
pass += 1;
|
||||
return;
|
||||
}
|
||||
if (!payload.cash && !payload.credit && !payload.check && !payload.other) {
|
||||
notify({ title: "Error", text: "Please select a payment method.", type: "error" });
|
||||
pass += 1;
|
||||
}
|
||||
if (pass === 0) {
|
||||
let path = import.meta.env.VITE_BASE_URL + "/delivery/create/" + this.customer.id;
|
||||
axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() })
|
||||
.then((response: SimpleResponse<{ ok: boolean; delivery_id: number; error?: string }>) => {
|
||||
if (response.data.ok) {
|
||||
this.$router.push({ name: "payOil", params: { id: response.data.delivery_id } });
|
||||
} else {
|
||||
this.$router.push("/");
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let path = `${import.meta.env.VITE_BASE_URL}/delivery/create/${this.customer.id}`;
|
||||
axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() })
|
||||
.then((response: SimpleResponse<{ ok: boolean; delivery_id: number }>) => {
|
||||
if (response.data.ok) {
|
||||
this.$router.push({ name: "payOil", params: { id: response.data.delivery_id } });
|
||||
} else {
|
||||
this.$router.push("/");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// --- FIX: Renamed to match template's @submit event ---
|
||||
|
||||
onCardSubmit() {
|
||||
this.v$.formCard.$validate();
|
||||
if (this.v$.formCard.$error) {
|
||||
notify({ title: "Validation Error", text: "Please fill out all card fields.", type: "error" });
|
||||
return;
|
||||
}
|
||||
let payload = {
|
||||
card_name: this.formCard.card_name,
|
||||
card_number: this.formCard.card_number,
|
||||
@@ -478,13 +574,12 @@ export default defineComponent({
|
||||
zip_code: this.formCard.zip_code,
|
||||
};
|
||||
|
||||
let path = import.meta.env.VITE_BASE_URL + "/payment/card/create/" + this.customer.id;
|
||||
let path = `${import.meta.env.VITE_BASE_URL}/payment/card/create/${this.customer.id}`;
|
||||
axios({ method: "post", url: path, data: payload, withCredentials: true, headers: authHeader() })
|
||||
.then((response: SimpleResponse<{ ok: boolean; error?: string }>) => {
|
||||
.then((response: SimpleResponse<{ ok: boolean }>) => {
|
||||
if (response.data.ok) {
|
||||
notify({ type: 'success', title: 'Card Saved!' });
|
||||
this.getPaymentCards(this.$route.params.id);
|
||||
// Optional: Reset form after successful submission
|
||||
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 {
|
||||
@@ -494,7 +589,4 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
@@ -23,7 +23,11 @@
|
||||
<div class="text-xl font-bold">{{ customer.customer_first_name }} {{ customer.customer_last_name }}</div>
|
||||
<div class="text-sm text-gray-400">Account: {{ customer.account_number }}</div>
|
||||
</div>
|
||||
<router-link :to="{ name: 'customerProfile', params: { id: customer.id } }" class="btn btn-secondary btn-sm">
|
||||
<!--
|
||||
FIX #1: Add a v-if guard.
|
||||
This prevents the link from rendering until `customer.user_id` has a valid, non-zero value.
|
||||
-->
|
||||
<router-link v-if="customer " :to="{ name: 'customerProfile', params: { id: customer.id } }" class="btn btn-secondary btn-sm">
|
||||
View Profile
|
||||
</router-link>
|
||||
</div>
|
||||
@@ -75,6 +79,7 @@
|
||||
<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 == 9">Pending</span>
|
||||
<span v-else-if="deliveryOrder.delivery_status == 10">Finalized</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -144,28 +149,50 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Payment, Notes, Actions -->
|
||||
<div class="space-y-4">
|
||||
<!-- Payment -->
|
||||
<div class="p-4 border rounded-md">
|
||||
<label class="label-text font-bold">Payment Method</label>
|
||||
<div class="mt-1">
|
||||
<div class="text-lg">
|
||||
<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-if="deliveryOrder.payment_type == 4">Other</span>
|
||||
<span v-else>Not Specified</span>
|
||||
</div>
|
||||
<div v-if="userCardfound && [1, 2, 3].includes(deliveryOrder.payment_type)" class="bg-base-100 p-3 rounded-md mt-2 text-sm">
|
||||
<div class="font-mono">{{ userCard.type_of_card }}</div>
|
||||
<div class="font-mono">{{ userCard.card_number }}</div>
|
||||
<div>{{ userCard.name_on_card }}</div>
|
||||
<div>Expires: {{ userCard.expiration_month }}/{{ userCard.expiration_year }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<!--
|
||||
START: Replaced Payment Section
|
||||
-->
|
||||
<div class="p-4 border rounded-md">
|
||||
<label class="label-text font-bold">Payment Method</label>
|
||||
<div class="mt-1">
|
||||
<div class="text-lg">
|
||||
<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-if="deliveryOrder.payment_type == 4">Other</span>
|
||||
<span v-else>Not Specified</span>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
This is the new, styled card display.
|
||||
It uses the same logic but applies the better CSS classes.
|
||||
-->
|
||||
<div v-if="userCardfound && [1, 2, 3].includes(deliveryOrder.payment_type)"
|
||||
class="p-4 rounded-lg border mt-2"
|
||||
:class="userCard.main_card ? 'bg-primary/10 border-primary' : 'bg-base-200 border-base-300'">
|
||||
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<div class="font-bold">{{ userCard.name_on_card }}</div>
|
||||
<div class="text-xs opacity-70">{{ userCard.type_of_card }}</div>
|
||||
</div>
|
||||
<div v-if="userCard.main_card" class="badge badge-primary badge-sm">Primary</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 text-sm font-mono tracking-wider">
|
||||
<!-- Using last_four_digits is more secure and looks cleaner -->
|
||||
<p>**** **** **** {{ userCard.last_four_digits }}</p>
|
||||
<p>
|
||||
Exp:
|
||||
<!-- Adds a leading zero for single-digit months -->
|
||||
<span v-if="Number(userCard.expiration_month) < 10">0</span>{{ userCard.expiration_month }} / {{ userCard.expiration_year }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notes & Options -->
|
||||
<div class="p-4 border rounded-md">
|
||||
@@ -180,8 +207,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex flex-wrap gap-2 pt-4">
|
||||
<!--
|
||||
FIX #2: Add a v-if guard to the container.
|
||||
This prevents the links from rendering until `deliveryOrder.id` is available.
|
||||
-->
|
||||
<div v-if="deliveryOrder && deliveryOrder.id" class="flex flex-wrap gap-2 pt-4">
|
||||
<router-link :to="{ name: 'deliveryEdit', params: { id: deliveryOrder.id } }">
|
||||
<button class="btn btn-secondary btn-sm">Edit Delivery</button>
|
||||
</router-link>
|
||||
@@ -196,7 +226,6 @@
|
||||
</div>
|
||||
<Footer />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import axios from 'axios'
|
||||
@@ -221,7 +250,7 @@ export default defineComponent({
|
||||
return {
|
||||
v$: useValidate(),
|
||||
user: {
|
||||
id: 0
|
||||
user_id: 0
|
||||
},
|
||||
priceprime: 0,
|
||||
pricesameday: 0,
|
||||
@@ -232,19 +261,18 @@ export default defineComponent({
|
||||
deliveryNotesDriver: [],
|
||||
userCardfound: false,
|
||||
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: '',
|
||||
},
|
||||
|
||||
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: {
|
||||
account_number: '',
|
||||
id: 0,
|
||||
@@ -358,7 +386,7 @@ export default defineComponent({
|
||||
text: "deleted delivery",
|
||||
type: "success",
|
||||
});
|
||||
this.$router.push({ name: "customerProfile", params: { id: this.customer.id } });
|
||||
this.$router.push({ name: "customerProfile", params: { id: this.customer.user_id } });
|
||||
} else {
|
||||
notify({
|
||||
title: "Failure",
|
||||
@@ -379,7 +407,7 @@ export default defineComponent({
|
||||
.then((response: any) => {
|
||||
if (response.data.ok) {
|
||||
this.user = response.data.user;
|
||||
this.user.id = response.data.user_id;
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -445,34 +473,40 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
|
||||
getOilOrder(delivery_id: any) {
|
||||
let path = import.meta.env.VITE_BASE_URL + "/delivery/order/" + delivery_id;
|
||||
axios({
|
||||
method: "get",
|
||||
url: path,
|
||||
withCredentials: true,
|
||||
headers: authHeader(),
|
||||
})
|
||||
.then((response: any) => {
|
||||
if (response.data) {
|
||||
this.deliveryOrder = response.data
|
||||
this.getCustomer(this.deliveryOrder.customer_id)
|
||||
if (this.deliveryOrder.payment_type == 1) {
|
||||
this.getPaymentCard(this.deliveryOrder.payment_card_id);
|
||||
}
|
||||
if (this.deliveryOrder.payment_type == 2) {
|
||||
this.getPaymentCard(this.deliveryOrder.payment_card_id);
|
||||
}
|
||||
if (this.deliveryOrder.payment_type == 3) {
|
||||
this.getPaymentCard(this.deliveryOrder.payment_card_id);
|
||||
}
|
||||
if (this.deliveryOrder.promo_id != null) {
|
||||
this.getPromo(this.deliveryOrder.promo_id);
|
||||
}
|
||||
getOilOrder(delivery_id: any) {
|
||||
if (!delivery_id) { // Add a guard to prevent calls with an undefined ID
|
||||
console.error("getOilOrder called with no ID.");
|
||||
return;
|
||||
}
|
||||
let path = import.meta.env.VITE_BASE_URL + "/delivery/" + delivery_id;
|
||||
axios({
|
||||
method: "get",
|
||||
url: path,
|
||||
withCredentials: true,
|
||||
headers: authHeader(),
|
||||
})
|
||||
.then((response: any) => {
|
||||
// FIX: Check for the 'ok' flag and access the nested 'delivery' object
|
||||
if (response.data && response.data.ok) {
|
||||
this.deliveryOrder = response.data.delivery; // <-- THIS IS THE CRITICAL CHANGE
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
// Now that this.deliveryOrder is the correct object, the rest of the logic will work.
|
||||
this.getCustomer(this.deliveryOrder.customer_id);
|
||||
|
||||
if ([1, 2, 3].includes(this.deliveryOrder.payment_type)) {
|
||||
this.getPaymentCard(this.deliveryOrder.payment_card_id);
|
||||
}
|
||||
if (this.deliveryOrder.promo_id != null) {
|
||||
this.getPromo(this.deliveryOrder.promo_id);
|
||||
}
|
||||
} else {
|
||||
console.error("API Error:", response.data.error || "Failed to fetch delivery data.");
|
||||
notify({ title: "Error", text: "Could not load delivery details.", type: "error" });
|
||||
}
|
||||
})
|
||||
.catch( console.log("")
|
||||
);
|
||||
},
|
||||
getOilOrderMoney(delivery_id: any) {
|
||||
let path = import.meta.env.VITE_MONEY_URL + "/delivery/order/money/" + delivery_id;
|
||||
axios({
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- Header: Title and Count -->
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold">Archived Cancelled Deliveries</h2>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} items Found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} items Found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- Header: Title and Count -->
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold">Deliveries Awaiting Finalization</h2>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} items Found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} items Found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<!-- Header: Title and Count -->
|
||||
<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>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} items Found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} items Found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<!-- Header: Title and Count -->
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold">Deliveries Requiring Attention</h2>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} items Found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} items Found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<!-- Header: Title and Count -->
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold">Deliveries Awaiting Payment</h2>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} items Found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} items Found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<h2 class="text-lg font-bold">Todays Deliveries</h2>
|
||||
<div class="form-control">
|
||||
<label class="label pt-1 pb-0">
|
||||
<span class="label-text-alt">{{ recordsLength }} deliveries found</span>
|
||||
<!-- <span class="label-text-alt">{{ recordsLength }} deliveries found</span> -->
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<!-- Header: Title and Count (No Search Input) -->
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold">Deliveries Scheduled</h2>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} deliveries found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} deliveries found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<!-- Header: Title and Count -->
|
||||
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
|
||||
<h2 class="text-lg font-bold">Deliveries Awaiting Dispatch</h2>
|
||||
<div class="badge badge-ghost">{{ recordsLength }} deliveries found</div>
|
||||
<!-- <div class="badge badge-ghost">{{ recordsLength }} deliveries found</div> -->
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
Reference in New Issue
Block a user