"Refactor OrderBookingsTable.vue: simplify table logic by removing unnecessary filters and pagination handling, migrate pagination to OrderBookingsPagination.vue, and update components for improved code maintainability and usability."
This commit is contained in:
@@ -363,6 +363,17 @@ const defaultActions = computed(() => {
|
||||
},
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-download',
|
||||
label: 'Download faktura',
|
||||
clickAction: () => {
|
||||
return SessionUser.objects.collectedOrderInvoices.functions.download(props.invoice_collection_id);
|
||||
},
|
||||
showFunction: () => {
|
||||
return true;
|
||||
},
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
icon: 'fas fa-trash-alt',
|
||||
label: 'Slet ordre',
|
||||
@@ -739,6 +750,19 @@ const defaultActions = computed(() => {
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<!-- Collected order invoice actions -->
|
||||
<template v-if="props.invoice_collection_id">
|
||||
<ActionSettingsWheelItemLabel
|
||||
:label="SessionUser.objects.collectedOrderInvoices.meta.title"
|
||||
v-show="props.invoice_collection_id"
|
||||
/>
|
||||
<!-- Download invoice -->
|
||||
<ActionSettingsWheelItem
|
||||
label="Download faktura"
|
||||
icon="fas fa-download"
|
||||
:click-action="() => SessionUser.objects.collectedOrderInvoices.functions.download(props.invoice_collection_id)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<!-- If no actions are defined, then show that no actions are defined -->
|
||||
<template v-else>
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
<script setup>
|
||||
import {
|
||||
list,
|
||||
loadList,
|
||||
setEndpoint,
|
||||
setFilter,
|
||||
} from "@/components/pagination/paginatedList.vue";
|
||||
import {SessionUser} from "@/components/session/token/SessionUser.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { defineProps, onMounted, ref} from "vue";
|
||||
import TableLabeledPagination from "@/components/displays/pagination/TableLabeledPagination.vue";
|
||||
import OrderBookingsTable from "@/views/dashboards/userDashboard/bookings/displays/tables/OrderBookingsTable.vue";
|
||||
import { departments, getDepartments } from "@/components/pagination/departmentTabs.vue";
|
||||
import { Colors } from "@/ThemeConfig.vue";
|
||||
|
||||
/**
|
||||
* Router
|
||||
*/
|
||||
const router = useRouter();
|
||||
/**
|
||||
* Props
|
||||
*/
|
||||
const props = defineProps({
|
||||
filters: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
required: false
|
||||
},
|
||||
})
|
||||
const orderIdFilter = ref('*');
|
||||
const onOrderIdFilterChange = (event) => {
|
||||
const val = event.target.value;
|
||||
orderIdFilter.value = val;
|
||||
// Apply filter: '*' clears, 'is null' shows without order, 'not null' shows with order
|
||||
setFilter('order_id', val);
|
||||
};
|
||||
|
||||
// Department filter
|
||||
const departmentFilter = ref('*');
|
||||
const onDepartmentFilterChange = (event) => {
|
||||
const val = event.target.value;
|
||||
departmentFilter.value = val;
|
||||
setFilter('department', val);
|
||||
};
|
||||
|
||||
// Only today filter
|
||||
const onlyTodayFilter = ref('*');
|
||||
const onOnlyTodayFilterChange = (event, autoLoadList = true) => {
|
||||
const val = event.target.value;
|
||||
onlyTodayFilter.value = val;
|
||||
if (val === '*') {
|
||||
setFilter('datetime', val, false); // Clear filter
|
||||
setFilter('datetime-date_from', null, false);
|
||||
setFilter('datetime-date_to', null, false);
|
||||
} else {
|
||||
const startOfDay = new Date().setHours(0, 0, 0, 0);
|
||||
const endOfDay = new Date().setHours(23, 59, 59, 999);
|
||||
setFilter('datetime', null, false);
|
||||
setFilter('datetime-date_from', new Date(startOfDay).toISOString(), false);
|
||||
setFilter('datetime-date_to', new Date(endOfDay).toISOString(), false);
|
||||
}
|
||||
if (autoLoadList) {
|
||||
loadList();
|
||||
}
|
||||
};
|
||||
|
||||
// Version selector + helpers
|
||||
const versionSelector = ref('new');
|
||||
const resetVersionToNew = () => {
|
||||
versionSelector.value = 'new';
|
||||
};
|
||||
const showLegacyOrderBookingsPortal = () => {
|
||||
const departmentId = SessionUser.functions.getDepartmentIdFromUrl();
|
||||
if (!departmentId) {
|
||||
SessionUser.functions.redirectTo.user('/bookings-legacy', true);
|
||||
return;
|
||||
}
|
||||
SessionUser.functions.redirectTo.department(SessionUser.functions.getDepartmentIdFromUrl(), 'modules/bookings-legacy', true);
|
||||
};
|
||||
|
||||
// Filters
|
||||
onMounted(() => {
|
||||
setEndpoint(SessionUser.objects.order_bookings.meta.endpoint, false);
|
||||
for (const [key, value] of Object.entries(props.filters)) {
|
||||
let setFilterKey = true;
|
||||
// Also set the filter controls if applicable
|
||||
if (key === 'order_id') {
|
||||
orderIdFilter.value = value;
|
||||
} else if (key === 'department') {
|
||||
departmentFilter.value = value;
|
||||
} else if (key === 'only_today' && value === true) {
|
||||
setFilterKey = false; // Since the only_today filter is handled separately
|
||||
onOnlyTodayFilterChange({ target: { value: new Date().toISOString().split('T')[0] } }, false);
|
||||
}
|
||||
if (setFilterKey) {
|
||||
setFilter(key, value, false);
|
||||
}
|
||||
}
|
||||
loadList();
|
||||
// Load departments for filter options
|
||||
getDepartments().catch(() => {});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<TableLabeledPagination label="Oversigt over bookinger">
|
||||
<template #paginationDisplayFiltersElement>
|
||||
<!-- Status filter -->
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Status</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select :value="orderIdFilter" @change="onOrderIdFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option value="is null">Ikke udført</option>
|
||||
<option value="not null">Udført</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Department filter -->
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Afdeling</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select :value="departmentFilter" @change="onDepartmentFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option v-for="department in departments" :key="department.id" :value="department.id">{{ department.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Version selector -->
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Version</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select @change="showLegacyOrderBookingsPortal(); resetVersionToNew()" v-model="versionSelector">
|
||||
<option value="new">Ny</option>
|
||||
<option value="legacy">Gammel</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Only today filter -->
|
||||
<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>
|
||||
</template>
|
||||
<template #leftPaginationColumns>
|
||||
</template>
|
||||
<template #rightPaginationColumns>
|
||||
<!-- Toggles and actions depending on route -->
|
||||
<!-- User: Only today switch + New booking button -->
|
||||
<div class="column is-narrow my-3" v-if="router.currentRoute.value.path.startsWith('/user')">
|
||||
<label class="label is-small">Vis kun dagens bookinger</label>
|
||||
<div class="field">
|
||||
<input id="today" type="checkbox" class="switch is-rounded" @change="(event) => { onOnlyTodayFilterChange({ target: { value: event.target.checked ? new Date().toISOString().split('T')[0] : '*' } }) }" :class="{ 'is-link': onlyTodayFilter !== '*' }" :checked="onlyTodayFilter !== '*'" />
|
||||
<label for="today"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-narrow my-3" v-if="router.currentRoute.value.path.startsWith('/user')">
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="SessionUser.functions.redirectTo.external('/user/bookings/new', true)"
|
||||
:style="{ 'color': Colors.buttons.textColor, 'background-color': Colors.buttons.backgroundColor }"
|
||||
>
|
||||
Ny booking
|
||||
</button>
|
||||
</div>
|
||||
<!-- Admin: pending + only today combined switch -->
|
||||
<div class="column is-narrow my-3" v-if="router.currentRoute.value.path.startsWith('/admin')">
|
||||
<label class="label is-small">Vis kun dagens afventende</label>
|
||||
<div class="field">
|
||||
<input id="today-pending" type="checkbox" class="switch is-rounded" @change="(event) => { onOnlyTodayFilterChange({ target: { value: event.target.checked ? new Date().toISOString().split('T')[0] : '*' } }, false); onOrderIdFilterChange({ target: { value: event.target.checked ? 'is null' : '*' } }); }" :class="{ 'is-link': onlyTodayFilter !== '*' && orderIdFilter === 'is null' }" :checked="onlyTodayFilter !== '*' && orderIdFilter === 'is null'" />
|
||||
<label for="today-pending"></label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #default>
|
||||
<OrderBookingsTable :objects="list" />
|
||||
</template>
|
||||
</TableLabeledPagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -13,6 +13,7 @@ import { ref } from 'vue';
|
||||
import { departments, getDepartments, isLoading, getDepartmentName} from "@/components/pagination/departmentTabs.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import ColorIndicator from "@/components/displays/buttons/ColorIndicator.vue";
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
|
||||
const su_object = SessionUser.objects.collectedOrderInvoices;
|
||||
|
||||
@@ -115,6 +116,7 @@ const dropdown_content = (object) => {
|
||||
<th>{{su_object.columns.created_at.label}}</th>
|
||||
<th>{{su_object.columns.po_number.label}}</th>
|
||||
<th>{{SessionUser.objects.global.language.total}}</th>
|
||||
<th><!-- Actions --></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -136,6 +138,13 @@ const dropdown_content = (object) => {
|
||||
:permission-check-function="() => canUserEditObject(object)"
|
||||
/>
|
||||
<td>{{ SessionUser.functions.currency.toLocal(object.total_net_amount) }}</td>
|
||||
<td>
|
||||
<ActionSettingsWheelButton
|
||||
:invoice_collection_id="object.id"
|
||||
>
|
||||
<template #actions></template>
|
||||
</ActionSettingsWheelButton>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
|
||||
@@ -254,6 +254,24 @@ export const CollectedOrderInvoices = {
|
||||
}
|
||||
},
|
||||
functions: {
|
||||
download: async (id) => {
|
||||
// Send the request
|
||||
return authenticatedRequest('/invoices/pdf', 'GET', {
|
||||
id: parseInt(id)
|
||||
}).then((response) => {
|
||||
//console.warn(response);
|
||||
// Create a blob from the response
|
||||
window.open(response.data.data.url, '_blank');
|
||||
return response;
|
||||
}).catch((error) => {
|
||||
Swal.fire({
|
||||
title: 'Der skete en fejl under hentning af PDF',
|
||||
text: SessionUser.functions.parseErrorMessage(error),
|
||||
icon: 'error'
|
||||
});
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
split_invoice: async (id) => {
|
||||
// Send the request
|
||||
return authenticatedRequest('/collected-invoices/split', 'POST', {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<script setup>
|
||||
import RestrictedPageWrapper from "@/components/page/wrappers/RestrictedPageWrapper.vue";
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import BookingsPagination from "@/components/displays/pagination/models/UserDashboard/BookingsPagination.vue";
|
||||
import DepartmentDashboardPageWrapper from "@/views/dashboards/departmentDashboard/DepartmentDashboardPageWrapper.vue";
|
||||
import NotFoundFallBackPageWrapper from "@/components/page/wrappers/NotFoundFallBackPageWrapper.vue";
|
||||
import OrderBookingsTable from "@/views/dashboards/userDashboard/bookings/displays/tables/OrderBookingsTable.vue";
|
||||
import OrderBookingsPagination from "@/components/displays/pagination/models/UserDashboard/OrderBookingsPagination.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -14,8 +13,7 @@ import OrderBookingsTable from "@/views/dashboards/userDashboard/bookings/displa
|
||||
subtitle="Oversigt over bookinger"
|
||||
>
|
||||
<NotFoundFallBackPageWrapper :exists="SessionUser.functions.getDepartmentIdFromUrl() && SessionUser.canAccessDepartment(SessionUser.functions.getDepartmentIdFromUrl())" error="Please select a department, that you have access to. If you believe this is an error, please contact support.">
|
||||
<OrderBookingsTable :filters="{ department: SessionUser.functions.getDepartmentIdFromUrl(), order_id: 'is null', only_today: true }"/>
|
||||
<!--<BookingsPagination :filters="{ department: SessionUser.functions.getDepartmentIdFromUrl() }" v-else/> -->
|
||||
<OrderBookingsPagination :filters="{ department: SessionUser.functions.getDepartmentIdFromUrl(), order_id: 'is null', only_today: true }"/>
|
||||
</NotFoundFallBackPageWrapper>
|
||||
</DepartmentDashboardPageWrapper>
|
||||
</RestrictedPageWrapper>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<script setup>
|
||||
|
||||
import BookingsPagination from "@/components/displays/pagination/models/UserDashboard/BookingsPagination.vue";
|
||||
import UserDashboardPageWrapper from "@/views/dashboards/userDashboard/UserDashboardPageWrapper.vue";
|
||||
import OrderBookingsTable from "@/views/dashboards/userDashboard/bookings/displays/tables/OrderBookingsTable.vue";
|
||||
import OrderBookingsPagination from "@/components/displays/pagination/models/UserDashboard/OrderBookingsPagination.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UserDashboardPageWrapper title="Mine bookinger" subtitle="Se dine bookinger">
|
||||
<!--<BookingsPagination/>-->
|
||||
<OrderBookingsTable :filters="{ only_today: true }"/>
|
||||
<OrderBookingsPagination :filters="{ only_today: true }"/>
|
||||
<!-- TODO: Complete implementation! -->
|
||||
</UserDashboardPageWrapper>
|
||||
</div>
|
||||
|
||||
+13
-389
@@ -1,105 +1,23 @@
|
||||
<script setup>
|
||||
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
||||
import {onMounted, ref, defineProps, computed, reactive} from "vue";
|
||||
import { getDepartmentName, departments, getDepartments } from "@/components/pagination/departmentTabs.vue";
|
||||
import { ref, defineProps, computed, reactive } from "vue";
|
||||
import { getDepartmentName } from "@/components/pagination/departmentTabs.vue";
|
||||
import EditableTableColumn from "@/components/displays/buttons/EditableTableColumn.vue";
|
||||
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
||||
import {
|
||||
list,
|
||||
isLoading,
|
||||
setEndpoint,
|
||||
loadList,
|
||||
metaCurrentPage,
|
||||
metaItemsPerPage,
|
||||
metaTotalItems,
|
||||
setMetaItemsPerPage,
|
||||
setPage,
|
||||
search,
|
||||
metaSearch,
|
||||
setFilter
|
||||
} from "@/components/pagination/paginatedList.vue";
|
||||
import PaginationDisplay from "@/components/displays/pagination/PaginationDisplay.vue";
|
||||
import PaginationNavigation from "@/components/displays/pagination/PaginationNavigation.vue";
|
||||
import LoadButtonWhileAwait from "@/components/request/LoadButtonWhileAwait.vue";
|
||||
import { loadList } from "@/components/pagination/paginatedList.vue";
|
||||
import { showPopper, removePopperIfOpen, popperBox } from "@/components/displays/PopperDefault.vue";
|
||||
import ViewportResponsiveWrapper from "@/components/viewport/conditions/elements/ViewportResponsiveWrapper.vue";
|
||||
import WhiteBoxCard from "@/components/displays/boxes/WhiteBoxCard.vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Colors } from "@/ThemeConfig.vue";
|
||||
import PaginationDisplayGeneralSearchReload
|
||||
from "@/components/displays/pagination/PaginationDisplayGeneralSearchReload.vue";
|
||||
|
||||
/**
|
||||
* Router
|
||||
*/
|
||||
const router = useRouter();
|
||||
/**
|
||||
* Props
|
||||
*/
|
||||
const props = defineProps({
|
||||
filters: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
required: false
|
||||
objects: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => [],
|
||||
}
|
||||
})
|
||||
const orderIdFilter = ref('*');
|
||||
const onOrderIdFilterChange = (event) => {
|
||||
const val = event.target.value;
|
||||
orderIdFilter.value = val;
|
||||
// Apply filter: '*' clears, 'is null' shows without order, 'not null' shows with order
|
||||
setFilter('order_id', val);
|
||||
};
|
||||
|
||||
// Department filter
|
||||
const departmentFilter = ref('*');
|
||||
const onDepartmentFilterChange = (event) => {
|
||||
const val = event.target.value;
|
||||
departmentFilter.value = val;
|
||||
setFilter('department', val);
|
||||
};
|
||||
|
||||
// Only today filter
|
||||
const onlyTodayFilter = ref('*');
|
||||
const onOnlyTodayFilterChange = (event, autoLoadList = true) => {
|
||||
const val = event.target.value;
|
||||
onlyTodayFilter.value = val;
|
||||
if (val === '*') {
|
||||
setFilter('datetime', val, false); // Clear filter
|
||||
setFilter('datetime-date_from', null, false);
|
||||
setFilter('datetime-date_to', null, false);
|
||||
} else {
|
||||
const startOfDay = new Date().setHours(0, 0, 0, 0);
|
||||
const endOfDay = new Date().setHours(23, 59, 59, 999);
|
||||
setFilter('datetime', null, false);
|
||||
setFilter('datetime-date_from', new Date(startOfDay).toISOString(), false);
|
||||
setFilter('datetime-date_to', new Date(endOfDay).toISOString(), false);
|
||||
}
|
||||
if (autoLoadList) {
|
||||
loadList();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setEndpoint("/order-bookings", false);
|
||||
for (const [key, value] of Object.entries(props.filters)) {
|
||||
let setFilterKey = true;
|
||||
// Also set the filter controls if applicable
|
||||
if (key === 'order_id') {
|
||||
orderIdFilter.value = value;
|
||||
} else if (key === 'department') {
|
||||
departmentFilter.value = value;
|
||||
} else if (key === 'only_today' && value === true) {
|
||||
setFilterKey = false; // Since the only_today filter is handled separately
|
||||
onOnlyTodayFilterChange({ target: { value: new Date().toISOString().split('T')[0] } }, false);
|
||||
}
|
||||
if (setFilterKey) {
|
||||
setFilter(key, value, false);
|
||||
}
|
||||
}
|
||||
loadList();
|
||||
// Load departments for filter options
|
||||
getDepartments().catch(() => {});
|
||||
});
|
||||
/**
|
||||
* This function will return a string that tells how long until the given time
|
||||
@@ -219,7 +137,7 @@ const canEditBooking = (bookingobj) => {
|
||||
}
|
||||
|
||||
const sortedList = computed(() => {
|
||||
return list.value.slice().sort((a, b) => {
|
||||
return (props.objects || []).slice().sort((a, b) => {
|
||||
const aDate = new Date(a.datetime);
|
||||
const bDate = new Date(b.datetime);
|
||||
return aDate - bDate;
|
||||
@@ -258,58 +176,7 @@ const getColspan = () => {
|
||||
return colspan;
|
||||
}
|
||||
|
||||
const showLegacyOrderBookingsPortal = () => {
|
||||
const departmentId = SessionUser.functions.getDepartmentIdFromUrl();
|
||||
if (!departmentId) {
|
||||
SessionUser.functions.redirectTo.user('/bookings-legacy', true);
|
||||
return;
|
||||
}
|
||||
SessionUser.functions.redirectTo.department(SessionUser.functions.getDepartmentIdFromUrl(), 'modules/bookings-legacy', true);
|
||||
}
|
||||
|
||||
// If the screen is mobile, set the is small variable to true
|
||||
const isSmall = ref(window.innerWidth < 1024);
|
||||
|
||||
/**
|
||||
* Switch between only today and all bookings
|
||||
*/
|
||||
const switchOnlyToday = (event) => {
|
||||
onOnlyTodayFilterChange({ target: { value: event.target.checked ? new Date().toISOString().split('T')[0] : '*' } });
|
||||
}
|
||||
|
||||
const switchOnlyPending = (event) => {
|
||||
onOrderIdFilterChange({ target: { value: event.target.checked ? 'is null' : '*' } });
|
||||
}
|
||||
|
||||
const switchOnlyPendingAndOnlyToday = (event) => {
|
||||
onOnlyTodayFilterChange({ target: { value: event.target.checked ? new Date().toISOString().split('T')[0] : '*' } }, false);
|
||||
onOrderIdFilterChange({ target: { value: event.target.checked ? 'is null' : '*' } }, false);
|
||||
loadList();
|
||||
}
|
||||
|
||||
const isFilterApplied = () => {
|
||||
if (!router.currentRoute.value.path.startsWith('/admin')) {
|
||||
if (departmentFilter.value !== '*') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return orderIdFilter.value !== '*' || onlyTodayFilter.value !== '*';
|
||||
}
|
||||
|
||||
const showAllBookings = () => {
|
||||
if (!router.currentRoute.value.path.startsWith('/admin')) {
|
||||
departmentFilter.value = '*';
|
||||
setFilter('department', '*', false);
|
||||
}
|
||||
switchOnlyToday({ target: { checked: false } }, false);
|
||||
switchOnlyPending({ target: { checked: false } }, false);
|
||||
loadList();
|
||||
}
|
||||
|
||||
const versionSelector = ref('new');
|
||||
const resetVersionToNew = () => {
|
||||
versionSelector.value = 'new';
|
||||
};
|
||||
// No pagination or filter handling here. This component is presentational only.
|
||||
|
||||
</script>
|
||||
|
||||
@@ -317,95 +184,6 @@ const resetVersionToNew = () => {
|
||||
<div>
|
||||
<ViewportResponsiveWrapper>
|
||||
<template #desktop>
|
||||
<div class="mb-3">
|
||||
<PaginationDisplayGeneralSearchReload/>
|
||||
<!-- Second row: Amount per page, Filters -->
|
||||
<div class="columns is-vcentered is-multiline">
|
||||
<div class="column is-narrow">
|
||||
<PaginationDisplay :metaItemsPerPage="metaItemsPerPage" :loadFunction="loadList" :isLoading="isLoading" :setMetaItemsPerPage="setMetaItemsPerPage" />
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Status</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select :value="orderIdFilter" @change="onOrderIdFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option value="is null">Ikke udført</option>
|
||||
<option value="not null">Udført</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Afdeling</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select :value="departmentFilter" @change="onDepartmentFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option v-for="department in departments" :key="department.id" :value="department.id">{{ department.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Version</label>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select @change="showLegacyOrderBookingsPortal(); resetVersionToNew()" v-model="versionSelector">
|
||||
<option value="new">Ny</option>
|
||||
<option value="legacy">Gammel</option>
|
||||
</select>
|
||||
</div>
|
||||
</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 class="column is-auto-fill my-3" v-if="!isSmall"/>
|
||||
<!-- Only show the bookings for today (Switch, if the route is /user) -->
|
||||
<div class="column is-narrow my-3" v-if="router.currentRoute.value.path.startsWith('/user')" :class="{ 'has-text-right': !isSmall }">
|
||||
<label class="label is-small">{{ isSmall ? 'I dag' : 'Vis kun dagens bookinger' }}</label>
|
||||
<div class="field">
|
||||
<input id="today" type="checkbox" class="switch is-rounded" @change="(event) => { switchOnlyToday(event); }" :class="{ 'is-link': onlyTodayFilter !== '*' }" :checked="onlyTodayFilter !== '*'" />
|
||||
<label for="today"></label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Create a new booking, if the route is /user -->
|
||||
<div class="column is-narrow my-3" v-if="router.currentRoute.value.path.startsWith('/user')" :class="{ 'has-text-right': !isSmall }">
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="SessionUser.functions.redirectTo.external('/user/bookings/new', true)"
|
||||
:style="{ 'color': Colors.buttons.textColor, 'background-color': Colors.buttons.backgroundColor }"
|
||||
>
|
||||
Ny booking
|
||||
</button>
|
||||
</div>
|
||||
<!-- Only show the pending bookings (Switch, if the route is /admin) -->
|
||||
<div class="column is-narrow my-3" v-if="router.currentRoute.value.path.startsWith('/admin')" :class="{ 'has-text-right': !isSmall }">
|
||||
<label class="label">{{ isSmall ? 'Afventende' : 'Vis kun dagens afventende' }}</label>
|
||||
<div class="field">
|
||||
<input id="today" type="checkbox" class="switch is-rounded" @change="(event) => { switchOnlyPendingAndOnlyToday(event); }" :class="{ 'is-link': onlyTodayFilter !== '*' && orderIdFilter === 'is null' }" :checked="onlyTodayFilter !== '*' && orderIdFilter === 'is null'" />
|
||||
<label for="today"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<table class="table is-fullwidth is-hoverable is-striped"
|
||||
style="table-layout: fixed;">
|
||||
@@ -420,14 +198,9 @@ const resetVersionToNew = () => {
|
||||
<th>Ydelser</th>
|
||||
<th><!-- Actions --></th>
|
||||
</tr>
|
||||
<template v-if="list.length === 0 && !isLoading">
|
||||
<template v-if="(objects || []).length === 0">
|
||||
<tr>
|
||||
<template v-if="isFilterApplied()">
|
||||
<td :colspan="getColspan()" class="has-text-centered">Ingen bookinger fundet med de valgte filtre.</td>
|
||||
</template>
|
||||
<template v-else>
|
||||
<td :colspan="getColspan()" class="has-text-centered">Ingen bookinger fundet.</td>
|
||||
</template>
|
||||
<td :colspan="getColspan()" class="has-text-centered">Ingen bookinger fundet.</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -596,145 +369,14 @@ const resetVersionToNew = () => {
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
<!-- Show all row if there is any filtering applied -->
|
||||
<tr v-if="isFilterApplied()">
|
||||
<td :colspan="getColspan()" class="has-text-centered">
|
||||
<button class="button is-small is-light" @click="showAllBookings()">
|
||||
<span>
|
||||
Vis alle bookinger
|
||||
</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<PaginationNavigation :currentPage="metaCurrentPage" :totalPages="Math.ceil(metaTotalItems / metaItemsPerPage)" :loadFunction="loadList" :setPage="setPage" :isLoading="isLoading" />
|
||||
</div>
|
||||
</template>
|
||||
<template #mobile>
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<!-- Search -->
|
||||
<div class="column">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Søg..."
|
||||
v-model="metaSearch"
|
||||
@input="search($event.target.value)"
|
||||
/>
|
||||
</div>
|
||||
<!-- Reload button -->
|
||||
<div class="column is-narrow">
|
||||
<LoadButtonWhileAwait class="is-dark is-fullwidth" :isLoading="isLoading" :loadFunction="loadList" icon="fas fa-sync-alt">Reload</LoadButtonWhileAwait>
|
||||
</div>
|
||||
<!-- Filters -->
|
||||
<div class="column is-full">
|
||||
<PaginationDisplay :metaItemsPerPage="metaItemsPerPage" :loadFunction="loadList" :isLoading="isLoading" :setMetaItemsPerPage="setMetaItemsPerPage" :allowSmallScreen="true">
|
||||
<template #paginationColumns>
|
||||
<!-- Version selector (align with desktop) -->
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Version</label>
|
||||
<div class="control">
|
||||
<div class="select is-small">
|
||||
<select @change="showLegacyOrderBookingsPortal(); resetVersionToNew()" v-model="versionSelector">
|
||||
<option value="new">Ny</option>
|
||||
<option value="legacy">Gammel</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Department filter -->
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Afdeling</label>
|
||||
<div class="control">
|
||||
<div class="select is-small">
|
||||
<select :value="departmentFilter" @change="onDepartmentFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option v-for="department in departments" :key="department.id" :value="department.id">{{ department.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Status filter -->
|
||||
<div class="column is-narrow">
|
||||
<div class="field mb-0">
|
||||
<label class="label is-small">Status</label>
|
||||
<div class="control">
|
||||
<div class="select is-small">
|
||||
<select :value="orderIdFilter" @change="onOrderIdFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option value="is null">Ikke udført</option>
|
||||
<option value="not null">Udført</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Only today filter -->
|
||||
<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 is-small">
|
||||
<select :value="onlyTodayFilter" @change="onOnlyTodayFilterChange">
|
||||
<option value="*">Alle</option>
|
||||
<option :value="new Date().toISOString().split('T')[0]">Ja</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Mobile switches are handled below -->
|
||||
<div class="column is-auto-fill is-hidden-desktop" v-if="router.currentRoute.value.path.startsWith('/user')" :class="{ 'has-text-right': !isSmall }">
|
||||
<label class="label is-small">{{ isSmall ? 'I dag' : 'Vis kun dagens bookinger' }}</label>
|
||||
<div class="field">
|
||||
<input id="today-mobile" type="checkbox" class="switch is-rounded is-small" @change="(event) => { switchOnlyToday(event); }" :class="{ 'is-link': onlyTodayFilter !== '*' }" :checked="onlyTodayFilter !== '*'" />
|
||||
<label for="today-mobile" class="label is-small"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-auto-fill is-hidden-desktop" v-if="router.currentRoute.value.path.startsWith('/admin')" :class="{ 'has-text-right': !isSmall }">
|
||||
<label class="label is-small">{{ isSmall ? 'Afventende' : 'Vis kun dagens afventende' }}</label>
|
||||
<div class="field">
|
||||
<input id="today-pending-mobile" type="checkbox" class="switch is-rounded is-small" @change="(event) => { switchOnlyPendingAndOnlyToday(event); }" :class="{ 'is-link': onlyTodayFilter !== '*' && orderIdFilter === 'is null' }" :checked="onlyTodayFilter !== '*' && orderIdFilter === 'is null'" />
|
||||
<label for="today-pending-mobile" class="label is-small"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-auto-fill is-hidden-desktop" v-if="router.currentRoute.value.path.startsWith('/user')" :class="{ 'has-text-right': !isSmall }">
|
||||
<button
|
||||
class="button is-link is-fullwidth"
|
||||
@click="SessionUser.functions.redirectTo.external('/user/bookings/new', true)"
|
||||
:style="{ 'color': Colors.buttons.textColor, 'background-color': Colors.buttons.backgroundColor }"
|
||||
>
|
||||
Ny booking
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</PaginationDisplay>
|
||||
</div>
|
||||
<!-- Toggles (align with desktop behavior) -->
|
||||
<!-- Only show the bookings for today (Switch, if the route is /user) -->
|
||||
<div class="column is-narrow my-3 is-hidden-touch" v-if="router.currentRoute.value.path.startsWith('/user')" :class="{ 'has-text-right': !isSmall }">
|
||||
<label class="label">{{ isSmall ? 'I dag' : 'Vis kun dagens bookinger' }}</label>
|
||||
<div class="field">
|
||||
<input id="today-mobile" type="checkbox" class="switch is-rounded" @change="(event) => { switchOnlyToday(event); }" :class="{ 'is-link': onlyTodayFilter !== '*' }" :checked="onlyTodayFilter !== '*'" />
|
||||
<label for="today-mobile"></label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Only show the pending bookings (Switch, if the route is /admin) -->
|
||||
<div class="column is-narrow my-3 is-hidden-touch" v-if="router.currentRoute.value.path.startsWith('/admin')" :class="{ 'has-text-right': !isSmall }">
|
||||
<label class="label">{{ isSmall ? 'Afventende' : 'Vis kun dagens afventende' }}</label>
|
||||
<div class="field">
|
||||
<input id="today-pending-mobile" type="checkbox" class="switch is-rounded" @change="(event) => { switchOnlyPendingAndOnlyToday(event); }" :class="{ 'is-link': onlyTodayFilter !== '*' && orderIdFilter === 'is null' }" :checked="onlyTodayFilter !== '*' && orderIdFilter === 'is null'" />
|
||||
<label for="today-pending-mobile"></label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Bookings -->
|
||||
<div class="column is-full">
|
||||
<div v-if="list.length === 0 && !isLoading">
|
||||
<div v-if="(objects || []).length === 0">
|
||||
<p class="has-text-centered">Ingen bookinger fundet.</p>
|
||||
</div>
|
||||
<template v-else>
|
||||
@@ -790,17 +432,9 @@ const resetVersionToNew = () => {
|
||||
<!-- Check, when completed -->
|
||||
<i class="fas fa-check-circle has-text-success" v-else></i>
|
||||
</span>
|
||||
<small v-if="!departmentFilter || departmentFilter === '*'">
|
||||
<small>
|
||||
{{ 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 -->
|
||||
@@ -868,16 +502,6 @@ const resetVersionToNew = () => {
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<!-- Show all row if there is any filtering applied -->
|
||||
<div class="column is-full" v-if="isFilterApplied()">
|
||||
<div class="has-text-centered">
|
||||
<button class="button is-small is-light" @click="showAllBookings()">
|
||||
<span>
|
||||
Vis alle bookinger
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user