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