mirror of
				https://github.com/bartvdbraak/omnidash.git
				synced 2025-10-31 16:39:12 +00:00 
			
		
		
		
	feat: add profile form data and avatar
This commit is contained in:
		
							parent
							
								
									2fed4ffdf6
								
							
						
					
					
						commit
						b989c855ac
					
				
					 5 changed files with 64 additions and 67 deletions
				
			
		|  | @ -4,13 +4,6 @@ | |||
| 	import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; | ||||
| 	import type { BaseAuthStore } from 'pocketbase'; | ||||
| 
 | ||||
| 	const fullNameToInitials = (fullName: string) => | ||||
| 		fullName | ||||
| 			.split(' ') | ||||
| 			.map((word) => word[0].toUpperCase()) | ||||
| 			.slice(0, 2) | ||||
| 			.join(''); | ||||
| 
 | ||||
| 	export let authenticated = false; | ||||
| 	export let user: BaseAuthStore['model']; | ||||
| </script> | ||||
|  | @ -21,7 +14,7 @@ | |||
| 			<Button variant="ghost" builders={[builder]} class="relative h-8 w-8 rounded-full"> | ||||
| 				<Avatar.Root class="h-9 w-9"> | ||||
| 					<Avatar.Image src={user?.avatarUrl} alt={user?.name} /> | ||||
| 					<Avatar.Fallback>{fullNameToInitials(user?.name)}</Avatar.Fallback> | ||||
| 					<Avatar.Fallback>{user?.initials}</Avatar.Fallback> | ||||
| 				</Avatar.Root> | ||||
| 			</Button> | ||||
| 		</DropdownMenu.Trigger> | ||||
|  |  | |||
|  | @ -2,7 +2,9 @@ | |||
| 	import type { PageData } from './$types'; | ||||
| 	import ProfileForm from './profile-form.svelte'; | ||||
| 	import { Separator } from '$lib/components/ui/separator'; | ||||
| 
 | ||||
| 	export let data: PageData; | ||||
| 	export let { form, user } = data; | ||||
| </script> | ||||
| 
 | ||||
| <div class="space-y-6"> | ||||
|  | @ -11,5 +13,5 @@ | |||
| 		<p class="text-sm text-muted-foreground">This is how others will see you on the site.</p> | ||||
| 	</div> | ||||
| 	<Separator /> | ||||
| 	<ProfileForm data={data.form} /> | ||||
| 	<ProfileForm data={form} {user} /> | ||||
| </div> | ||||
|  |  | |||
|  | @ -5,12 +5,8 @@ | |||
| 			.string() | ||||
| 			.min(2, 'Username must be at least 2 characters.') | ||||
| 			.max(30, 'Username must not be longer than 30 characters'), | ||||
| 		email: z.string({ required_error: 'Please select an email to display' }).email(), | ||||
| 		bio: z.string().min(4).max(160).default('I own a computer.'), | ||||
| 		website: z | ||||
| 			.string() | ||||
| 			.url({ message: 'Please enter a valid URL.' }) | ||||
| 			.default('https://shadcn-svelte.com') | ||||
| 		email: z.string({ required_error: 'Please enter a valid email' }).email(), | ||||
| 		avatar: z.any().refine((val) => val.length > 0, 'File is required') | ||||
| 	}); | ||||
| 	export type ProfileFormSchema = typeof profileFormSchema; | ||||
| </script> | ||||
|  | @ -19,7 +15,11 @@ | |||
| 	import * as Form from '$lib/components/ui/form'; | ||||
| 	import type { SuperValidated } from 'sveltekit-superforms'; | ||||
| 	import { dev } from '$app/environment'; | ||||
| 	import type { LayoutData } from '../$types'; | ||||
| 	import * as Avatar from '$lib/components/ui/avatar'; | ||||
| 
 | ||||
| 	export let data: SuperValidated<ProfileFormSchema>; | ||||
| 	export let user: LayoutData['user']; | ||||
| </script> | ||||
| 
 | ||||
