Added service plan. Password change
This commit is contained in:
@@ -3,8 +3,33 @@
|
||||
<div class="w-full min-h-screen bg-base-200 px-4 md:px-10">
|
||||
<!-- ... breadcrumbs ... -->
|
||||
|
||||
<div v-if="customer && customer.id" class="bg-neutral rounded-lg p-4 sm:p-6 mt-6">
|
||||
|
||||
<div v-if="customer && customer.id" class="bg-neutral rounded-lg p-4 sm:p-6 mt-6">
|
||||
|
||||
<!-- Current Plan Status Banner - Same as ServicePlanEdit.vue -->
|
||||
<div v-if="servicePlan && servicePlan.contract_plan > 0"
|
||||
class="alert alert-info mb-6"
|
||||
:class="servicePlan.contract_plan === 2 ? 'border-4 border-yellow-400 bg-yellow-50' : ''">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-3">
|
||||
<h3 class="font-bold">Current Plan: {{ getPlanName(servicePlan.contract_plan) }}</h3>
|
||||
<!-- Premium Star Icon -->
|
||||
<svg v-if="servicePlan.contract_plan === 2"
|
||||
class="w-8 h-8 text-yellow-500 fill-current"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<p>{{ servicePlan.contract_years }} Year{{ servicePlan.contract_years > 1 ? 's' : '' }} Contract</p>
|
||||
<p class="text-sm">Expires: {{ formatEndDate(servicePlan.contract_start_date, servicePlan.contract_years) }}</p>
|
||||
</div>
|
||||
<div class="badge" :class="getStatusBadge(servicePlan.contract_start_date, servicePlan.contract_years)">
|
||||
{{ getStatusText(servicePlan.contract_start_date, servicePlan.contract_years) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FIX: Changed `lg:` to `xl:` for a later breakpoint -->
|
||||
<div class="grid grid-cols-1 xl:grid-cols-12 gap-6">
|
||||
|
||||
@@ -177,6 +202,14 @@ interface ServiceParts {
|
||||
oil_nozzle_2: string;
|
||||
}
|
||||
|
||||
interface ServicePlan {
|
||||
id: number;
|
||||
customer_id: number;
|
||||
contract_plan: number;
|
||||
contract_years: number;
|
||||
contract_start_date: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
@@ -225,6 +258,7 @@ export default defineComponent({
|
||||
selectedServiceForEdit: null as ServiceCall | null,
|
||||
isPartsModalOpen: false,
|
||||
currentParts: null as ServiceParts | null,
|
||||
servicePlan: null as ServicePlan | null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -282,6 +316,7 @@ export default defineComponent({
|
||||
this.getCustomerLastDelivery(this.customer.id);
|
||||
this.getServiceCalls(this.customer.id);
|
||||
this.fetchCustomerParts(this.customer.id);
|
||||
this.loadServicePlan(this.customer.id);
|
||||
|
||||
}).catch((error: any) => {
|
||||
console.error("CRITICAL: Failed to fetch main customer data. Aborting other calls.", error);
|
||||
@@ -615,6 +650,78 @@ onSubmitSocial(commentText: string) {
|
||||
getServiceTypeColor(typeId: number): string {
|
||||
const colorMap: { [key: number]: string } = { 0: 'blue', 1: 'red', 2: 'green', 3: '#B58900', 4: 'black' };
|
||||
return colorMap[typeId] || 'gray';
|
||||
},
|
||||
formatEndDate(startDate: string, years: number): string {
|
||||
if (!startDate) return 'N/A';
|
||||
return dayjs(startDate).add(years, 'year').format('MMM D, YYYY');
|
||||
},
|
||||
getPlanStatusText(startDate: string, years: number): string {
|
||||
if (!startDate) return 'Unknown';
|
||||
const endDate = dayjs(startDate).add(years, 'year');
|
||||
const now = dayjs();
|
||||
if (now.isAfter(endDate)) {
|
||||
return 'Expired';
|
||||
} else if (now.isAfter(endDate.subtract(30, 'day'))) {
|
||||
return 'Expiring Soon';
|
||||
} else {
|
||||
return 'Active';
|
||||
}
|
||||
},
|
||||
getPlanStatusBadge(startDate: string, years: number): string {
|
||||
if (!startDate) return 'badge-ghost';
|
||||
const endDate = dayjs(startDate).add(years, 'year');
|
||||
const now = dayjs();
|
||||
if (now.isAfter(endDate)) {
|
||||
return 'badge-error';
|
||||
} else if (now.isAfter(endDate.subtract(30, 'day'))) {
|
||||
return 'badge-warning';
|
||||
} else {
|
||||
return 'badge-success';
|
||||
}
|
||||
},
|
||||
getPlanName(planType: number): string {
|
||||
const planNames: { [key: number]: string } = {
|
||||
1: 'Standard Plan',
|
||||
2: 'Premium Plan'
|
||||
};
|
||||
return planNames[planType] || 'No Plan';
|
||||
},
|
||||
getStatusText(startDate: string, years: number): string {
|
||||
if (!startDate) return 'Unknown';
|
||||
const endDate = dayjs(startDate).add(years, 'year');
|
||||
const now = dayjs();
|
||||
if (now.isAfter(endDate)) {
|
||||
return 'Expired';
|
||||
} else if (now.isAfter(endDate.subtract(30, 'day'))) {
|
||||
return 'Expiring Soon';
|
||||
} else {
|
||||
return 'Active';
|
||||
}
|
||||
},
|
||||
getStatusBadge(startDate: string, years: number): string {
|
||||
if (!startDate) return 'badge-ghost';
|
||||
const endDate = dayjs(startDate).add(years, 'year');
|
||||
const now = dayjs();
|
||||
if (now.isAfter(endDate)) {
|
||||
return 'badge-error';
|
||||
} else if (now.isAfter(endDate.subtract(30, 'day'))) {
|
||||
return 'badge-warning';
|
||||
} else {
|
||||
return 'badge-success';
|
||||
}
|
||||
},
|
||||
async loadServicePlan(customerId: number) {
|
||||
try {
|
||||
const path = `${import.meta.env.VITE_BASE_URL}/service/plans/customer/${customerId}`;
|
||||
const response = await axios.get(path, { headers: authHeader() });
|
||||
|
||||
if (response.data && response.data.contract_plan !== undefined) {
|
||||
this.servicePlan = response.data;
|
||||
}
|
||||
} catch (error) {
|
||||
// Plan doesn't exist yet, that's okay
|
||||
console.log('No existing service plan found');
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user