1
+ <script lang =" ts" >
2
+ import AdminLayout from ' $lib/components/AdminLayout.svelte' ;
3
+ import { User , Mail , Phone , MapPin , Camera } from ' @lucide/svelte' ;
4
+ import { superForm } from ' sveltekit-superforms' ;
5
+ import { zod } from ' sveltekit-superforms/adapters' ;
6
+ import toast from ' svelte-french-toast' ;
7
+
8
+ export let data;
9
+
10
+ const { form, errors, enhance } = superForm (data .form , {
11
+ onUpdated : ({ form }) => {
12
+ if (form .valid ) {
13
+ toast .success (' Profile updated successfully' );
14
+ }
15
+ }
16
+ });
17
+
18
+ let profileImage: string | null = null ;
19
+
20
+ function handleImageUpload(event : Event ) {
21
+ const target = event .target as HTMLInputElement ;
22
+ if (target .files && target .files [0 ]) {
23
+ const reader = new FileReader ();
24
+ reader .onload = (e ) => {
25
+ profileImage = e .target ?.result as string ;
26
+ };
27
+ reader .readAsDataURL (target .files [0 ]);
28
+ }
29
+ }
30
+ </script >
31
+
32
+ <AdminLayout >
33
+ <div class =" max-w-4xl mx-auto px-4 py-8" >
34
+ <h1 class =" text-2xl font-semibold text-gray-900" >Profile Settings</h1 >
35
+ <p class =" mt-2 text-sm text-gray-700" >Manage your account settings and preferences.</p >
36
+
37
+ <form class =" mt-8 space-y-8" use:enhance >
38
+ <!-- Profile Photo -->
39
+ <div class =" bg-white rounded-xl shadow-sm border border-gray-100 p-6" >
40
+ <h2 class =" text-lg font-medium text-gray-900 mb-6" >Profile Photo</h2 >
41
+ <div class =" flex items-center" >
42
+ <div class =" relative" >
43
+ <div class =" w-24 h-24 rounded-full bg-gray-200 flex items-center justify-center overflow-hidden" >
44
+ {#if profileImage }
45
+ <img src ={profileImage } alt =" Profile" class =" w-full h-full object-cover" />
46
+ {:else }
47
+ <User class =" w-12 h-12 text-gray-400" />
48
+ {/if }
49
+ </div >
50
+ <label class =" absolute bottom-0 right-0 bg-indigo-600 rounded-full p-2 cursor-pointer hover:bg-indigo-700" >
51
+ <Camera class =" w-4 h-4 text-white" />
52
+ <input type ="file" class ="hidden" accept ="image/*" on:change ={handleImageUpload } />
53
+ </label >
54
+ </div >
55
+ <div class =" ml-6" >
56
+ <p class =" text-sm font-medium text-gray-900" >Upload new photo</p >
57
+ <p class =" text-sm text-gray-500 mt-1" >JPG, GIF or PNG. Max size of 2MB</p >
58
+ </div >
59
+ </div >
60
+ </div >
61
+
62
+ <!-- Personal Information -->
63
+ <div class =" bg-white rounded-xl shadow-sm border border-gray-100 p-6" >
64
+ <h2 class =" text-lg font-medium text-gray-900 mb-6" >Personal Information</h2 >
65
+ <div class =" grid grid-cols-1 gap-6 sm:grid-cols-2" >
66
+ <div >
67
+ <label class =" block text-sm font-medium text-gray-700 mb-2" >Full Name</label >
68
+ <div class =" relative" >
69
+ <User class =" absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
70
+ <input
71
+ type =" text"
72
+ bind:value ={$form .name }
73
+ class =" w-full pl-10 pr-4 py-2.5 rounded-lg border border-gray-200 focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500"
74
+ placeholder =" John Doe"
75
+ />
76
+ </div >
77
+ {#if $errors .name }
78
+ <p class ="mt-1.5 text-sm text-red-500" >{$errors .name }</p >
79
+ {/if }
80
+ </div >
81
+
82
+ <div >
83
+ <label class =" block text-sm font-medium text-gray-700 mb-2" >Email</label >
84
+ <div class =" relative" >
85
+ <Mail class =" absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
86
+ <input
87
+ type =" email"
88
+ bind:value ={$form .email }
89
+ class =" w-full pl-10 pr-4 py-2.5 rounded-lg border border-gray-200 focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500"
90
+ placeholder =" john@example.com"
91
+ />
92
+ </div >
93
+ {#if $errors .email }
94
+ <p class ="mt-1.5 text-sm text-red-500" >{$errors .email }</p >
95
+ {/if }
96
+ </div >
97
+
98
+ <div >
99
+ <label class =" block text-sm font-medium text-gray-700 mb-2" >Phone</label >
100
+ <div class =" relative" >
101
+ <Phone class =" absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
102
+ <input
103
+ type =" tel"
104
+ bind:value ={$form .phone }
105
+ class =" w-full pl-10 pr-4 py-2.5 rounded-lg border border-gray-200 focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500"
106
+ placeholder =" +1 (555) 000-0000"
107
+ />
108
+ </div >
109
+ {#if $errors .phone }
110
+ <p class ="mt-1.5 text-sm text-red-500" >{$errors .phone }</p >
111
+ {/if }
112
+ </div >
113
+
114
+ <div >
115
+ <label class =" block text-sm font-medium text-gray-700 mb-2" >Location</label >
116
+ <div class =" relative" >
117
+ <MapPin class =" absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
118
+ <input
119
+ type =" text"
120
+ bind:value ={$form .location }
121
+ class =" w-full pl-10 pr-4 py-2.5 rounded-lg border border-gray-200 focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500"
122
+ placeholder =" New York, USA"
123
+ />
124
+ </div >
125
+ {#if $errors .location }
126
+ <p class ="mt-1.5 text-sm text-red-500" >{$errors .location }</p >
127
+ {/if }
128
+ </div >
129
+ </div >
130
+ </div >
131
+
132
+ <!-- Submit Button -->
133
+ <div class =" flex justify-end" >
134
+ <button
135
+ type =" submit"
136
+ class =" px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
137
+ >
138
+ Save Changes
139
+ </button >
140
+ </div >
141
+ </form >
142
+ </div >
143
+ </AdminLayout >
0 commit comments