| <Form.Root | ||||
|  | @ -30,55 +30,45 @@ | |||
| 	class="space-y-8" | ||||
| 	debug={dev ? true : false} | ||||
| > | ||||
| 	<Form.Item> | ||||
| 		<Form.Field {config} name="username"> | ||||
| 			<Form.Label>Username</Form.Label> | ||||
| 			<Form.Input placeholder="@shadcn" /> | ||||
| 			<Form.Description> | ||||
| 				This is your public display name. It can be your real name or a pseudonym. | ||||
| 			</Form.Description> | ||||
| 			<Form.Validation /> | ||||
| 		</Form.Field> | ||||
| 	</Form.Item> | ||||
| 	<Form.Item> | ||||
| 		<Form.Field {config} name="email"> | ||||
| 			<Form.Label>Email</Form.Label> | ||||
| 			<Form.Select> | ||||
| 				<Form.SelectTrigger placeholder="Select a verified email to display" /> | ||||
| 				<Form.SelectContent> | ||||
| 					<Form.SelectItem value="m@example.com" label="m@example.com" | ||||
| 						>m@example.com | ||||
| 					</Form.SelectItem> | ||||
| 					<Form.SelectItem value="m@google.com" label="m@google.com">m@google.com</Form.SelectItem> | ||||
| 					<Form.SelectItem value="m@support.com" label="m@support.com" | ||||
| 						>m@support.com | ||||
| 					</Form.SelectItem> | ||||
| 				</Form.SelectContent> | ||||
| 			</Form.Select> | ||||
| 			<Form.Description> | ||||
| 				You can manage verified email addresses in your <a href="/examples/forms">email settings</a | ||||
| 				>. | ||||
| 			</Form.Description> | ||||
| 			<Form.Validation /> | ||||
| 		</Form.Field> | ||||
| 	</Form.Item> | ||||
| 	<Form.Item> | ||||
| 		<Form.Field {config} name="bio"> | ||||
| 			<Form.Label>Bio</Form.Label> | ||||
| 			<Form.Textarea placeholder="Tell us a little bit about yourself" class="resize-none" /> | ||||
| 			<Form.Description> | ||||
| 				You can <span>@mention</span> other users and organizations to link to them. | ||||
| 			</Form.Description> | ||||
| 			<Form.Validation /> | ||||
| 		</Form.Field> | ||||
| 	</Form.Item> | ||||
| 	<Form.Item> | ||||
| 		<Form.Field {config} name="website"> | ||||
| 			<Form.Label>Website</Form.Label> | ||||
| 			<Form.Input /> | ||||
| 			<Form.Description>Your personal website, blog, or portfolio.</Form.Description> | ||||
| 			<Form.Validation /> | ||||
| 		</Form.Field> | ||||
| 	</Form.Item> | ||||
| 	<div class="grid grid-cols-[1fr,16rem] gap-4"> | ||||
| 		<div> | ||||
| 			<Form.Item> | ||||
| 				<Form.Field {config} name="username"> | ||||
| 					<Form.Label>Username</Form.Label> | ||||
| 					<Form.Input placeholder={user?.username} /> | ||||
| 					<Form.Description> | ||||
| 						This is your public display name. It can be your real name or a pseudonym. | ||||
| 					</Form.Description> | ||||
| 					<Form.Validation /> | ||||
| 				</Form.Field> | ||||
| 			</Form.Item> | ||||
| 			<Form.Item> | ||||
| 				<Form.Field {config} name="email"> | ||||
| 					<Form.Label>Email</Form.Label> | ||||
| 					<Form.Input placeholder={user?.email} /> | ||||
| 					<Form.Description> | ||||
| 						<Form.Description> | ||||
| 							This is the email address associated with your account. | ||||
| 						</Form.Description> | ||||
| 					</Form.Description> | ||||
| 					<Form.Validation /> | ||||
| 				</Form.Field> | ||||
| 			</Form.Item> | ||||
| 		</div> | ||||
| 		<Form.Item> | ||||
| 			<Form.Field {config} name="avatar"> | ||||
| 				<Form.Label>Profile Picture</Form.Label> | ||||
| 				<Avatar.Root class="aspect-square h-auto w-full"> | ||||
| 					<Avatar.Image src={user?.avatarUrl} alt={user?.name} /> | ||||
| 					<Avatar.Fallback>{user?.initials}</Avatar.Fallback> | ||||
| 				</Avatar.Root> | ||||
| 				<Form.Input type="file" placeholder={user?.email} /> | ||||
| 				<Form.Description> | ||||
| 					<Form.Description>Your avatar image displayed.</Form.Description> | ||||
| 				</Form.Description> | ||||
| 				<Form.Validation /> | ||||
| 			</Form.Field> | ||||
| 		</Form.Item> | ||||
| 	</div> | ||||
| 	<Form.Button>Update profile</Form.Button> | ||||
| </Form.Root> | ||||
|  |  | |||
|  | @ -1,8 +1,18 @@ | |||
| import type { LayoutServerLoad } from './$types'; | ||||
| 
 | ||||
| const fullNameToInitials = (fullName: string) => | ||||
| 	fullName | ||||
| 		.split(' ') | ||||
| 		.map((word) => word[0].toUpperCase()) | ||||
| 		.slice(0, 2) | ||||
| 		.join(''); | ||||
| 
 | ||||
| export const load: LayoutServerLoad = async ({ locals }: { locals: App.Locals }) => { | ||||
| 	const user = locals.pocketBase.authStore.model; | ||||
| 	if (user) user.avatarUrl = locals.pocketBase.getFileUrl(user, user.avatar); | ||||
| 	if (user) { | ||||
| 		user.avatarUrl = locals.pocketBase.getFileUrl(user, user.avatar); | ||||
| 		user.initials = fullNameToInitials(user.name); | ||||
| 	} | ||||
| 
 | ||||
| 	return { | ||||
| 		authenticated: locals.pocketBase.authStore.isValid, | ||||
|  |  | |||
|  | @ -31,7 +31,9 @@ | |||
| 					class="text-primary-500 ml-1 h-3 w-3 tracking-normal transition-transform duration-150 ease-in-out group-hover:translate-x-0.5" | ||||
| 				/> | ||||
| 			</Button> | ||||
| 			<Button href={siteConfig.links.gitHubProject} variant="outline">Star on GitHub</Button> | ||||
| 			<Button href={siteConfig.links.gitHubProject} target="_blank" variant="outline" | ||||
| 				>Star on GitHub</Button | ||||
| 			> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue