diff --git a/frontend/src/lib/components/Header.svelte b/frontend/src/lib/components/Header.svelte index f5faa92..756d0a0 100644 --- a/frontend/src/lib/components/Header.svelte +++ b/frontend/src/lib/components/Header.svelte @@ -5,6 +5,8 @@ import { page } from '$app/stores'; import { t } from 'svelte-i18n'; import { writable } from 'svelte/store'; + import { PERMISSIONS } from '$lib/utils/constants'; + import { hasPrivilige } from '$lib/utils/helpers'; let isMobileMenuOpen = false; @@ -104,7 +106,7 @@ {$page.data.user.last_name} - {#if $page.data.user.role_id > 0} + {#if hasPrivilige($page.data.user, PERMISSIONS.View)}
- {#if role_id === 8} + {#if hasPrivilige(editor, PERMISSIONS.Super)} {/if} - - + {#if hasPrivilige(localUser, PERMISSIONS.Member)} + + + {/if} - + {#if hasPrivilige(localUser, PERMISSIONS.Member)} + + {/if} - {#if role_id > 0} + {#if !readonlyUser} {/if}
-
- - - - - -
-

{$t('licence_categories')}

-
- {#each Object.entries(groupedCategories) as [, categories], groupIndex} - {#if groupIndex > 0} -
- {/if} - {#each categories as category} -
-
- cat.category === category.category - )} - /> + + {#if hasPrivilige(localUser, PERMISSIONS.Member)} +
+ + + + + +
+

{$t('licence_categories')}

+
+ {#each Object.entries(groupedCategories) as [, categories], groupIndex} + {#if groupIndex > 0} +
+ {/if} + {#each categories as category} +
+
+ cat.category === category.category + )} + /> +
+ + {$t(`licenceCategory.${category.category}`)} +
- - {$t(`licenceCategory.${category.category}`)} - -
+ {/each} {/each} - {/each} +
-
+ {/if}
-
-

- {$t('subscription.monthly_fee')}: - {selectedSubscriptionModel?.monthly_fee || '-'} € -

-

- {$t('subscription.hourly_rate')}: - {selectedSubscriptionModel?.hourly_rate || '-'} € -

- {#if selectedSubscriptionModel?.included_hours_per_year} + {#if hasPrivilige(editor, PERMISSIONS.Member)} +

- {$t('subscription.included_hours_per_year')}: - {selectedSubscriptionModel?.included_hours_per_year} + {$t('subscription.monthly_fee')}: + {selectedSubscriptionModel?.monthly_fee || '-'} €

- {/if} - {#if selectedSubscriptionModel?.included_hours_per_month}

- {$t('subscription.included_hours_per_month')}: - {selectedSubscriptionModel?.included_hours_per_month} + {$t('subscription.hourly_rate')}: + {selectedSubscriptionModel?.hourly_rate || '-'} €

- {/if} -
+ {#if selectedSubscriptionModel?.included_hours_per_year} +

+ {$t('subscription.included_hours_per_year')}: + {selectedSubscriptionModel?.included_hours_per_year} +

+ {/if} + {#if selectedSubscriptionModel?.included_hours_per_month} +

+ {$t('subscription.included_hours_per_month')}: + {selectedSubscriptionModel?.included_hours_per_month} +

+ {/if} +
+ {/if}

{$t('details')}: @@ -465,7 +478,7 @@ label={$t('start')} bind:value={localUser.membership.start_date} placeholder={$t('placeholder.start_date')} - readonly={role_id === 0} + readonly={readonlyUser} /> - + {#if hasPrivilige(editor, PERMISSIONS.Member)} + + {/if}

- {$t(`userRole.${user.role_id}`, { default: 'unknown role' })} + {$t(`userRole.${user.role_id}`, { default: 'unknown' })} {/if} @@ -93,7 +93,7 @@ {licence_categories} on:close={close} on:cancel={close} - role_id={user.role_id} + editor={user} /> {/if} diff --git a/frontend/src/routes/auth/admin/users/+page.server.js b/frontend/src/routes/auth/admin/users/+page.server.js index d125d38..15d06b1 100644 --- a/frontend/src/routes/auth/admin/users/+page.server.js +++ b/frontend/src/routes/auth/admin/users/+page.server.js @@ -2,8 +2,8 @@ // - Implement a load function to fetch a list of all users. // - Create actions for updating user information (similar to the about/[id] route). -import { BASE_API_URI } from '$lib/utils/constants'; -import { formatError, userDatesFromRFC3339 } from '$lib/utils/helpers'; +import { BASE_API_URI, PERMISSIONS } from '$lib/utils/constants'; +import { formatError, hasPrivilige, userDatesFromRFC3339 } from '$lib/utils/helpers'; import { fail, redirect } from '@sveltejs/kit'; import { formDataToObject, @@ -18,7 +18,7 @@ export async function load({ locals }) { if (!locals.user) { throw redirect(302, `${base}/auth/login?next=${base}/auth/admin/users`); } - if (locals.user.role_id === 0) { + if (!hasPrivilige(locals.user, PERMISSIONS.View)) { throw redirect(302, `${base}/auth/about/${locals.user.id}`); } } diff --git a/frontend/src/routes/auth/admin/users/+page.svelte b/frontend/src/routes/auth/admin/users/+page.svelte index 5ecd009..dfcda3d 100644 --- a/frontend/src/routes/auth/admin/users/+page.svelte +++ b/frontend/src/routes/auth/admin/users/+page.svelte @@ -6,7 +6,8 @@ import { t } from 'svelte-i18n'; import { page } from '$app/stores'; import { applyAction, enhance } from '$app/forms'; - import { receive, send } from '$lib/utils/helpers'; + import { hasPrivilige, receive, send } from '$lib/utils/helpers'; + import { PERMISSIONS } from '$lib/utils/constants'; /** @type {import('./$types').ActionData} */ export let form; @@ -19,7 +20,7 @@ payments = [] } = $page.data); - let activeSection = 'users'; + let activeSection = 'members'; /** @type{App.Locals['user'] | null} */ let selectedUser = null; /** @type{App.Types['subscription'] | null} */ @@ -28,9 +29,21 @@ let showUserModal = false; let searchTerm = ''; - $: filteredUsers = searchTerm ? getFilteredUsers() : users; + $: members = users.filter((/** @type{App.Locals['user']} */ user) => { + return user.role_id >= PERMISSIONS.Member; + }); + $: supporters = users.filter((/** @type{App.Locals['user']} */ user) => { + return user.role_id < PERMISSIONS.Member; + }); + $: filteredMembers = searchTerm ? getFilteredUsers(members) : members; - function handleMailButtonClick() { + $: filteredSupporters = searchTerm ? getFilteredUsers(supporters) : supporters; + + /** + * Handles Mail button click to open a formatted mailto link + * @param {App.Locals['user'][]} filteredUsers - the users to send the mail to + */ + function handleMailButtonClick(filteredUsers) { const subject = 'Important Announcement'; const body = `Hello everyone,\n\nThis is an important message.`; const bccEmails = filteredUsers @@ -43,14 +56,15 @@ } /** - * returns a set of users depending on the entered search query + * returns a set of members depending on the entered search query + * @param {App.Locals['user'][]} userSet Set to filter * @return {App.Locals['user'][]}*/ - const getFilteredUsers = () => { - if (!searchTerm.trim()) return users; + const getFilteredUsers = (userSet) => { + if (!searchTerm.trim()) return userSet; const term = searchTerm.trim().toLowerCase(); - return users.filter((/** @type{App.Locals['user']}*/ user) => { + return userSet.filter((/** @type{App.Locals['user']}*/ user) => { const basicMatch = [ user.first_name?.toLowerCase(), user.last_name?.toLowerCase(), @@ -124,12 +138,22 @@