feat(ui): Massive frontend modernization including customer table redesign, new map features, and consistent styling
This commit is contained in:
@@ -9,19 +9,35 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Card -->
|
||||
<div class="bg-neutral rounded-lg p-4 sm:p-6 mt-6">
|
||||
<!-- 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> -->
|
||||
<!-- Page Header with Stats -->
|
||||
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4 mt-4 mb-6">
|
||||
<div>
|
||||
<h1 class="text-2xl md:text-3xl font-bold flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-xl bg-gradient-to-br from-primary to-primary/60 flex items-center justify-center shadow-lg">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-5 h-5 text-primary-content">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
Pending Deliveries
|
||||
</h1>
|
||||
<p class="text-base-content/60 mt-1 ml-13">Awaiting payment or credit approval</p>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<!-- Quick Stats -->
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<div class="stat-pill">
|
||||
<span class="stat-pill-value">{{ recordsLength }}</span>
|
||||
<span class="stat-pill-label">Deliveries</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Table Card -->
|
||||
<div class="modern-table-card">
|
||||
|
||||
<!-- DESKTOP VIEW: Table -->
|
||||
<div class="overflow-x-auto hidden xl:block">
|
||||
<table class="table w-full">
|
||||
<div class="hidden xl:block overflow-x-auto">
|
||||
<table class="modern-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Delivery #</th>
|
||||
@@ -63,8 +79,8 @@
|
||||
<div class="text-xs opacity-70">{{ oil.customer_address }}</div>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="oil.customer_asked_for_fill == 1" class="badge badge-info">FILL</span>
|
||||
<span v-else>{{ oil.gallons_ordered }}</span>
|
||||
<span v-if="oil.customer_asked_for_fill == 1" class="badge badge-info text-lg h-auto py-1">FILL</span>
|
||||
<span v-else class="inline-flex items-center gap-1 px-3 py-1.5 rounded-lg bg-success/10 border border-success/20 text-success font-mono text-lg font-bold shadow-sm">{{ oil.gallons_ordered }} gal</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="oil.payment_type == 0">Cash</span>
|
||||
@@ -81,11 +97,11 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<router-link :to="{ name: 'deliveryOrder', params: { id: oil.id } }" class="btn btn-sm btn-ghost">View</router-link>
|
||||
<router-link :to="{ name: 'deliveryEdit', params: { id: oil.id } }" class="btn btn-sm btn-secondary">Edit</router-link>
|
||||
<router-link :to="{ name: 'finalizeTicket', params: { id: oil.id } }" class="btn btn-sm btn-accent">Finalize</router-link>
|
||||
<router-link :to="{ name: 'Ticket', params: { id: oil.id } }" class="btn btn-sm btn-success">Print</router-link>
|
||||
<div class="flex items-center justify-end gap-1">
|
||||
<router-link :to="{ name: 'deliveryOrder', params: { id: oil.id } }" class="btn btn-xs btn-ghost">View</router-link>
|
||||
<router-link :to="{ name: 'deliveryEdit', params: { id: oil.id } }" class="btn btn-xs btn-info btn-outline">Edit</router-link>
|
||||
<router-link :to="{ name: 'finalizeTicket', params: { id: oil.id } }" class="btn btn-xs btn-accent btn-outline">Finalize</router-link>
|
||||
<router-link :to="{ name: 'Ticket', params: { id: oil.id } }" class="btn btn-xs btn-success btn-outline">Print</router-link>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -97,12 +113,21 @@
|
||||
<!-- MOBILE VIEW: Cards -->
|
||||
<div class="xl:hidden space-y-4">
|
||||
<template v-for="oil in deliveries" :key="oil.id">
|
||||
<div v-if="oil.id" class="card bg-base-100 shadow-md">
|
||||
<div class="card-body p-4">
|
||||
<div
|
||||
v-if="oil.id"
|
||||
class="mobile-card"
|
||||
:class="{
|
||||
'mobile-card-urgent': oil.emergency,
|
||||
'mobile-card-prime': oil.prime && !oil.emergency,
|
||||
'mobile-card-sameday': oil.same_day && !oil.prime && !oil.emergency
|
||||
}"
|
||||
>
|
||||
<!-- Card content adapted to new style but preserving data fields -->
|
||||
<div class="p-3">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<h2 class="card-title text-base">{{ oil.customer_name }}</h2>
|
||||
<p class="text-xs text-gray-400">Delivery #{{ oil.id }}</p>
|
||||
<h2 class="text-base font-bold">{{ oil.customer_name }}</h2>
|
||||
<p class="text-xs text-base-content/60">Delivery #{{ oil.id }}</p>
|
||||
</div>
|
||||
<div class="badge" :class="{
|
||||
'badge-warning': oil.delivery_status == 0,
|
||||
@@ -124,27 +149,38 @@
|
||||
<div v-if="oil.emergency" class="badge badge-error badge-sm">EMERGENCY</div>
|
||||
</div>
|
||||
|
||||
<div class="text-sm mt-2 grid grid-cols-2 gap-x-4 gap-y-1">
|
||||
<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">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>
|
||||
</p>
|
||||
<p><strong class="font-semibold">Payment:</strong>
|
||||
<span v-if="oil.payment_type == 0">Cash</span>
|
||||
<span v-else-if="oil.payment_type == 1">CC</span>
|
||||
<span v-else-if="oil.payment_type == 2">Cash/CC</span>
|
||||
<span v-else-if="oil.payment_type == 3">Check</span>
|
||||
<span v-else-if="oil.payment_type == 4">Other</span>
|
||||
</p>
|
||||
<div class="text-sm mt-3 grid grid-cols-2 gap-x-4 gap-y-2">
|
||||
<div>
|
||||
<p class="text-xs text-base-content/50">Address</p>
|
||||
<p class="font-medium">{{ oil.customer_address }}</p>
|
||||
<p class="text-xs">{{ oil.customer_town }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-base-content/50">Gallons</p>
|
||||
<p class="font-bold text-lg text-success">
|
||||
<span v-if="oil.customer_asked_for_fill" class="badge badge-info badge-xs">FILL</span>
|
||||
<span v-else>{{ oil.gallons_ordered }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs text-base-content/50">Payment</p>
|
||||
<span v-if="oil.payment_type == 0">Cash</span>
|
||||
<span v-else-if="oil.payment_type == 1">CC</span>
|
||||
<span v-else-if="oil.payment_type == 2">Cash/CC</span>
|
||||
<span v-else-if="oil.payment_type == 3">Check</span>
|
||||
<span v-else-if="oil.payment_type == 4">Other</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-actions justify-end flex-wrap gap-2 mt-2">
|
||||
<router-link :to="{ name: 'deliveryOrder', params: { id: oil.id } }" class="btn btn-sm btn-ghost">View</router-link>
|
||||
<router-link :to="{ name: 'deliveryEdit', params: { id: oil.id } }" class="btn btn-sm btn-secondary">Edit</router-link>
|
||||
<router-link :to="{ name: 'finalizeTicket', params: { id: oil.id } }" class="btn btn-sm btn-accent">Finalize</router-link>
|
||||
<router-link :to="{ name: 'Ticket', params: { id: oil.id } }" class="btn btn-sm btn-success">Print</router-link>
|
||||
<div class="flex gap-2 pt-3 mt-3 border-t border-base-content/10">
|
||||
<router-link :to="{ name: 'deliveryOrder', params: { id: oil.id } }" class="btn btn-sm btn-ghost flex-1">View</router-link>
|
||||
<router-link :to="{ name: 'deliveryEdit', params: { id: oil.id } }" class="btn btn-sm btn-info btn-outline flex-1">Edit</router-link>
|
||||
<router-link :to="{ name: 'finalizeTicket', params: { id: oil.id } }" class="btn btn-sm btn-accent btn-outline flex-1">Finalize</router-link>
|
||||
<router-link :to="{ name: 'Ticket', params: { id: oil.id } }" class="btn btn-sm btn-success btn-outline">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6.72 13.829c-.24.03-.48.062-.72.096m.72-.096a42.415 42.415 0 0110.56 0m-10.56 0L6.34 18m10.94-4.171c.24.03.48.062.72.096m-.72-.096L17.66 18m0 0l.229 2.523a1.125 1.125 0 01-1.12 1.227H7.231c-.662 0-1.18-.568-1.12-1.227L6.34 18m11.318 0h1.091A2.25 2.25 0 0021 15.75V9.456c0-1.081-.768-2.015-1.837-2.175a48.055 48.055 0 00-1.913-.247M6.34 18H5.25A2.25 2.25 0 013 15.75V9.456c0-1.081.768-2.015 1.837-2.175a48.041 48.041 0 011.913-.247m10.5 0a48.536 48.536 0 00-10.5 0m10.5 0V3.375c0-.621-.504-1.125-1.125-1.125h-8.25c-.621 0-1.125.504-1.125 1.125v3.659M18 10.5h.008v.008H18V10.5zm-3 0h.008v.008H15V10.5z" />
|
||||
</svg>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -245,4 +281,187 @@ onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
/* Stat Pills */
|
||||
.stat-pill {
|
||||
@apply flex items-center gap-2 px-4 py-2 rounded-xl bg-base-200/80 border border-base-content/5;
|
||||
}
|
||||
.stat-pill-value {
|
||||
@apply text-xl font-bold;
|
||||
}
|
||||
.stat-pill-label {
|
||||
@apply text-xs text-base-content/60 uppercase tracking-wider;
|
||||
}
|
||||
.stat-pill-success {
|
||||
@apply bg-success/10 border-success/20;
|
||||
}
|
||||
.stat-pill-success .stat-pill-value {
|
||||
@apply text-success;
|
||||
}
|
||||
.stat-pill-info {
|
||||
@apply bg-info/10 border-info/20;
|
||||
}
|
||||
.stat-pill-info .stat-pill-value {
|
||||
@apply text-info;
|
||||
}
|
||||
|
||||
/* Town Chips */
|
||||
.town-chip {
|
||||
@apply flex items-center gap-2 px-3 py-1.5 rounded-full bg-base-200 hover:bg-base-300 transition-all text-sm whitespace-nowrap cursor-pointer;
|
||||
}
|
||||
.town-chip-count {
|
||||
@apply px-2 py-0.5 rounded-full bg-base-content/10 text-xs font-mono;
|
||||
}
|
||||
.town-chip-active {
|
||||
@apply bg-primary text-primary-content;
|
||||
}
|
||||
.town-chip-active .town-chip-count {
|
||||
@apply bg-primary-content/20;
|
||||
}
|
||||
.town-chip-clear {
|
||||
@apply bg-error/10 text-error hover:bg-error/20;
|
||||
}
|
||||
|
||||
/* Modern Table Card */
|
||||
.modern-table-card {
|
||||
@apply bg-gradient-to-br from-neutral to-neutral/80 rounded-2xl shadow-xl border border-base-content/5 overflow-hidden;
|
||||
}
|
||||
|
||||
/* Modern Table */
|
||||
.modern-table {
|
||||
@apply w-full;
|
||||
}
|
||||
.modern-table thead {
|
||||
@apply bg-base-content/5;
|
||||
}
|
||||
.modern-table th {
|
||||
@apply px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-base-content/60;
|
||||
}
|
||||
.modern-table td {
|
||||
@apply px-4 py-4;
|
||||
}
|
||||
.modern-table tbody tr {
|
||||
@apply border-t border-base-content/5;
|
||||
}
|
||||
|
||||
/* Sort Header */
|
||||
.sort-header {
|
||||
@apply flex items-center gap-1 hover:text-primary transition-colors cursor-pointer;
|
||||
}
|
||||
|
||||
/* Table Row Hover */
|
||||
.table-row-hover {
|
||||
@apply transition-all duration-200;
|
||||
}
|
||||
.table-row-hover:hover {
|
||||
@apply bg-primary/5;
|
||||
}
|
||||
|
||||
/* Row urgency highlighting */
|
||||
.row-urgent {
|
||||
@apply bg-error/5 border-l-4 border-l-error;
|
||||
}
|
||||
.row-urgent:hover {
|
||||
@apply bg-error/10;
|
||||
}
|
||||
.row-prime {
|
||||
@apply bg-warning/5 border-l-4 border-l-warning;
|
||||
}
|
||||
.row-prime:hover {
|
||||
@apply bg-warning/10;
|
||||
}
|
||||
.row-sameday {
|
||||
@apply bg-info/5 border-l-4 border-l-info;
|
||||
}
|
||||
.row-sameday:hover {
|
||||
@apply bg-info/10;
|
||||
}
|
||||
|
||||
/* Status Badge */
|
||||
.status-badge {
|
||||
@apply inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium;
|
||||
}
|
||||
.status-dot {
|
||||
@apply w-1.5 h-1.5 rounded-full;
|
||||
}
|
||||
.status-waiting {
|
||||
@apply bg-warning/10 text-warning;
|
||||
}
|
||||
.status-waiting .status-dot {
|
||||
@apply bg-warning animate-pulse;
|
||||
}
|
||||
.status-outfordelivery {
|
||||
@apply bg-info/10 text-info;
|
||||
}
|
||||
.status-outfordelivery .status-dot {
|
||||
@apply bg-info animate-pulse;
|
||||
}
|
||||
.status-finalized {
|
||||
@apply bg-success/10 text-success;
|
||||
}
|
||||
.status-finalized .status-dot {
|
||||
@apply bg-success;
|
||||
}
|
||||
.status-cancelled, .status-issue {
|
||||
@apply bg-error/10 text-error;
|
||||
}
|
||||
.status-cancelled .status-dot, .status-issue .status-dot {
|
||||
@apply bg-error;
|
||||
}
|
||||
.status-default {
|
||||
@apply bg-base-content/10 text-base-content/60;
|
||||
}
|
||||
.status-default .status-dot {
|
||||
@apply bg-base-content/40;
|
||||
}
|
||||
|
||||
/* Special Tags */
|
||||
.special-tag {
|
||||
@apply inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-bold uppercase tracking-wide;
|
||||
}
|
||||
.tag-emergency {
|
||||
@apply bg-error text-error-content animate-pulse;
|
||||
}
|
||||
.tag-prime {
|
||||
@apply bg-warning text-warning-content;
|
||||
}
|
||||
.tag-sameday {
|
||||
@apply bg-info text-info-content;
|
||||
}
|
||||
|
||||
/* Gallons Badge */
|
||||
.gallons-badge {
|
||||
@apply inline-flex items-center gap-1 px-3 py-1.5 rounded-lg bg-success/10 border border-success/20 text-success font-mono text-lg font-bold shadow-sm;
|
||||
}
|
||||
.gallons-fill {
|
||||
@apply bg-info/10 text-info border-info/20;
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.action-btn {
|
||||
@apply p-2 rounded-lg hover:bg-base-content/10 transition-colors text-base-content/60 hover:text-base-content;
|
||||
}
|
||||
.action-btn-secondary {
|
||||
@apply hover:bg-secondary/20 hover:text-secondary;
|
||||
}
|
||||
.action-btn-accent {
|
||||
@apply hover:bg-accent/20 hover:text-accent;
|
||||
}
|
||||
.action-btn-success {
|
||||
@apply hover:bg-success/20 hover:text-success;
|
||||
}
|
||||
|
||||
/* Mobile Cards */
|
||||
.mobile-card {
|
||||
@apply bg-base-100/50 backdrop-blur-sm rounded-xl mb-4 shadow-sm border border-base-content/5;
|
||||
}
|
||||
.mobile-card-urgent {
|
||||
@apply border-l-4 border-l-error bg-error/5;
|
||||
}
|
||||
.mobile-card-prime {
|
||||
@apply border-l-4 border-l-warning bg-warning/5;
|
||||
}
|
||||
.mobile-card-sameday {
|
||||
@apply border-l-4 border-l-info bg-info/5;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user