204 lines
5.8 KiB
TypeScript
204 lines
5.8 KiB
TypeScript
import { createAsyncThunk } from '@reduxjs/toolkit';
|
|
import { apiService, LoginRequest, RegisterRequest } from '../../services/api';
|
|
import { setLoading, setError, loginSuccess, logout, setTokens } from './authSlice';
|
|
|
|
export const loginUser = createAsyncThunk(
|
|
'auth/login',
|
|
async (credentials: LoginRequest, { dispatch }) => {
|
|
try {
|
|
dispatch(setLoading(true));
|
|
dispatch(setError(null));
|
|
|
|
const response = await apiService.login(credentials);
|
|
|
|
if (response.success && response.data) {
|
|
// Store tokens in localStorage
|
|
localStorage.setItem('accessToken', response.data.accessToken);
|
|
localStorage.setItem('refreshToken', response.data.refreshToken);
|
|
localStorage.setItem('sessionId', response.data.sessionId);
|
|
|
|
// Dispatch login success
|
|
dispatch(loginSuccess({
|
|
user: response.data.user,
|
|
token: response.data.accessToken,
|
|
refreshToken: response.data.refreshToken,
|
|
sessionId: response.data.sessionId,
|
|
}));
|
|
|
|
return response.data;
|
|
} else {
|
|
throw new Error(response.message || 'Login failed');
|
|
}
|
|
} catch (error: any) {
|
|
const errorMessage = error.message || 'Login failed. Please try again.';
|
|
dispatch(setError(errorMessage));
|
|
throw error;
|
|
} finally {
|
|
dispatch(setLoading(false));
|
|
}
|
|
}
|
|
);
|
|
|
|
export const registerUser = createAsyncThunk(
|
|
'auth/register',
|
|
async (userData: RegisterRequest, { dispatch }) => {
|
|
try {
|
|
dispatch(setLoading(true));
|
|
dispatch(setError(null));
|
|
|
|
const response = await apiService.register(userData);
|
|
|
|
if (response.success) {
|
|
return response;
|
|
} else {
|
|
throw new Error(response.message || 'Registration failed');
|
|
}
|
|
} catch (error: any) {
|
|
const errorMessage = error.message || 'Registration failed. Please try again.';
|
|
dispatch(setError(errorMessage));
|
|
throw error;
|
|
} finally {
|
|
dispatch(setLoading(false));
|
|
}
|
|
}
|
|
);
|
|
|
|
export const verifyEmail = createAsyncThunk(
|
|
'auth/verifyEmail',
|
|
async ({ email, otp }: { email: string; otp: string }, { dispatch }) => {
|
|
try {
|
|
dispatch(setLoading(true));
|
|
dispatch(setError(null));
|
|
|
|
const response = await apiService.verifyEmail(email, otp);
|
|
|
|
if (response.success) {
|
|
return response;
|
|
} else {
|
|
throw new Error(response.message || 'Email verification failed');
|
|
}
|
|
} catch (error: any) {
|
|
const errorMessage = error.message || 'Email verification failed. Please try again.';
|
|
dispatch(setError(errorMessage));
|
|
throw error;
|
|
} finally {
|
|
dispatch(setLoading(false));
|
|
}
|
|
}
|
|
);
|
|
|
|
export const resendVerificationEmail = createAsyncThunk(
|
|
'auth/resendVerification',
|
|
async (email: string, { dispatch }) => {
|
|
try {
|
|
dispatch(setLoading(true));
|
|
dispatch(setError(null));
|
|
|
|
const response = await apiService.resendVerificationEmail(email);
|
|
|
|
if (response.success) {
|
|
return response;
|
|
} else {
|
|
throw new Error(response.message || 'Failed to resend verification email');
|
|
}
|
|
} catch (error: any) {
|
|
const errorMessage = error.message || 'Failed to resend verification email. Please try again.';
|
|
dispatch(setError(errorMessage));
|
|
throw error;
|
|
} finally {
|
|
dispatch(setLoading(false));
|
|
}
|
|
}
|
|
);
|
|
|
|
export const logoutUser = createAsyncThunk(
|
|
'auth/logout',
|
|
async (_, { dispatch, getState }) => {
|
|
try {
|
|
const state = getState() as any;
|
|
const sessionId = state.auth.sessionId;
|
|
|
|
if (sessionId) {
|
|
await apiService.logout(sessionId);
|
|
}
|
|
|
|
// Clear localStorage
|
|
localStorage.removeItem('accessToken');
|
|
localStorage.removeItem('refreshToken');
|
|
localStorage.removeItem('sessionId');
|
|
|
|
// Dispatch logout
|
|
dispatch(logout());
|
|
} catch (error) {
|
|
console.error('Logout error:', error);
|
|
// Still logout locally even if API call fails
|
|
localStorage.removeItem('accessToken');
|
|
localStorage.removeItem('refreshToken');
|
|
localStorage.removeItem('sessionId');
|
|
dispatch(logout());
|
|
}
|
|
}
|
|
);
|
|
|
|
export const getCurrentUser = createAsyncThunk(
|
|
'auth/getCurrentUser',
|
|
async (_, { dispatch }) => {
|
|
try {
|
|
dispatch(setLoading(true));
|
|
dispatch(setError(null));
|
|
|
|
const response = await apiService.getCurrentUser();
|
|
|
|
if (response.success) {
|
|
return response.data;
|
|
} else {
|
|
throw new Error('Failed to get current user');
|
|
}
|
|
} catch (error: any) {
|
|
const errorMessage = error.message || 'Failed to get current user';
|
|
dispatch(setError(errorMessage));
|
|
throw error;
|
|
} finally {
|
|
dispatch(setLoading(false));
|
|
}
|
|
}
|
|
);
|
|
|
|
export const refreshUserToken = createAsyncThunk(
|
|
'auth/refreshToken',
|
|
async (_, { dispatch, getState }) => {
|
|
try {
|
|
const state = getState() as any;
|
|
const refreshToken = state.auth.refreshToken;
|
|
|
|
if (!refreshToken) {
|
|
throw new Error('No refresh token available');
|
|
}
|
|
|
|
const response = await apiService.refreshToken(refreshToken);
|
|
|
|
if (response.success && response.data) {
|
|
// Update tokens in localStorage
|
|
localStorage.setItem('accessToken', response.data.accessToken);
|
|
localStorage.setItem('refreshToken', response.data.refreshToken);
|
|
localStorage.setItem('sessionId', response.data.sessionId);
|
|
|
|
// Update tokens in store
|
|
dispatch(setTokens({
|
|
token: response.data.accessToken,
|
|
refreshToken: response.data.refreshToken,
|
|
sessionId: response.data.sessionId,
|
|
}));
|
|
|
|
return response.data;
|
|
} else {
|
|
throw new Error(response.message || 'Token refresh failed');
|
|
}
|
|
} catch (error: any) {
|
|
console.error('Token refresh failed:', error);
|
|
// If refresh fails, logout the user
|
|
dispatch(logoutUser());
|
|
throw error;
|
|
}
|
|
}
|
|
);
|