Files
pleno-vue/src/components/models/navigation/items/NavigationMenuItemsSuperUser.vue
T

491 lines
15 KiB
Vue

<script lang="ts">
import { NavigationItemProps } from "@/components/models/navigation/NavigationItem.vue";
import { computed, defineComponent, ref, watch } from "vue";
import SessionUser from "@/components/session/token/SessionUser.vue";
import i18n from "@/i18n";
import {
ensureDraftTransactionCustomerLoaded,
getDraftTransactionCustomerNumber,
} from "@/composables/useDraftTransactionCustomer.js";
import { fetchSuperUserDraftCount } from "@/components/models/navigation/items/superUserDraftCount.js";
import { fetchSuperUserBookingCounts } from "@/components/models/navigation/items/superUserBookingCount.js";
import { NAVIGATION_COUNT_REFRESH_EVENT } from "@/components/models/navigation/items/navigationCountEvents.js";
const firstToUpperCase = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
const t = (key: string) => i18n.global.t(key);
const tf = (key: string, fallback: string) => {
const value = t(key);
return value === key ? fallback : value;
};
const superuser_draft_count = ref(0);
const superuser_draft_count_loading = ref(false);
const superuser_booking_counts = ref({
past: 0,
current: 0,
future: 0,
});
const superuser_booking_count_loading = ref(false);
const draftTransactionCustomerNumber = computed(() => getDraftTransactionCustomerNumber());
let draftCountRequestId = 0;
let bookingCountRequestId = 0;
let superUserBookingCountFetchInFlight = false;
let superUserDraftCountFetchInFlight = false;
let superUserBookingCountRefreshQueued = false;
let superUserDraftCountRefreshQueued = false;
let queuedSuperUserBookingLoadingIndicator = false;
let queuedSuperUserDraftLoadingIndicator = false;
const canUseSuperUserNavigationCounts = () => SessionUser.canAccessSuperUser();
const resetSuperUserNavigationCounts = () => {
bookingCountRequestId += 1;
draftCountRequestId += 1;
superuser_booking_counts.value = {
past: 0,
current: 0,
future: 0,
};
superuser_booking_count_loading.value = false;
superuser_draft_count.value = 0;
superuser_draft_count_loading.value = false;
superUserBookingCountFetchInFlight = false;
superUserDraftCountFetchInFlight = false;
superUserBookingCountRefreshQueued = false;
superUserDraftCountRefreshQueued = false;
queuedSuperUserBookingLoadingIndicator = false;
queuedSuperUserDraftLoadingIndicator = false;
};
const getSuperUserBookingsBadges = () => {
if (superuser_booking_count_loading.value) {
return [
{
type: "info" as const,
text: "",
condition: true,
classes: ["desktop-buefy-badge-loading"],
testId: "desktop-buefy-nav-bookings-badge-loading",
tooltip: "Indlæser bookinger",
tooltipTestId: "desktop-buefy-nav-bookings-badge-loading-tooltip",
},
];
}
return [
{
type: "danger" as const,
text: superuser_booking_counts.value.past.toString(),
condition: superuser_booking_counts.value.past > 0,
testId: "desktop-buefy-nav-bookings-badge-overdue",
tooltip: "Tidligere",
tooltipTestId: "desktop-buefy-nav-bookings-badge-overdue-tooltip",
},
{
type: "info" as const,
text: superuser_booking_counts.value.current.toString(),
condition: superuser_booking_counts.value.current > 0,
testId: "desktop-buefy-nav-bookings-badge",
tooltip: "I dag",
tooltipTestId: "desktop-buefy-nav-bookings-badge-tooltip",
},
{
type: "info" as const,
text: superuser_booking_counts.value.future.toString(),
condition: superuser_booking_counts.value.future > 0,
classes: ["desktop-buefy-bookings-badge-future"],
testId: "desktop-buefy-nav-bookings-badge-future",
tooltip: "Fremtidige",
tooltipTestId: "desktop-buefy-nav-bookings-badge-future-tooltip",
},
];
};
const getSuperUserDraftsBadge = () => {
if (superuser_draft_count_loading.value) {
return {
type: "info" as const,
text: "",
condition: true,
classes: ["desktop-buefy-badge-loading"],
testId: "desktop-buefy-nav-drafts-badge-loading",
tooltip: "Indlæser kladder",
tooltipTestId: "desktop-buefy-nav-drafts-badge-loading-tooltip",
};
}
return {
type: "info" as const,
text: superuser_draft_count.value.toString(),
condition: superuser_draft_count.value > 0,
testId: "desktop-buefy-nav-drafts-badge",
tooltip: t("nav.drafts"),
tooltipTestId: "desktop-buefy-nav-drafts-badge-tooltip",
};
};
const fetchCurrentSuperUserBookingCount = async ({ showLoadingIndicator = false } = {}) => {
if (!canUseSuperUserNavigationCounts()) {
resetSuperUserNavigationCounts();
return;
}
if (superUserBookingCountFetchInFlight) {
superUserBookingCountRefreshQueued = true;
queuedSuperUserBookingLoadingIndicator = queuedSuperUserBookingLoadingIndicator || showLoadingIndicator;
return;
}
if (showLoadingIndicator) {
superuser_booking_count_loading.value = true;
superuser_booking_counts.value = {
past: 0,
current: 0,
future: 0,
};
}
superUserBookingCountFetchInFlight = true;
const requestId = ++bookingCountRequestId;
let didApply = false;
try {
const nextBookingCounts = await fetchSuperUserBookingCounts();
if (requestId !== bookingCountRequestId) {
return;
}
superuser_booking_counts.value = nextBookingCounts;
superuser_booking_count_loading.value = false;
didApply = true;
} finally {
superUserBookingCountFetchInFlight = false;
const shouldRerun = superUserBookingCountRefreshQueued;
const shouldShowLoadingIndicator = queuedSuperUserBookingLoadingIndicator;
superUserBookingCountRefreshQueued = false;
queuedSuperUserBookingLoadingIndicator = false;
if (shouldRerun) {
void fetchCurrentSuperUserBookingCount({
showLoadingIndicator: shouldShowLoadingIndicator,
});
return;
}
if (!didApply) {
superuser_booking_count_loading.value = false;
}
}
};
const fetchCurrentSuperUserDraftCount = async ({ showLoadingIndicator = false } = {}) => {
if (!canUseSuperUserNavigationCounts()) {
resetSuperUserNavigationCounts();
return;
}
if (draftTransactionCustomerNumber.value === null) {
superuser_draft_count.value = 0;
superuser_draft_count_loading.value = false;
superUserDraftCountFetchInFlight = false;
superUserDraftCountRefreshQueued = false;
queuedSuperUserDraftLoadingIndicator = false;
return;
}
if (superUserDraftCountFetchInFlight) {
superUserDraftCountRefreshQueued = true;
queuedSuperUserDraftLoadingIndicator = queuedSuperUserDraftLoadingIndicator || showLoadingIndicator;
return;
}
if (showLoadingIndicator) {
superuser_draft_count_loading.value = true;
superuser_draft_count.value = 0;
}
superUserDraftCountFetchInFlight = true;
const requestId = ++draftCountRequestId;
const currentCustomerNumber = draftTransactionCustomerNumber.value;
let didApply = false;
try {
const nextDraftCount = await fetchSuperUserDraftCount({
customerNumber: currentCustomerNumber,
});
if (requestId !== draftCountRequestId || currentCustomerNumber !== draftTransactionCustomerNumber.value) {
return;
}
superuser_draft_count.value = nextDraftCount;
superuser_draft_count_loading.value = false;
didApply = true;
} finally {
superUserDraftCountFetchInFlight = false;
const shouldRerun = superUserDraftCountRefreshQueued;
const shouldShowLoadingIndicator = queuedSuperUserDraftLoadingIndicator;
superUserDraftCountRefreshQueued = false;
queuedSuperUserDraftLoadingIndicator = false;
if (shouldRerun) {
void fetchCurrentSuperUserDraftCount({
showLoadingIndicator: shouldShowLoadingIndicator,
});
return;
}
if (!didApply) {
superuser_draft_count_loading.value = false;
}
}
};
const refreshSuperUserNavigationCounts = ({
showBookingLoadingIndicator = false,
showDraftLoadingIndicator = false,
} = {}) => {
if (!canUseSuperUserNavigationCounts()) {
resetSuperUserNavigationCounts();
return;
}
void fetchCurrentSuperUserBookingCount({
showLoadingIndicator: showBookingLoadingIndicator,
});
if (draftTransactionCustomerNumber.value === null) {
superuser_draft_count.value = 0;
superuser_draft_count_loading.value = false;
superUserDraftCountFetchInFlight = false;
superUserDraftCountRefreshQueued = false;
queuedSuperUserDraftLoadingIndicator = false;
return;
}
void fetchCurrentSuperUserDraftCount({
showLoadingIndicator: showDraftLoadingIndicator,
});
};
watch(
draftTransactionCustomerNumber,
() => {
refreshSuperUserNavigationCounts({
showBookingLoadingIndicator: true,
showDraftLoadingIndicator: true,
});
},
{ immediate: true }
);
void ensureDraftTransactionCustomerLoaded();
if (typeof window !== "undefined") {
window.addEventListener(NAVIGATION_COUNT_REFRESH_EVENT, refreshSuperUserNavigationCounts);
}
setInterval(() => {
if (canUseSuperUserNavigationCounts()) {
refreshSuperUserNavigationCounts();
}
}, 5000);
const items = computed<NavigationItemProps[]>(() => [
// Invoicing
{
label: t("superuser.nav.invoicing"),
type: "category",
children: [
{ label: t("common.invoices"), to: "/superuser/invoices" },
{ label: t("superuser.nav.orders"), to: "/superuser/orders" },
{
label: t("nav.bookings"),
to: "/superuser/bookings",
badges: getSuperUserBookingsBadges(),
},
{
label: t("nav.drafts"),
to: "/superuser/orders/drafts",
hidden: draftTransactionCustomerNumber.value === null,
badge: getSuperUserDraftsBadge(),
},
],
},
// Products
{
label: t("common.products"),
type: "category",
children: [
{ label: t("common.products"), to: "/superuser/products" },
{ label: t("superuser.nav.categories"), to: "/superuser/categories" },
],
},
// Users
{
label: t("common.users"),
type: "category",
children: [
{ label: t("superuser.nav.employees"), to: "/superuser/users" },
{ label: t("superuser.nav.customers"), to: "/superuser/customers" },
{ label: t("superuser.nav.complaints"), to: "/superuser/complaints" },
{ label: t("superuser.nav.roles"), to: "/superuser/roles" },
],
},
// Departments
{
label: t("common.departments"),
type: "category",
children: [
{ label: t("common.departments"), to: "/superuser/departments" },
{ label: t("superuser.nav.department_lanes"), to: "/superuser/department/lanes" },
{ label: t("superuser.nav.department_gates"), to: "/superuser/department/gates" },
{ label: t("superuser.nav.department_relays"), to: "/superuser/department/relays" },
{ label: t("superuser.nav.scanners"), to: "/superuser/scanners" },
{ label: t("superuser.nav.selfserve"), to: "/superuser/selfserve" },
{ label: "Self-serve sessions", to: "/superuser/selfserve/sessions" },
{ label: "Edge Agents", to: "/superuser/selfserve/edge-agents" },
],
},
// Configurations
{
label: t("superuser.nav.configuration"),
type: "category",
children: [
{
label: firstToUpperCase(SessionUser.superUser.modules.xlvask.meta.labels.multiple),
to: "/superuser/configuration/xlvask",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.economic.meta.labels.multiple),
to: "/superuser/configuration/economic",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.reCAPTCHA.meta.labels.multiple),
to: "/superuser/configuration/recaptcha",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.email.meta.labels.multiple),
to: "/superuser/configuration/email",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.backups.meta.labels.multiple),
to: "/superuser/configuration/backup",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.failover.meta.labels.multiple),
to: "/superuser/configuration/failover",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.coolify.meta.labels.multiple),
to: "/superuser/configuration/coolify",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.releasemanager.meta.labels.multiple),
to: "/superuser/configuration/releases",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.motorapi.meta.labels.multiple),
to: "/superuser/configuration/motorapi",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.stripe.meta.labels.multiple),
to: "/superuser/configuration/stripe",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.fxratesapi.meta.labels.multiple),
to: "/superuser/configuration/fxratesapi",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.weatherapi.meta.labels.multiple),
to: "/superuser/configuration/weatherapi",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.workfeed.meta.labels.multiple),
to: "/superuser/configuration/workfeed",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.gatewayapi.meta.labels.multiple),
to: "/superuser/configuration/gatewayapi",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.entra.meta.labels.multiple),
to: "/superuser/configuration/entra",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.limble.meta.labels.multiple),
to: "/superuser/configuration/limble",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.ocrspace.meta.labels.multiple),
to: "/superuser/configuration/ocrspace",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.openai.meta.labels.multiple),
to: "/superuser/configuration/openai",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.licenseplaterecognizer.meta.labels.multiple),
to: "/superuser/configuration/licenseplaterecognizer",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.virkdata.meta.labels.multiple),
to: "/superuser/configuration/virkdata",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.shelly.meta.labels.multiple),
to: "/superuser/configuration/shelly",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.edgegateway.meta.labels.multiple),
to: "/superuser/configuration/edgegateway",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.selfserve.meta.labels.multiple),
to: "/superuser/configuration/selfserve",
},
{
label: firstToUpperCase(SessionUser.superUser.modules.bird.meta.labels.multiple),
to: "/superuser/configuration/bird",
},
],
},
// Other
{
label: t("superuser.nav.other"),
type: "category",
children: [
//{ label: 'Statistics', to: '/superuser/statistics' },
{ label: tf("superuser.nav.error_reports", "Error reports"), to: "/superuser/error-reports" },
{ label: t("common.vehicles"), to: "/superuser/vehicles" },
],
},
]);
const parsedItems = () => {
return items.value;
};
export default defineComponent({
name: "NavigationMenuItemsSuperUser",
setup() {
return {
items,
parsedItems,
};
},
});
// Named exports if needed
export { items, parsedItems };
</script>
<template>
<!-- Add a template section even if empty -->
</template>