import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; // Auth Slice interface User { id: string; email: string; username?: string; } interface AuthState { user: User | null; loading: boolean; error: string | null; } const initialAuthState: AuthState = { user: null, loading: false, error: null, }; const authSlice = createSlice({ name: 'auth', initialState: initialAuthState, reducers: { setLoading: (state, action: PayloadAction) => { state.loading = action.payload; }, setUser: (state, action: PayloadAction) => { state.user = action.payload; state.loading = false; state.error = null; }, setError: (state, action: PayloadAction) => { state.error = action.payload; state.loading = false; }, logout: (state) => { state.user = null; state.loading = false; state.error = null; }, }, }); export const { setLoading, setUser, setError, logout } = authSlice.actions; // Messaging Slice interface Conversation { id: string; participantName: string; lastMessage: string; unreadCount: number; } interface Message { id: string; conversationId: string; content: string; senderId: string; timestamp: string; createdAt: string; } interface MessagingState { conversations: Conversation[]; messages: Record; } const initialMessagingState: MessagingState = { conversations: [], messages: {}, }; const messagingSlice = createSlice({ name: 'messaging', initialState: initialMessagingState, reducers: { setConversations: (state, action: PayloadAction) => { state.conversations = action.payload; }, addMessage: (state, action: PayloadAction) => { const msg = action.payload; if (!state.messages[msg.conversationId]) { state.messages[msg.conversationId] = []; } state.messages[msg.conversationId].push(msg); }, }, }); export const { setConversations, addMessage } = messagingSlice.actions; // Calls Slice interface Call { id: string; participantName: string; type: 'audio' | 'video' | 'voice'; status: 'active' | 'ended' | 'missed'; duration?: string; timestamp: string; isMuted?: boolean; isCameraOn?: boolean; } interface CallsState { activeCall: Call | null; callHistory: Call[]; } const initialCallsState: CallsState = { activeCall: null, callHistory: [], }; const callsSlice = createSlice({ name: 'calls', initialState: initialCallsState, reducers: { setActiveCall: (state, action: PayloadAction) => { state.activeCall = action.payload; }, addCallToHistory: (state, action: PayloadAction) => { state.callHistory.unshift(action.payload); }, }, }); export const { setActiveCall, addCallToHistory } = callsSlice.actions; // Async thunks export const loginAsync = (credentials: { email: string; password: string }) => async (dispatch: AppDispatch) => { dispatch(setLoading(true)); try { // TODO: Integrate with Supabase auth const mockUser: User = { id: '1', email: credentials.email, username: credentials.email.split('@')[0], }; dispatch(setUser(mockUser)); } catch (error) { dispatch(setError((error as Error).message)); } }; export const logoutAsync = () => async (dispatch: AppDispatch) => { dispatch(setLoading(true)); try { // TODO: Integrate with Supabase auth dispatch(logout()); } catch (error) { dispatch(setError((error as Error).message)); } }; // Store export const store = configureStore({ reducer: { auth: authSlice.reducer, messaging: messagingSlice.reducer, calls: callsSlice.reducer, }, }); export type RootState = ReturnType; export type AppDispatch = typeof store.dispatch; export const useAppDispatch = () => useDispatch(); export const useAppSelector: TypedUseSelectorHook = useSelector;