Implemented pagination controls and page size selection for the top customers section in CustomerInsightsChart. Updated analytics-service to support paginated customer insights API calls and handle pagination metadata. Improves usability for stores with large customer bases.
200 lines
5.4 KiB
TypeScript
200 lines
5.4 KiB
TypeScript
'use client';
|
|
|
|
import { clientFetch } from '../api-client';
|
|
|
|
// Analytics Types
|
|
export interface AnalyticsOverview {
|
|
orders: {
|
|
total: number;
|
|
completed: number;
|
|
pending: number;
|
|
completionRate: string;
|
|
};
|
|
revenue: {
|
|
total: number;
|
|
monthly: number;
|
|
weekly: number;
|
|
averageOrderValue: number;
|
|
};
|
|
products: {
|
|
total: number;
|
|
};
|
|
customers: {
|
|
unique: number;
|
|
};
|
|
userType?: 'vendor' | 'staff';
|
|
}
|
|
|
|
export interface RevenueData {
|
|
_id: {
|
|
year: number;
|
|
month: number;
|
|
day: number;
|
|
};
|
|
revenue: number;
|
|
orders: number;
|
|
}
|
|
|
|
export interface ProductPerformance {
|
|
productId: string;
|
|
name: string;
|
|
image: string;
|
|
unitType: string;
|
|
currentStock: number;
|
|
stockStatus: string;
|
|
totalSold: number;
|
|
totalRevenue: number;
|
|
orderCount: number;
|
|
averagePrice: number;
|
|
}
|
|
|
|
export interface CustomerInsights {
|
|
totalCustomers: number;
|
|
segments: {
|
|
new: number;
|
|
returning: number;
|
|
loyal: number;
|
|
vip: number;
|
|
};
|
|
topCustomers: Array<{
|
|
_id: string;
|
|
orderCount: number;
|
|
totalSpent: number;
|
|
averageOrderValue: number;
|
|
firstOrder: string;
|
|
lastOrder: string;
|
|
displayName?: string;
|
|
username?: string;
|
|
}>;
|
|
averageOrdersPerCustomer: string;
|
|
pagination?: {
|
|
currentPage: number;
|
|
totalPages: number;
|
|
totalCustomers: number;
|
|
limit: number;
|
|
hasNextPage: boolean;
|
|
hasPrevPage: boolean;
|
|
startIndex: number;
|
|
endIndex: number;
|
|
};
|
|
}
|
|
|
|
export interface OrderAnalytics {
|
|
statusDistribution: Array<{
|
|
_id: string;
|
|
count: number;
|
|
}>;
|
|
}
|
|
|
|
// Analytics Service Functions
|
|
|
|
/**
|
|
* Get analytics overview data
|
|
* @param storeId Optional storeId for staff users
|
|
*/
|
|
export const getAnalyticsOverview = async (storeId?: string): Promise<AnalyticsOverview> => {
|
|
const url = storeId ? `/analytics/overview?storeId=${storeId}` : '/analytics/overview';
|
|
return clientFetch<AnalyticsOverview>(url);
|
|
};
|
|
|
|
/**
|
|
* Get revenue trends data
|
|
* @param period Time period in days (7, 30, 90)
|
|
* @param storeId Optional storeId for staff users
|
|
*/
|
|
export const getRevenueTrends = async (period: string = '30', storeId?: string): Promise<RevenueData[]> => {
|
|
const params = new URLSearchParams({ period });
|
|
if (storeId) params.append('storeId', storeId);
|
|
|
|
const url = `/analytics/revenue-trends?${params.toString()}`;
|
|
return clientFetch<RevenueData[]>(url);
|
|
};
|
|
|
|
/**
|
|
* Get product performance data
|
|
* @param storeId Optional storeId for staff users
|
|
*/
|
|
export const getProductPerformance = async (storeId?: string): Promise<ProductPerformance[]> => {
|
|
const url = storeId ? `/analytics/product-performance?storeId=${storeId}` : '/analytics/product-performance';
|
|
return clientFetch<ProductPerformance[]>(url);
|
|
};
|
|
|
|
/**
|
|
* Get customer insights data
|
|
* @param storeId Optional storeId for staff users
|
|
* @param page Page number (default: 1)
|
|
* @param limit Number of customers per page (default: 10)
|
|
*/
|
|
export const getCustomerInsights = async (storeId?: string, page: number = 1, limit: number = 10): Promise<CustomerInsights> => {
|
|
const params = new URLSearchParams({
|
|
page: page.toString(),
|
|
limit: limit.toString()
|
|
});
|
|
if (storeId) params.append('storeId', storeId);
|
|
|
|
const url = `/analytics/customer-insights?${params.toString()}`;
|
|
return clientFetch<CustomerInsights>(url);
|
|
};
|
|
|
|
/**
|
|
* Get order analytics data
|
|
* @param period Time period in days (7, 30, 90)
|
|
* @param storeId Optional storeId for staff users
|
|
*/
|
|
export const getOrderAnalytics = async (period: string = '30', storeId?: string): Promise<OrderAnalytics> => {
|
|
const params = new URLSearchParams({ period });
|
|
if (storeId) params.append('storeId', storeId);
|
|
|
|
const url = `/analytics/order-analytics?${params.toString()}`;
|
|
return clientFetch<OrderAnalytics>(url);
|
|
};
|
|
|
|
// Helper function to determine if user is staff and get storeId
|
|
export const getStoreIdForUser = (): string | undefined => {
|
|
if (typeof window === 'undefined') return undefined;
|
|
|
|
// Check if user is staff (you might need to adjust this based on your auth system)
|
|
const userType = localStorage.getItem('userType');
|
|
const storeId = localStorage.getItem('storeId');
|
|
|
|
if (userType === 'staff' && storeId) {
|
|
return storeId;
|
|
}
|
|
|
|
return undefined;
|
|
};
|
|
|
|
// Enhanced analytics functions that automatically handle storeId for staff users
|
|
export const getAnalyticsOverviewWithStore = async (): Promise<AnalyticsOverview> => {
|
|
const storeId = getStoreIdForUser();
|
|
return getAnalyticsOverview(storeId);
|
|
};
|
|
|
|
export const getRevenueTrendsWithStore = async (period: string = '30'): Promise<RevenueData[]> => {
|
|
const storeId = getStoreIdForUser();
|
|
return getRevenueTrends(period, storeId);
|
|
};
|
|
|
|
export const getProductPerformanceWithStore = async (): Promise<ProductPerformance[]> => {
|
|
const storeId = getStoreIdForUser();
|
|
return getProductPerformance(storeId);
|
|
};
|
|
|
|
export const getCustomerInsightsWithStore = async (page: number = 1, limit: number = 10): Promise<CustomerInsights> => {
|
|
const storeId = getStoreIdForUser();
|
|
return getCustomerInsights(storeId, page, limit);
|
|
};
|
|
|
|
export const getOrderAnalyticsWithStore = async (period: string = '30'): Promise<OrderAnalytics> => {
|
|
const storeId = getStoreIdForUser();
|
|
return getOrderAnalytics(period, storeId);
|
|
};
|
|
|
|
export function formatGBP(value: number) {
|
|
return value.toLocaleString('en-GB', {
|
|
style: 'currency',
|
|
currency: 'GBP',
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2,
|
|
});
|
|
}
|