first commit
This commit is contained in:
158
app/pages/settings/index.vue
Normal file
158
app/pages/settings/index.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<script setup lang="ts">
|
||||
import * as z from 'zod'
|
||||
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||
|
||||
const fileRef = ref<HTMLInputElement>()
|
||||
|
||||
const profileSchema = z.object({
|
||||
name: z.string().min(2, 'Too short'),
|
||||
email: z.string().email('Invalid email'),
|
||||
username: z.string().min(2, 'Too short'),
|
||||
avatar: z.string().optional(),
|
||||
bio: z.string().optional()
|
||||
})
|
||||
|
||||
type ProfileSchema = z.output<typeof profileSchema>
|
||||
|
||||
const profile = reactive<Partial<ProfileSchema>>({
|
||||
name: 'Benjamin Canac',
|
||||
email: 'ben@nuxtlabs.com',
|
||||
username: 'benjamincanac',
|
||||
avatar: undefined,
|
||||
bio: undefined
|
||||
})
|
||||
const toast = useToast()
|
||||
async function onSubmit(event: FormSubmitEvent<ProfileSchema>) {
|
||||
toast.add({
|
||||
title: 'Success',
|
||||
description: 'Your settings have been updated.',
|
||||
icon: 'i-lucide-check',
|
||||
color: 'success'
|
||||
})
|
||||
console.log(event.data)
|
||||
}
|
||||
|
||||
function onFileChange(e: Event) {
|
||||
const input = e.target as HTMLInputElement
|
||||
|
||||
if (!input.files?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
profile.avatar = URL.createObjectURL(input.files[0]!)
|
||||
}
|
||||
|
||||
function onFileClick() {
|
||||
fileRef.value?.click()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm
|
||||
id="settings"
|
||||
:schema="profileSchema"
|
||||
:state="profile"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<UPageCard
|
||||
title="Profile"
|
||||
description="These informations will be displayed publicly."
|
||||
variant="naked"
|
||||
orientation="horizontal"
|
||||
class="mb-4"
|
||||
>
|
||||
<UButton
|
||||
form="settings"
|
||||
label="Save changes"
|
||||
color="neutral"
|
||||
type="submit"
|
||||
class="w-fit lg:ms-auto"
|
||||
/>
|
||||
</UPageCard>
|
||||
|
||||
<UPageCard variant="subtle">
|
||||
<UFormField
|
||||
name="name"
|
||||
label="Name"
|
||||
description="Will appear on receipts, invoices, and other communication."
|
||||
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="Email"
|
||||
description="Used to sign in, for email receipts and product updates."
|
||||
required
|
||||
class="flex max-sm:flex-col justify-between items-start gap-4"
|
||||
>
|
||||
<UInput
|
||||
v-model="profile.email"
|
||||
type="email"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</UFormField>
|
||||
<USeparator />
|
||||
<UFormField
|
||||
name="username"
|
||||
label="Username"
|
||||
description="Your unique username for logging in and your profile URL."
|
||||
required
|
||||
class="flex max-sm:flex-col justify-between items-start gap-4"
|
||||
>
|
||||
<UInput
|
||||
v-model="profile.username"
|
||||
type="username"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</UFormField>
|
||||
<USeparator />
|
||||
<UFormField
|
||||
name="avatar"
|
||||
label="Avatar"
|
||||
description="JPG, GIF or PNG. 1MB Max."
|
||||
class="flex max-sm:flex-col justify-between sm:items-center gap-4"
|
||||
>
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<UAvatar
|
||||
:src="profile.avatar"
|
||||
:alt="profile.name"
|
||||
size="lg"
|
||||
/>
|
||||
<UButton
|
||||
label="Choose"
|
||||
color="neutral"
|
||||
@click="onFileClick"
|
||||
/>
|
||||
<input
|
||||
ref="fileRef"
|
||||
type="file"
|
||||
class="hidden"
|
||||
accept=".jpg, .jpeg, .png, .gif"
|
||||
@change="onFileChange"
|
||||
>
|
||||
</div>
|
||||
</UFormField>
|
||||
<USeparator />
|
||||
<UFormField
|
||||
name="bio"
|
||||
label="Bio"
|
||||
description="Brief description for your profile. URLs are hyperlinked."
|
||||
class="flex max-sm:flex-col justify-between items-start gap-4"
|
||||
:ui="{ container: 'w-full' }"
|
||||
>
|
||||
<UTextarea
|
||||
v-model="profile.bio"
|
||||
:rows="5"
|
||||
autoresize
|
||||
class="w-full"
|
||||
/>
|
||||
</UFormField>
|
||||
</UPageCard>
|
||||
</UForm>
|
||||
</template>
|
||||
Reference in New Issue
Block a user