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
This commit is contained in:
2026-02-01 19:04:07 -05:00
parent 72d8e35e06
commit 61f93ec4e8
86 changed files with 3931 additions and 2086 deletions

View File

@@ -92,84 +92,87 @@
</div>
</div>
</div>
<Footer />
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import axios from 'axios'
import authHeader from '../../services/auth.header'
import Footer from '../../layouts/footers/footer.vue'
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { notify } from "@kyvg/vue3-notification";
import { adminService } from '../../services/adminService';
import { authService } from '../../services/authService';
import { AxiosResponse, AxiosError } from '../../types/models';
export default defineComponent({
name: 'auth',
components: {
Footer,
},
data() {
return {
user: null,
// --- REFACTORED: Simplified, flat form object ---
OilForm: {
price_from_supplier: 0,
price_for_customer: 0,
price_for_employee: 0,
price_same_day: 0,
price_prime: 0,
price_emergency: 0,
},
// State
const user = ref<any>(null);
const OilForm = ref({
price_from_supplier: 0,
price_for_customer: 0,
price_for_employee: 0,
price_same_day: 0,
price_prime: 0,
price_emergency: 0,
});
const router = useRouter();
// Methods
const userStatus = async () => {
try {
const response: AxiosResponse<any> = await authService.whoami();
if (response.data.ok) {
user.value = response.data.user;
}
} catch (error) {
user.value = null;
}
},
created() {
this.userStatus();
},
mounted() {
this.getCurrentPrices();
},
methods: {
userStatus() {
const path = import.meta.env.VITE_BASE_URL + '/auth/whoami';
axios.get(path, { withCredentials: true, headers: authHeader() })
.then((response: any) => {
if (response.data.ok) { this.user = response.data.user; }
})
.catch(() => { this.user = null; });
},
getCurrentPrices() {
const path = import.meta.env.VITE_BASE_URL + "/admin/oil/get";
axios.get(path, { withCredentials: true, headers: authHeader() })
.then((response: any) => {
if (response.data) {
// --- REFACTORED: Populate the flat form object ---
this.OilForm = response.data;
}
});
},
CreatePricing(payload: any) {
const path = import.meta.env.VITE_BASE_URL + "/admin/oil/create";
axios.post(path, payload, { withCredentials: true, headers: authHeader() })
.then((response: any) => {
if (response.data.ok) {
};
const getCurrentPrices = async () => {
try {
const response: AxiosResponse<any> = await adminService.getOilPricing();
if (response.data) {
OilForm.value = response.data;
}
} catch (err) {
console.error("Failed to fetch oil prices", err);
}
};
const CreatePricing = async (payload: any) => {
try {
const response: AxiosResponse<any> = await adminService.updateOilPricing(payload);
if (response.data.ok) {
notify({
title: "Success",
text: "Prices have been updated!",
type: "success",
title: "Success",
text: "Prices have been updated!",
type: "success",
});
this.$router.push({ name: "home" });
} else {
notify({
title: "Error",
text: response.data.error || "An unknown error occurred.",
type: "error",
router.push({ name: "home" });
} else {
notify({
title: "Error",
text: response.data.error || "An unknown error occurred.",
type: "error",
});
}
}
} catch (err: unknown) {
const error = err as AxiosError<{ error?: string }>;
notify({
title: "Error",
text: error.response?.data?.error || "An error occurred while updating prices.",
type: "error",
});
},
onSubmit() {
// --- REFACTORED: Submit the flat form object ---
this.CreatePricing(this.OilForm);
},
},
}
};
const onSubmit = () => {
CreatePricing(OilForm.value);
};
// Lifecycle
onMounted(() => {
userStatus();
getCurrentPrices();
});
</script>