304 lines
9.0 KiB
TypeScript
304 lines
9.0 KiB
TypeScript
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
|
|
import { resellerDashboardService, ResellerDashboardStats, ResellerCustomer, ResellerProduct, ResellerSale, ResellerReceipt, ResellerPayment, ResellerRecentActivity } from '../../services/resellerDashboardService';
|
|
|
|
export interface ResellerDashboardState {
|
|
stats: ResellerDashboardStats;
|
|
customers: ResellerCustomer[];
|
|
products: ResellerProduct[];
|
|
sales: ResellerSale[];
|
|
receipts: ResellerReceipt[];
|
|
payments: ResellerPayment[];
|
|
recentActivities: ResellerRecentActivity[];
|
|
isLoading: boolean;
|
|
error: string | null;
|
|
}
|
|
|
|
const initialState: ResellerDashboardState = {
|
|
stats: {
|
|
totalRevenue: 0,
|
|
activeCustomers: 0,
|
|
totalProducts: 0,
|
|
commissionRate: 0,
|
|
monthlyGrowth: 0,
|
|
currency: 'USD',
|
|
commissionEarned: 0,
|
|
averageDealSize: 0,
|
|
conversionRate: 0,
|
|
},
|
|
customers: [],
|
|
products: [],
|
|
sales: [],
|
|
receipts: [],
|
|
payments: [],
|
|
recentActivities: [],
|
|
isLoading: false,
|
|
error: null,
|
|
};
|
|
|
|
// Async thunks
|
|
export const fetchDashboardStats = createAsyncThunk(
|
|
'resellerDashboard/fetchStats',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getDashboardStats();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const fetchCustomers = createAsyncThunk(
|
|
'resellerDashboard/fetchCustomers',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getCustomers();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const fetchProducts = createAsyncThunk(
|
|
'resellerDashboard/fetchProducts',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getProducts();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const fetchSales = createAsyncThunk(
|
|
'resellerDashboard/fetchSales',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getSales();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const fetchReceipts = createAsyncThunk(
|
|
'resellerDashboard/fetchReceipts',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getReceipts();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const fetchPayments = createAsyncThunk(
|
|
'resellerDashboard/fetchPayments',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getPayments();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const fetchRecentActivities = createAsyncThunk(
|
|
'resellerDashboard/fetchRecentActivities',
|
|
async (_, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.getRecentActivities();
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const addCustomer = createAsyncThunk(
|
|
'resellerDashboard/addCustomer',
|
|
async (customerData: Partial<ResellerCustomer>, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.addCustomer(customerData);
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
export const createSale = createAsyncThunk(
|
|
'resellerDashboard/createSale',
|
|
async (saleData: Partial<ResellerSale>, { rejectWithValue }) => {
|
|
try {
|
|
return await resellerDashboardService.createSale(saleData);
|
|
} catch (error: any) {
|
|
return rejectWithValue(error.message);
|
|
}
|
|
}
|
|
);
|
|
|
|
const resellerDashboardSlice = createSlice({
|
|
name: 'resellerDashboard',
|
|
initialState,
|
|
reducers: {
|
|
setLoading: (state, action: PayloadAction<boolean>) => {
|
|
state.isLoading = action.payload;
|
|
},
|
|
setError: (state, action: PayloadAction<string | null>) => {
|
|
state.error = action.payload;
|
|
},
|
|
updateStats: (state, action: PayloadAction<Partial<ResellerDashboardStats>>) => {
|
|
state.stats = { ...state.stats, ...action.payload };
|
|
},
|
|
addRecentActivity: (state, action: PayloadAction<ResellerRecentActivity>) => {
|
|
state.recentActivities.unshift(action.payload);
|
|
if (state.recentActivities.length > 20) {
|
|
state.recentActivities = state.recentActivities.slice(0, 20);
|
|
}
|
|
},
|
|
updateCustomer: (state, action: PayloadAction<ResellerCustomer>) => {
|
|
const index = state.customers.findIndex(c => c.id === action.payload.id);
|
|
if (index !== -1) {
|
|
state.customers[index] = action.payload;
|
|
}
|
|
},
|
|
removeCustomer: (state, action: PayloadAction<string>) => {
|
|
state.customers = state.customers.filter(c => c.id !== action.payload);
|
|
},
|
|
addSale: (state, action: PayloadAction<ResellerSale>) => {
|
|
state.sales.unshift(action.payload);
|
|
if (state.sales.length > 100) {
|
|
state.sales = state.sales.slice(0, 100);
|
|
}
|
|
},
|
|
addReceipt: (state, action: PayloadAction<ResellerReceipt>) => {
|
|
state.receipts.unshift(action.payload);
|
|
if (state.receipts.length > 100) {
|
|
state.receipts = state.receipts.slice(0, 100);
|
|
}
|
|
},
|
|
addPayment: (state, action: PayloadAction<ResellerPayment>) => {
|
|
state.payments.unshift(action.payload);
|
|
if (state.payments.length > 100) {
|
|
state.payments = state.payments.slice(0, 100);
|
|
}
|
|
},
|
|
},
|
|
extraReducers: (builder) => {
|
|
builder
|
|
// Dashboard Stats
|
|
.addCase(fetchDashboardStats.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchDashboardStats.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.stats = action.payload;
|
|
})
|
|
.addCase(fetchDashboardStats.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Customers
|
|
.addCase(fetchCustomers.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchCustomers.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.customers = action.payload;
|
|
})
|
|
.addCase(fetchCustomers.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Products
|
|
.addCase(fetchProducts.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchProducts.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.products = action.payload;
|
|
})
|
|
.addCase(fetchProducts.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Sales
|
|
.addCase(fetchSales.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchSales.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.sales = action.payload;
|
|
})
|
|
.addCase(fetchSales.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Receipts
|
|
.addCase(fetchReceipts.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchReceipts.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.receipts = action.payload;
|
|
})
|
|
.addCase(fetchReceipts.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Payments
|
|
.addCase(fetchPayments.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchPayments.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.payments = action.payload;
|
|
})
|
|
.addCase(fetchPayments.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Recent Activities
|
|
.addCase(fetchRecentActivities.pending, (state) => {
|
|
state.isLoading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchRecentActivities.fulfilled, (state, action) => {
|
|
state.isLoading = false;
|
|
state.recentActivities = action.payload;
|
|
})
|
|
.addCase(fetchRecentActivities.rejected, (state, action) => {
|
|
state.isLoading = false;
|
|
state.error = action.payload as string;
|
|
})
|
|
// Add Customer
|
|
.addCase(addCustomer.fulfilled, (state, action) => {
|
|
state.customers.unshift(action.payload);
|
|
state.stats.activeCustomers += 1;
|
|
})
|
|
// Create Sale
|
|
.addCase(createSale.fulfilled, (state, action) => {
|
|
state.sales.unshift(action.payload);
|
|
state.stats.totalRevenue += action.payload.amount;
|
|
state.stats.commissionEarned += action.payload.commission;
|
|
});
|
|
},
|
|
});
|
|
|
|
export const {
|
|
setLoading,
|
|
setError,
|
|
updateStats,
|
|
addRecentActivity,
|
|
updateCustomer,
|
|
removeCustomer,
|
|
addSale,
|
|
addReceipt,
|
|
addPayment,
|
|
} = resellerDashboardSlice.actions;
|
|
|
|
export default resellerDashboardSlice.reducer;
|