feat(#23): Add email notifications

This commit is contained in:
2025-11-23 18:46:14 +01:00
parent e769bfb011
commit b72d564868
26 changed files with 613 additions and 18 deletions

View File

@@ -5,3 +5,5 @@ export { useApplicationFormVersionApi } from './applicationFormVersion/useApplic
export { useApplicationFormNavigation } from './useApplicationFormNavigation'
export { useNotification } from './notification/useNotification'
export { useNotificationApi } from './notification/useNotificationApi'
export { useUser } from './user/useUser'
export { useUserApi } from './user/useUserApi'

View File

@@ -0,0 +1,26 @@
import type { UpdateEmailPreferencesDto, UserDto } from '~~/.api-client'
import { useUserApi } from '~/composables'
export function useUser() {
const userApi = useUserApi()
async function getUserById(userId: string): Promise<UserDto> {
return await userApi.getUserById(userId)
}
async function updateEmailPreferences(
userId: string,
email: string | null,
emailOnFormCreated: boolean,
emailOnFormSubmitted: boolean
): Promise<UserDto> {
const updateDto: UpdateEmailPreferencesDto = { email, emailOnFormCreated, emailOnFormSubmitted }
return await userApi.updateEmailPreferences(userId, updateDto)
}
return {
getUserById,
updateEmailPreferences
}
}

View File

@@ -0,0 +1,42 @@
import { UserApi, Configuration, type UserDto, type UpdateEmailPreferencesDto } from '~~/.api-client'
import { cleanDoubleSlashes, withoutTrailingSlash } from 'ufo'
import { wrappedFetchWrap } from '~/utils/wrappedFetch'
export function useUserApi() {
const appBaseUrl = useRuntimeConfig().app.baseURL
const { serverApiBasePath, clientProxyBasePath } = useRuntimeConfig().public
const basePath = withoutTrailingSlash(
cleanDoubleSlashes(
import.meta.client
? appBaseUrl + clientProxyBasePath
: useRequestURL().origin + clientProxyBasePath + serverApiBasePath
)
)
const userApiClient = new UserApi(
new Configuration({ basePath, fetchApi: wrappedFetchWrap(useRequestFetch()) })
)
async function getUserById(id: string): Promise<UserDto> {
return userApiClient.getUserById({ id })
}
async function updateEmailPreferences(
id: string,
updateEmailPreferencesDto: UpdateEmailPreferencesDto
): Promise<UserDto> {
return userApiClient.updateUserEmailPreferences({ id, updateEmailPreferencesDto })
}
async function deleteUser(id: string): Promise<void> {
return userApiClient.deleteUser({ id })
}
return {
getUserById,
updateEmailPreferences,
deleteUser
}
}

View File

@@ -72,6 +72,33 @@
</div>
</div>
</UCard>
<!-- Email Notifications Section -->
<UCard>
<template #header>
<div>
<h3 class="text-lg font-semibold text-highlighted">{{ $t('settings.email.title') }}</h3>
<p class="text-sm text-muted mt-1">{{ $t('settings.email.description') }}</p>
</div>
</template>
<div class="space-y-4">
<UInput
v-model="emailAddress"
:label="$t('settings.email.emailAddress')"
type="email"
placeholder="user@example.com"
class="w-full max-w-md"
/>
<div class="space-y-3">
<UCheckbox v-model="emailOnFormCreated" :label="$t('settings.email.onFormCreated')" />
<UCheckbox v-model="emailOnFormSubmitted" :label="$t('settings.email.onFormSubmitted')" />
</div>
<UButton :label="$t('common.save')" color="primary" :loading="isSaving" @click="saveEmailPreferences" />
</div>
</UCard>
</div>
</template>
</UDashboardPanel>
@@ -79,6 +106,8 @@
<script setup lang="ts">
import { de, en } from '@nuxt/ui/locale'
import { useUserStore } from '~~/stores/useUserStore'
import { useUser } from '~/composables'
definePageMeta({
layout: 'default'
@@ -87,6 +116,9 @@ definePageMeta({
const { t: $t, locale, setLocale } = useI18n()
const colorMode = useColorMode()
const appConfig = useAppConfig()
const toast = useToast()
const userStore = useUserStore()
const { getUserById, updateEmailPreferences } = useUser()
const colors = [
'red',
@@ -107,6 +139,50 @@ const colors = [
'pink'
]
const emailAddress = ref('')
const emailOnFormCreated = ref(true)
const emailOnFormSubmitted = ref(true)
const isSaving = ref(false)
onMounted(async () => {
if (userStore.user) {
try {
const userData = await getUserById(userStore.user.keycloakId)
emailAddress.value = userData.email || ''
emailOnFormCreated.value = userData.emailOnFormCreated ?? true
emailOnFormSubmitted.value = userData.emailOnFormSubmitted ?? true
} catch (error) {
console.error('Failed to load user email preferences:', error)
}
}
})
async function saveEmailPreferences() {
if (!userStore.user) return
isSaving.value = true
try {
await updateEmailPreferences(
userStore.user.keycloakId,
emailAddress.value || null,
emailOnFormCreated.value,
emailOnFormSubmitted.value
)
toast.add({
title: $t('settings.email.saved'),
color: 'success'
})
} catch {
toast.add({
title: $t('common.error'),
color: 'error'
})
} finally {
isSaving.value = false
}
}
function handleLocaleChange(newLocale: string | undefined) {
if (newLocale) {
setLocale(newLocale as 'de' | 'en')

View File

@@ -170,5 +170,31 @@
"employer": "Arbeitgeber",
"worksCouncilMember": "Betriebsratsmitglied",
"worksCouncilChair": "Betriebsratsvorsitzender"
},
"settings": {
"title": "Einstellungen",
"language": {
"title": "Sprache",
"description": "Wählen Sie Ihre bevorzugte Sprache"
},
"appearance": {
"title": "Erscheinungsbild",
"description": "Wählen Sie Ihr bevorzugtes Farbschema",
"light": "Hell",
"dark": "Dunkel"
},
"theme": {
"title": "Designfarben",
"description": "Passen Sie die Primärfarbe an",
"primary": "Primärfarbe"
},
"email": {
"title": "E-Mail-Benachrichtigungen",
"description": "Verwalten Sie Ihre E-Mail-Benachrichtigungseinstellungen",
"emailAddress": "E-Mail-Adresse",
"onFormCreated": "Bei Erstellung eines Antrags",
"onFormSubmitted": "Bei Einreichung eines Antrags",
"saved": "Einstellungen gespeichert"
}
}
}

View File

@@ -170,5 +170,31 @@
"employer": "Employer",
"worksCouncilMember": "Works Council Member",
"worksCouncilChair": "Works Council Chair"
},
"settings": {
"title": "Settings",
"language": {
"title": "Language",
"description": "Select your preferred language"
},
"appearance": {
"title": "Appearance",
"description": "Choose your preferred color scheme",
"light": "Light",
"dark": "Dark"
},
"theme": {
"title": "Theme Colors",
"description": "Customize the primary color",
"primary": "Primary Color"
},
"email": {
"title": "Email Notifications",
"description": "Manage your email notification preferences",
"emailAddress": "Email Address",
"onFormCreated": "When an application form is created",
"onFormSubmitted": "When an application form is submitted",
"saved": "Settings saved"
}
}
}