import { FormEvent, useEffect, useState } from 'react' import { ArrowLeft, Building2, ChevronRight, Coins, KeyRound, LoaderCircle, Save, UserRound } from 'lucide-react' import { Link, useSearchParams } from 'react-router-dom' import { api } from '../api' import { useAuth } from '../AuthContext' import type { PointsTransaction } from '../types' import { useWorkspace } from '../WorkspaceContext' type ProfileTab = 'profile' | 'security' | 'points' const tabs: Array<{ id: ProfileTab; label: string; description: string; icon: typeof UserRound }> = [ { id: 'profile', label: '用户信息', description: '姓名与组织资料', icon: UserRound }, { id: 'security', label: '账户安全', description: '修改登录密码', icon: KeyRound }, { id: 'points', label: '积分账单', description: '余额与积分流水', icon: Coins } ] export function Profile() { const { user, setUser } = useAuth() const { organizations, currentOrganization } = useWorkspace() const [searchParams, setSearchParams] = useSearchParams() const requestedTab = searchParams.get('tab') const activeTab: ProfileTab = user?.mustChangePassword ? 'security' : tabs.some((tab) => tab.id === requestedTab) ? (requestedTab as ProfileTab) : 'profile' const [message, setMessage] = useState('') const [error, setError] = useState('') const [transactions, setTransactions] = useState([]) const [pointsLoading, setPointsLoading] = useState(false) const [displayBalance, setDisplayBalance] = useState(null) useEffect(() => { if (activeTab !== 'points') return setPointsLoading(true) setError(''); (currentOrganization ? api.organizations.points(currentOrganization.id) : api.getPointsTransactions()) .then((result) => { setTransactions(result.transactions) setDisplayBalance(result.balance) if (!currentOrganization && user && result.balance !== user.pointsBalance) setUser({ ...user, pointsBalance: result.balance }) }) .catch((reason) => setError((reason as Error).message)) .finally(() => setPointsLoading(false)) }, [activeTab, currentOrganization?.id]) if (!user) return null const changeTab = (tab: ProfileTab) => { setMessage('') setError('') setSearchParams(tab === 'profile' ? {} : { tab }) } async function save(event: FormEvent) { event.preventDefault() const form = new FormData(event.currentTarget) setError('') setMessage('') try { const result = await api.updateMe({ wechat: String(form.get('wechat')), contactName: String(form.get('contactName')), bio: String(form.get('bio')) }) setUser(result.user) setMessage('个人信息已保存') } catch (reason) { setError((reason as Error).message) } } async function password(event: FormEvent) { event.preventDefault() const formElement = event.currentTarget const form = new FormData(formElement) setError('') setMessage('') if (form.get('newPassword') !== form.get('confirm')) return setError('两次输入的新密码不一致') try { await api.changePassword(String(form.get('currentPassword')), String(form.get('newPassword'))) setUser({ ...user!, mustChangePassword: false }) formElement.reset() setMessage('密码修改成功') } catch (reason) { setError((reason as Error).message) } } return (
返回课程
{activeTab === 'profile' && (

用户信息

管理您的基本资料和联系方式

隶属组织 {organizations.length > 0 ? (
{organizations.map((org) => (
{org.name} {org.role === 'MANAGER' ? '组织管理员' : '组织成员'} {!org.isActive && 已停用}
{org.role === 'MANAGER' && ( 组织管理 )}
))}
) : user.organization ? (
{user.organization} 成员
) : (
当前为个人账号,暂未加入任何企业或组织
)}