"Refactor booking-related components: update terminology in OrderBookings.vue, enhance error handling in ShowErrorField.vue, and improve action handling with extended support and dynamic display in ActionSettingsWheelButton.vue."
This commit is contained in:
@@ -7,6 +7,7 @@ import Swal from "sweetalert2";
|
||||
import { ref } from "vue";
|
||||
import CustomerModal from "@/components/displays/modals/CustomerModal.vue";
|
||||
import ActionSettingsWheelItemLabel from "@/components/displays/buttons/ActionSettingsWheelItemLabel.vue";
|
||||
import ShowErrorField from "@/components/global/ShowErrorField.vue";
|
||||
const emit = defineEmits(['deleted']);
|
||||
const emitDeleted = () => {
|
||||
emit('deleted');
|
||||
@@ -61,6 +62,10 @@ const props = defineProps({
|
||||
attachments: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
displayActionsDirectly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
@@ -155,6 +160,7 @@ const hasUser = () => {
|
||||
}
|
||||
|
||||
const attachmentsFromOrder = ref([]);
|
||||
const attachmentsFromOrderError = ref(null);
|
||||
onMounted(() => {
|
||||
if (props.order_id) {
|
||||
SessionUser.objects.orders.functions.fetchAttachments(props.order_id).then((response) => {
|
||||
@@ -181,220 +187,495 @@ onMounted(() => {
|
||||
response = [];
|
||||
}
|
||||
attachmentsFromOrder.value = response;
|
||||
}).catch((error) => {});
|
||||
}).catch((error) => {
|
||||
const parsedErrorMessage = SessionUser.functions.parseErrorMessage(error);
|
||||
console.warn('Error fetching attachments from order:', error, parsedErrorMessage);
|
||||
// Check if there's an error message in the response
|
||||
attachmentsFromOrderError.value = `ERROR: ${parsedErrorMessage || 'Failed to fetch attachments'}`;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const defaultActions = computed(() => {
|
||||
return [
|
||||
/**
|
||||
* Example action
|
||||
{
|
||||
icon: 'fas fa-eye',
|
||||
label: 'View Order',
|
||||
clickAction: () => {
|
||||
console.warn('View Order clicked');
|
||||
},
|
||||
showFunction: () => {
|
||||
return true; // Logic to determine if action should be shown
|
||||
},
|
||||
disabled: false,
|
||||
template: 'success' // Optional: Set the template to 'success' or 'danger'
|
||||
isLabel: false // Optional: Set to true to render the label as a button
|
||||
}
|
||||
*/
|
||||
/** Bookings actions */
|
||||
{
|
||||
label: 'Booking',
|
||||
isLabel: true,
|
||||
showFunction: () => {
|
||||
return !!props.order_booking_id;
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-check-circle',
|
||||
label: 'Marker som gennemført',
|
||||
template: 'success',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.order_bookings.functions.showCompleteConfirmationModal(props.order_booking_id, () => {
|
||||
props.refreshFunction();
|
||||
});
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_booking_id && SessionUser.canAccessAdmin() && !props.order_id;
|
||||
},
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-external-link-alt',
|
||||
label: 'Se booking i ny fane',
|
||||
clickAction: () => {
|
||||
return SessionUser.functions.redirectTo.department(props.department_id, 'modules/bookings/order/' + props.order_booking_id, true);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_booking_id;
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-edit',
|
||||
label: 'Ændr tilknytning',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.order_bookings.showEditObjectFieldForm(props.order_booking_id, 'order_id', props.order_id, () => {
|
||||
props.refreshFunction();
|
||||
}, {
|
||||
filters: {
|
||||
...(props.customer_number ? {customer_id: props.customer_number} : {}),
|
||||
...(props.department_id ? {department_id: props.department_id} : {})
|
||||
},
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 100
|
||||
}
|
||||
});
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_booking_id && SessionUser.canAccessAdmin();
|
||||
},
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-trash-alt',
|
||||
label: 'Slet booking',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.order_bookings.functions.showDeleteConfirmationModal(props.order_booking_id, () => {
|
||||
props.refreshFunction();
|
||||
});
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_booking_id && SessionUser.canAccessAdmin() && !props.order_id;
|
||||
},
|
||||
disabled: false,
|
||||
template: 'danger'
|
||||
},
|
||||
/** Orders actions */
|
||||
{
|
||||
label: SessionUser.functions.ucFirst(SessionUser.objects.orders.meta.labels.single),
|
||||
isLabel: true,
|
||||
showFunction: () => {
|
||||
return !!props.order_id;
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-external-link-alt',
|
||||
label: 'Se ordre i ny fane',
|
||||
clickAction: async () => {
|
||||
return redirectDepartmentOrderPage(props.order_id, true);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_id && (SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser());
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-user-edit',
|
||||
label: 'Skift kunde',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.orders.functions.showChangeCustomerForm(props.order_id);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_id && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-invoice-dollar',
|
||||
label: 'Skift faktura samling',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.orders.functions.showChangeInvoiceCollectionForm(props.order_id);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_id && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-trash-alt',
|
||||
label: 'Slet ordre',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.orders.functions.showDeleteConfirmationModal(props.order_id, () => {
|
||||
emitDeleted();
|
||||
});
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.order_id && (SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser());
|
||||
},
|
||||
disabled: false,
|
||||
template: 'danger'
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-file-invoice-dollar',
|
||||
label: 'Vis faktura samling i ny fane',
|
||||
clickAction: () => {
|
||||
return redirectSuperUserInvoiceCollectionPage(props.invoice_collection_id);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.invoice_collection_id && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
},
|
||||
/** Vehicle actions */
|
||||
{
|
||||
label: props.reg_1 && props.reg_2 ? `${SessionUser.objects.vehicles.meta.labels.multiple}` : `${SessionUser.objects.vehicles.meta.labels.single}`,
|
||||
isLabel: true,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-car',
|
||||
label: `Se køretøj i ny fane`,
|
||||
clickAction: () => {
|
||||
return SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_1, true);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.reg_1 && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-car',
|
||||
label: `Se køretøj i ny fane`,
|
||||
clickAction: () => {
|
||||
return SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_2, true);
|
||||
},
|
||||
showFunction: () => {
|
||||
return !!props.reg_2 && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
},
|
||||
/** User actions */
|
||||
{ label: SessionUser.objects.global.language.customer,
|
||||
isLabel: true,
|
||||
showFunction: () => {
|
||||
return hasUser() && SessionUser.canAccessSuperUser();
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-user-edit',
|
||||
label: 'Se kunde i ny fane',
|
||||
clickAction: () => {
|
||||
return SessionUser.functions.redirectTo.superUser('/users/' + userIdFromCustomerNumber.value, true);
|
||||
},
|
||||
showFunction: () => {
|
||||
return hasUser() && SessionUser.canAccessSuperUser() && userIdFromCustomerNumber.value;
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-user-shield',
|
||||
label: 'Log ind som kunde',
|
||||
clickAction: () => {
|
||||
return SessionUser.superUser.intimidate.intimidateUser(userIdFromCustomerNumber.value);
|
||||
},
|
||||
showFunction: () => {
|
||||
return hasUser() && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-key',
|
||||
label: 'Skift kodeord',
|
||||
clickAction: () => {
|
||||
return showSetCustomerPassword(userIdFromCustomerNumber.value);
|
||||
},
|
||||
showFunction: () => {
|
||||
return hasUser() && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-user',
|
||||
label: 'Vis kunde',
|
||||
clickAction: () => {
|
||||
customerModalVisible.value = true;
|
||||
},
|
||||
showFunction: () => {
|
||||
return hasUser() && SessionUser.canAccessSuperUser();
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown is-right is-hoverable">
|
||||
<div class="dropdown-trigger">
|
||||
<button class="button is-small is-dark" aria-haspopup="true" aria-controls="dropdown-menu">
|
||||
<span class="icon">
|
||||
<i :class="props.icon"></i>
|
||||
</span>
|
||||
<span v-if="props.label.length > 0" class="ml-2">{{ props.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<!-- Actions (If defined) -->
|
||||
<template v-if="useSlots().actions">
|
||||
<slot name="actions"></slot>
|
||||
<!-- If there is an order_booking_id, show the order booking actions -->
|
||||
<template v-if="props.order_booking_id">
|
||||
<ActionSettingsWheelItemLabel :label="'Booking'"/>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="(SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()) && !props.order_id"
|
||||
:icon="'fas fa-check-circle'"
|
||||
:label="'Marker som gennemført'"
|
||||
template="success"
|
||||
:click-action="() => SessionUser.objects.order_bookings.functions.showCompleteConfirmationModal(props.order_booking_id, () => {
|
||||
props.refreshFunction();
|
||||
})"
|
||||
<div>
|
||||
<template v-if="displayActionsDirectly">
|
||||
<!-- Error -->
|
||||
<template v-if="attachmentsFromOrderError">
|
||||
<div class="message is-danger">
|
||||
<div class="message-body">
|
||||
{{ attachmentsFromOrderError }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-for="(action, index) in [ ...defaultActions, ...(useSlots().actions ? [] : []) ]" :key="index">
|
||||
<ActionSettingsWheelItem
|
||||
v-if="(!action.showFunction || action.showFunction()) && (!action.isLabel || action.isLabel === false)"
|
||||
:icon="action.icon"
|
||||
:label="action.label"
|
||||
:template="action.template"
|
||||
:click-action="action.clickAction"
|
||||
:show-function="action.showFunction"
|
||||
:disabled="action.disabled"
|
||||
/>
|
||||
<ActionSettingsWheelItemLabel
|
||||
v-else-if="action.isLabel && action.isLabel === true && (!action.showFunction || action.showFunction())"
|
||||
:label="action.label"
|
||||
/>
|
||||
<ActionSettingsWheelItem
|
||||
:icon="'fas fa-external-link-alt'"
|
||||
:label="'Se booking i ny fane'"
|
||||
:click-action="() => SessionUser.functions.redirectTo.department(props.department_id, 'modules/bookings/order/' + props.order_booking_id, true)"
|
||||
/>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()"
|
||||
:icon="'fas fa-edit'"
|
||||
:label="(!props.order_id) ? `Tilknyt ${SessionUser.objects.orders.meta.labels.single.toLowerCase()}` : `Ændr ${SessionUser.objects.orders.meta.labels.single.toLowerCase()}`"
|
||||
:click-action="() => SessionUser.objects.order_bookings.showEditObjectFieldForm(props.order_booking_id, 'order_id', props.order_id, () => {
|
||||
props.refreshFunction();
|
||||
}, {
|
||||
filters: {
|
||||
...(customer_number ? {customer_id: props.customer_number} : {}),
|
||||
...(props.department_id ? {department_id: props.department_id} : {})
|
||||
},
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 100
|
||||
}
|
||||
})"
|
||||
/>
|
||||
<ActionSettingsWheelItem
|
||||
:icon="'fas fa-trash-alt'"
|
||||
:label="'Slet booking'"
|
||||
template="danger"
|
||||
v-show="!props.order_id"
|
||||
:click-action="() => SessionUser.objects.order_bookings.functions.showDeleteConfirmationModal(props.order_booking_id, () => {
|
||||
props.refreshFunction();
|
||||
})"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there's an order_id, show the order actions -->
|
||||
<template v-if="props.order_id">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="SessionUser.functions.ucFirst(SessionUser.objects.orders.meta.labels.single)"
|
||||
/>
|
||||
<!-- Go to the order page, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()"
|
||||
:label="`Se ${SessionUser.objects.orders.meta.labels.single.toLowerCase()} i ny fane`"
|
||||
icon="fas fa-external-link-alt"
|
||||
:click-action="async () => redirectDepartmentOrderPage(props.order_id, true)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Go to the user/order/:order_id page, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
v-if="!SessionUser.canAccessAdmin() && !SessionUser.canAccessSuperUser()"
|
||||
:label="`Se ${SessionUser.objects.orders.meta.labels.single.toLowerCase()} i ny fane`"
|
||||
icon="fas fa-external-link-alt"
|
||||
:click-action="() => SessionUser.functions.redirectTo.user('/orders/' + props.order_id, true)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Change the customer (of the order) -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
label="Skift kunde"
|
||||
icon="fas fa-user-edit"
|
||||
:click-action="() => SessionUser.objects.orders.functions.showChangeCustomerForm(props.order_id)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Change the invoice collection (of the order) -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
label="Skift faktura samling"
|
||||
icon="fas fa-file-invoice-dollar"
|
||||
:click-action="() => SessionUser.objects.orders.functions.showChangeInvoiceCollectionForm(props.order_id)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Delete the order -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()"
|
||||
:label="`Slet ${SessionUser.objects.orders.meta.labels.single.toLowerCase()}`"
|
||||
template="danger"
|
||||
icon="fas fa-trash-alt"
|
||||
:click-action="() => SessionUser.objects.orders.functions.showDeleteConfirmationModal(props.order_id, () => {
|
||||
emitDeleted();
|
||||
})"
|
||||
:disabled="false"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there is an invoice collection id, show the invoice actions -->
|
||||
<template v-if="props.invoice_collection_id">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="SessionUser.objects.collectedOrderInvoices.meta.title"
|
||||
v-show="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Show the invoice collection, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
label="Vis faktura samling i ny fane"
|
||||
icon="fas fa-file-invoice-dollar"
|
||||
:click-action="() => redirectSuperUserInvoiceCollectionPage(props.invoice_collection_id)"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there's a user_id, show the user actions -->
|
||||
<template v-if="hasUser()">
|
||||
<!-- Label -->
|
||||
<ActionSettingsWheelItemLabel
|
||||
:label="SessionUser.objects.global.language.customer"
|
||||
v-show="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Se bruger -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Se kunde i ny fane"
|
||||
icon="fas fa-user-edit"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/users/' + userIdFromCustomerNumber, true)"
|
||||
v-if="SessionUser.canAccessSuperUser() && userIdFromCustomerNumber"
|
||||
/>
|
||||
<!-- Log ind som kunde -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Log ind som kunde"
|
||||
icon="fas fa-user-shield"
|
||||
:click-action="() => SessionUser.superUser.intimidate.intimidateUser(userIdFromCustomerNumber)"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
|
||||
<!-- Set password -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Skift kodeord"
|
||||
icon="fas fa-key"
|
||||
:click-action="() => showSetCustomerPassword(userIdFromCustomerNumber)"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Show customer modal -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Vis kunde"
|
||||
icon="fas fa-user"
|
||||
:click-action="() => customerModalVisible = true"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there is a reg_1, show the reg_1 actions -->
|
||||
<template v-if="props.reg_1 || props.reg_2">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="props.reg_1 && props.reg_2 ? `${SessionUser.objects.vehicles.meta.labels.multiple}` : `${SessionUser.objects.vehicles.meta.labels.single}`"
|
||||
v-show="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Show the vehicle, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
:label="`Se ${SessionUser.objects.vehicles.meta.labels.single.toLowerCase()} ${props.reg_1} i ny fane`"
|
||||
icon="fas fa-car"
|
||||
v-if="props.reg_1 && SessionUser.canAccessSuperUser()"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_1, true)"
|
||||
/>
|
||||
<action-settings-wheel-item
|
||||
:label="`Se ${SessionUser.objects.vehicles.meta.labels.single.toLowerCase()} ${props.reg_2} i ny fane`"
|
||||
icon="fas fa-car"
|
||||
v-if="props.reg_2 && SessionUser.canAccessSuperUser()"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_2, true)"
|
||||
/>
|
||||
<!-- If there are any attachments, show the attachments actions -->
|
||||
<template v-if="attachmentsFromOrder.length > 0">
|
||||
<action-settings-wheel-item-label
|
||||
:label="'Vedhæftede filer'"
|
||||
</template>
|
||||
<!-- If there are attachments, show the attachments -->
|
||||
<template v-if="attachmentsFromOrder.length > 0">
|
||||
<ActionSettingsWheelItemLabel :label="'Vedhæftede filer'"/>
|
||||
<ActionSettingsWheelItem
|
||||
v-for="attachment in attachmentsFromOrder"
|
||||
:key="attachment.id"
|
||||
:icon="'fas fa-paperclip'"
|
||||
:label="`Åbn vedhæftede fil #${attachment.id}`"
|
||||
:click-action="() => SessionUser.objects.orders.functions.downloadAttachment(props.order_id, attachment.id, true)
|
||||
.catch((error) => {
|
||||
Swal.fire({
|
||||
title: 'Fejl',
|
||||
text: 'Der opstod en fejl under download af vedhæftede fil.',
|
||||
icon: 'error',
|
||||
});
|
||||
})"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<div class="dropdown is-right is-hoverable" v-else>
|
||||
<div class="dropdown-trigger">
|
||||
<button class="button is-small is-dark" aria-haspopup="true" aria-controls="dropdown-menu">
|
||||
<span class="icon">
|
||||
<i :class="props.icon"></i>
|
||||
</span>
|
||||
<span v-if="props.label.length > 0" class="ml-2">{{ props.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<!-- Actions (If defined) -->
|
||||
<template v-if="useSlots().actions">
|
||||
<slot name="actions"></slot>
|
||||
<!-- If there is an order_booking_id, show the order booking actions -->
|
||||
<template v-if="props.order_booking_id">
|
||||
<ActionSettingsWheelItemLabel :label="'Booking'"/>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="(SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()) && !props.order_id"
|
||||
:icon="'fas fa-check-circle'"
|
||||
:label="'Marker som gennemført'"
|
||||
template="success"
|
||||
:click-action="() => SessionUser.objects.order_bookings.functions.showCompleteConfirmationModal(props.order_booking_id, () => {
|
||||
props.refreshFunction();
|
||||
})"
|
||||
/>
|
||||
<template v-for="(attachment, index) in attachmentsFromOrder" :key="index">
|
||||
<action-settings-wheel-item
|
||||
:label="`${attachment.content?.document || attachment.content?.other}`"
|
||||
icon="fas fa-paperclip"
|
||||
:click-action="() => SessionUser.objects.orders.functions.downloadAttachment(props.order_id, attachment.id, true)
|
||||
.catch((error) => {
|
||||
Swal.fire({
|
||||
title: 'Fejl',
|
||||
text: 'Der opstod en fejl under download af vedhæftede fil.',
|
||||
icon: 'error',
|
||||
});
|
||||
})"
|
||||
<ActionSettingsWheelItem
|
||||
:icon="'fas fa-external-link-alt'"
|
||||
:label="'Se booking i ny fane'"
|
||||
:click-action="() => SessionUser.functions.redirectTo.department(props.department_id, 'modules/bookings/order/' + props.order_booking_id, true)"
|
||||
/>
|
||||
<ActionSettingsWheelItem
|
||||
v-if="SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()"
|
||||
:icon="'fas fa-edit'"
|
||||
:label="(!props.order_id) ? `Tilknyt ${SessionUser.objects.orders.meta.labels.single.toLowerCase()}` : `Ændr ${SessionUser.objects.orders.meta.labels.single.toLowerCase()}`"
|
||||
:click-action="() => SessionUser.objects.order_bookings.showEditObjectFieldForm(props.order_booking_id, 'order_id', props.order_id, () => {
|
||||
props.refreshFunction();
|
||||
}, {
|
||||
filters: {
|
||||
...(customer_number ? {customer_id: props.customer_number} : {}),
|
||||
...(props.department_id ? {department_id: props.department_id} : {})
|
||||
},
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 100
|
||||
}
|
||||
})"
|
||||
/>
|
||||
<ActionSettingsWheelItem
|
||||
:icon="'fas fa-trash-alt'"
|
||||
:label="'Slet booking'"
|
||||
template="danger"
|
||||
v-show="!props.order_id"
|
||||
:click-action="() => SessionUser.objects.order_bookings.functions.showDeleteConfirmationModal(props.order_booking_id, () => {
|
||||
props.refreshFunction();
|
||||
})"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there's an order_id, show the order actions -->
|
||||
<template v-if="props.order_id">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="SessionUser.functions.ucFirst(SessionUser.objects.orders.meta.labels.single)"
|
||||
/>
|
||||
<!-- Go to the order page, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()"
|
||||
:label="`Se ${SessionUser.objects.orders.meta.labels.single.toLowerCase()} i ny fane`"
|
||||
icon="fas fa-external-link-alt"
|
||||
:click-action="async () => redirectDepartmentOrderPage(props.order_id, true)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Go to the user/order/:order_id page, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
v-if="!SessionUser.canAccessAdmin() && !SessionUser.canAccessSuperUser()"
|
||||
:label="`Se ${SessionUser.objects.orders.meta.labels.single.toLowerCase()} i ny fane`"
|
||||
icon="fas fa-external-link-alt"
|
||||
:click-action="() => SessionUser.functions.redirectTo.user('/orders/' + props.order_id, true)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Change the customer (of the order) -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
label="Skift kunde"
|
||||
icon="fas fa-user-edit"
|
||||
:click-action="() => SessionUser.objects.orders.functions.showChangeCustomerForm(props.order_id)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Change the invoice collection (of the order) -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
label="Skift faktura samling"
|
||||
icon="fas fa-file-invoice-dollar"
|
||||
:click-action="() => SessionUser.objects.orders.functions.showChangeInvoiceCollectionForm(props.order_id)"
|
||||
:disabled="false"
|
||||
/>
|
||||
<!-- Delete the order -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessAdmin() || SessionUser.canAccessSuperUser()"
|
||||
:label="`Slet ${SessionUser.objects.orders.meta.labels.single.toLowerCase()}`"
|
||||
template="danger"
|
||||
icon="fas fa-trash-alt"
|
||||
:click-action="() => SessionUser.objects.orders.functions.showDeleteConfirmationModal(props.order_id, () => {
|
||||
emitDeleted();
|
||||
})"
|
||||
:disabled="false"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there is an invoice collection id, show the invoice actions -->
|
||||
<template v-if="props.invoice_collection_id">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="SessionUser.objects.collectedOrderInvoices.meta.title"
|
||||
v-show="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Show the invoice collection, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
label="Vis faktura samling i ny fane"
|
||||
icon="fas fa-file-invoice-dollar"
|
||||
:click-action="() => redirectSuperUserInvoiceCollectionPage(props.invoice_collection_id)"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there's a user_id, show the user actions -->
|
||||
<template v-if="hasUser()">
|
||||
<!-- Label -->
|
||||
<ActionSettingsWheelItemLabel
|
||||
:label="SessionUser.objects.global.language.customer"
|
||||
v-show="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Se bruger -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Se kunde i ny fane"
|
||||
icon="fas fa-user-edit"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/users/' + userIdFromCustomerNumber, true)"
|
||||
v-if="SessionUser.canAccessSuperUser() && userIdFromCustomerNumber"
|
||||
/>
|
||||
<!-- Log ind som kunde -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Log ind som kunde"
|
||||
icon="fas fa-user-shield"
|
||||
:click-action="() => SessionUser.superUser.intimidate.intimidateUser(userIdFromCustomerNumber)"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
|
||||
<!-- Set password -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Skift kodeord"
|
||||
icon="fas fa-key"
|
||||
:click-action="() => showSetCustomerPassword(userIdFromCustomerNumber)"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Show customer modal -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Vis kunde"
|
||||
icon="fas fa-user"
|
||||
:click-action="() => customerModalVisible = true"
|
||||
v-if="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
</template>
|
||||
<!-- If there is a reg_1, show the reg_1 actions -->
|
||||
<template v-if="props.reg_1 || props.reg_2">
|
||||
<!-- Label -->
|
||||
<action-settings-wheel-item-label
|
||||
:label="props.reg_1 && props.reg_2 ? `${SessionUser.objects.vehicles.meta.labels.multiple}` : `${SessionUser.objects.vehicles.meta.labels.single}`"
|
||||
v-show="SessionUser.canAccessSuperUser()"
|
||||
/>
|
||||
<!-- Show the vehicle, in a new tab -->
|
||||
<action-settings-wheel-item
|
||||
:label="`Se ${SessionUser.objects.vehicles.meta.labels.single.toLowerCase()} ${props.reg_1} i ny fane`"
|
||||
icon="fas fa-car"
|
||||
v-if="props.reg_1 && SessionUser.canAccessSuperUser()"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_1, true)"
|
||||
/>
|
||||
<action-settings-wheel-item
|
||||
:label="`Se ${SessionUser.objects.vehicles.meta.labels.single.toLowerCase()} ${props.reg_2} i ny fane`"
|
||||
icon="fas fa-car"
|
||||
v-if="props.reg_2 && SessionUser.canAccessSuperUser()"
|
||||
:click-action="() => SessionUser.functions.redirectTo.superUser('/vehicles/' + props.reg_2, true)"
|
||||
/>
|
||||
<!-- If there are any attachments, show the attachments actions -->
|
||||
<template v-if="attachmentsFromOrder.length > 0">
|
||||
<action-settings-wheel-item-label
|
||||
:label="'Vedhæftede filer'"
|
||||
/>
|
||||
<template v-for="(attachment, index) in attachmentsFromOrder" :key="index">
|
||||
<action-settings-wheel-item
|
||||
:label="`${attachment.content?.document || attachment.content?.other}`"
|
||||
icon="fas fa-paperclip"
|
||||
:click-action="() => SessionUser.objects.orders.functions.downloadAttachment(props.order_id, attachment.id, true)
|
||||
.catch((error) => {
|
||||
Swal.fire({
|
||||
title: 'Fejl',
|
||||
text: 'Der opstod en fejl under download af vedhæftede fil.',
|
||||
icon: 'error',
|
||||
});
|
||||
})"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<!-- If no actions are defined, then show that no actions are defined -->
|
||||
<template v-else>
|
||||
<div class="dropdown-item">
|
||||
<p class="has-text-centered">Ingen handlinger defineret</p>
|
||||
</div>
|
||||
</template>
|
||||
<!-- If no actions are defined, then show that no actions are defined -->
|
||||
<template v-else>
|
||||
<div class="dropdown-item">
|
||||
<p class="has-text-centered">Ingen handlinger defineret</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CustomerModal
|
||||
|
||||
@@ -12,14 +12,18 @@ const props = defineProps({
|
||||
type: [String, Function, Object],
|
||||
default: null,
|
||||
required: false
|
||||
},
|
||||
template: {
|
||||
type: String,
|
||||
default: 'is-warning',
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="message">
|
||||
<div class="notification is-warning">
|
||||
<button class="delete"
|
||||
<div class="notification" :class="template">
|
||||
<button class="delete" v-show="false"
|
||||
@click="clearErrors()"
|
||||
></button>
|
||||
{{ typeof message === 'function' ? message() : message }}
|
||||
|
||||
@@ -11,13 +11,13 @@ import { getDepartmentName } from "@/components/pagination/departmentTabs.vue";
|
||||
*/
|
||||
export const OrderBookings = {
|
||||
meta: {
|
||||
title: "Order Bookinger",
|
||||
title: "Bookinger",
|
||||
icon: "fas fa-list",
|
||||
description: "Oversigt over order bookinger",
|
||||
endpoint: "/order-bookings",
|
||||
labels: {
|
||||
single: "orderbooking",
|
||||
multiple: "orderbookinger",
|
||||
single: "booking",
|
||||
multiple: "bookinger",
|
||||
fields: {
|
||||
names: {
|
||||
customer_number: {
|
||||
|
||||
@@ -605,6 +605,7 @@ const showChangeOrderInvoiceCollectionForm = async (id) => {
|
||||
return response.data.data;
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
||||
+152
-25
@@ -300,10 +300,24 @@ const fieldVisibility = reactive({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Kun i dag</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select :value="onlyTodayFilter" @change="onOnlyTodayFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option :value="new Date().toISOString().split('T')[0]">Ja</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<table class="table is-fullwidth">
|
||||
<table class="table is-fullwidth is-hoverable is-striped"
|
||||
style="table-layout: fixed;">
|
||||
<tr>
|
||||
<th>Dato</th>
|
||||
<th v-show="fieldVisibility.customer_number">Kunde</th>
|
||||
@@ -323,7 +337,37 @@ const fieldVisibility = reactive({
|
||||
<template v-else>
|
||||
<template v-for="booking in sortedList" :key="booking.id">
|
||||
<tr v-if="isFirstBookingOfDay(booking)">
|
||||
<td colspan="9"><strong>{{ new Date(booking.datetime).toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric' }) }}</strong></td>
|
||||
<td colspan="9" class="has-text-left">
|
||||
<span class="has-text-grey">
|
||||
<i class="fas fa-calendar-day"></i>
|
||||
</span>
|
||||
<span class="has-text-grey">
|
||||
<!-- Human readable date (Today, Yesterday, etc.) -->
|
||||
{{
|
||||
(() => {
|
||||
const bookingDate = new Date(booking.datetime);
|
||||
const today = new Date();
|
||||
const yesterday = new Date();
|
||||
yesterday.setDate(today.getDate() - 1);
|
||||
if (bookingDate.toDateString() === today.toDateString()) {
|
||||
return 'I dag';
|
||||
} else if (bookingDate.toDateString() === yesterday.toDateString()) {
|
||||
return 'I går';
|
||||
} else {
|
||||
return bookingDate.toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
}
|
||||
})()
|
||||
}}
|
||||
<!-- Number of bookings on the date -->
|
||||
{{ sortedList.filter((b) => {
|
||||
const bDate = new Date(b.datetime);
|
||||
const bookingDate = new Date(booking.datetime);
|
||||
return bDate.getFullYear() === bookingDate.getFullYear() &&
|
||||
bDate.getMonth() === bookingDate.getMonth() &&
|
||||
bDate.getDate() === bookingDate.getDate();
|
||||
}).length }} {{SessionUser.objects.order_bookings.meta.labels.multiple.toLowerCase()}}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
@@ -436,10 +480,22 @@ const fieldVisibility = reactive({
|
||||
</td>
|
||||
<!-- Actions -->
|
||||
<td>
|
||||
<ActionSettingsWheelButton :order_booking_id="booking.id" :order_id="booking.order_id" :customer_number="booking.customer_number" :department_id="booking.department" :refresh-function="loadList" :reg_1="booking.reg_1" :reg_2="booking.reg_2">
|
||||
<template #actions>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
<div class="buttons is-right">
|
||||
<button v-if="canEditBooking(booking) && !booking.order_id" class="button is-small is-warning" @click="SessionUser.objects.order_bookings.functions.showCompleteConfirmationModal(booking.id, loadList)">
|
||||
<span class="icon">
|
||||
<i class="fas fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button v-if="!!booking.order_id" class="button is-small is-success" disabled>
|
||||
<span class="icon">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
</span>
|
||||
</button>
|
||||
<ActionSettingsWheelButton :order_booking_id="booking.id" :order_id="booking.order_id" :customer_number="booking.customer_number" :department_id="booking.department" :refresh-function="loadList" :reg_1="booking.reg_1" :reg_2="booking.reg_2" :icon="'fas fa-ellipsis-v'">
|
||||
<template #actions>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -523,33 +579,104 @@ const fieldVisibility = reactive({
|
||||
<template v-else>
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<template v-for="booking in sortedList" :key="booking.id">
|
||||
<!-- Date separator -->
|
||||
<div class="column is-full" v-if="isFirstBookingOfDay(booking)">
|
||||
<hr/>
|
||||
<strong>{{ new Date(booking.datetime).toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric' }) }}</strong>
|
||||
<hr/>
|
||||
</div>
|
||||
<div class="column is-full">
|
||||
<WhiteBoxCard :forceStateFooter="false" :forceState="false" :defaultOpen="false" :toggleable="false" class="is-clickable" :has-hover-effect="true" :hasSelectionStyle="false">
|
||||
<WhiteBoxCard :forceStateFooter="false" :forceState="false" :defaultOpen="false" :toggleable="true" class="is-clickable" :has-hover-effect="true" :hasSelectionStyle="false">
|
||||
<template v-slot:header>
|
||||
<div class="card-header-title is-flex is-justify-content-space-between is-align-items-center" style="width: 100%;">
|
||||
<div>
|
||||
<strong>{{ new Date(booking.datetime).toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }) }}</strong>
|
||||
<div>{{ booking.customer_name || 'Ukendt kunde' }}</div>
|
||||
<div>{{ booking.reg_1 || 'Ingen registreret' }} {{ booking.reg_2 ? ', ' + booking.reg_2 : '' }}</div>
|
||||
<div>{{ getDepartmentName(parseInt(booking.department)) }}</div>
|
||||
<div>Ydelser:
|
||||
<span
|
||||
@mouseenter="onItemsMouseEnter($event, booking)"
|
||||
@mouseleave="onItemsMouseLeave"
|
||||
@click="onItemsClick($event, booking)"
|
||||
style="cursor: pointer; text-overflow: ellipsis; overflow: hidden;"
|
||||
>
|
||||
{{ formatSummaryString(booking.items) }}
|
||||
</span>
|
||||
<div><small>{{ booking.customer_name || 'Ukendt kunde' }}</small></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-pulled-right" style="width: fit-content">
|
||||
<div>
|
||||
<div class="columns is-multiline is-mobile is-gapless is-justify-content-flex-end is-align-items-center">
|
||||
<!-- Department tag and status icon -->
|
||||
<div class="column is-narrow has-text-right mb-2">
|
||||
<span class="tag is-light is-small mr-1">
|
||||
<span class="icon">
|
||||
<!-- Clock, when pending -->
|
||||
<i class="fas fa-clock has-text-warning" v-if="!booking.order_id"></i>
|
||||
<!-- Check, when completed -->
|
||||
<i class="fas fa-check-circle has-text-success" v-else></i>
|
||||
</span>
|
||||
<small v-if="!departmentFilter || departmentFilter === '*'">
|
||||
{{ getDepartmentName(parseInt(booking.department)) }}
|
||||
</small>
|
||||
<small v-else>
|
||||
<!-- Status message -->
|
||||
{{ booking.order_id
|
||||
? 'Udført'
|
||||
: (!booking.pickup)
|
||||
? `${SessionUser.functions.ucFirst(getTimeUntilString(booking.datetime))}`
|
||||
: `Pickup ${getTimeUntilString(booking.datetime)}` }}
|
||||
</small>
|
||||
</span>
|
||||
</div>
|
||||
<!-- Edit button -->
|
||||
<div class="column is-12 has-text-right mb-2">
|
||||
<span class="buttons is-right mr-1">
|
||||
<span class="button is-light is-danger is-small" @click="SessionUser.objects.order_bookings.functions.showDeleteConfirmationModal(booking.id, loadList)">
|
||||
<span class="icon">
|
||||
<i class="fas fa-trash-alt fa-lg"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="button is-warning is-small" v-if="canEditBooking(booking) && !booking.order_id" @click="SessionUser.objects.order_bookings.functions.showCompleteConfirmationModal(booking.id, loadList)">
|
||||
<span class="icon">
|
||||
<i class="fas fa-edit fa-lg"></i>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ActionSettingsWheelButton :order_booking_id="booking.id" :order_id="booking.order_id" :customer_number="booking.customer_number" :department_id="booking.department" :refresh-function="loadList" :reg_1="booking.reg_1" :reg_2="booking.reg_2">
|
||||
<template #actions>
|
||||
</template>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:default>
|
||||
<div class="card-content">
|
||||
<div><small>{{ booking.reg_1 || 'Ingen registreret' }} {{ booking.reg_2 ? ', ' + booking.reg_2 : '' }}</small></div>
|
||||
<div>
|
||||
<div class="columns is-mobile is-multiline">
|
||||
<div class="column is-narrow">
|
||||
<span
|
||||
@mouseenter="onItemsMouseEnter($event, booking)"
|
||||
@mouseleave="onItemsMouseLeave"
|
||||
@click="onItemsClick($event, booking)"
|
||||
style="cursor: pointer; text-overflow: ellipsis; overflow: hidden;"
|
||||
class="mr-1"
|
||||
>
|
||||
<small class="is-size-7">{{ formatSummaryString(booking.items) }}</small>
|
||||
</span>
|
||||
</div>
|
||||
<div class="column is-fixed-bottom is-12">
|
||||
<strong><small class="is-size-7" >{{ new Date(booking.datetime).toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }) }}</small></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:content>
|
||||
<div>
|
||||
<p v-show="!!booking.po"><strong>PO:</strong> {{ booking.po || '-' }}</p>
|
||||
<p v-show="!!booking.reference"><strong>Reference:</strong> {{ booking.reference || '-' }}</p>
|
||||
<strong>Ydelser:</strong>
|
||||
<ul>
|
||||
<li v-for="item in booking.items" :key="item.id">
|
||||
{{ item.name }} <span v-if="item.quantity && item.quantity !== 1">
|
||||
({{ item.quantity }} stk)
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<ActionSettingsWheelButton :order_booking_id="booking.id" :order_id="booking.order_id" :customer_number="booking.customer_number" :department_id="booking.department" :refresh-function="loadList" :reg_1="booking.reg_1" :reg_2="booking.reg_2" :displayActionsDirectly="true">
|
||||
<template #actions/>
|
||||
</ActionSettingsWheelButton>
|
||||
</div>
|
||||
</template>
|
||||
</WhiteBoxCard>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user