From 167eb1bd24fb42c66128a743d4d5ff144da0b9c2 Mon Sep 17 00:00:00 2001 From: Oleandertengesdal Date: Fri, 10 Apr 2026 09:54:27 +0200 Subject: [PATCH 1/2] Add location selection for MANAGER/STAFF Add location support when assigning MANAGER or STAFF roles. Introduces BackendLocation and organizationService.getLocations(), and extends updateUser to accept and forward locationId when updating a user's role. --- frontend/src/services/organization.service.ts | 17 ++++++++-- frontend/src/views/settings/UsersTab.vue | 32 ++++++++++++++++--- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/frontend/src/services/organization.service.ts b/frontend/src/services/organization.service.ts index 3f3721f..9c3c5e9 100644 --- a/frontend/src/services/organization.service.ts +++ b/frontend/src/services/organization.service.ts @@ -17,6 +17,12 @@ const ROLE_PERMISSIONS: Record = { STAFF: { temperatureLogging: true, checklists: true, reports: false, deviations: true, userAdmin: false, settings: false }, } +interface BackendLocation { + id: number + name: string + address: string +} + interface BackendUser { id: number firstName: string @@ -76,7 +82,12 @@ export const organizationService = { })) }, - async updateUser(id: number, data: Partial): Promise { + async getLocations(): Promise { + const res = await api.get('/locations') + return res.data + }, + + async updateUser(id: number, data: Partial & { locationId?: number }): Promise { // Name update if (data.firstName !== undefined || data.lastName !== undefined) { await api.put(`/users/${id}`, { @@ -84,9 +95,9 @@ export const organizationService = { lastName: data.lastName, }) } - // Role update (separate endpoint) + // Role update (separate endpoint) — locationId required for MANAGER/STAFF if (data.role !== undefined) { - await api.put(`/users/${id}/role`, { role: data.role }) + await api.put(`/users/${id}/role`, { role: data.role, locationId: data.locationId ?? null }) } // Re-fetch the updated user from the list const users = await this.getUsers() diff --git a/frontend/src/views/settings/UsersTab.vue b/frontend/src/views/settings/UsersTab.vue index ee4c903..64e6ebb 100644 --- a/frontend/src/views/settings/UsersTab.vue +++ b/frontend/src/views/settings/UsersTab.vue @@ -86,6 +86,17 @@ +
+ + +
+

Tillatelser

@@ -139,6 +150,7 @@ import { organizationService } from '@/services/organization.service' import type { SettingsUser, UserRole } from '@/types' const users = ref([]) +const locations = ref<{ id: number; name: string }[]>([]) const loading = ref(false) const showModal = ref(false) const isEditing = ref(false) @@ -146,13 +158,14 @@ const editingId = ref(null) const originalRole = ref(null) const saveError = ref(null) -type FormData = Omit +type FormData = Omit & { locationId: number | null } const emptyForm = (): FormData => ({ firstName: '', lastName: '', email: '', role: 'STAFF', + locationId: null, isActive: true, permissions: { temperatureLogging: false, @@ -169,7 +182,10 @@ const form = reactive(emptyForm()) async function fetchUsers() { loading.value = true try { - users.value = await organizationService.getUsers() + ;[users.value, locations.value] = await Promise.all([ + organizationService.getUsers(), + organizationService.getLocations(), + ]) } finally { loading.value = false } @@ -223,20 +239,28 @@ function openEditModal(user: SettingsUser) { role: user.role, isActive: user.isActive, permissions: { ...user.permissions }, + locationId: null, }) showModal.value = true } async function save() { saveError.value = null + const needsLocation = form.role === 'MANAGER' || form.role === 'STAFF' + const roleChanged = form.role !== originalRole.value + if (roleChanged && needsLocation && !form.locationId) { + saveError.value = 'Velg en lokasjon for denne rollen.' + return + } + const colors = getAvatarColors(form.role) - const userData: Partial & { colorBg: string; colorText: string } = { + const userData: Partial & { colorBg: string; colorText: string; locationId?: number | null } = { ...form, colorBg: colors.bg, colorText: colors.text, } // Only send role if it actually changed — role endpoint returns 403 otherwise - if (isEditing.value && form.role === originalRole.value) { + if (isEditing.value && !roleChanged) { delete userData.role } From f67a7b501a01fef0316e68c828c97a3f175a99e2 Mon Sep 17 00:00:00 2001 From: Oleandertengesdal Date: Fri, 10 Apr 2026 09:56:08 +0200 Subject: [PATCH 2/2] quickfix --- frontend/src/services/organization.service.ts | 3 ++- frontend/src/views/settings/UsersTab.vue | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/services/organization.service.ts b/frontend/src/services/organization.service.ts index 9c3c5e9..e0c18fb 100644 --- a/frontend/src/services/organization.service.ts +++ b/frontend/src/services/organization.service.ts @@ -106,12 +106,13 @@ export const organizationService = { return updated }, - async createUser(data: Omit): Promise { + async createUser(data: Omit & { locationId?: number | null }): Promise { const res = await api.post('/users', { firstName: data.firstName, lastName: data.lastName, email: data.email, role: data.role, + locationId: data.locationId ?? null, }) return { id: res.data.id, diff --git a/frontend/src/views/settings/UsersTab.vue b/frontend/src/views/settings/UsersTab.vue index 64e6ebb..0f2c7d0 100644 --- a/frontend/src/views/settings/UsersTab.vue +++ b/frontend/src/views/settings/UsersTab.vue @@ -223,6 +223,7 @@ function openAddModal() { isEditing.value = false editingId.value = null saveError.value = null + originalRole.value = null Object.assign(form, emptyForm()) showModal.value = true } @@ -248,7 +249,7 @@ async function save() { saveError.value = null const needsLocation = form.role === 'MANAGER' || form.role === 'STAFF' const roleChanged = form.role !== originalRole.value - if (roleChanged && needsLocation && !form.locationId) { + if (needsLocation && (roleChanged || !isEditing.value) && !form.locationId) { saveError.value = 'Velg en lokasjon for denne rollen.' return }