Newer
Older
navi-1 / webclient / src / components / settings / NotificationSettingsPanel.vue
<template>
  <div class="notifications-panel">
    <h2 class="notifications-title">{{ t('settings.notificationsTitle') }}</h2>

    <p class="notifications-description">
      <template v-if="bridgeMode">{{ t('settings.notificationsBridgeText') }}</template>
      <template v-else>{{ t('settings.notificationsWebText') }}</template>
    </p>

    <GnAlert v-if="!supported" variant="info" class="notifications-unsupported">
      <i class="ph ph-info"></i>
      <span>{{ t('settings.notificationsUnsupported') }}</span>
    </GnAlert>

    <div v-else class="notifications-row">
      <div class="notifications-row-text">
        <div class="notifications-row-title">{{ t('settings.notificationsRowTitle') }}</div>
        <div class="notifications-row-status">
          <template v-if="subscribed">
            <template v-if="bridgeMode">{{ t('settings.notificationsOnBackground') }}</template>
            <template v-else>{{ t('settings.notificationsOn') }}</template>
          </template>
          <template v-else-if="permission === 'denied'">
            {{ t(bridgeMode ? 'settings.notificationsBlockedApp' : 'settings.notificationsBlockedBrowser') }}
          </template>
          <template v-else>{{ t('settings.notificationsOff') }}</template>
        </div>
      </div>
      <GnSwitch
        :model-value="subscribed"
        :disabled="busy || permission === 'denied'"
        @update:model-value="onToggle"
      />
    </div>
  </div>
</template>

<script setup>
import { onMounted } from 'vue'
import { t } from '@/i18n/index.js'
import { usePush } from '@/composables/usePush.js'
import { useToast } from 'gnexus-ui-kit/vue'

const { supported, bridgeMode, permission, subscribed, busy, enable, disable, syncState } = usePush()
const toast = useToast()

onMounted(() => {
  syncState()
})

async function onToggle(want) {
  try {
    if (want) {
      const ok = await enable()
      if (ok === false && permission.value === 'denied') {
        toast.error({
          title: t('toast.notificationsDenied'),
          text: t(
            bridgeMode.value
              ? 'toast.notificationsAllowApp'
              : 'toast.notificationsAllowBrowser'
          ),
        })
      } else if (ok === false) {
        toast.error({
          title: t('toast.notificationsUnavailable'),
          text: t('toast.notificationsUnavailableText'),
        })
      }
    } else {
      await disable()
    }
  } catch (err) {
    toast.error({ title: t('toast.notificationsFailed'), text: err.message })
  }
}
</script>

<style scoped lang="scss">
.notifications-panel {
  margin-bottom: 24px;
}

.notifications-title {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 0 0 12px;
  color: var(--gn-color-text-medium);
}

.notifications-description {
  margin: 0 0 16px;
  font-size: 0.875rem;
  color: var(--gn-color-text-medium);
}

.notifications-unsupported {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 16px;

  i {
    font-size: 16px;
    flex-shrink: 0;
  }
}

.notifications-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  border: 1px solid var(--gn-border-color-muted);
  border-radius: 8px;
}

.notifications-row-title {
  font-size: 0.9rem;
  color: var(--gn-color-text-medium);
}

.notifications-row-status {
  font-size: 0.8rem;
  color: var(--gn-color-text-dark);
  margin-top: 2px;
}
</style>