API & Client - add a user preference for dark mode
This commit is contained in:
		@@ -0,0 +1,34 @@
 | 
			
		||||
"""add dark theme preferences
 | 
			
		||||
 | 
			
		||||
Revision ID: 14f48e46f320
 | 
			
		||||
Revises: 24eb097614e4
 | 
			
		||||
Create Date: 2023-12-16 18:35:31.377007
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from alembic import op
 | 
			
		||||
import sqlalchemy as sa
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# revision identifiers, used by Alembic.
 | 
			
		||||
revision = '14f48e46f320'
 | 
			
		||||
down_revision = '24eb097614e4'
 | 
			
		||||
branch_labels = None
 | 
			
		||||
depends_on = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def upgrade():
 | 
			
		||||
    # ### commands auto generated by Alembic - please adjust! ###
 | 
			
		||||
    with op.batch_alter_table('users', schema=None) as batch_op:
 | 
			
		||||
        batch_op.add_column(
 | 
			
		||||
            sa.Column('use_dark_mode', sa.Boolean(), nullable=True)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    # ### end Alembic commands ###
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def downgrade():
 | 
			
		||||
    # ### commands auto generated by Alembic - please adjust! ###
 | 
			
		||||
    with op.batch_alter_table('users', schema=None) as batch_op:
 | 
			
		||||
        batch_op.drop_column('use_dark_mode')
 | 
			
		||||
 | 
			
		||||
    # ### end Alembic commands ###
 | 
			
		||||
@@ -1459,6 +1459,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
 | 
			
		||||
                    imperial_units=True,
 | 
			
		||||
                    display_ascent=False,
 | 
			
		||||
                    start_elevation_at_zero=False,
 | 
			
		||||
                    use_dark_mode=True,
 | 
			
		||||
                    use_raw_gpx_speed=True,
 | 
			
		||||
                    date_format='yyyy-MM-dd',
 | 
			
		||||
                )
 | 
			
		||||
@@ -1478,6 +1479,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
 | 
			
		||||
        assert data['data']['timezone'] == 'America/New_York'
 | 
			
		||||
        assert data['data']['date_format'] == 'yyyy-MM-dd'
 | 
			
		||||
        assert data['data']['weekm'] is True
 | 
			
		||||
        assert data['data']['use_dark_mode'] is True
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize(
 | 
			
		||||
        'client_scope, can_access',
 | 
			
		||||
 
 | 
			
		||||
@@ -77,6 +77,12 @@ class TestUserSerializeAsAuthUser(UserModelAssertMixin):
 | 
			
		||||
        assert serialized_user['timezone'] == user_1.timezone
 | 
			
		||||
        assert serialized_user['weekm'] == user_1.weekm
 | 
			
		||||
        assert serialized_user['display_ascent'] == user_1.display_ascent
 | 
			
		||||
        assert (
 | 
			
		||||
            serialized_user['start_elevation_at_zero']
 | 
			
		||||
            == user_1.start_elevation_at_zero
 | 
			
		||||
        )
 | 
			
		||||
        assert serialized_user['use_raw_gpx_speed'] == user_1.use_raw_gpx_speed
 | 
			
		||||
        assert serialized_user['use_dark_mode'] == user_1.use_dark_mode
 | 
			
		||||
 | 
			
		||||
    def test_it_returns_workouts_infos(self, app: Flask, user_1: User) -> None:
 | 
			
		||||
        serialized_user = user_1.serialize(user_1)
 | 
			
		||||
@@ -155,6 +161,9 @@ class TestUserSerializeAsAdmin(UserModelAssertMixin):
 | 
			
		||||
        assert 'language' not in serialized_user
 | 
			
		||||
        assert 'timezone' not in serialized_user
 | 
			
		||||
        assert 'weekm' not in serialized_user
 | 
			
		||||
        assert 'start_elevation_at_zero' not in serialized_user
 | 
			
		||||
        assert 'use_raw_gpx_speed' not in serialized_user
 | 
			
		||||
        assert 'use_dark_mode' not in serialized_user
 | 
			
		||||
 | 
			
		||||
    def test_it_returns_workouts_infos(
 | 
			
		||||
        self, app: Flask, user_1_admin: User, user_2: User
 | 
			
		||||
 
 | 
			
		||||
@@ -361,6 +361,7 @@ def get_authenticated_user_profile(
 | 
			
		||||
          "total_ascent": 720.35,
 | 
			
		||||
          "total_distance": 67.895,
 | 
			
		||||
          "total_duration": "6:50:27",
 | 
			
		||||
          "use_dark_mode": null,
 | 
			
		||||
          "use_raw_gpx_speed": false,
 | 
			
		||||
          "username": "sam",
 | 
			
		||||
          "weekm": false
 | 
			
		||||
@@ -478,6 +479,7 @@ def edit_user(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
          "total_ascent": 720.35,
 | 
			
		||||
          "total_distance": 67.895,
 | 
			
		||||
          "total_duration": "6:50:27",
 | 
			
		||||
          "use_dark_mode": null,
 | 
			
		||||
          "use_raw_gpx_speed": false,
 | 
			
		||||
          "username": "sam"
 | 
			
		||||
          "weekm": true,
 | 
			
		||||
@@ -650,6 +652,7 @@ def update_user_account(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
          "total_ascent": 720.35,
 | 
			
		||||
          "total_distance": 67.895,
 | 
			
		||||
          "total_duration": "6:50:27",
 | 
			
		||||
          "use_dark_mode": null,
 | 
			
		||||
          "use_raw_gpx_speed": false,
 | 
			
		||||
          "username": "sam"
 | 
			
		||||
          "weekm": true,
 | 
			
		||||
@@ -878,6 +881,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
          "total_ascent": 720.35,
 | 
			
		||||
          "total_distance": 67.895,
 | 
			
		||||
          "total_duration": "6:50:27",
 | 
			
		||||
          "use_dark_mode": null,
 | 
			
		||||
          "use_raw_gpx_speed": true,
 | 
			
		||||
          "username": "sam"
 | 
			
		||||
          "weekm": true,
 | 
			
		||||
@@ -892,6 +896,8 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
    :<json string language: language preferences
 | 
			
		||||
    :<json boolean start_elevation_at_zero: do elevation plots start at zero?
 | 
			
		||||
    :<json string timezone: user time zone
 | 
			
		||||
    :<json boolean use_dark_mode: Display interface with dark mode if true.
 | 
			
		||||
                   If null, it uses browser preferences.
 | 
			
		||||
    :<json boolean use_raw_gpx_speed: Use unfiltered gpx to calculate speeds
 | 
			
		||||
    :<json boolean weekm: does week start on Monday?
 | 
			
		||||
 | 
			
		||||
@@ -916,6 +922,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
        'language',
 | 
			
		||||
        'start_elevation_at_zero',
 | 
			
		||||
        'timezone',
 | 
			
		||||
        'use_dark_mode',
 | 
			
		||||
        'use_raw_gpx_speed',
 | 
			
		||||
        'weekm',
 | 
			
		||||
    }
 | 
			
		||||
@@ -928,6 +935,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
    language = get_language(post_data.get('language'))
 | 
			
		||||
    start_elevation_at_zero = post_data.get('start_elevation_at_zero')
 | 
			
		||||
    use_raw_gpx_speed = post_data.get('use_raw_gpx_speed')
 | 
			
		||||
    use_dark_mode = post_data.get('use_dark_mode')
 | 
			
		||||
    timezone = post_data.get('timezone')
 | 
			
		||||
    weekm = post_data.get('weekm')
 | 
			
		||||
 | 
			
		||||
@@ -938,6 +946,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
 | 
			
		||||
        auth_user.language = language
 | 
			
		||||
        auth_user.start_elevation_at_zero = start_elevation_at_zero
 | 
			
		||||
        auth_user.timezone = timezone
 | 
			
		||||
        auth_user.use_dark_mode = use_dark_mode
 | 
			
		||||
        auth_user.use_raw_gpx_speed = use_raw_gpx_speed
 | 
			
		||||
        auth_user.weekm = weekm
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,7 @@ class User(BaseModel):
 | 
			
		||||
        db.Boolean, default=True, nullable=False
 | 
			
		||||
    )
 | 
			
		||||
    use_raw_gpx_speed = db.Column(db.Boolean, default=False, nullable=False)
 | 
			
		||||
    use_dark_mode = db.Column(db.Boolean, default=False, nullable=True)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self) -> str:
 | 
			
		||||
        return f'<User {self.username!r}>'
 | 
			
		||||
@@ -217,6 +218,7 @@ class User(BaseModel):
 | 
			
		||||
                    'language': self.language,
 | 
			
		||||
                    'start_elevation_at_zero': self.start_elevation_at_zero,
 | 
			
		||||
                    'timezone': self.timezone,
 | 
			
		||||
                    'use_dark_mode': self.use_dark_mode,
 | 
			
		||||
                    'use_raw_gpx_speed': self.use_raw_gpx_speed,
 | 
			
		||||
                    'weekm': self.weekm,
 | 
			
		||||
                },
 | 
			
		||||
 
 | 
			
		||||
@@ -107,7 +107,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
  import { computed, ref, capitalize, onBeforeMount } from 'vue'
 | 
			
		||||
  import { computed, ref, capitalize, onBeforeMount, watch } from 'vue'
 | 
			
		||||
  import type { ComputedRef, Ref } from 'vue'
 | 
			
		||||
 | 
			
		||||
  import UserPicture from '@/components/User/UserPicture.vue'
 | 
			
		||||
@@ -133,12 +133,18 @@
 | 
			
		||||
  )
 | 
			
		||||
  const isMenuOpen: Ref<boolean> = ref(false)
 | 
			
		||||
  const displayModal: Ref<boolean> = ref(false)
 | 
			
		||||
  const darkTheme: Ref<boolean> = ref(false)
 | 
			
		||||
 | 
			
		||||
  const darkMode: ComputedRef<boolean | null> = computed(
 | 
			
		||||
    () => store.getters[ROOT_STORE.GETTERS.DARK_MODE]
 | 
			
		||||
  )
 | 
			
		||||
  const darkTheme: ComputedRef<boolean> = computed(
 | 
			
		||||
    () => darkMode.value !== false
 | 
			
		||||
  )
 | 
			
		||||
  const themeIcon: ComputedRef<string> = computed(() =>
 | 
			
		||||
    darkTheme.value ? 'fa-moon' : 'fa-sun-o'
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  onBeforeMount(() => initTheme())
 | 
			
		||||
  onBeforeMount(() => setTheme())
 | 
			
		||||
 | 
			
		||||
  function openMenu() {
 | 
			
		||||
    isMenuOpen.value = true
 | 
			
		||||
@@ -163,22 +169,21 @@
 | 
			
		||||
  }
 | 
			
		||||
  function setTheme() {
 | 
			
		||||
    if (darkTheme.value) {
 | 
			
		||||
      darkTheme.value = true
 | 
			
		||||
      document.body.setAttribute('data-theme', 'dark')
 | 
			
		||||
    } else {
 | 
			
		||||
      document.body.removeAttribute('data-theme')
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  function initTheme() {
 | 
			
		||||
    if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
 | 
			
		||||
      darkTheme.value = true
 | 
			
		||||
    }
 | 
			
		||||
    setTheme()
 | 
			
		||||
  }
 | 
			
		||||
  function toggleTheme() {
 | 
			
		||||
    darkTheme.value = !darkTheme.value
 | 
			
		||||
    setTheme()
 | 
			
		||||
    store.commit(ROOT_STORE.MUTATIONS.UPDATE_DARK_MODE, !darkTheme.value)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  watch(
 | 
			
		||||
    () => darkTheme.value,
 | 
			
		||||
    () => {
 | 
			
		||||
      setTheme()
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@
 | 
			
		||||
    <dl>
 | 
			
		||||
      <dt>{{ $t('user.PROFILE.LANGUAGE') }}:</dt>
 | 
			
		||||
      <dd>{{ userLanguage }}</dd>
 | 
			
		||||
      <dt>{{ $t('user.PROFILE.THEME_MODE.LABEL') }}:</dt>
 | 
			
		||||
      <dd>{{ $t(`user.PROFILE.THEME_MODE.VALUES.${darkMode}`) }}</dd>
 | 
			
		||||
      <dt>{{ $t('user.PROFILE.TIMEZONE') }}:</dt>
 | 
			
		||||
      <dd>{{ timezone }}</dd>
 | 
			
		||||
      <dt>{{ $t('user.PROFILE.DATE_FORMAT') }}:</dt>
 | 
			
		||||
@@ -95,6 +97,13 @@
 | 
			
		||||
  const display_ascent = computed(() =>
 | 
			
		||||
    props.user.display_ascent ? 'DISPLAYED' : 'HIDDEN'
 | 
			
		||||
  )
 | 
			
		||||
  const darkMode = computed(() =>
 | 
			
		||||
    props.user.use_dark_mode === true
 | 
			
		||||
      ? 'DARK'
 | 
			
		||||
      : props.user.use_dark_mode === false
 | 
			
		||||
        ? 'LIGHT'
 | 
			
		||||
        : 'DEFAULT'
 | 
			
		||||
  )
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,22 @@
 | 
			
		||||
            </option>
 | 
			
		||||
          </select>
 | 
			
		||||
        </label>
 | 
			
		||||
        <label class="form-items">
 | 
			
		||||
          {{ $t('user.PROFILE.THEME_MODE.LABEL') }}
 | 
			
		||||
          <select
 | 
			
		||||
            id="use_dark_mode"
 | 
			
		||||
            v-model="userForm.use_dark_mode"
 | 
			
		||||
            :disabled="loading"
 | 
			
		||||
          >
 | 
			
		||||
            <option
 | 
			
		||||
              v-for="mode in useDarkMode"
 | 
			
		||||
              :value="mode.value"
 | 
			
		||||
              :key="mode.label"
 | 
			
		||||
            >
 | 
			
		||||
              {{ $t(`user.PROFILE.THEME_MODE.VALUES.${mode.label}`) }}
 | 
			
		||||
            </option>
 | 
			
		||||
          </select>
 | 
			
		||||
        </label>
 | 
			
		||||
        <label class="form-items">
 | 
			
		||||
          {{ $t('user.PROFILE.TIMEZONE') }}
 | 
			
		||||
          <TimezoneDropdown
 | 
			
		||||
@@ -195,6 +211,7 @@
 | 
			
		||||
    weekm: false,
 | 
			
		||||
    start_elevation_at_zero: false,
 | 
			
		||||
    use_raw_gpx_speed: false,
 | 
			
		||||
    use_dark_mode: false,
 | 
			
		||||
  })
 | 
			
		||||
  const weekStart = [
 | 
			
		||||
    {
 | 
			
		||||
@@ -246,6 +263,20 @@
 | 
			
		||||
      value: true,
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
  const useDarkMode = [
 | 
			
		||||
    {
 | 
			
		||||
      label: 'DARK',
 | 
			
		||||
      value: true,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: 'DEFAULT',
 | 
			
		||||
      value: null,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: 'LIGHT',
 | 
			
		||||
      value: false,
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
  const loading = computed(
 | 
			
		||||
    () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
 | 
			
		||||
  )
 | 
			
		||||
@@ -279,6 +310,7 @@
 | 
			
		||||
    userForm.timezone = user.timezone ? user.timezone : 'Europe/Paris'
 | 
			
		||||
    userForm.date_format = user.date_format ? user.date_format : 'dd/MM/yyyy'
 | 
			
		||||
    userForm.weekm = user.weekm ? user.weekm : false
 | 
			
		||||
    userForm.use_dark_mode = user.use_dark_mode
 | 
			
		||||
  }
 | 
			
		||||
  function updateProfile() {
 | 
			
		||||
    store.dispatch(AUTH_USER_STORE.ACTIONS.UPDATE_USER_PREFERENCES, userForm)
 | 
			
		||||
@@ -339,7 +371,8 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #language,
 | 
			
		||||
    #date_format {
 | 
			
		||||
    #date_format,
 | 
			
		||||
    #use_dark_mode {
 | 
			
		||||
      padding: $default-padding * 0.5;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -115,6 +115,14 @@
 | 
			
		||||
      "PROFILE": "profile",
 | 
			
		||||
      "SPORTS": "sports"
 | 
			
		||||
    },
 | 
			
		||||
    "THEME_MODE": {
 | 
			
		||||
      "LABEL": "Theme mode",
 | 
			
		||||
      "VALUES": {
 | 
			
		||||
        "DARK": "Dark",
 | 
			
		||||
        "DEFAULT": "Browser preference",
 | 
			
		||||
        "LIGHT": "Light"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "TIMEZONE": "Timezone",
 | 
			
		||||
    "UNITS": {
 | 
			
		||||
      "IMPERIAL": "Imperial system (ft, mi, mph, °F)",
 | 
			
		||||
 
 | 
			
		||||
@@ -115,6 +115,14 @@
 | 
			
		||||
      "PROFILE": "profil",
 | 
			
		||||
      "SPORTS": "sports"
 | 
			
		||||
    },
 | 
			
		||||
    "THEME_MODE": {
 | 
			
		||||
      "LABEL": "Thème",
 | 
			
		||||
      "VALUES": {
 | 
			
		||||
        "DARK": "Sombre",
 | 
			
		||||
        "DEFAULT": "Préférence du navigateur",
 | 
			
		||||
        "LIGHT": "Clair"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "TIMEZONE": "Fuseau horaire",
 | 
			
		||||
    "UNITS": {
 | 
			
		||||
      "IMPERIAL": "Système impérial (ft, mi, mph, °F)",
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,10 @@ export const actions: ActionTree<IAuthUserState, IRootState> &
 | 
			
		||||
              res.data.data.language
 | 
			
		||||
            )
 | 
			
		||||
          }
 | 
			
		||||
          context.commit(
 | 
			
		||||
            ROOT_STORE.MUTATIONS.UPDATE_DARK_MODE,
 | 
			
		||||
            res.data.data.use_dark_mode
 | 
			
		||||
          )
 | 
			
		||||
          context.dispatch(SPORTS_STORE.ACTIONS.GET_SPORTS)
 | 
			
		||||
        } else {
 | 
			
		||||
          handleError(context, null)
 | 
			
		||||
@@ -270,6 +274,10 @@ export const actions: ActionTree<IAuthUserState, IRootState> &
 | 
			
		||||
            AUTH_USER_STORE.MUTATIONS.UPDATE_AUTH_USER_PROFILE,
 | 
			
		||||
            res.data.data
 | 
			
		||||
          )
 | 
			
		||||
          context.commit(
 | 
			
		||||
            ROOT_STORE.MUTATIONS.UPDATE_DARK_MODE,
 | 
			
		||||
            res.data.data.use_dark_mode
 | 
			
		||||
          )
 | 
			
		||||
          context
 | 
			
		||||
            .dispatch(
 | 
			
		||||
              ROOT_STORE.ACTIONS.UPDATE_APPLICATION_LANGUAGE,
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ export enum RootGetters {
 | 
			
		||||
  APP_CONFIG = 'APP_CONFIG',
 | 
			
		||||
  APP_LOADING = 'APP_LOADING',
 | 
			
		||||
  APP_STATS = 'APP_STATS',
 | 
			
		||||
  DARK_MODE = 'DARK_MODE',
 | 
			
		||||
  ERROR_MESSAGES = 'ERROR_MESSAGES',
 | 
			
		||||
  LANGUAGE = 'LANGUAGE',
 | 
			
		||||
  LOCALE = 'LOCALE', // date-fns
 | 
			
		||||
@@ -22,5 +23,6 @@ export enum RootMutations {
 | 
			
		||||
  UPDATE_APPLICATION_LOADING = 'UPDATE_APPLICATION_LOADING',
 | 
			
		||||
  UPDATE_APPLICATION_PRIVACY_POLICY = 'UPDATE_APPLICATION_PRIVACY_POLICY',
 | 
			
		||||
  UPDATE_APPLICATION_STATS = 'UPDATE_APPLICATION_STATS',
 | 
			
		||||
  UPDATE_DARK_MODE = 'UPDATE_DARK_MODE',
 | 
			
		||||
  UPDATE_LANG = 'UPDATE_LANG',
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,9 @@ export const getters: GetterTree<IRootState, IRootState> & IRootGetters = {
 | 
			
		||||
  [ROOT_STORE.GETTERS.APP_STATS]: (state: IRootState) => {
 | 
			
		||||
    return state.application.statistics
 | 
			
		||||
  },
 | 
			
		||||
  [ROOT_STORE.GETTERS.DARK_MODE]: (state: IRootState) => {
 | 
			
		||||
    return state.darkMode
 | 
			
		||||
  },
 | 
			
		||||
  [ROOT_STORE.GETTERS.ERROR_MESSAGES]: (state: IRootState) => {
 | 
			
		||||
    return state.errorMessages
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -45,4 +45,10 @@ export const mutations: MutationTree<IRootState> & TRootMutations = {
 | 
			
		||||
    state.language = language
 | 
			
		||||
    state.locale = localeFromLanguage[language]
 | 
			
		||||
  },
 | 
			
		||||
  [ROOT_STORE.MUTATIONS.UPDATE_DARK_MODE](
 | 
			
		||||
    state: IRootState,
 | 
			
		||||
    darkMode: boolean | null
 | 
			
		||||
  ) {
 | 
			
		||||
    state.darkMode = darkMode
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,4 +17,5 @@ export const state: IRootState = {
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  appLoading: false,
 | 
			
		||||
  darkMode: null,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ export interface IRootState {
 | 
			
		||||
  errorMessages: string | string[] | null
 | 
			
		||||
  application: IApplication
 | 
			
		||||
  appLoading: boolean
 | 
			
		||||
  darkMode: boolean | null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IRootActions {
 | 
			
		||||
@@ -51,6 +52,8 @@ export interface IRootGetters {
 | 
			
		||||
 | 
			
		||||
  [ROOT_STORE.GETTERS.APP_STATS](state: IRootState): IAppStatistics
 | 
			
		||||
 | 
			
		||||
  [ROOT_STORE.GETTERS.DARK_MODE](state: IRootState): boolean | null
 | 
			
		||||
 | 
			
		||||
  [ROOT_STORE.GETTERS.ERROR_MESSAGES](
 | 
			
		||||
    state: IRootState
 | 
			
		||||
  ): string | string[] | null
 | 
			
		||||
@@ -83,6 +86,10 @@ export type TRootMutations<S = IRootState> = {
 | 
			
		||||
    statistics: IAppStatistics
 | 
			
		||||
  ): void
 | 
			
		||||
  [ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: TLanguage): void
 | 
			
		||||
  [ROOT_STORE.MUTATIONS.UPDATE_DARK_MODE](
 | 
			
		||||
    state: S,
 | 
			
		||||
    darkMode: boolean | null
 | 
			
		||||
  ): void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type TRootStoreModule<S = IRootState> = Omit<
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@ export interface IAuthUserProfile extends IUserProfile {
 | 
			
		||||
  timezone: string
 | 
			
		||||
  date_format: string
 | 
			
		||||
  weekm: boolean
 | 
			
		||||
  use_dark_mode: boolean | null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IUserPayload {
 | 
			
		||||
@@ -73,6 +74,7 @@ export interface IUserPreferencesPayload {
 | 
			
		||||
  timezone: string
 | 
			
		||||
  date_format: string
 | 
			
		||||
  weekm: boolean
 | 
			
		||||
  use_dark_mode: boolean | null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IUserSportPreferencesPayload {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user