Added infrastructure for editable properties in settings page.

This commit is contained in:
Andrew Lalis 2023-02-16 10:20:05 +01:00
parent 40891656d0
commit 88089f2e11
4 changed files with 144 additions and 12 deletions

View File

@ -127,10 +127,20 @@ class AuthModule {
return response.data; return response.data;
} }
public async updateMyPersonalDetails(authStore: AuthStoreType, newPersonalDetails: UserPersonalDetails): Promise<UserPersonalDetails> {
const response = await api.post('/auth/me/personal-details', newPersonalDetails, authStore.axiosConfig);
return response.data;
}
public async getMyPreferences(authStore: AuthStoreType): Promise<UserPreferences> { public async getMyPreferences(authStore: AuthStoreType): Promise<UserPreferences> {
const response = await api.get('/auth/me/preferences', authStore.axiosConfig); const response = await api.get('/auth/me/preferences', authStore.axiosConfig);
return response.data; return response.data;
} }
public async updateMyPreferences(authStore: AuthStoreType, newPreferences: UserPreferences): Promise<UserPreferences> {
const response = await api.post('/auth/me/preferences', newPreferences, authStore.axiosConfig);
return response.data;
}
} }
export default AuthModule; export default AuthModule;

View File

@ -0,0 +1,42 @@
<template>
<div class="row justify-between">
<span class="property-label">{{ label }}</span>
<div v-if="typeof modelValue === 'string'">
<q-input
:model-value="modelValue"
@update:modelValue="onValueUpdated"
:type="inputType"
dense
/>
</div>
<div v-if="typeof modelValue === 'boolean'">
<q-toggle :model-value="modelValue" @update:modelValue="onValueUpdated"/>
</div>
</div>
</template>
<script setup lang="ts">
import {DateTime} from 'luxon';
interface Props {
label: string;
inputType?: any;
modelValue: string | number | boolean | DateTime;
}
defineProps<Props>();
const emits = defineEmits(['update:modelValue']);
function onValueUpdated(newValue: string) {
emits('update:modelValue', newValue);
}
</script>
<style scoped>
.property-label {
font-weight: bold;
margin-top: auto;
margin-bottom: auto;
}
</style>

View File

@ -47,7 +47,15 @@ export default {
} }
}, },
userSettingsPage: { userSettingsPage: {
title: 'Account Settings' title: 'Account Settings',
personalDetails: {
birthDate: 'Date of Birth'
},
preferences: {
accountPrivate: 'Private Account'
},
save: 'Save',
undo: 'Undo'
}, },
accountMenuItem: { accountMenuItem: {
logIn: 'Login', logIn: 'Login',

View File

@ -3,33 +3,105 @@
<StandardCenteredPage> <StandardCenteredPage>
<h3>{{ $t('userSettingsPage.title') }}</h3> <h3>{{ $t('userSettingsPage.title') }}</h3>
<hr> <hr>
<q-form> <div v-if="personalDetails">
<h4>Personal Information</h4>
<EditablePropertyRow
v-model="personalDetails.birthDate"
:label="$t('userSettingsPage.personalDetails.birthDate')"
input-type="date"
/>
<div v-if="personalDetailsChanged">
<q-btn :label="$t('userSettingsPage.save')" color="positive" @click="savePersonalDetails"/>
<q-btn :label="$t('userSettingsPage.undo')" color="secondary" @click="undoPersonalDetailsChanges"/>
</div>
</div>
<div v-if="preferences">
<h4>Preferences</h4>
<EditablePropertyRow
v-model="preferences.accountPrivate"
:label="$t('userSettingsPage.preferences.accountPrivate')"
/>
<div v-if="preferencesChanged">
<q-btn :label="$t('userSettingsPage.save')" color="positive" @click="savePreferences"/>
<q-btn :label="$t('userSettingsPage.undo')" color="secondary" @click="undoPreferencesChanges"/>
</div>
</div>
</q-form>
</StandardCenteredPage> </StandardCenteredPage>
</q-page> </q-page>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import StandardCenteredPage from 'components/StandardCenteredPage.vue'; import StandardCenteredPage from 'components/StandardCenteredPage.vue';
import { User } from 'src/api/main/auth'; import {useRoute, useRouter} from 'vue-router';
import { getUserRoute } from 'src/router/user-routing'; import {useAuthStore} from 'stores/auth-store';
import { useAuthStore } from 'src/stores/auth-store'; import {computed, onMounted, ref, Ref, toRaw} from 'vue';
import { onMounted } from 'vue'; import {UserPersonalDetails, UserPreferences} from 'src/api/main/auth';
import { useRoute, useRouter } from 'vue-router'; import api from 'src/api/main';
import EditablePropertyRow from 'components/EditablePropertyRow.vue';
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const authStore = useAuthStore(); const authStore = useAuthStore();
const personalDetails: Ref<UserPersonalDetails | undefined> = ref();
const preferences: Ref<UserPreferences | undefined> = ref();
let initialPersonalDetails: UserPersonalDetails | null = null;
let initialPreferences: UserPreferences | null = null;
onMounted(async () => { onMounted(async () => {
// If the user isn't on their own settings page, redirect them back to the user's profile page. // Redirect away from the page if the user isn't viewing their own settings.
const userId = route.params.userId as string; const userId = route.params.userId as string;
if (authStore.user?.id !== userId) { if (!authStore.user || authStore.user.id !== userId) {
await router.push(`/users/${userId}`); await router.push(`/users/${userId}`);
} }
personalDetails.value = await api.auth.getMyPersonalDetails(authStore);
initialPersonalDetails = structuredClone(toRaw(personalDetails.value));
preferences.value = await api.auth.getMyPreferences(authStore);
initialPreferences = structuredClone(toRaw(preferences.value));
}); });
const personalDetailsChanged = computed(() => {
return initialPersonalDetails !== null &&
JSON.stringify(initialPersonalDetails) !== JSON.stringify(personalDetails.value);
});
const preferencesChanged = computed(() => {
return initialPreferences !== null &&
JSON.stringify(initialPreferences) !== JSON.stringify(preferences.value);
});
async function savePersonalDetails() {
if (personalDetails.value) {
personalDetails.value = await api.auth.updateMyPersonalDetails(authStore, personalDetails.value);
initialPersonalDetails = structuredClone(toRaw(personalDetails.value));
}
}
function undoPersonalDetailsChanges() {
personalDetails.value = structuredClone(initialPersonalDetails);
}
async function savePreferences() {
if (preferences.value) {
preferences.value = await api.auth.updateMyPreferences(authStore, preferences.value);
initialPreferences = structuredClone(toRaw(preferences.value));
}
}
function undoPreferencesChanges() {
preferences.value = structuredClone(initialPreferences);
}
</script> </script>
<style scoped> <style scoped>
</style> </style>