@@ -162,37 +162,77 @@ export default function SettingsAccount({ user }: SettingsAccountProps) {
162
162
}
163
163
164
164
return (
165
- < div className = 'flex justify-center w-full max-w-sm' >
166
- < div className = 'flex flex-col gap-6 w-full' >
167
- < div className = 'flex flex-col gap-2' >
168
- < div className = 'block font-bold' >
169
- Options
165
+ < div className = 'space-y-8' >
166
+ { /* Preferences Section */ }
167
+ < div >
168
+ < div className = 'flex items-center mb-6' >
169
+ < div className = 'w-10 h-10 bg-blue-100 dark:bg-blue-900 rounded-lg flex items-center justify-center mr-3' >
170
+ < svg className = 'w-5 h-5 text-blue-600 dark:text-blue-400' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
171
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 100 4m0-4v2m0-6V4' />
172
+ </ svg >
170
173
</ div >
171
- < div className = 'flex gap-2' >
174
+ < div >
175
+ < h2 className = 'text-xl font-semibold text-gray-900 dark:text-white' > Preferences</ h2 >
176
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Customize your experience</ p >
177
+ </ div >
178
+ </ div >
179
+ < div className = 'grid grid-cols-1 md:grid-cols-2 gap-4 mb-8' >
180
+ < div className = 'flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700 rounded-lg' >
181
+ < div className = 'flex items-center space-x-3' >
182
+ < div className = 'w-8 h-8 bg-green-100 dark:bg-green-900 rounded-full flex items-center justify-center' >
183
+ < div className = { `w-2 h-2 rounded-full ${ showStatus ? 'bg-green-500' : 'bg-gray-400' } ` } />
184
+ </ div >
185
+ < div >
186
+ < label className = 'font-medium text-gray-900 dark:text-white' htmlFor = 'showStatus' >
187
+ Online Status
188
+ </ label >
189
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Show when you're online</ p >
190
+ </ div >
191
+ </ div >
172
192
< input
173
193
checked = { showStatus }
174
194
id = 'showStatus'
175
195
name = 'showStatus'
176
196
onChange = { updateStatus }
177
197
type = 'checkbox'
198
+ className = 'w-5 h-5 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'
178
199
/>
179
- < label className = 'text-sm' htmlFor = 'showStatus' >
180
- Show online status
181
- </ label >
182
200
</ div >
183
- < div className = 'flex gap-2' >
201
+ < div className = 'flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700 rounded-lg' >
202
+ < div className = 'flex items-center space-x-3' >
203
+ < div className = 'w-8 h-8 bg-yellow-100 dark:bg-yellow-900 rounded-full flex items-center justify-center' >
204
+ < span className = 'text-yellow-600 dark:text-yellow-400' > 🎉</ span >
205
+ </ div >
206
+ < div >
207
+ < label className = 'font-medium text-gray-900 dark:text-white' htmlFor = 'showConfetti' >
208
+ Confetti Effects
209
+ </ label >
210
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Celebrate beating levels</ p >
211
+ </ div >
212
+ </ div >
184
213
< input
185
214
checked = { showConfetti }
186
215
id = 'showConfetti'
187
216
name = 'showConfetti'
188
217
onChange = { updateConfetti }
189
218
type = 'checkbox'
219
+ className = 'w-5 h-5 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'
190
220
/>
191
- < label className = 'text-sm' htmlFor = 'showConfetti' >
192
- Confetti
193
- </ label >
194
221
</ div >
195
- < div className = 'flex gap-2' >
222
+ < div className = 'flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700 rounded-lg' >
223
+ < div className = 'flex items-center space-x-3' >
224
+ < div className = 'w-8 h-8 bg-purple-100 dark:bg-purple-900 rounded-full flex items-center justify-center' >
225
+ < svg className = 'w-4 h-4 text-purple-600 dark:text-purple-400' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
226
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z' />
227
+ </ svg >
228
+ </ div >
229
+ < div >
230
+ < label className = 'font-medium text-gray-900 dark:text-white' htmlFor = 'hideAfterLevelPopup' >
231
+ Hide Level Popup
232
+ </ label >
233
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Skip after-level notifications</ p >
234
+ </ div >
235
+ </ div >
196
236
< input
197
237
checked = { hideAfterLevelPopup }
198
238
id = 'hideAfterLevelPopup'
@@ -207,12 +247,23 @@ export default function SettingsAccount({ user }: SettingsAccountProps) {
207
247
) ;
208
248
} }
209
249
type = 'checkbox'
250
+ className = 'w-5 h-5 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'
210
251
/>
211
- < label className = 'text-sm' htmlFor = 'hideAfterLevelPopup' >
212
- Hide after level popup
213
- </ label >
214
252
</ div >
215
- < div className = 'flex gap-2' >
253
+ < div className = 'flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700 rounded-lg' >
254
+ < div className = 'flex items-center space-x-3' >
255
+ < div className = 'w-8 h-8 bg-orange-100 dark:bg-orange-900 rounded-full flex items-center justify-center' >
256
+ < svg className = 'w-4 h-4 text-orange-600 dark:text-orange-400' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
257
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 .5-5 2.986-7C14 5 16.09 5.777 17.656 7.343A7.975 7.975 0 0120 13a7.975 7.975 0 01-2.343 5.657z' />
258
+ </ svg >
259
+ </ div >
260
+ < div >
261
+ < label className = 'font-medium text-gray-900 dark:text-white' htmlFor = 'hideStreakPopup' >
262
+ Hide Streak Popup
263
+ </ label >
264
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Skip streak notifications</ p >
265
+ </ div >
266
+ </ div >
216
267
< input
217
268
checked = { hideStreakPopup }
218
269
id = 'hideStreakPopup'
@@ -227,62 +278,154 @@ export default function SettingsAccount({ user }: SettingsAccountProps) {
227
278
) ;
228
279
} }
229
280
type = 'checkbox'
281
+ className = 'w-5 h-5 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'
230
282
/>
231
- < label className = 'text-sm' htmlFor = 'hideStreakPopup' >
232
- Hide streak popup
233
- </ label >
234
283
</ div >
235
284
</ div >
236
- < form className = 'flex flex-col items-start gap-2' onSubmit = { updateUsername } >
237
- < label className = 'block font-bold' htmlFor = 'username' >
238
- Username
239
- </ label >
240
- < input
241
- className = 'w-full'
242
- id = 'username'
243
- name = 'username'
244
- onChange = { e => setUsername ( e . target . value ) }
245
- placeholder = 'Username'
246
- required
247
- type = 'text'
248
- value = { username }
249
- />
250
- < button className = 'italic underline' type = 'submit' > Update</ button >
251
- </ form >
252
- < form className = 'flex flex-col items-start gap-2' onSubmit = {
253
- ( ! user . emailConfirmed && email === user . email ? resendEmailConfirmation : updateEmail )
254
- } >
255
- < label className = 'block font-bold' htmlFor = 'email' >
256
- { 'Email - ' }
257
- { user . emailConfirmed && email === user . email ?
258
- < span className = 'text-green-500' > Confirmed</ span >
259
- :
260
- < span className = 'text-red-500' > Unconfirmed</ span >
261
- }
262
- </ label >
263
- < input
264
- className = 'w-full'
265
- id = 'email'
266
- name = 'email'
267
- onChange = { e => setEmail ( e . target . value ) }
268
- placeholder = 'Email'
269
- required
270
- type = 'email'
271
- value = { email }
272
- />
273
- < button className = 'italic underline' type = 'submit' >
274
- { ! user . emailConfirmed && email === user . email ? 'Resend confirmation' : 'Update' }
285
+ </ div >
286
+ { /* Profile Information */ }
287
+ < div >
288
+ < div className = 'flex items-center mb-6' >
289
+ < div className = 'w-10 h-10 bg-indigo-100 dark:bg-indigo-900 rounded-lg flex items-center justify-center mr-3' >
290
+ < svg className = 'w-5 h-5 text-indigo-600 dark:text-indigo-400' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
291
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z' />
292
+ </ svg >
293
+ </ div >
294
+ < div >
295
+ < h2 className = 'text-xl font-semibold text-gray-900 dark:text-white' > Profile Information</ h2 >
296
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Update your personal details</ p >
297
+ </ div >
298
+ </ div >
299
+ < div className = 'grid grid-cols-1 md:grid-cols-2 gap-6 mb-8' >
300
+ < form className = 'space-y-4' onSubmit = { updateUsername } >
301
+ < div >
302
+ < label className = 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2' htmlFor = 'username' >
303
+ Username
304
+ </ label >
305
+ < input
306
+ className = 'w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-colors'
307
+ id = 'username'
308
+ name = 'username'
309
+ onChange = { e => setUsername ( e . target . value ) }
310
+ placeholder = 'Enter your username'
311
+ required
312
+ type = 'text'
313
+ value = { username }
314
+ />
315
+ </ div >
316
+ < button
317
+ className = 'w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-4 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800'
318
+ type = 'submit'
319
+ >
320
+ Update Username
321
+ </ button >
322
+ </ form >
323
+ < form className = 'space-y-4' onSubmit = {
324
+ ( ! user . emailConfirmed && email === user . email ? resendEmailConfirmation : updateEmail )
325
+ } >
326
+ < div >
327
+ < label className = 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2' htmlFor = 'email' >
328
+ Email Address
329
+ </ label >
330
+ < div className = 'relative' >
331
+ < input
332
+ className = 'w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-colors pr-12'
333
+ id = 'email'
334
+ name = 'email'
335
+ onChange = { e => setEmail ( e . target . value ) }
336
+ placeholder = 'Enter your email'
337
+ required
338
+ type = 'email'
339
+ value = { email }
340
+ />
341
+ < div className = 'absolute inset-y-0 right-0 flex items-center pr-3' >
342
+ { user . emailConfirmed && email === user . email ? (
343
+ < svg className = 'w-5 h-5 text-green-500' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
344
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z' />
345
+ </ svg >
346
+ ) : (
347
+ < svg className = 'w-5 h-5 text-red-500' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
348
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.854-.833-2.624 0L3.228 16.5c-.77.833.192 2.5 1.732 2.5z' />
349
+ </ svg >
350
+ ) }
351
+ </ div >
352
+ </ div >
353
+ < p className = { `text-sm mt-1 ${ user . emailConfirmed && email === user . email ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400' } ` } >
354
+ { user . emailConfirmed && email === user . email ? 'Email confirmed' : 'Email not confirmed' }
355
+ </ p >
356
+ </ div >
357
+ < button
358
+ className = { `w-full font-medium py-3 px-4 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-800 ${
359
+ ! user . emailConfirmed && email === user . email
360
+ ? 'bg-orange-600 hover:bg-orange-700 text-white focus:ring-orange-500'
361
+ : 'bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-500'
362
+ } `}
363
+ type = 'submit'
364
+ >
365
+ { ! user . emailConfirmed && email === user . email ? 'Resend Confirmation' : 'Update Email' }
366
+ </ button >
367
+ </ form >
368
+ </ div >
369
+ </ div >
370
+ { /* Security Section */ }
371
+ < div >
372
+ < div className = 'flex items-center mb-6' >
373
+ < div className = 'w-10 h-10 bg-red-100 dark:bg-red-900 rounded-lg flex items-center justify-center mr-3' >
374
+ < svg className = 'w-5 h-5 text-red-600 dark:text-red-400' fill = 'none' stroke = 'currentColor' viewBox = '0 0 24 24' >
375
+ < path strokeLinecap = 'round' strokeLinejoin = 'round' strokeWidth = { 2 } d = 'M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z' />
376
+ </ svg >
377
+ </ div >
378
+ < div >
379
+ < h2 className = 'text-xl font-semibold text-gray-900 dark:text-white' > Security</ h2 >
380
+ < p className = 'text-sm text-gray-600 dark:text-gray-400' > Update your password to keep your account secure</ p >
381
+ </ div >
382
+ </ div >
383
+ < form className = 'space-y-4 max-w-md' onSubmit = { updatePassword } >
384
+ < div >
385
+ < label className = 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2' htmlFor = 'currentPassword' >
386
+ Current Password
387
+ </ label >
388
+ < input
389
+ onChange = { e => setCurrentPassword ( e . target . value ) }
390
+ className = 'w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-colors'
391
+ id = 'currentPassword'
392
+ value = { currentPassword }
393
+ type = 'password'
394
+ placeholder = 'Enter current password'
395
+ required
396
+ />
397
+ </ div >
398
+ < div >
399
+ < label className = 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2' >
400
+ New Password
401
+ </ label >
402
+ < input
403
+ onChange = { e => setPassword ( e . target . value ) }
404
+ className = 'w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-colors'
405
+ type = 'password'
406
+ placeholder = 'Enter new password'
407
+ required
408
+ />
409
+ </ div >
410
+ < div >
411
+ < label className = 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2' >
412
+ Confirm New Password
413
+ </ label >
414
+ < input
415
+ onChange = { e => setPassword2 ( e . target . value ) }
416
+ className = 'w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-colors'
417
+ type = 'password'
418
+ placeholder = 'Re-enter new password'
419
+ required
420
+ />
421
+ </ div >
422
+ < button
423
+ className = 'w-full bg-red-600 hover:bg-red-700 text-white font-medium py-3 px-4 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800'
424
+ type = 'submit'
425
+ >
426
+ Update Password
275
427
</ button >
276
428
</ form >
277
- < form className = 'flex flex-col items-start gap-2' onSubmit = { updatePassword } >
278
- < label className = 'block font-bold' htmlFor = 'password' >
279
- Password
280
- </ label >
281
- < input onChange = { e => setCurrentPassword ( e . target . value ) } className = 'w-full' id = 'password' value = { currentPassword } type = 'password' placeholder = 'Enter current password' required />
282
- < input onChange = { e => setPassword ( e . target . value ) } className = 'w-full' type = 'password' placeholder = 'Enter new password' required />
283
- < input onChange = { e => setPassword2 ( e . target . value ) } className = 'w-full' type = 'password' placeholder = 'Re-enter new password' required />
284
- < button className = 'italic underline' type = 'submit' > Update</ button >
285
- </ form >
286
429
</ div >
287
430
</ div >
288
431
) ;
0 commit comments