Smooth analytics page reloads
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 34s

This commit is contained in:
Cauê Faleiros
2026-06-23 14:45:21 -03:00
parent 335d231903
commit 7d60073757
7 changed files with 233 additions and 126 deletions

View File

@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
import { Link, useOutletContext } from 'react-router-dom';
import { Search, ChevronRight, Filter, ChevronLeft, X } from 'lucide-react';
import type { ClientAnalyticsItem, ClientFilterOptions, ClientMetadataFilters, DateRange, RfmAnalytics, RfmClient } from '../types';
import { fetchClientAnalytics, fetchClientFilterOptions, fetchRfmAnalytics } from '../dataService';
import { fetchClientAnalytics, fetchClientFilterOptions, fetchRfmAnalytics, getCachedClientAnalytics, getCachedClientFilterOptions, getCachedRfmAnalytics } from '../dataService';
import { endOfLocalDay, formatDateParam, parseLocalDateInput, rangeForDay, rangeForLastDays, rangeForPreviousDay, startOfLocalDay } from '../dateRanges';
import type { ClientSortOption, ClientSummary } from '../analytics/clients';
@@ -114,11 +114,14 @@ const Clients = () => {
const [sortBy, setSortBy] = useState<ClientSortOption>('recent');
const [clientTypeFilter, setClientTypeFilter] = useState('all');
const [metadataFilters, setMetadataFilters] = useState<ClientMetadataFilters>(emptyClientFilters);
const [filterOptions, setFilterOptions] = useState<ClientFilterOptions>(emptyClientFilterOptions);
const initialFilterOptions = getCachedClientFilterOptions(dateRange);
const initialClientAnalytics = getCachedClientAnalytics(dateRange, emptyClientFilters);
const initialRfmAnalytics = getCachedRfmAnalytics(dateRange, emptyClientFilters);
const [filterOptions, setFilterOptions] = useState<ClientFilterOptions>(initialFilterOptions || emptyClientFilterOptions);
const [isFilterMenuOpen, setIsFilterMenuOpen] = useState(false);
const filterMenuRef = useRef<HTMLDivElement>(null);
const [rfmAnalytics, setRfmAnalytics] = useState<RfmAnalytics | null>(null);
const [clientAnalytics, setClientAnalytics] = useState<ClientAnalyticsItem[]>([]);
const [rfmAnalytics, setRfmAnalytics] = useState<RfmAnalytics | null>(initialRfmAnalytics || null);
const [clientAnalytics, setClientAnalytics] = useState<ClientAnalyticsItem[]>(initialClientAnalytics || []);
// Pagination state
const [currentPage, setCurrentPage] = useState(1);
@@ -128,15 +131,27 @@ const Clients = () => {
let isMounted = true;
const loadClients = async () => {
const options = await fetchClientFilterOptions(dateRange);
const clientsData = await fetchClientAnalytics(dateRange, metadataFilters);
const cachedOptions = getCachedClientFilterOptions(dateRange);
const cachedClients = getCachedClientAnalytics(dateRange, metadataFilters);
const cachedRfm = getCachedRfmAnalytics(dateRange, metadataFilters);
if (isMounted) {
if (cachedOptions) setFilterOptions(cachedOptions);
if (cachedClients) setClientAnalytics(cachedClients);
setRfmAnalytics(cachedRfm || null);
}
const filterOptionsPromise = fetchClientFilterOptions(dateRange);
const clientsPromise = fetchClientAnalytics(dateRange, metadataFilters);
const rfmPromise = fetchRfmAnalytics(dateRange, metadataFilters);
const [options, clientsData] = await Promise.all([filterOptionsPromise, clientsPromise]);
if (isMounted) {
setFilterOptions(options);
setClientAnalytics(clientsData);
setRfmAnalytics(null);
}
const rfmData = await fetchRfmAnalytics(dateRange, metadataFilters);
const rfmData = await rfmPromise;
if (isMounted) {
setRfmAnalytics(rfmData);
}

View File

@@ -55,9 +55,9 @@ const Dashboard = () => {
const [serverMetrics, setServerMetrics] = useState<DashboardAnalytics | null>(null);
const [isMetricsLoading, setIsMetricsLoading] = useState(true);
const loadDashboardMetrics = useCallback(async (range: DateRange) => {
const loadDashboardMetrics = useCallback(async (range: DateRange, options?: { force?: boolean }) => {
setIsMetricsLoading(true);
const metrics = await fetchDashboardAnalytics(range);
const metrics = await fetchDashboardAnalytics(range, options);
setServerMetrics(metrics);
setIsMetricsLoading(false);
}, []);
@@ -72,7 +72,7 @@ const Dashboard = () => {
if (refreshInterval === 0) return;
const intervalId = setInterval(() => {
void loadDashboardMetrics(dateRange);
void loadDashboardMetrics(dateRange, { force: true });
}, refreshInterval);
return () => clearInterval(intervalId);
@@ -84,7 +84,7 @@ const Dashboard = () => {
}, [dateRange, ordersData, serverMetrics]);
const handleManualRefresh = () => {
void loadDashboardMetrics(dateRange);
void loadDashboardMetrics(dateRange, { force: true });
};
return (

View File

@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { Link, useOutletContext } from 'react-router-dom';
import { ChevronLeft, ChevronRight, Download, Filter, Loader2, Search, Users } from 'lucide-react';
import DateRangePicker from '../components/DateRangePicker';
import { exportToCSV, fetchRfmAnalytics } from '../dataService';
import { exportToCSV, fetchRfmAnalytics, getCachedRfmAnalytics } from '../dataService';
import type { DateRange, RfmAnalytics, RfmClient, RfmSegment } from '../types';
const emptyClients: RfmClient[] = [];
@@ -127,17 +127,25 @@ const Rfm = () => {
setRefreshInterval: (interval: number) => void;
}>();
const [analytics, setAnalytics] = useState<RfmAnalytics | null>(null);
const [isLoading, setIsLoading] = useState(true);
const initialCachedAnalytics = getCachedRfmAnalytics(dateRange);
const [analytics, setAnalytics] = useState<RfmAnalytics | null>(initialCachedAnalytics || null);
const [isLoading, setIsLoading] = useState(!initialCachedAnalytics);
const [searchTerm, setSearchTerm] = useState('');
const [segmentFilter, setSegmentFilter] = useState('all');
const [selectedSegmentKey, setSelectedSegmentKey] = useState('');
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(20);
const loadRfm = useCallback(async (range: DateRange) => {
const loadRfm = useCallback(async (range: DateRange, options?: { force?: boolean }) => {
const cachedAnalytics = options?.force ? undefined : getCachedRfmAnalytics(range);
if (cachedAnalytics) {
setAnalytics(cachedAnalytics);
setIsLoading(false);
return;
}
setIsLoading(true);
const data = await fetchRfmAnalytics(range);
const data = await fetchRfmAnalytics(range, undefined, options);
setAnalytics(data);
setIsLoading(false);
}, []);
@@ -152,7 +160,7 @@ const Rfm = () => {
if (refreshInterval === 0) return;
const intervalId = setInterval(() => {
void loadRfm(dateRange);
void loadRfm(dateRange, { force: true });
}, refreshInterval);
return () => clearInterval(intervalId);
@@ -276,7 +284,7 @@ const Rfm = () => {
onChange={setDateRange}
refreshInterval={refreshInterval}
setRefreshInterval={setRefreshInterval}
onManualRefresh={() => void loadRfm(dateRange)}
onManualRefresh={() => void loadRfm(dateRange, { force: true })}
/>
</div>
</div>