pages_settings.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import React from 'react'
  2. import { useForm } from 'react-hook-form'
  3. import { useMutation } from '@tanstack/react-query'
  4. import { UserAPI } from './api.ts'
  5. import { useAuth } from './hooks.tsx'
  6. export default function SettingsPage() {
  7. const { register, handleSubmit, formState: { errors } } = useForm<{
  8. nickname: string
  9. email: string
  10. phone?: string
  11. password?: string
  12. }>()
  13. const { mutate: updateUser, isPending } = useMutation({
  14. mutationFn: async (data: {
  15. nickname: string
  16. email: string
  17. phone?: string
  18. password?: string
  19. }) => {
  20. const res = await UserAPI.getUsers({ limit: 1 })
  21. if (!res.data?.[0]?.id) throw new Error('用户ID不存在')
  22. return UserAPI.updateUser(res.data[0].id, {
  23. nickname: data.nickname,
  24. email: data.email,
  25. phone: data.phone,
  26. ...(data.password ? { password: data.password } : {})
  27. })
  28. },
  29. onSuccess: () => alert('更新成功'),
  30. onError: (error) => {
  31. console.error('更新失败:', error)
  32. alert('更新失败')
  33. }
  34. })
  35. const onSubmit = (data: {
  36. nickname: string
  37. email: string
  38. phone?: string
  39. password?: string
  40. }) => {
  41. updateUser(data)
  42. }
  43. return (
  44. <div className="p-4">
  45. <h1 className="text-2xl font-bold mb-4">设置</h1>
  46. <div className="bg-white rounded-lg shadow p-4 mb-4">
  47. <h2 className="text-lg font-semibold mb-4">编辑个人信息</h2>
  48. <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
  49. <div>
  50. <label className="block text-sm font-medium text-gray-700 mb-1">昵称</label>
  51. <input
  52. {...register('nickname', { required: '请输入昵称' })}
  53. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  54. />
  55. {errors.nickname && <p className="mt-1 text-sm text-red-600">{errors.nickname.message}</p>}
  56. </div>
  57. <div>
  58. <label className="block text-sm font-medium text-gray-700 mb-1">邮箱</label>
  59. <input
  60. {...register('email', {
  61. required: '请输入邮箱',
  62. pattern: {
  63. value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
  64. message: '请输入有效的邮箱地址'
  65. }
  66. })}
  67. type="email"
  68. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  69. />
  70. {errors.email && <p className="mt-1 text-sm text-red-600">{errors.email.message}</p>}
  71. </div>
  72. <div>
  73. <label className="block text-sm font-medium text-gray-700 mb-1">手机号</label>
  74. <input
  75. {...register('phone')}
  76. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  77. />
  78. </div>
  79. <div>
  80. <label className="block text-sm font-medium text-gray-700 mb-1">新密码</label>
  81. <input
  82. {...register('password')}
  83. type="password"
  84. placeholder="留空则不修改密码"
  85. className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
  86. />
  87. </div>
  88. <div className="flex space-x-3 pt-4">
  89. <button
  90. type="submit"
  91. disabled={isPending}
  92. className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50"
  93. >
  94. {isPending ? '保存中...' : '保存'}
  95. </button>
  96. </div>
  97. </form>
  98. </div>
  99. </div>
  100. )
  101. }