Add XLVask integration for user management and vehicles
Introduces XLVask functionality, including user account linking, fetching vehicles, and conditional UI updates for user accounts. Adds new routes, components, and localization strings to support the integration.
This commit is contained in:
@@ -28,7 +28,11 @@ const props = defineProps({
|
||||
invoice_collection_id: {
|
||||
type: Number,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
reg_1: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
});
|
||||
|
||||
const customerModalVisible = ref(false);
|
||||
@@ -185,6 +189,20 @@ const redirectDepartmentOrderPage = async (orderId) => {
|
||||
:click-action="() => redirectSuperUserInvoiceCollectionPage(props.invoice_collection_id)"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there is a reg_1, show the reg_1 actions -->
|
||||
<template v-if="props.reg_1">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="SessionUser.objects.vehicles.meta.labels.single"
|
||||
/>
|
||||
<!-- Show the vehicle, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
label="Vis køretøj i ny fane"
|
||||
icon="fas fa-car"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_1, true)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<!-- If no actions are defined, then show that no actions are defined -->
|
||||
<template v-else>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup>
|
||||
import { defineProps } from 'vue';
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
|
||||
const props = defineProps({
|
||||
icon: {
|
||||
@@ -117,7 +118,7 @@ const hasIcon = () => {
|
||||
</span>
|
||||
<span class="ml-1"
|
||||
:class="getLabelColor()"
|
||||
>{{ getLabel() }}</span>
|
||||
>{{ SessionUser.functions.ucFirst(getLabel()) }}</span>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@ const isVehicleAddonApplied = (addon) => {
|
||||
<ActionSettingsWheelButton
|
||||
v-if="!props.compact"
|
||||
:user_id="object.user_id"
|
||||
:reg_1="object.reg"
|
||||
>
|
||||
<template #actions>
|
||||
<!-- Delete -->
|
||||
|
||||
@@ -25,6 +25,7 @@ export const ObjectsGlobal = {
|
||||
succeeded: "Fuldførte",
|
||||
customers: "Kunder",
|
||||
selected: "Valgt",
|
||||
found: "Fundet",
|
||||
waiting: "Afventer",
|
||||
selected_multiple: "Valgte",
|
||||
queue: "Kø",
|
||||
@@ -125,6 +126,7 @@ export const ObjectsGlobal = {
|
||||
payment_intent: 'Betalingsintention',
|
||||
receipt: 'Kvittering',
|
||||
receipt_url: 'Kvitterings URL',
|
||||
discount: 'Rabat',
|
||||
},
|
||||
invoice: 'Faktura',
|
||||
},
|
||||
|
||||
@@ -88,6 +88,8 @@ import UserProfile from "@/views/dashboards/userDashboard/profile/UserProfile.vu
|
||||
import DepartmentNotifications
|
||||
from "@/views/dashboards/departmentDashboard/modules/notifications/DepartmentNotifications.vue";
|
||||
import Vehicles from "@/views/dashboards/superUserDashboard/Vehicles.vue";
|
||||
import ConfigurationXLVask from "@/views/dashboards/superUserDashboard/configuration/ConfigurationXLVask.vue";
|
||||
import UserXLVask from "@/views/dashboards/superUserDashboard/user/UserXLVask.vue";
|
||||
|
||||
// Export the router as router
|
||||
export const router = createRouter({
|
||||
@@ -304,6 +306,12 @@ export const router = createRouter({
|
||||
component: UserWashSubscriptions,
|
||||
meta: { middleware: superUserMiddleware }
|
||||
},
|
||||
{
|
||||
name: 'userxlvask',
|
||||
path: '/superuser/users/:userId/xlvask',
|
||||
component: UserXLVask,
|
||||
meta: { middleware: superUserMiddleware }
|
||||
},
|
||||
{
|
||||
name: 'products',
|
||||
path: '/superuser/products',
|
||||
@@ -418,6 +426,12 @@ export const router = createRouter({
|
||||
component: ConfigurationGatewayAPI,
|
||||
meta: { middleware: superUserMiddleware }
|
||||
},
|
||||
{
|
||||
name: 'configurationXLVask',
|
||||
path: '/superuser/configuration/xlvask',
|
||||
component: ConfigurationXLVask,
|
||||
meta: { middleware: superUserMiddleware }
|
||||
},
|
||||
{
|
||||
name: 'customers',
|
||||
path: '/superuser/customers',
|
||||
|
||||
@@ -14,6 +14,7 @@ const tabs = [
|
||||
{ name: 'Pricing', path: '/superuser/users/' + userId.value + '/pricing' },
|
||||
{ name: 'Other', path: '/superuser/users/' + userId.value + '/other' },
|
||||
{ name: 'Vehicles', path: '/superuser/users/' + userId.value + '/vehicles' },
|
||||
{ name: SessionUser.superUser.modules.xlvask.meta.title, path: '/superuser/users/' + userId.value + '/xlvask' },
|
||||
];
|
||||
|
||||
// Get the current path
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
|
||||
import {ref} from "vue";
|
||||
import {ref, watch} from "vue";
|
||||
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
|
||||
// Get the user from the route
|
||||
export const userId = ref(0);
|
||||
@@ -11,6 +11,14 @@ export const setUser = (id) => {
|
||||
getUserData();
|
||||
}
|
||||
|
||||
export const onUserChange = (callback) => {
|
||||
watch(userId, (newValue) => {
|
||||
if (newValue) {
|
||||
callback(newValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
import SuperUserDashboardUserNavigation from "@/views/dashboards/superUserDashboard/user/SuperUserDashboardUserNavigation.vue";
|
||||
import SuperUserDashboardNavigation from "@/views/dashboards/superUserDashboard/SuperUserDashboardNavigation.vue";
|
||||
|
||||
import {user, getUserData, userId, setUser, getUserCustomerNumber} from "@/views/dashboards/superUserDashboard/user/SuperUserSelectedUserObject.vue";
|
||||
import {useRouter} from "vue-router";
|
||||
const router = useRouter()
|
||||
setUser(router.currentRoute.value.params.userId);
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
<script setup>
|
||||
import UserSubPageWrapper from "@/views/dashboards/superUserDashboard/user/UserSubPageWrapper.vue";
|
||||
import PageTitle from "@/components/global/PageTitle.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import {user, getUserData, userId, setUser, getUserCustomerNumber, onUserChange} from "@/views/dashboards/superUserDashboard/user/SuperUserSelectedUserObject.vue";
|
||||
import {ref, watch} from "vue";
|
||||
|
||||
|
||||
/** XLVask User vehicles */
|
||||
const xlvaskUserVehicles = ref([]);
|
||||
const getXlvaskUserVehicles = async () => {
|
||||
// Get the vehicles from XLVask
|
||||
await SessionUser.superUser.modules.xlvask.functions.getVehicles(
|
||||
xlvaskUserObject.value.customerId,
|
||||
).then((response) => {
|
||||
let matchingVehicles = response.data.data;
|
||||
if (matchingVehicles.length !== 0) {
|
||||
xlvaskUserVehicles.value = matchingVehicles;
|
||||
}
|
||||
}
|
||||
).catch((error => {}));
|
||||
}
|
||||
|
||||
/** XLVask User */
|
||||
const xlvaskDefaultUserFunctions = {
|
||||
hasXLVaskAccount: () => {
|
||||
return xlvaskUserObject.value.customerId !== null
|
||||
},
|
||||
getThis: () => {
|
||||
return xlvaskUserObject
|
||||
},
|
||||
}
|
||||
const xlvaskDefaultUserObject = {
|
||||
customerId: null,
|
||||
name: null,
|
||||
vendorId: null,
|
||||
customerTypeId: null,
|
||||
discount: null, // Int
|
||||
phone: null,
|
||||
email: null,
|
||||
address: null,
|
||||
address2: null,
|
||||
zip: null,
|
||||
city: null,
|
||||
userId: null,
|
||||
vatnumber: null,
|
||||
excludeFromAutoInvoice: null,
|
||||
country: null,
|
||||
createDate: null,
|
||||
externId: null,
|
||||
active: null,
|
||||
language: null,
|
||||
note: null,
|
||||
updated: null,
|
||||
...xlvaskDefaultUserFunctions,
|
||||
}
|
||||
const generateXlVaskUserObject = async () => {
|
||||
let tmp_xlvaskUserObject = {
|
||||
...xlvaskDefaultUserObject
|
||||
}
|
||||
// If the customer number is set, then we can contact XLVask
|
||||
if (user.customer_number.value) {
|
||||
//console.log("XLVask customer number set", user.customer_number.value);
|
||||
// Get all the matching customers from XLVask
|
||||
await SessionUser.superUser.modules.xlvask.functions.getCustomers(
|
||||
null,
|
||||
null,
|
||||
user.customer_number.value,
|
||||
).then((response) => {
|
||||
//console.log("XLVask response", response.data.data);
|
||||
let matchingCustomers = response.data.data;
|
||||
if (matchingCustomers.length === 0) {
|
||||
//console.log("XLVask customer not found");
|
||||
} else {
|
||||
//console.log("XLVask customer found", matchingCustomers);
|
||||
// Get the first customer
|
||||
let customer = matchingCustomers[0];
|
||||
//console.log("XLVask customer", customer);
|
||||
// Set the customer data
|
||||
tmp_xlvaskUserObject = {
|
||||
...tmp_xlvaskUserObject,
|
||||
...customer,
|
||||
externId: parseInt(customer.externId),
|
||||
}
|
||||
}
|
||||
}
|
||||
).catch((error => {
|
||||
//console.error("XLVask error", error);
|
||||
})).finally(() => {
|
||||
//console.log("XLVask finally");
|
||||
xlvaskUserObject.value = tmp_xlvaskUserObject;
|
||||
});
|
||||
} else {
|
||||
//console.log("XLVask customer number not set");
|
||||
}
|
||||
}
|
||||
const xlvaskUserObject = ref(xlvaskDefaultUserObject);
|
||||
const initXlvaskUserObject = async (userId = null) => {
|
||||
// Reset the xlvask user object
|
||||
xlvaskUserObject.value = {...xlvaskDefaultUserObject};
|
||||
if (userId) {
|
||||
await generateXlVaskUserObject();
|
||||
}
|
||||
}
|
||||
onUserChange(newUserId => {
|
||||
// Get the user data
|
||||
initXlvaskUserObject(newUserId);
|
||||
})
|
||||
initXlvaskUserObject(user.id);
|
||||
watch(user.customer_number, (newValue) => {
|
||||
initXlvaskUserObject(user.id);
|
||||
});
|
||||
|
||||
watch(xlvaskUserObject, (newValue) => {
|
||||
// Check if the user has an XLVask account
|
||||
if (xlvaskUserObject.value.hasXLVaskAccount()) {
|
||||
// Get the vehicles from XLVask
|
||||
getXlvaskUserVehicles();
|
||||
} else {
|
||||
// If the user does not have an XLVask account, reset the vehicles
|
||||
xlvaskUserVehicles.value = [];
|
||||
}
|
||||
}, { immediate: true });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UserSubPageWrapper>
|
||||
<template #title>
|
||||
<PageTitle title="User" :subtitle="SessionUser.superUser.modules.xlvask.meta.title"/>
|
||||
</template>
|
||||
<div v-if="xlvaskUserObject">
|
||||
{{ userId }} (Customer number: {{ user.customer_number }})
|
||||
<template v-if="xlvaskUserObject.hasXLVaskAccount()">
|
||||
<!-- The user has an XLVask account -->
|
||||
<div class="message is-success">
|
||||
<div class="message-body">
|
||||
<strong>{{ SessionUser.superUser.modules.xlvask.meta.title }} {{ SessionUser.objects.global.language.customer.toLowerCase() }} {{ SessionUser.objects.global.language.found.toLowerCase()}}</strong>
|
||||
<p>Navn: {{ xlvaskUserObject.name }}</p>
|
||||
<p>Telefon: {{ xlvaskUserObject.phone }}</p>
|
||||
<p>Email: {{ xlvaskUserObject.email }}</p>
|
||||
<p>Adresse: {{ xlvaskUserObject.address }} {{ xlvaskUserObject.address2 }}</p>
|
||||
<p>Postnummer: {{ xlvaskUserObject.zip }}</p>
|
||||
<p>By: {{ xlvaskUserObject.city }}</p>
|
||||
<p>Land: {{ xlvaskUserObject.country }}</p>
|
||||
<!-- If the customer has a discount, show it -->
|
||||
<p v-if="xlvaskUserObject.discount !== null">{{ SessionUser.objects.global.language.payment.discount }}: <strong>{{ xlvaskUserObject.discount }}%</strong></p>
|
||||
<p>XLVask ID: <strong>{{ xlvaskUserObject.customerId }}</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Vehicles connected to the user -->
|
||||
<!--{{ xlvaskUserVehicles }} -->
|
||||
</template>
|
||||
<template v-else>
|
||||
<!-- The user does not have an XLVask account -->
|
||||
XLVask ID: <strong>Ingen</strong>
|
||||
</template>
|
||||
</div>
|
||||
</UserSubPageWrapper>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user