Files
shiftcraft/app/pages/profile.vue
2026-04-17 23:26:01 +00:00

143 lines
3.4 KiB
Vue

<template>
<UForm
id="settings"
:schema="profileSchema"
:state="profile"
@submit="onSubmit"
>
<UPageCard
:title="$t('profile.title')"
:description="$t('profile.description')"
variant="naked"
orientation="horizontal"
class="mb-4"
>
<UButton
form="settings"
:label="$t('profile.save')"
color="neutral"
type="submit"
class="w-fit lg:ms-auto"
/>
</UPageCard>
<UPageCard variant="subtle">
<UFormField
name="name"
:label="$t('profile.name')"
:description="$t('profile.nameDescription')"
required
class="flex max-sm:flex-col justify-between items-start gap-4"
>
<UInput
v-model="profile.name"
autocomplete="off"
/>
</UFormField>
<USeparator />
<UFormField
name="email"
:label="$t('profile.email')"
:description="$t('profile.emailDescription')"
required
class="flex max-sm:flex-col justify-between items-start gap-4"
>
<UInput
:model-value="user?.email"
type="email"
autocomplete="off"
disabled
/>
</UFormField>
<USeparator />
<UFormField
name="avatar"
:label="$t('profile.avatar')"
:description="$t('profile.avatarDescription')"
class="flex max-sm:flex-col justify-between sm:items-center gap-4"
>
<ProfileAvatarUpload />
</UFormField>
<USeparator />
<UFormField
name="delete"
:label="$t('profile.delete')"
:description="$t('profile.deleteDescription')"
class="flex max-sm:flex-col justify-between sm:items-center gap-4"
>
<UModal
:title="$t('profile.delete')"
:description="$t('profile.deleteWarning')"
:ui="{ footer: 'justify-end' }"
:close="false"
>
<UButton
:label="$t('profile.delete')"
color="error"
/>
<template #footer="{ close }">
<UButton
:label="$t('cancel')"
color="neutral"
variant="outline"
@click="close"
/>
<UButton
:label="$t('profile.delete')"
color="error"
@click="onDelete"
/>
</template>
</UModal>
</UFormField>
</UPageCard>
</UForm>
</template>
<script setup lang="ts">
import * as z from 'zod'
definePageMeta({
middleware: ['auth']
})
const { t } = useI18n()
const { user, updateUser, deleteUser } = useUser()
const profileSchema = z.object({
name: z.string().min(2, t('profile.tooShort'))
})
type ProfileSchema = z.output<typeof profileSchema>
const profile = reactive<Partial<ProfileSchema>>({
name: user?.name ?? ''
})
const toast = useToast()
async function onSubmit() {
try {
if (profile.name) {
await updateUser({ name: profile.name })
}
toast.add({
title: t('profile.success'),
description: t('profile.settingsUpdated'),
icon: 'i-lucide-check',
color: 'success'
})
} catch (error) {
toast.add({ color: 'error', description: (error as Error).message })
console.warn(error)
}
}
const onDelete = async () => {
try {
await deleteUser()
navigateTo('/')
} catch (error) {
toast.add({ color: 'error', description: (error as Error).message })
}
}
</script>