diff --git a/.env.production b/.env.production index c41ca8d..6ce6816 100644 --- a/.env.production +++ b/.env.production @@ -1,3 +1,4 @@ + # Disable telemetry for faster builds NEXT_TELEMETRY_DISABLED=1 @@ -11,4 +12,4 @@ NEXT_LOG_LEVEL=error GENERATE_SOURCEMAP=false # API configuration -SERVER_API_URL=https://internal-api.inboxi.ng/api +SERVER_API_URL=https://internal-api.inboxi.ng/api \ No newline at end of file diff --git a/components/analytics/AnalyticsDashboard.tsx b/components/analytics/AnalyticsDashboard.tsx index a97ed69..87cc37b 100644 --- a/components/analytics/AnalyticsDashboard.tsx +++ b/components/analytics/AnalyticsDashboard.tsx @@ -27,6 +27,10 @@ import { formatGBP } from "@/utils/format"; import { MetricsCardSkeleton } from './SkeletonLoaders'; import dynamic from 'next/dynamic'; import { Skeleton } from "@/components/ui/skeleton"; +import { DateRangePicker } from "@/components/ui/date-picker"; +import { DateRange } from "react-day-picker"; +import { addDays, startOfDay, endOfDay } from "date-fns"; +import type { DateRange as ProfitDateRange } from "@/lib/services/profit-analytics-service"; // Lazy load chart components const RevenueChart = dynamic(() => import('./RevenueChart'), { @@ -78,6 +82,10 @@ export default function AnalyticsDashboard({ initialData }: AnalyticsDashboardPr const [isLoading, setIsLoading] = useState(false); const [timeRange, setTimeRange] = useState('30'); const [hideNumbers, setHideNumbers] = useState(false); + const [profitDateRange, setProfitDateRange] = useState({ + from: startOfDay(addDays(new Date(), -29)), + to: endOfDay(new Date()) + }); const { toast } = useToast(); // Function to mask sensitive numbers @@ -302,8 +310,41 @@ export default function AnalyticsDashboard({ initialData }: AnalyticsDashboardPr + {/* Date Range Selector for Profit Calculator */} + + + Date Range + + Select a custom date range for profit calculations + + + +
+ + {profitDateRange?.from && profitDateRange?.to && ( +
+ + {profitDateRange.from.toLocaleDateString()} - {profitDateRange.to.toLocaleDateString()} + +
+ )} +
+
+
}> - +
diff --git a/components/analytics/ProfitAnalyticsChart.tsx b/components/analytics/ProfitAnalyticsChart.tsx index eeacd19..cc7fc29 100644 --- a/components/analytics/ProfitAnalyticsChart.tsx +++ b/components/analytics/ProfitAnalyticsChart.tsx @@ -15,15 +15,16 @@ import { } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { formatGBP } from "@/utils/format"; -import { getProfitOverview, type ProfitOverview } from "@/lib/services/profit-analytics-service"; +import { getProfitOverview, type ProfitOverview, type DateRange } from "@/lib/services/profit-analytics-service"; import { Skeleton } from "@/components/ui/skeleton"; interface ProfitAnalyticsChartProps { - timeRange: string; + timeRange?: string; + dateRange?: DateRange; hideNumbers?: boolean; } -export default function ProfitAnalyticsChart({ timeRange, hideNumbers = false }: ProfitAnalyticsChartProps) { +export default function ProfitAnalyticsChart({ timeRange, dateRange, hideNumbers = false }: ProfitAnalyticsChartProps) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); @@ -44,7 +45,8 @@ export default function ProfitAnalyticsChart({ timeRange, hideNumbers = false }: try { setIsLoading(true); setError(null); - const response = await getProfitOverview(timeRange); + // Use dateRange if provided, otherwise fall back to timeRange + const response = await getProfitOverview(dateRange || timeRange || '30'); setData(response); } catch (error) { console.error('Error fetching profit data:', error); @@ -60,7 +62,7 @@ export default function ProfitAnalyticsChart({ timeRange, hideNumbers = false }: }; fetchData(); - }, [timeRange, toast]); + }, [timeRange, dateRange, toast]); if (isLoading) { return ( @@ -304,7 +306,10 @@ export default function ProfitAnalyticsChart({ timeRange, hideNumbers = false }: Most Profitable Products - Products generating the highest total profit (last {timeRange} days) + {dateRange + ? `Products generating the highest total profit (${new Date(dateRange.from).toLocaleDateString()} - ${new Date(dateRange.to).toLocaleDateString()})` + : `Products generating the highest total profit (last ${timeRange || '30'} days)` + } diff --git a/lib/services/profit-analytics-service.ts b/lib/services/profit-analytics-service.ts index da88c12..b9c16d3 100644 --- a/lib/services/profit-analytics-service.ts +++ b/lib/services/profit-analytics-service.ts @@ -2,6 +2,8 @@ import { apiRequest } from '../api'; export interface ProfitOverview { period: string; + startDate?: string; + endDate?: string; summary: { totalRevenue: number; revenueFromTrackedProducts: number; @@ -40,10 +42,45 @@ export interface ProfitTrend { profitMargin: number; } -export const getProfitOverview = async (period: string = '30'): Promise => { - return apiRequest(`/analytics/profit-overview?period=${period}`); +export interface DateRange { + from: Date; + to: Date; +} + +export const getProfitOverview = async ( + periodOrRange?: string | DateRange +): Promise => { + let url = '/analytics/profit-overview'; + + if (periodOrRange && typeof periodOrRange !== 'string') { + // Date range provided + const startDate = periodOrRange.from.toISOString().split('T')[0]; + const endDate = periodOrRange.to.toISOString().split('T')[0]; + url += `?startDate=${startDate}&endDate=${endDate}`; + } else { + // Period provided (backward compatibility) + const period = periodOrRange || '30'; + url += `?period=${period}`; + } + + return apiRequest(url); }; -export const getProfitTrends = async (period: string = '30'): Promise => { - return apiRequest(`/analytics/profit-trends?period=${period}`); +export const getProfitTrends = async ( + periodOrRange?: string | DateRange +): Promise => { + let url = '/analytics/profit-trends'; + + if (periodOrRange && typeof periodOrRange !== 'string') { + // Date range provided + const startDate = periodOrRange.from.toISOString().split('T')[0]; + const endDate = periodOrRange.to.toISOString().split('T')[0]; + url += `?startDate=${startDate}&endDate=${endDate}`; + } else { + // Period provided (backward compatibility) + const period = periodOrRange || '30'; + url += `?period=${period}`; + } + + return apiRequest(url); }; diff --git a/public/git-info.json b/public/git-info.json index da9e458..0b9483c 100644 --- a/public/git-info.json +++ b/public/git-info.json @@ -1,4 +1,4 @@ { - "commitHash": "928d94c", - "buildTime": "2025-10-31T00:03:09.717Z" + "commitHash": "28e292a", + "buildTime": "2025-11-28T18:29:50.128Z" } \ No newline at end of file