feat: added a profile settings and settings nav (#432)
This commit is contained in:
parent
c8a7e6e7e7
commit
613c5315b3
23 changed files with 698 additions and 7 deletions
135
pages/settings/profile/appearance.vue
Normal file
135
pages/settings/profile/appearance.vue
Normal file
|
@ -0,0 +1,135 @@
|
|||
<script lang="ts" setup>
|
||||
import { invoke } from '@vueuse/shared'
|
||||
import { useForm } from 'slimeform'
|
||||
|
||||
definePageMeta({
|
||||
// Keep alive the form page will reduce raw data timeliness and its status timeliness
|
||||
keepalive: false,
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const my = $computed(() => currentUser.value?.account)
|
||||
|
||||
watch($$(my), (value) => {
|
||||
if (!value)
|
||||
router.push('/')
|
||||
})
|
||||
|
||||
const onlineSrc = $computed(() => ({
|
||||
avatar: my?.avatar || '',
|
||||
header: my?.header || '',
|
||||
}))
|
||||
|
||||
const { form, reset, submitter, dirtyFields, isError } = useForm({
|
||||
form: () => ({
|
||||
displayName: my?.displayName ?? '',
|
||||
note: my?.source.note.replaceAll('\r', '') ?? '',
|
||||
|
||||
avatar: null as null | File,
|
||||
header: null as null | File,
|
||||
|
||||
// These look more like account and privacy settings than appearance settings
|
||||
// discoverable: false,
|
||||
// bot: false,
|
||||
// locked: false,
|
||||
}),
|
||||
})
|
||||
|
||||
// Keep the information to be edited up to date
|
||||
invoke(async () => {
|
||||
await pullMyAccountInfo()
|
||||
reset()
|
||||
})
|
||||
|
||||
const isCanSubmit = computed(() => !isError.value && !isEmptyObject(dirtyFields.value))
|
||||
|
||||
const { submit, submitting } = submitter(async ({ dirtyFields }) => {
|
||||
const res = await useMasto().accounts.updateCredentials(dirtyFields.value)
|
||||
.then(account => ({ account }))
|
||||
.catch((error: Error) => ({ error }))
|
||||
|
||||
if ('error' in res) {
|
||||
// TODO: Show error message
|
||||
console.error('Error(updateCredentials):', res.error)
|
||||
return
|
||||
}
|
||||
|
||||
setAccountInfo(my!.id, res.account)
|
||||
reset()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MainContent back>
|
||||
<template #title>
|
||||
<div text-lg font-bold flex items-center gap-2 @click="$scrollToTop">
|
||||
<span>{{ $t('settings.profile.appearance.title') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<form space-y-5 @submit.prevent="submit">
|
||||
<div>
|
||||
<!-- banner -->
|
||||
<div of-hidden bg="gray-500/20" aspect="3">
|
||||
<CommonInputImage
|
||||
ref="elInputImage"
|
||||
v-model="form.header"
|
||||
:original="onlineSrc.header"
|
||||
w-full h-full
|
||||
/>
|
||||
</div>
|
||||
<CommonCropImage v-model="form.header" :stencil-aspect-ratio="3 / 1" />
|
||||
|
||||
<!-- avatar -->
|
||||
<div px-4>
|
||||
<CommonInputImage
|
||||
v-model="form.avatar"
|
||||
:original="onlineSrc.avatar"
|
||||
mt--10
|
||||
rounded-full border="bg-base 4"
|
||||
w="sm:30 24" min-w="sm:30 24" h="sm:30 24"
|
||||
/>
|
||||
</div>
|
||||
<CommonCropImage v-model="form.avatar" />
|
||||
</div>
|
||||
|
||||
<div px4 py3 space-y-5>
|
||||
<!-- display name -->
|
||||
<label space-y-2 block>
|
||||
<p font-medium>
|
||||
{{ $t('settings.profile.appearance.display_name') }}
|
||||
</p>
|
||||
<input v-model="form.displayName" type="text" input-base>
|
||||
</label>
|
||||
|
||||
<!-- note -->
|
||||
<label space-y-2 block>
|
||||
<p font-medium>
|
||||
{{ $t('settings.profile.appearance.bio') }}
|
||||
</p>
|
||||
<textarea v-model="form.note" maxlength="500" min-h-10ex input-base />
|
||||
</label>
|
||||
|
||||
<!-- submit -->
|
||||
<div text-right>
|
||||
<button
|
||||
type="submit"
|
||||
btn-solid rounded-full text-sm
|
||||
flex-inline gap-x-2 items-center
|
||||
:disabled="submitting || !isCanSubmit"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
inline-block
|
||||
:class="submitting ? 'i-ri:loader-2-fill animate animate-spin' : 'i-ri:save-line'"
|
||||
/>
|
||||
<span>
|
||||
{{ $t('action.save') }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</MainContent>
|
||||
</template>
|
18
pages/settings/profile/featured-tags.vue
Normal file
18
pages/settings/profile/featured-tags.vue
Normal file
|
@ -0,0 +1,18 @@
|
|||
<template>
|
||||
<MainContent back>
|
||||
<template #title>
|
||||
<div text-lg font-bold flex items-center gap-2 @click="$scrollToTop">
|
||||
<div i-ri:test-tube-line />
|
||||
<span>{{ $t('settings.profile.featured_tags.label') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div text-center mt-10>
|
||||
<h1 text-4xl>
|
||||
🚧
|
||||
</h1>
|
||||
<h3 text-xl>
|
||||
{{ $t('settings.profile.featured_tags.label') }}
|
||||
</h3>
|
||||
</div>
|
||||
</MainContent>
|
||||
</template>
|
34
pages/settings/profile/index.vue
Normal file
34
pages/settings/profile/index.vue
Normal file
|
@ -0,0 +1,34 @@
|
|||
<script lang="ts" setup>
|
||||
const { lg } = breakpoints
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MainContent :back="!lg">
|
||||
<template #title>
|
||||
<div text-lg font-bold flex items-center gap-2 @click="$scrollToTop">
|
||||
<span>{{ $t('settings.profile.label') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<SettingsNavItem
|
||||
command
|
||||
icon="i-ri:user-settings-line"
|
||||
:text="$t('settings.profile.appearance.label')"
|
||||
to="/settings/profile/appearance"
|
||||
>
|
||||
<template #description>
|
||||
{{ $t('settings.profile.appearance.description') }}
|
||||
</template>
|
||||
</SettingsNavItem>
|
||||
<SettingsNavItem
|
||||
command
|
||||
icon="i-ri:hashtag"
|
||||
:text="$t('settings.profile.featured_tags.label')"
|
||||
to="/settings/profile/featured-tags"
|
||||
>
|
||||
<template #description>
|
||||
{{ $t('settings.profile.featured_tags.description') }}
|
||||
</template>
|
||||
</SettingsNavItem>
|
||||
</MainContent>
|
||||
</template>
|
Loading…
Add table
Add a link
Reference in a new issue