mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 05:55:02 +00:00
181 lines
5.7 KiB
TypeScript
181 lines
5.7 KiB
TypeScript
import { create } from 'zustand';
|
|
import { apiClient } from './api-client';
|
|
|
|
interface User {
|
|
id: string;
|
|
email: string;
|
|
fullName: string;
|
|
phone?: string;
|
|
role: string;
|
|
passengerId?: string;
|
|
dateOfBirth?: string;
|
|
gender?: string;
|
|
nationality?: string;
|
|
nationalityCode?: string;
|
|
nationalId?: string;
|
|
passportNumber?: string;
|
|
passportCountry?: string;
|
|
passportIssueDate?: string;
|
|
passportExpiryDate?: string;
|
|
passportIssuingAuthority?: string;
|
|
faydaVerified?: boolean;
|
|
faydaSub?: string;
|
|
faydaVerifiedAt?: string;
|
|
lastLoginAt?: string;
|
|
createdAt?: string;
|
|
}
|
|
|
|
interface AuthState {
|
|
user: User | null;
|
|
token: string | null;
|
|
isAuthenticated: boolean;
|
|
isInitialized: boolean;
|
|
login: (email: string, password: string) => Promise<void>;
|
|
register: (data: RegisterData) => Promise<void>;
|
|
logout: () => Promise<void>;
|
|
setUser: (user: User, token: string) => void;
|
|
updateUser: (userData: Partial<User>) => void;
|
|
initialize: () => Promise<void>;
|
|
fetchProfile: () => Promise<void>;
|
|
}
|
|
|
|
interface RegisterData {
|
|
email: string;
|
|
phone: string;
|
|
fullName: string;
|
|
password: string;
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>((set, get) => ({
|
|
user: null,
|
|
token: null,
|
|
isAuthenticated: false,
|
|
isInitialized: false,
|
|
|
|
initialize: async () => {
|
|
if (typeof window === 'undefined') return;
|
|
const token = localStorage.getItem('auth_token');
|
|
const userStr = localStorage.getItem('auth_user');
|
|
|
|
if (token && userStr) {
|
|
try {
|
|
const user = JSON.parse(userStr);
|
|
set({ user, token, isAuthenticated: true, isInitialized: true });
|
|
|
|
// Fetch fresh profile data in background
|
|
get().fetchProfile().catch(() => {
|
|
// If profile fetch fails, token might be expired
|
|
console.warn('Failed to fetch profile, token might be expired');
|
|
});
|
|
} catch (e) {
|
|
localStorage.removeItem('auth_token');
|
|
localStorage.removeItem('auth_user');
|
|
set({ isInitialized: true });
|
|
}
|
|
} else {
|
|
set({ isInitialized: true });
|
|
}
|
|
},
|
|
|
|
fetchProfile: async () => {
|
|
if (typeof window === 'undefined') return;
|
|
const token = localStorage.getItem('auth_token');
|
|
if (!token) return;
|
|
|
|
try {
|
|
const response: any = await apiClient.get('/auth/profile', {
|
|
headers: { 'Authorization': `Bearer ${token}` }
|
|
});
|
|
const userData = response.data || response;
|
|
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('auth_user', JSON.stringify(userData));
|
|
}
|
|
set({ user: userData });
|
|
} catch (error: any) {
|
|
// If 401, token is invalid - logout
|
|
if (error.response?.status === 401) {
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.removeItem('auth_token');
|
|
localStorage.removeItem('auth_user');
|
|
}
|
|
set({ user: null, token: null, isAuthenticated: false });
|
|
}
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
login: async (email: string, password: string) => {
|
|
const response: any = await apiClient.post('/auth/login', { email, password });
|
|
const { token, user } = response.data || response;
|
|
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('auth_token', token);
|
|
localStorage.setItem('auth_user', JSON.stringify(user));
|
|
}
|
|
|
|
set({ user, token, isAuthenticated: true });
|
|
},
|
|
|
|
register: async (data: RegisterData) => {
|
|
const response: any = await apiClient.post('/auth/register', data);
|
|
const { token, user } = response.data || response;
|
|
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('auth_token', token);
|
|
localStorage.setItem('auth_user', JSON.stringify(user));
|
|
}
|
|
|
|
set({ user, token, isAuthenticated: true });
|
|
},
|
|
|
|
logout: async () => {
|
|
try {
|
|
const token = typeof window !== 'undefined' ? localStorage.getItem('auth_token') : null;
|
|
if (token) {
|
|
// Call logout endpoint to invalidate session on backend
|
|
await apiClient.post('/auth/logout', {}, {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('Logout API call failed:', error);
|
|
// Continue with logout even if API call fails
|
|
}
|
|
|
|
// Clear local storage and state
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.removeItem('auth_token');
|
|
localStorage.removeItem('auth_user');
|
|
}
|
|
set({ user: null, token: null, isAuthenticated: false });
|
|
|
|
// Redirect to home page after state is updated
|
|
if (typeof window !== 'undefined') {
|
|
setTimeout(() => {
|
|
window.location.href = '/';
|
|
}, 100);
|
|
}
|
|
},
|
|
|
|
setUser: (user: User, token: string) => {
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('auth_token', token);
|
|
localStorage.setItem('auth_user', JSON.stringify(user));
|
|
}
|
|
set({ user, token, isAuthenticated: true });
|
|
},
|
|
|
|
updateUser: (userData: Partial<User>) => {
|
|
if (typeof window !== 'undefined') {
|
|
const currentUser = JSON.parse(localStorage.getItem('auth_user') || '{}');
|
|
const updatedUser = { ...currentUser, ...userData };
|
|
localStorage.setItem('auth_user', JSON.stringify(updatedUser));
|
|
set({ user: updatedUser });
|
|
}
|
|
},
|
|
})
|
|
);
|