notifications.vue 3.48 KB
<script setup lang="ts">
import type { SettingsNotifications } from '~/types'

const { t } = useAppI18n()
const toast = useToast()
const settingsApi = useSettingsApi()
const defaultSettings: SettingsNotifications = {
  email: true,
  desktop: false,
  product_updates: true,
  weekly_digest: false,
  important_updates: true
}

const { data: initialSettings } = await settingsApi.getNotifications()

const settings = initialSettings.value ?? defaultSettings

const state = reactive<SettingsNotifications>({
  email: settings.email,
  desktop: settings.desktop,
  product_updates: settings.product_updates,
  weekly_digest: settings.weekly_digest,
  important_updates: settings.important_updates
})

interface NotificationField {
  name: keyof SettingsNotifications
  label: string
  description: string
}

interface NotificationSection {
  title: string
  description: string
  fields: NotificationField[]
}

const sections = computed<NotificationSection[]>(() => [{
  title: t('settings.notifications.sections.channels.title'),
  description: t('settings.notifications.sections.channels.description'),
  fields: [{
    name: 'email',
    label: t('settings.notifications.fields.email.label'),
    description: t('settings.notifications.fields.email.description')
  }, {
    name: 'desktop',
    label: t('settings.notifications.fields.desktop.label'),
    description: t('settings.notifications.fields.desktop.description')
  }]
}, {
  title: t('settings.notifications.sections.account.title'),
  description: t('settings.notifications.sections.account.description'),
  fields: [{
    name: 'weekly_digest',
    label: t('settings.notifications.fields.weeklyDigest.label'),
    description: t('settings.notifications.fields.weeklyDigest.description')
  }, {
    name: 'product_updates',
    label: t('settings.notifications.fields.productUpdates.label'),
    description: t('settings.notifications.fields.productUpdates.description')
  }, {
    name: 'important_updates',
    label: t('settings.notifications.fields.importantUpdates.label'),
    description: t('settings.notifications.fields.importantUpdates.description')
  }]
}])

async function onChange() {
  try {
    const result = await settingsApi.updateNotifications({
      email: state.email,
      desktop: state.desktop,
      product_updates: state.product_updates,
      weekly_digest: state.weekly_digest,
      important_updates: state.important_updates
    } satisfies SettingsNotifications)

    if (!result.success) {
      toast.add({
        title: t('common.error'),
        description: result.message,
        icon: 'i-lucide-circle-alert',
        color: 'error'
      })
      return
    }
  } catch {
    toast.add({
      title: t('common.error'),
      description: t('common.requestFailed'),
      icon: 'i-lucide-circle-alert',
      color: 'error'
    })
  }
}
</script>

<template>
  <div v-for="(section, index) in sections" :key="index">
    <UPageCard
      :title="section.title"
      :description="section.description"
      variant="naked"
      class="mb-4"
    />

    <UPageCard variant="subtle" :ui="{ container: 'divide-y divide-default' }">
      <UFormField
        v-for="field in section.fields"
        :key="field.name"
        :name="field.name"
        :label="field.label"
        :description="field.description"
        class="flex items-center justify-between not-last:pb-4 gap-2"
      >
        <USwitch
          v-model="state[field.name]"
          @update:model-value="onChange"
        />
      </UFormField>
    </UPageCard>
  </div>
</template>