310 lines
9.4 KiB
Vue
310 lines
9.4 KiB
Vue
<script setup>
|
|
import Swal from "sweetalert2";
|
|
import { usePaginatedListInstance } from "@/components/pagination/paginatedList.vue";
|
|
import { SessionUser } from "@/components/session/token/SessionUser.vue";
|
|
import ActionSettingsWheelButton from "@/components/displays/buttons/ActionSettingsWheelButton.vue";
|
|
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
|
|
|
|
const props = defineProps({
|
|
objects: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
showCustomer: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
|
|
const { loadList } = usePaginatedListInstance();
|
|
|
|
const canEditPermissions = () =>
|
|
props.showCustomer ? SessionUser.canAccessSuperUser() : SessionUser.canAccessUser() || SessionUser.hasPermission("SUBUSERS_EDIT");
|
|
const canDisableAccess = () =>
|
|
props.showCustomer ? SessionUser.canAccessSuperUser() : SessionUser.canAccessUser() || SessionUser.hasPermission("SUBUSERS_DELETE");
|
|
const canResendInvite = (subuser) =>
|
|
(props.showCustomer ? SessionUser.canAccessSuperUser() : SessionUser.canAccessUser() || SessionUser.hasPermission("SUBUSERS_EDIT"))
|
|
&& Boolean(subuser?.can_resend_invite ?? subuser?.setup_required);
|
|
const hasRowActions = (subuser) =>
|
|
(canEditPermissions() && subuser?.grant_id) || canResendInvite(subuser) || (canDisableAccess() && subuser?.grant_id);
|
|
|
|
const formatDateTime = (dateString) => {
|
|
if (!dateString) {
|
|
return "-";
|
|
}
|
|
|
|
return new Date(dateString).toLocaleString("da-DK");
|
|
};
|
|
|
|
const formatPhone = (subuser) => {
|
|
if (!subuser?.phone_country_code || !subuser?.phone) {
|
|
return subuser?.setup_required ? "Oplyses ved accept" : "-";
|
|
}
|
|
|
|
return `+${subuser.phone_country_code} ${subuser.phone}`;
|
|
};
|
|
|
|
const formatUsername = (subuser) => {
|
|
if (subuser?.username) {
|
|
return `@${subuser.username}`;
|
|
}
|
|
|
|
return subuser?.setup_required ? "Brugernavn oplyses ved accept" : "-";
|
|
};
|
|
|
|
const formatEmail = (subuser) => {
|
|
if (subuser?.email) {
|
|
return subuser.email;
|
|
}
|
|
|
|
return subuser?.setup_required ? "E-mail oplyses ved accept" : "-";
|
|
};
|
|
|
|
const formatCustomer = (subuser) => {
|
|
if (!props.showCustomer) {
|
|
return "";
|
|
}
|
|
|
|
const number = subuser?.customer_number ?? "-";
|
|
const name = subuser?.customer_name || "Ukendt kunde";
|
|
return `${number} - ${name}`;
|
|
};
|
|
|
|
const permissionSummary = (subuser) =>
|
|
SessionUser.objects.subusers.functions.permissionSummary(subuser?.grant_permissions || []);
|
|
|
|
const statusLabel = (subuser) => {
|
|
switch (subuser?.access_state) {
|
|
case "active":
|
|
return "Aktiv";
|
|
case "pending_setup":
|
|
return "Afventer opsætning";
|
|
case "disabled":
|
|
return "Deaktiveret";
|
|
default:
|
|
return "Ingen adgang";
|
|
}
|
|
};
|
|
|
|
const statusClass = (subuser) => {
|
|
switch (subuser?.access_state) {
|
|
case "active":
|
|
return "is-success";
|
|
case "pending_setup":
|
|
return "is-warning";
|
|
case "disabled":
|
|
return "is-light";
|
|
default:
|
|
return "is-light";
|
|
}
|
|
};
|
|
|
|
const refreshList = async () => {
|
|
await loadList();
|
|
};
|
|
|
|
const onEditPermissions = async (subuser) => {
|
|
if (!subuser?.grant_id) {
|
|
return;
|
|
}
|
|
|
|
await SessionUser.objects.subuser_grants.functions.showPermissionEditForm(
|
|
{
|
|
id: subuser.grant_id,
|
|
permissions: subuser.grant_permissions || [],
|
|
name: subuser.name || formatPhone(subuser) || `Chauffør ${subuser.id}`,
|
|
},
|
|
refreshList
|
|
);
|
|
};
|
|
|
|
const onEditNote = async (subuser) => {
|
|
if (!subuser?.grant_id) {
|
|
return;
|
|
}
|
|
|
|
const result = await Swal.fire({
|
|
title: "Redigér note",
|
|
input: "textarea",
|
|
inputLabel: "Intern note",
|
|
inputValue: subuser.grant_note || "",
|
|
inputPlaceholder: "Skriv en note til chaufførens adgang",
|
|
showCancelButton: true,
|
|
confirmButtonText: "Gem",
|
|
cancelButtonText: "Annuller",
|
|
preConfirm: async (value) => {
|
|
try {
|
|
await SessionUser.objects.subuser_grants.set.note(subuser.grant_id, value || "");
|
|
return value || "";
|
|
} catch (error) {
|
|
Swal.showValidationMessage("Kunne ikke gemme noten.");
|
|
return false;
|
|
}
|
|
},
|
|
});
|
|
|
|
if (result.isConfirmed) {
|
|
await refreshList();
|
|
}
|
|
};
|
|
|
|
const onToggleEnabled = async (subuser, enabled) => {
|
|
if (!subuser?.grant_id) {
|
|
return;
|
|
}
|
|
|
|
const actionLabel = enabled ? "genaktivere" : "deaktivere";
|
|
const result = await Swal.fire({
|
|
title: `${enabled ? "Genaktivér" : "Deaktivér"} adgang`,
|
|
text: `Vil du ${actionLabel} chaufførens adgang for den valgte kunde?`,
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
confirmButtonText: enabled ? "Genaktivér" : "Deaktivér",
|
|
cancelButtonText: "Annuller",
|
|
});
|
|
|
|
if (!result.isConfirmed) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await SessionUser.objects.subuser_grants.set.enabled(subuser.grant_id, enabled);
|
|
await refreshList();
|
|
} catch (error) {
|
|
await Swal.fire({
|
|
title: "Kunne ikke opdatere adgang",
|
|
text: error?.response?.data?.data?.message || error?.response?.data?.message || "Der opstod en fejl.",
|
|
icon: "error",
|
|
confirmButtonText: "Luk",
|
|
});
|
|
}
|
|
};
|
|
|
|
const onResendInvite = async (subuser) => {
|
|
await SessionUser.objects.subusers.functions.resendInvite(subuser, refreshList, { superuser: props.showCustomer });
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="table-container">
|
|
<table class="table is-fullwidth is-striped is-hoverable">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th v-if="showCustomer">Kunde</th>
|
|
<th>Chauffør</th>
|
|
<th>Kontakt</th>
|
|
<th>Adgang</th>
|
|
<th>Tilladelser</th>
|
|
<th>Note</th>
|
|
<th>Oprettet</th>
|
|
<th>Opdateret</th>
|
|
<th class="has-text-right">Handlinger</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-if="props.objects.length === 0">
|
|
<td :colspan="showCustomer ? 10 : 9" class="has-text-centered has-text-grey py-6">Ingen chauffører fundet.</td>
|
|
</tr>
|
|
|
|
<tr v-for="subuser in props.objects" :key="`${subuser.id}-${subuser.grant_id || 'none'}`">
|
|
<td>{{ subuser.id }}</td>
|
|
|
|
<td v-if="showCustomer">
|
|
<div class="has-text-weight-semibold">{{ formatCustomer(subuser) }}</div>
|
|
<div class="is-size-7 has-text-grey">Grant #{{ subuser.grant_id }}</div>
|
|
</td>
|
|
|
|
<td>
|
|
<div class="has-text-weight-semibold">{{ subuser.name || "-" }}</div>
|
|
<div class="is-size-7 has-text-grey" :data-testid="`subuser-username-${subuser.id}`">
|
|
{{ formatUsername(subuser) }}
|
|
</div>
|
|
</td>
|
|
|
|
<td>
|
|
<div :data-testid="`subuser-email-${subuser.id}`">{{ formatEmail(subuser) }}</div>
|
|
<div class="is-size-7 has-text-grey" :data-testid="`subuser-phone-${subuser.id}`">
|
|
{{ formatPhone(subuser) }}
|
|
</div>
|
|
</td>
|
|
|
|
<td>
|
|
<span class="tag" :class="statusClass(subuser)" :data-testid="`subuser-status-${subuser.id}`">
|
|
{{ statusLabel(subuser) }}
|
|
</span>
|
|
<div class="is-size-7 has-text-grey mt-2">
|
|
<span v-if="subuser.grant_enabled">Grant aktiv</span>
|
|
<span v-else>Grant inaktiv</span>
|
|
</div>
|
|
</td>
|
|
|
|
<td>
|
|
<div class="permission-summary">{{ permissionSummary(subuser) }}</div>
|
|
</td>
|
|
|
|
<td>
|
|
<div>{{ subuser.grant_note || "-" }}</div>
|
|
</td>
|
|
|
|
<td>{{ formatDateTime(subuser.created_at) }}</td>
|
|
<td>{{ formatDateTime(subuser.updated_at) }}</td>
|
|
|
|
<td>
|
|
<div class="buttons is-justify-content-flex-end action-buttons">
|
|
<ActionSettingsWheelButton v-if="hasRowActions(subuser)">
|
|
<template #actions>
|
|
<ActionSettingsWheelItem
|
|
v-if="canEditPermissions() && subuser.grant_id"
|
|
icon="fas fa-pen"
|
|
label="Redigér note"
|
|
:click-action="() => onEditNote(subuser)"
|
|
:test-id="`subuser-note-${subuser.id}`"
|
|
/>
|
|
|
|
<ActionSettingsWheelItem
|
|
v-if="canEditPermissions() && subuser.grant_id"
|
|
icon="fas fa-user-shield"
|
|
label="Tilladelser"
|
|
:click-action="() => onEditPermissions(subuser)"
|
|
:test-id="`subuser-permissions-${subuser.id}`"
|
|
/>
|
|
|
|
<ActionSettingsWheelItem
|
|
v-if="canResendInvite(subuser)"
|
|
icon="fas fa-paper-plane"
|
|
label="Gensend"
|
|
:click-action="() => onResendInvite(subuser)"
|
|
:test-id="`subuser-resend-${subuser.id}`"
|
|
/>
|
|
|
|
<ActionSettingsWheelItem
|
|
v-if="canDisableAccess() && subuser.grant_id"
|
|
:icon="subuser.grant_enabled ? 'fas fa-ban' : 'fas fa-check'"
|
|
:label="subuser.grant_enabled ? 'Deaktivér' : 'Aktivér'"
|
|
:template="subuser.grant_enabled ? 'danger' : 'success'"
|
|
:click-action="() => onToggleEnabled(subuser, !subuser.grant_enabled)"
|
|
:test-id="`subuser-toggle-${subuser.id}`"
|
|
/>
|
|
</template>
|
|
</ActionSettingsWheelButton>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.permission-summary {
|
|
max-width: 260px;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.action-buttons {
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
</style>
|