feat: add reward code

This commit is contained in:
2025-12-22 17:37:41 +08:00
commit 1226bbe724
34 changed files with 8857 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
import { createContext, useContext, useEffect, useState, ReactNode, useCallback } from 'react';
import { authService } from '../lib/authService';
import { ApiErrorMessages } from '../types/api';
import type { UserInfo } from '../types/api';
interface AuthContextType {
user: UserInfo | null;
token: string | null;
loading: boolean;
initializing: boolean; // 新增初始化状态
signIn: (email: string, password: string) => Promise<{ error: Error | null }>;
signUp: (email: string, password: string) => Promise<{ error: Error | null }>;
signOut: () => Promise<void>;
isAuthenticated: boolean;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
// 直接在 useState 初始化函数中同步恢复会话
const [user, setUser] = useState<UserInfo | null>(() => {
try {
const session = authService.restoreSession();
return session ? session.user : null;
} catch {
return null;
}
});
const [token, setToken] = useState<string | null>(() => {
try {
const session = authService.restoreSession();
return session ? session.token : null;
} catch {
return null;
}
});
const [loading, setLoading] = useState(false);
const [initializing, setInitializing] = useState(false); // 不需要初始化过程了,因为是同步的
// 不再需要 useEffect 里的 restoreSession
/**
* 从错误对象中提取用户友好的错误消息
*/
const getErrorMessage = (error: unknown, fallback: string): string => {
// 检查是否是 ApiError通过 code 属性判断,避免 instanceof 在热更新时失效)
if (error && typeof error === 'object' && 'code' in error) {
const apiError = error as { code: number; message: string };
return ApiErrorMessages[apiError.code] || apiError.message || fallback;
}
if (error instanceof Error) {
return error.message;
}
return fallback;
};
/**
* 登录
*/
const signIn = useCallback(async (email: string, password: string) => {
setLoading(true);
try {
const result = await authService.login({ email, password });
setUser(result.user);
setToken(result.token);
return { error: null };
} catch (error) {
const message = getErrorMessage(error, '登录失败');
return { error: new Error(message) };
} finally {
setLoading(false);
}
}, []);
/**
* 注册
*/
const signUp = useCallback(async (email: string, password: string) => {
setLoading(true);
try {
const result = await authService.register({ email, password });
setUser(result.user);
setToken(result.token);
return { error: null };
} catch (error) {
const message = getErrorMessage(error, '注册失败');
return { error: new Error(message) };
} finally {
setLoading(false);
}
}, []);
/**
* 登出
*/
const signOut = useCallback(async () => {
setLoading(true);
try {
authService.logout();
setUser(null);
setToken(null);
} finally {
setLoading(false);
}
}, []);
const value: AuthContextType = {
user,
token,
loading,
initializing,
signIn,
signUp,
signOut,
isAuthenticated: !!user && !!token,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
}