diff --git a/COMPONENTS.md b/COMPONENTS.md
new file mode 100644
index 0000000..d11dade
--- /dev/null
+++ b/COMPONENTS.md
@@ -0,0 +1,262 @@
+# Component Library Documentation
+
+## Overview
+This document provides usage examples for all the enhanced UI components created for the EAMCO frontend.
+
+---
+
+## Components
+
+### 1. StatCard
+Animated statistics card with trend indicators.
+
+**Props:**
+- `label` (string, required) - Card label
+- `value` (number | string, required) - Value to display
+- `color` (string) - Color variant (primary, secondary, accent, info, success, warning, error)
+- `trend` (string) - Trend text
+- `trendDirection` (string) - up, down, or neutral
+- `animate` (boolean) - Enable number counting animation
+- `wrapperClass` (string) - Additional CSS classes
+
+**Usage:**
+```vue
+
+
+
+
+
+```
+
+---
+
+### 2. FloatingInput
+Modern input with floating label animation.
+
+**Props:**
+- `id` (string, required) - Input ID
+- `label` (string, required) - Label text
+- `modelValue` (string | number, required) - v-model value
+- `type` (string) - Input type (default: 'text')
+- `error` (string) - Error message
+- `hint` (string) - Hint text
+- `disabled` (boolean) - Disabled state
+- `required` (boolean) - Required field
+
+**Usage:**
+```vue
+
+```
+
+---
+
+### 3. EnhancedTable
+Feature-rich table with sticky headers and zebra striping.
+
+**Props:**
+- `columns` (Column[], required) - Column definitions
+- `data` (any[], required) - Table data
+- `title` (string) - Table title
+- `description` (string) - Table description
+- `stickyHeader` (boolean) - Enable sticky header
+- `zebra` (boolean) - Enable zebra striping
+- `rowKey` (string) - Unique row key (default: 'id')
+
+**Usage:**
+```vue
+
+
+
+ {{ value }}
+
+
+
+```
+
+---
+
+### 4. EnhancedButton
+Button with loading states, success animations, and ripple effects.
+
+**Props:**
+- `variant` (string) - primary, secondary, accent, success, warning, error, ghost, outline
+- `size` (string) - xs, sm, md, lg
+- `type` (string) - button, submit, reset
+- `disabled` (boolean) - Disabled state
+- `loading` (boolean) - Loading state
+- `success` (boolean) - Success state
+- `icon` (Component) - Icon component
+- `fullWidth` (boolean) - Full width button
+
+**Usage:**
+```vue
+
+ Save Changes
+
+```
+
+---
+
+### 5. EnhancedBadge
+Badge component with variants, pulse animations, and icons.
+
+**Props:**
+- `variant` (string) - primary, secondary, accent, info, success, warning, error, ghost
+- `size` (string) - xs, sm, md, lg
+- `outline` (boolean) - Outline style
+- `dot` (boolean) - Show status dot
+- `pulse` (boolean) - Pulse animation
+- `icon` (Component) - Icon component
+
+**Usage:**
+```vue
+
+ Active
+
+
+
+ Pending
+
+```
+
+---
+
+### 6. EnhancedModal
+Modal dialog with backdrop blur and smooth animations.
+
+**Props:**
+- `modelValue` (boolean, required) - v-model for open/close state
+- `title` (string) - Modal title
+- `description` (string) - Modal description
+- `size` (string) - sm, md, lg, xl, full
+- `hideHeader` (boolean) - Hide header
+- `hideClose` (boolean) - Hide close button
+- `closeOnOverlay` (boolean) - Close on overlay click
+- `noPadding` (boolean) - Remove body padding
+
+**Usage:**
+```vue
+
+
+
+
+
+ Cancel
+
+
+ Save
+
+
+
+```
+
+---
+
+### 7. PageTransition
+Wrapper component for page transitions.
+
+**Props:**
+- `name` (string) - fade, slide-left, slide-right, slide-up, slide-down, scale, rotate
+
+**Usage:**
+```vue
+
+
+
+```
+
+---
+
+### 8. LoadingCard
+Skeleton loader for cards.
+
+**Usage:**
+```vue
+
+
+```
+
+---
+
+### 9. EmptyState
+Empty state component with icon and action button.
+
+**Props:**
+- `title` (string, required) - Title text
+- `description` (string, required) - Description text
+- `actionLabel` (string) - Action button label
+
+**Usage:**
+```vue
+
+
+
+
+
+```
+
+---
+
+## Design Tokens
+
+### Shadow Utilities
+- `.shadow-soft` - Subtle elevation
+- `.shadow-medium` - Standard elevation
+- `.shadow-strong` - Strong elevation
+
+### Hover Effects
+- `.hover-lift` - Lift on hover with shadow
+
+### Animations
+- `animate-fade-in` - Fade in animation
+- `animate-slide-up` - Slide up animation
+- `animate-slide-down` - Slide down animation
+- `animate-scale-in` - Scale in animation
+
+---
+
+## Best Practices
+
+1. **Consistency**: Use the same component variants throughout the app
+2. **Accessibility**: Always provide labels and ARIA attributes
+3. **Performance**: Use loading states to indicate async operations
+4. **Feedback**: Show success/error states after user actions
+5. **Responsiveness**: Test components on all screen sizes
diff --git a/Dockerfile.dev b/Dockerfile.dev
index d4536dc..2e8b7a2 100755
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -5,6 +5,7 @@ ENV VITE_AUTO_URL="http://localhost:9514"
ENV VITE_MONEY_URL="http://localhost:9513"
ENV VITE_AUTHORIZE_URL="http://localhost:9516"
ENV VITE_VOIPMS_URL="http://localhost:9517"
+ENV VITE_SERVICE_URL="http://localhost:9515"
ENV VITE_VOIPMS_TOKEN="my_secret_token"
diff --git a/Dockerfile.local b/Dockerfile.local
index 6bd942c..93494fc 100644
--- a/Dockerfile.local
+++ b/Dockerfile.local
@@ -5,6 +5,7 @@ ENV VITE_AUTO_URL="http://192.168.1.204:9614"
ENV VITE_MONEY_URL="http://192.168.1.204:9613"
ENV VITE_AUTHORIZE_URL="http://192.168.1.204:9616"
ENV VITE_VOIPMS_URL="http://192.168.1.204:9617"
+ENV VITE_SERVICE_URL="http://192.168.1.204:9615"
ENV VITE_COMPANY_ID='1'
diff --git a/Dockerfile.prod b/Dockerfile.prod
index bf6bf82..cf5ffaa 100644
--- a/Dockerfile.prod
+++ b/Dockerfile.prod
@@ -9,6 +9,7 @@ ENV VITE_AUTO_URL="https://apiauto.edwineames.com"
ENV VITE_MONEY_URL="https://apimoney.edwineames.com"
ENV VITE_AUTHORIZE_URL="https://apicard.edwineames.com"
ENV VITE_VOIPMS_URL="https://apiphone.edwineames.com"
+ENV VITE_SERVICE_URL="https://apiservice.edwineames.com"
ENV VITE_VOIPMS_TOKEN="my_secret_token"
diff --git a/src/components/EmptyState.vue b/src/components/EmptyState.vue
new file mode 100644
index 0000000..a4fba04
--- /dev/null
+++ b/src/components/EmptyState.vue
@@ -0,0 +1,37 @@
+
+
+
+
{{ title }}
+
{{ description }}
+
+
+ {{ actionLabel }}
+
+
+
+
+
+
+
+
diff --git a/src/components/EnhancedBadge.vue b/src/components/EnhancedBadge.vue
new file mode 100644
index 0000000..2feddfb
--- /dev/null
+++ b/src/components/EnhancedBadge.vue
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/EnhancedButton.vue b/src/components/EnhancedButton.vue
new file mode 100644
index 0000000..950b154
--- /dev/null
+++ b/src/components/EnhancedButton.vue
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/EnhancedModal.vue b/src/components/EnhancedModal.vue
new file mode 100644
index 0000000..623bc04
--- /dev/null
+++ b/src/components/EnhancedModal.vue
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/EnhancedTable.vue b/src/components/EnhancedTable.vue
new file mode 100644
index 0000000..32a0d8f
--- /dev/null
+++ b/src/components/EnhancedTable.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+ {{ column.label }}
+
+
+
+
+
+
+
+ {{ row[column.key] }}
+
+
+
+
+
+
+
+
+
+
+
No data available
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/FloatingInput.vue b/src/components/FloatingInput.vue
new file mode 100644
index 0000000..8f1c943
--- /dev/null
+++ b/src/components/FloatingInput.vue
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
diff --git a/src/components/LoadingCard.vue b/src/components/LoadingCard.vue
new file mode 100644
index 0000000..fd47ffc
--- /dev/null
+++ b/src/components/LoadingCard.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/src/components/PageTransition.vue b/src/components/PageTransition.vue
new file mode 100644
index 0000000..210272d
--- /dev/null
+++ b/src/components/PageTransition.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/StatCard.vue b/src/components/StatCard.vue
new file mode 100644
index 0000000..9e36488
--- /dev/null
+++ b/src/components/StatCard.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
{{ label }}
+
{{ displayValue }}
+
+ {{ trendArrow }}
+ {{ trend }}
+
+
+
+
+
+
+
+
diff --git a/src/index.css b/src/index.css
index b155180..d9f3ae1 100755
--- a/src/index.css
+++ b/src/index.css
@@ -1,6 +1,61 @@
+/* Import modern font */
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
+/* Base styles */
+@layer base {
+ body {
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+}
+
+/* Custom utilities */
+@layer utilities {
+ /* Shadow system for elevation */
+ .shadow-soft {
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ }
+
+ .shadow-medium {
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
+ }
+
+ .shadow-strong {
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
+ }
+
+ /* Hover lift effect */
+ .hover-lift {
+ transition: transform 0.2s ease-out, box-shadow 0.2s ease-out;
+ }
+
+ .hover-lift:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
+ }
+
+ /* Smooth transitions */
+ .transition-smooth {
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
+ /* Gradient text */
+ .gradient-text {
+ background: linear-gradient(135deg, hsl(var(--p)) 0%, hsl(var(--a)) 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ }
+}
+
/* Hide header and sidebar when printing */
+@media print {
+ header, .drawer-side {
+ display: none !important;
+ }
+}
diff --git a/src/layouts/DefaultLayout.vue b/src/layouts/DefaultLayout.vue
index 45b0d27..65aa5d9 100644
--- a/src/layouts/DefaultLayout.vue
+++ b/src/layouts/DefaultLayout.vue
@@ -4,14 +4,19 @@
-
+
-
+
+
+
+
+
+
@@ -30,8 +35,9 @@
import { useSearchStore } from '../stores/search';
import HeaderAuth from './headers/headerauth.vue';
import SideBar from './sidebar/sidebar.vue';
-// Make sure this path and component name are correct
+import Footer from './footers/footer.vue';
import SearchResults from '../components/SearchResults.vue';
+import PageTransition from '../components/PageTransition.vue';
const searchStore = useSearchStore();
diff --git a/src/layouts/footers/footer.vue b/src/layouts/footers/footer.vue
index 5a6973f..154f6e9 100755
--- a/src/layouts/footers/footer.vue
+++ b/src/layouts/footers/footer.vue
@@ -1,5 +1,5 @@
-
-
diff --git a/src/layouts/headers/headerauth.vue b/src/layouts/headers/headerauth.vue
index ecf44f8..daf67c0 100755
--- a/src/layouts/headers/headerauth.vue
+++ b/src/layouts/headers/headerauth.vue
@@ -85,6 +85,15 @@
Profile
Change Password
+
+
+
+
+
+ {{ theme.label }}
+
+
+
Logout
@@ -219,6 +228,7 @@ import axios from 'axios'
import authHeader from '../../services/auth.header'
import { useSearchStore } from '../../stores/search' // Adjust path if needed
import { useAuthStore } from '../../stores/auth'
+import { useThemeStore, AVAILABLE_THEMES } from '../../stores/theme'
// Define the shape of your data for internal type safety
interface User {
@@ -253,6 +263,9 @@ const isTestModalVisible = ref(false)
const isTestLoading = ref(false)
const testResponse = ref(null as any)
+// Stores
+const themeStore = useThemeStore()
+
// Computed properties
const searchStore = computed(() => useSearchStore())
diff --git a/src/layouts/sidebar/sidebar.vue b/src/layouts/sidebar/sidebar.vue
index bc2ef8a..1c6f782 100755
--- a/src/layouts/sidebar/sidebar.vue
+++ b/src/layouts/sidebar/sidebar.vue
@@ -7,12 +7,24 @@
-
Home
+
+
+
+
+
+ Home
+
+
- Customer
+
+
+
+
+ Customer
+
@@ -22,7 +34,12 @@
- Delivery
+
+
+
+
+ Delivery
+
Home
@@ -58,7 +75,12 @@
- Service
+
+
+
+
+ Service
+
Service Calendar
@@ -82,7 +104,12 @@
- Automatics
+
+
+
+
+ Automatics
+
@@ -97,7 +124,12 @@
- Transactions
+
+
+
+
+ Transactions
+
-
+
- Admin
+
+
+
+
+
+ Admin
+
Employees
Oil Pricing
diff --git a/src/main.ts b/src/main.ts
index 09fe7c4..4076d7b 100755
--- a/src/main.ts
+++ b/src/main.ts
@@ -7,9 +7,16 @@ import router from './router';
import Notifications from '@kyvg/vue3-notification';
import Pagination from 'v-pagination-3';
import { createPinia } from 'pinia';
+import { useThemeStore } from './stores/theme';
+const pinia = createPinia()
const app = createApp(App)
- app.use(createPinia())
+ app.use(pinia)
app.use(router)
.component('pagination', Pagination);
- app.use(Notifications).mount('#app')
\ No newline at end of file
+
+// Initialize theme before mounting to prevent flash of default theme
+const themeStore = useThemeStore()
+themeStore.initTheme()
+
+app.use(Notifications).mount('#app')
\ No newline at end of file
diff --git a/src/pages/Index.vue b/src/pages/Index.vue
index 26be203..56ea892 100755
--- a/src/pages/Index.vue
+++ b/src/pages/Index.vue
@@ -13,76 +13,120 @@
-
+
-
-
-
Today's Stats
+
+
+
-
-
Total Deliveries Today:
-
{{ delivery_count }}
+
+ {{ delivery_count }}
+ total deliveries
-
-
Completed
-
{{ delivery_count_delivered }} / {{ delivery_count }}
+
+ Completed
+ {{ delivery_count_delivered }} / {{ delivery_count }}
-
+
-
-
Today's Oil Price
-
-
-
Price / Gallon:
-
${{ today_oil_price }}
+
+
+
Oil Pricing
+
-
- Same Day Fee:
- ${{ price_same_day }}
+
+
+
+ Per Gallon
+ ${{ today_oil_price }}
-
- Prime Fee:
- ${{ price_prime }}
-
-
-
Emergency Fee:
-
${{ price_emergency }}
+
+
+
+ Same Day
+ ${{ price_same_day }}
+
+
+ Prime
+ ${{ price_prime }}
+
+
+ Emergency
+ ${{ price_emergency }}
+
-
-
-
Service Price
-
-
-
Price / Hour:
-
$125
+
+
+
+
Service Pricing
+
-
- Price / Emergency:
- $200
+
+
+
+ Per Hour
+ $125
+
+
+ Emergency
+ $200
-
-
-
Customer Search Keys
-
-
@ - Searches customer last name only
-
! - Searches customer address only
-
# - Searches phone number only
-
$ - Searches account number only
+
+
+
+
+
+ @
+ Last name
+
+
+ !
+ Address
+
+
+ #
+ Phone number
+
+
+ $
+ Account number
+
+
-
+
@@ -248,7 +248,6 @@ import { serviceService } from '../../../services/serviceService'
import { adminService } from '../../../services/adminService'
import Header from '../../../layouts/headers/headerauth.vue'
import SideBar from '../../../layouts/sidebar/sidebar.vue'
-import Footer from '../../../layouts/footers/footer.vue'
import { notify } from "@kyvg/vue3-notification";
import "leaflet/dist/leaflet.css";
import L from 'leaflet';
@@ -269,7 +268,7 @@ import CreditCards from './profile/CreditCards.vue';
import CustomerComments from './profile/CustomerComments.vue';
import HistoryTabs from './profile/HistoryTabs.vue';
import TankEstimation from './TankEstimation.vue';
-import {AuthorizeTransaction} from '../../../types/models';
+import { AuthorizeTransaction, PricingData, CustomerDescriptionData, CustomersResponse, CustomerResponse, AxiosResponse, AxiosError } from '../../../types/models';
L.Icon.Default.mergeOptions({
iconUrl: iconUrl,
@@ -373,6 +372,15 @@ const isCreateAccountModalVisible = ref(false)
const isCreatingAccount = ref(false)
const createdProfileId = ref('')
const isDuplicateErrorModalVisible = ref(false) // Add for duplicate detection popup
+const pricing = ref
({
+ price_from_supplier: 0,
+ price_for_customer: 0,
+ price_for_employee: 0,
+ price_same_day: 0,
+ price_prime: 0,
+ price_emergency: 0,
+ date: ""
+})
// Computed
const hasPartsData = computed(() => {
@@ -403,7 +411,7 @@ onMounted(() => {
})
// Functions
-const getPage = (page: any) => {
+const getPage = (page: number) => {
if (customer.value && customer.value.id) {
getCustomerDelivery(customer.value.id, page);
}
@@ -411,8 +419,14 @@ const getPage = (page: any) => {
const getCustomer = (userid: number) => {
if (!userid) return;
- customerService.getById(userid).then((response: any) => {
- customer.value = response.data?.customer || response.data;
+ customerService.getById(userid).then((response: AxiosResponse) => {
+ // Correctly handle response structure - backend may return wrapped { customer: ... } or flat
+ const data = response.data;
+ customer.value = data.customer || data;
+ // Handle pricing - it might be missing or nested
+ if (data.pricing) {
+ pricing.value = data.pricing;
+ }
// --- DEPENDENT API CALLS ---
userStatus();
@@ -436,7 +450,8 @@ const getCustomer = (userid: number) => {
getCustomerTransactions(customer.value.id);
checkAuthorizeAccount();
- }).catch((error: any) => {
+ }).catch((err: unknown) => {
+ const error = err as AxiosError;
console.error("CRITICAL: Failed to fetch main customer data. Aborting other calls.", error);
});
}
@@ -450,7 +465,7 @@ const userStatus = () => {
}
const userAutomaticStatus = (userid: number) => {
- customerService.getAutomaticStatus(userid).then((response: any) => {
+ customerService.getAutomaticStatus(userid).then((response: AxiosResponse) => {
automatic_status.value = response.data.status
if (automatic_status.value === 1) {
getCustomerAutoDelivery(customer.value.id)
@@ -460,55 +475,29 @@ const userAutomaticStatus = (userid: number) => {
}
const userAutomatic = (userid: number) => {
- customerService.assignAutomatic(userid, { status: 0 }).then((response: any) => { // Status is handled by backend toggle? Or do I need to send current?
- // The original code was GET /customer/automatic/assign/{userid}. Wait, GET?
- // customerService.assignAutomatic is PUT with data.
- // Let's check the original code again.
- // Original: axios({ method: 'get', url: .../assign/userid })
- // Only GET? That's weird for assignment.
- // Let's assume it toggles or something.
- // customerService.assignAutomatic uses PUT.
- // I should check if backend supports GET for assignment or if I made a mistake in customerService definition.
- // If backend expects GET, I should use api.get via a custom call or update the service.
- // But assuming I want to migrate standardly...
- // Let's check the implementation plan/service again.
- // Ideally I'd fix the backend to be PUT/POST.
- // But for now, let's look at what `customerService` has.
- // `assignAutomatic: (id: number, data: { status: number }) => api.put(...)`
- // The original code was GET.
- // I'll stick to the existing behavior or use a raw api call if service is wrong.
- // Checking `customerService.ts`: `api.put`.
- // Checking `profile.vue`: `method: 'get'`.
- // mismatch!
- // I will use `api.get` directly here if service doesn't match, OR update service.
- // I'll use `api.get` for now via `customerService` if I add a method `toggleAutomatic`.
- // Or just use `api` imported from service.
- // I replaced axios imports, so I don't have axios.
- // I should import `api` from usage in services? No, I imported services.
- // I'll assume `customerService` should be updated or use `customerService.assignAutomatic` if the backend actually supports PUT too.
- // If not, I might break it.
- // Let's check `views.py` for `/customer/automatic/assign/`? No time.
- // I'll assume the service was written correctly for the *intended* API, maybe the frontend was using GET legacy.
- // I will use `customerService.assignAutomatic` but wait, it needs data.
- // The original didn't send data.
- // This is risky.
- // Use `api.get`? I didn't import `api`.
- // I'll skip migrating `userAutomatic` for a second and handle it in the next batch or add `toggleAutomatic` to `customerService`.
- // Let's skip `userAutomatic` replacement in this chunk and do it later.
- // Wait, I am replacing the block containing it.
- // I will leave `userAutomatic` using `customerService` but I need to be careful.
- // Let's look at `customerService` again.
- // I'll modify `customerService` to add `toggleAutomatic`.
- // But I can't do that in this tool call.
- // I'll leave `userAutomatic` as is (raw axios?) No, axios is gone.
- // I'll comment it out or put a placeholder?
- // No, I'll use `customerService` and hope `put` works, or I'll fix `customerService` in next step.
- // Actually, I can import `api` from `../../services/api`.
- // I'll add `import api from '../../../services/api'` to imports.
-
- // RE-PLAN: Add `import api` to imports.
- // Then use `api.get` for `userAutomatic` to replicate exact behavior.
- })
+ // Toggle status: 1 -> 0, 0 -> 1
+ const newStatus = automatic_status.value === 1 ? 0 : 1;
+ customerService.assignAutomatic(userid, { status: newStatus }).then((response: AxiosResponse) => {
+ // Update local status from response or the requested value
+ if (response.data && typeof response.data.status !== 'undefined') {
+ automatic_status.value = response.data.status;
+ } else {
+ automatic_status.value = newStatus;
+ }
+
+ if (automatic_status.value === 1) {
+ getCustomerAutoDelivery(customer.value.id);
+ }
+ checktotalOil(customer.value.id);
+ notify({
+ title: "Automatic Status Updated",
+ text: automatic_status.value === 1 ? "Customer set to Automatic" : "Customer set to Will Call",
+ type: "success"
+ });
+ }).catch((err: unknown) => {
+ console.error("Failed to update automatic status", err);
+ notify({ title: "Error", text: "Failed to update status", type: "error" });
+ });
}
const getNozzleColor = (nozzleString: string): string => {
@@ -523,54 +512,53 @@ const getNozzleColor = (nozzleString: string): string => {
}
const getCustomerLastDelivery = (userid: number) => {
- adminService.stats.userLastDelivery(userid).then((response: any) => {
+ adminService.stats.userLastDelivery(userid).then((response: AxiosResponse) => {
customer_last_delivery.value = response.data.date
})
}
const getCustomerStats = (userid: number) => {
- adminService.stats.userStats(userid).then((response: any) => {
+ adminService.stats.userStats(userid).then((response: AxiosResponse) => {
customer_stats.value = response.data
})
}
const checktotalOil = (userid: number) => {
- adminService.stats.customerGallonsTotal(userid) // Just a check? Original didn't do anything with response.
+ adminService.stats.customerGallonsTotal(userid) // Just a check
}
const getCustomerDescription = (userid: number) => {
- customerService.getDescription(userid).then((response: any) => {
- customer_description.value = response.data?.description || response.data || {}
+ customerService.getDescription(userid).then((response: AxiosResponse) => {
+ customer_description.value = response.data?.description || (response.data as unknown as CustomerDescriptionData);
})
}
const getCustomerTank = (userid: number) => {
- customerService.getTank(userid).then((response: any) => {
+ customerService.getTank(userid).then((response: AxiosResponse) => {
customer_tank.value = response.data
})
}
const getCreditCards = (user_id: number) => {
- paymentService.getCards(user_id).then((response: any) => {
+ paymentService.getCards(user_id).then((response: AxiosResponse) => {
credit_cards.value = response.data?.cards || []
})
}
const getCreditCardsCount = (user_id: number) => {
- paymentService.getCardsOnFile(user_id).then((response: any) => {
+ paymentService.getCardsOnFile(user_id).then((response: AxiosResponse) => {
credit_cards_count.value = response.data.cards
})
}
const getCustomerAutoDelivery = (userid: number) => {
- deliveryService.auto.getProfileDeliveries(userid).then((response: any) => {
+ deliveryService.auto.getProfileDeliveries(userid).then((response: AxiosResponse) => {
autodeliveries.value = response.data || []
- console.log(autodeliveries.value)
})
}
const getCustomerDelivery = (userid: number, delivery_page: number) => {
- deliveryService.getByCustomer(userid, delivery_page).then((response: any) => {
+ deliveryService.getByCustomer(userid, delivery_page).then((response: AxiosResponse) => {
deliveries.value = response.data?.deliveries || []
})
}
@@ -583,14 +571,14 @@ const removeCard = (card_id: number) => {
paymentService.removeCard(card_id).then(() => {
credit_cards.value = credit_cards.value.filter(card => card.id !== card_id);
credit_cards_count.value--;
- notify({ title: "Card Status", text: "Card Removed", type: "Success" });
+ notify({ title: "Card Status", text: "Card Removed", type: "success" });
}).catch(() => {
notify({ title: "Error", text: "Could not remove card.", type: "error" });
});
}
const deleteCall = (delivery_id: number) => {
- deliveryService.delete(delivery_id).then((response: any) => {
+ deliveryService.delete(delivery_id).then((response: AxiosResponse) => {
if (response.data.ok) {
notify({ title: "Success", text: "deleted delivery", type: "success" });
getPage(1)
@@ -601,22 +589,22 @@ const deleteCall = (delivery_id: number) => {
}
const deleteCustomerSocial = (comment_id: number) => {
- adminService.social.deletePost(comment_id).then((response: any) => {
+ adminService.social.deletePost(comment_id).then((response: AxiosResponse) => {
getCustomerSocial(customer.value.id, 1)
})
}
const getCustomerSocial = (userid: number, delivery_page: number) => {
- adminService.social.getPosts(userid, delivery_page).then((response: any) => {
+ adminService.social.getPosts(userid, delivery_page).then((response: AxiosResponse) => {
comments.value = response.data?.posts || []
})
}
const CreateSocialComment = (payload: { comment: string; poster_employee_id: number }) => {
- adminService.social.createPost(customer.value.id, payload).then((response: any) => {
+ adminService.social.createPost(customer.value.id, payload).then((response: AxiosResponse) => {
if (response.data.ok) {
getCustomerSocial(customer.value.id, 1)
- } else if (response.data.error) { // Verify error handling logic
+ } else if (response.data.error) {
router.push("/");
}
})
@@ -633,7 +621,7 @@ const onSubmitSocial = (commentText: string) => {
}
const getServiceCalls = (customerId: number) => {
- serviceService.getForCustomer(customerId).then((response: any) => {
+ serviceService.getForCustomer(customerId).then((response: AxiosResponse) => {
serviceCalls.value = response.data?.services || [];
}).catch((error: any) => {
console.error("Failed to get customer service calls:", error);
@@ -642,7 +630,7 @@ const getServiceCalls = (customerId: number) => {
}
const getCustomerTransactions = (customerId: number) => {
- paymentService.getCustomerTransactions(customerId, 1).then((response: any) => {
+ paymentService.getCustomerTransactions(customerId, 1).then((response: AxiosResponse) => {
transactions.value = response.data?.transactions || [];
}).catch((error: any) => {
console.error("Failed to get customer transactions:", error);
@@ -685,7 +673,11 @@ const handleDeleteService = async (serviceId: number) => {
const fetchCustomerParts = async (customerId: number) => {
try {
const response = await serviceService.getPartsForCustomer(customerId);
- currentParts.value = response.data?.parts || response.data;
+ if (response.data && 'parts' in response.data && Array.isArray(response.data.parts) && response.data.parts.length > 0) {
+ currentParts.value = response.data.parts[0];
+ } else {
+ currentParts.value = null;
+ }
} catch (error) {
console.error("Failed to fetch customer parts:", error);
}
diff --git a/src/pages/customer/tank/edit.vue b/src/pages/customer/tank/edit.vue
index bbc79b9..45c4940 100644
--- a/src/pages/customer/tank/edit.vue
+++ b/src/pages/customer/tank/edit.vue
@@ -82,7 +82,7 @@
-
+
diff --git a/src/pages/delivery/view.vue b/src/pages/delivery/view.vue
index 44f4fe7..52057e2 100755
--- a/src/pages/delivery/view.vue
+++ b/src/pages/delivery/view.vue
@@ -352,7 +352,7 @@
-
+
diff --git a/src/pages/delivery/viewstatus/cancelled.vue b/src/pages/delivery/viewstatus/cancelled.vue
index 778e730..34002e8 100755
--- a/src/pages/delivery/viewstatus/cancelled.vue
+++ b/src/pages/delivery/viewstatus/cancelled.vue
@@ -123,19 +123,17 @@
-
+
+
\ No newline at end of file
diff --git a/src/pages/delivery/viewstatus/todaysdeliveries.vue b/src/pages/delivery/viewstatus/todaysdeliveries.vue
index 6829180..1298b7e 100755
--- a/src/pages/delivery/viewstatus/todaysdeliveries.vue
+++ b/src/pages/delivery/viewstatus/todaysdeliveries.vue
@@ -167,25 +167,27 @@
-
+
\ No newline at end of file
+
+// Lifecycle
+onMounted(() => {
+ userStatus();
+ loadHolidays();
+})
+
+
+
\ No newline at end of file
diff --git a/src/pages/service/ServiceEditModal.vue b/src/pages/service/ServiceEditModal.vue
index be21390..3de8b53 100644
--- a/src/pages/service/ServiceEditModal.vue
+++ b/src/pages/service/ServiceEditModal.vue
@@ -102,8 +102,8 @@
diff --git a/src/pages/service/ServiceHome.vue b/src/pages/service/ServiceHome.vue
index df5a664..117c2ce 100644
--- a/src/pages/service/ServiceHome.vue
+++ b/src/pages/service/ServiceHome.vue
@@ -146,7 +146,7 @@
-
+
\ No newline at end of file
diff --git a/src/pages/service/calender/api.js b/src/pages/service/calender/api.js
deleted file mode 100644
index 7e4e57e..0000000
--- a/src/pages/service/calender/api.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import axios from 'axios';
-
-const BASE_URL = import.meta.env.VITE_BASE_URL;
-
-function authHeader() {
- // Return authorization header
- return {};
-}
-
-export function createEvent(payload) {
- const path = `${BASE_URL}/service/create`; // Example endpoint
- return axios.post(path, payload, {
- withCredentials: true,
- headers: authHeader(),
- });
-}
-
-export function deleteEventById(eventId) {
- const path = `${BASE_URL}/service/delete/${eventId}`; // Example endpoint
- return axios.delete(path, {
- withCredentials: true,
- headers: authHeader(),
- });
-}
\ No newline at end of file
diff --git a/src/pages/ticket/ticketauto.vue b/src/pages/ticket/ticketauto.vue
index c710b54..429d6fd 100644
--- a/src/pages/ticket/ticketauto.vue
+++ b/src/pages/ticket/ticketauto.vue
@@ -107,7 +107,6 @@ import axios from 'axios'
import authHeader from '../../services/auth.header'
import Header from '../../layouts/headers/headerauth.vue'
import SideBar from '../../layouts/sidebar/sidebar.vue'
-import Footer from '../../layouts/footers/footer.vue'
import { notify } from "@kyvg/vue3-notification"
export default defineComponent({
@@ -116,7 +115,6 @@ export default defineComponent({
components: {
Header,
SideBar,
- Footer,
},
data() {
diff --git a/src/pages/transactions/authorize/index.vue b/src/pages/transactions/authorize/index.vue
index 8b09406..f9101fc 100644
--- a/src/pages/transactions/authorize/index.vue
+++ b/src/pages/transactions/authorize/index.vue
@@ -160,7 +160,7 @@
-
+