Newer
Older
gnexus-tasks / frontend / src / views / SettingsView.vue
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { api } from '../api'
import { setLocale } from '../i18n/locale'
import { currencyOptions, setCurrency } from '../taskui'

// Глобальные настройки: валюта бюджетов и язык интерфейса.

const { t } = useI18n()

const currency = ref('UAH')
const language = ref('') // '' = как в аккаунте (SSO)
const error = ref('')
const saving = ref(false)
const saved = ref(false)

const languageOptions = computed(() => [
  { value: '', label: t('settings.languageAuto') },
  { value: 'ru', label: t('settings.langRu') },
  { value: 'en', label: t('settings.langEn') },
  { value: 'uk', label: t('settings.langUk') },
])

onMounted(async () => {
  try {
    const s = await api.getSettings()
    currency.value = s.currency
    language.value = s.language
  } catch (e) {
    error.value = String(e)
  }
})

async function save() {
  error.value = ''
  saved.value = false
  saving.value = true
  try {
    const s = await api.updateSettings({ currency: currency.value, language: language.value })
    setCurrency(s.currency)
    // язык применяется сразу; без переопределения — SSO locale или ru
    if (s.language === '') {
      const me = await fetch('/auth/me').then((r) => (r.ok ? r.json() : null))
      setLocale(me?.user?.locale || 'ru')
    } else {
      setLocale(s.language)
    }
    language.value = s.language
    saved.value = true
  } catch (e) {
    error.value = String(e)
  } finally {
    saving.value = false
  }
}
</script>

<template>
  <section>
    <GnPageHeader kicker="gntodo" :title="t('settings.title')" />

    <GnAlert v-if="error" variant="error">{{ error }}</GnAlert>

    <GnCard>
      <template #title>{{ t('settings.currencyTitle') }}</template>
      <p class="hint">{{ t('settings.currencyHint') }}</p>
      <GnSelect
        v-model="currency"
        :label="t('settings.currencyUnit')"
        :options="currencyOptions()"
      />
      <div class="form-actions">
        <GnButton
          variant="primary"
          icon="ph-floppy-disk"
          :disabled="saving"
          @click="save"
        >
          {{ t('common.save') }}
        </GnButton>
      </div>
      <GnAlert v-if="saved" variant="success">{{ t('settings.saved') }}</GnAlert>
    </GnCard>

    <GnCard>
      <template #title>{{ t('settings.languageTitle') }}</template>
      <p class="hint">{{ t('settings.languageHint') }}</p>
      <GnSelect
        v-model="language"
        :label="t('settings.languageUnit')"
        :options="languageOptions"
      />
      <div class="form-actions">
        <GnButton
          variant="primary"
          icon="ph-floppy-disk"
          :disabled="saving"
          @click="save"
        >
          {{ t('common.save') }}
        </GnButton>
      </div>
    </GnCard>
  </section>
</template>

<style scoped>
.hint {
  color: var(--muted, #888);
  margin: 0 0 0.75rem;
}
.form-actions {
  margin-top: 0.75rem;
}
.form-actions + .alert,
:deep(.alert) {
  margin-top: 0.75rem;
}
</style>