Files
eamco_office_frontend/src/pages/customer/tank/edit.vue
Edwin Eames 61f93ec4e8 Refactor frontend to Composition API and improve UI/UX
Major Changes:
- Migrate components from Options API to Composition API with <script setup>
- Add centralized service layer (serviceService, deliveryService, adminService)
- Implement new reusable components (EnhancedButton, EnhancedModal, StatCard, etc.)
- Add theme store for consistent theming across application
- Improve ServiceCalendar with federal holidays and better styling
- Refactor customer profile and tank estimation components
- Update all delivery and payment pages to use centralized services
- Add utility functions for formatting and validation
- Update Dockerfiles for better environment configuration
- Enhance Tailwind config with custom design tokens

UI Improvements:
- Modern, premium design with glassmorphism effects
- Improved form layouts with FloatingInput components
- Better loading states and empty states
- Enhanced modals and tables with consistent styling
- Responsive design improvements across all pages

Technical Improvements:
- Strict TypeScript types throughout
- Better error handling and validation
- Removed deprecated api.js in favor of TypeScript services
- Improved code organization and maintainability
2026-02-01 19:04:07 -05:00

182 lines
6.4 KiB
Vue

<!-- src/pages/customer/tank/edit.vue -->
<template>
<div class="flex">
<div class="w-full px-4 md:px-10 py-4">
<!-- Breadcrumbs & Title -->
<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>Edit Tank Details</li>
</ul>
</div>
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mt-4">
<h1 v-if="customer.id" class="text-3xl font-bold">
Tank for: {{ customer.customer_first_name }} {{ customer.customer_last_name }}
</h1>
<router-link v-if="customer.id" :to="{ name: 'customerProfile', params: { id: customer.id } }" class="btn btn-secondary btn-sm mt-2 sm:mt-0">
Back to Profile
</router-link>
</div>
<!-- Main Form Card -->
<div class="bg-neutral rounded-lg p-6 mt-6">
<form @submit.prevent="onSubmit" class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4">
<!-- Inspection Date -->
<div class="form-control">
<label class="label"><span class="label-text">Last Inspection Date</span></label>
<input v-model="TankForm.last_tank_inspection" type="date" class="input input-bordered input-sm w-full" />
</div>
<!-- Tank Size -->
<div class="form-control">
<label class="label"><span class="label-text">Tank Size (Gallons)</span></label>
<input v-model="TankForm.tank_size" type="number" placeholder="e.g., 275" class="input input-bordered input-sm w-full" />
</div>
<!-- Tank Status -->
<div class="form-control">
<label class="label"><span class="label-text">Tank Status</span></label>
<div class="flex items-center gap-6 bg-base-100 p-2 rounded-lg">
<label class="label cursor-pointer gap-2">
<span class="label-text">Good</span>
<input type="radio" v-model="TankForm.tank_status" :value="true" class="radio radio-primary" />
</label>
<label class="label cursor-pointer gap-2">
<span class="label-text">Bad</span>
<input type="radio" v-model="TankForm.tank_status" :value="false" class="radio radio-primary" />
</label>
</div>
</div>
<!-- Tank Location -->
<div class="form-control">
<label class="label"><span class="label-text">Tank Location</span></label>
<div class="flex items-center gap-6 bg-base-100 p-2 rounded-lg">
<label class="label cursor-pointer gap-2">
<span class="label-text">Inside</span>
<input type="radio" v-model="TankForm.outside_or_inside" :value="true" class="radio radio-primary" />
</label>
<label class="label cursor-pointer gap-2">
<span class="label-text">Outside</span>
<input type="radio" v-model="TankForm.outside_or_inside" :value="false" class="radio radio-primary" />
</label>
</div>
</div>
<!-- Fill Location -->
<div class="form-control md:col-span-2">
<label class="label"><span class="label-text">Fill Location </span></label>
<input v-model="TankForm.fill_location" type="text" placeholder="0-12 only" class="input input-bordered input-sm w-full" />
</div>
</div>
<!-- SUBMIT BUTTON -->
<div class="pt-4">
<button type="submit" class="btn btn-primary btn-sm">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { authService } from '../../../services/authService'
import { customerService } from '../../../services/customerService'
// Interface for our flat form model
interface TankFormData {
last_tank_inspection: string | null;
tank_status: boolean;
outside_or_inside: boolean;
tank_size: number;
fill_location: string;
}
const route = useRoute()
const router = useRouter()
// Reactive data
const user = ref(null as any)
const customer = ref({} as any)
// --- REFACTORED: Simplified, flat form object ---
const TankForm = ref({
last_tank_inspection: null,
tank_status: true,
outside_or_inside: true,
tank_size: 0,
fill_location: '',
} as TankFormData)
// Functions
const userStatus = () => {
authService.whoami()
.then((response: any) => {
if (response.data.ok) {
user.value = response.data.user;
}
})
.catch(() => { user.value = null; });
}
const getCustomer = (userid: number) => {
customerService.getById(userid)
.then((response: any) => {
customer.value = response.data?.customer || response.data;
});
}
const getCustomerDescription = (userid: number) => {
customerService.getDescription(userid)
.then((response: any) => {
const description = response.data?.description || response.data;
if (description && description.fill_location) {
TankForm.value.fill_location = description.fill_location;
}
});
}
const getTank = (customer_id: number) => {
customerService.getTank(customer_id)
.then((response: any) => {
if (response.data) {
TankForm.value.last_tank_inspection = response.data.last_tank_inspection;
TankForm.value.tank_status = response.data.tank_status;
TankForm.value.outside_or_inside = response.data.outside_or_inside;
TankForm.value.tank_size = response.data.tank_size;
}
});
}
const editTank = (payload: TankFormData) => {
customerService.updateTank(parseInt(route.params.id as string), payload)
.then((response: any) => {
if (response.data.ok) {
router.push({ name: "customerProfile", params: { id: customer.value.id } });
} else {
console.error("Failed to edit tank:", response.data.error);
}
});
}
const onSubmit = () => {
// The payload is simply the entire form object now
editTank(TankForm.value);
}
// Lifecycle
onMounted(() => {
userStatus();
const customerId = parseInt(route.params.id as string);
getCustomer(customerId);
getCustomerDescription(customerId);
getTank(customerId);
})
</script>