Show RFV loading state in clients table
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m30s

This commit is contained in:
Cauê Faleiros
2026-06-30 12:49:39 -03:00
parent 1e511f35a9
commit 839e1f814e

View File

@@ -188,6 +188,7 @@ const Clients = () => {
const [rfmAnalytics, setRfmAnalytics] = useState<RfmAnalytics | null>(initialRfmAnalytics || null); const [rfmAnalytics, setRfmAnalytics] = useState<RfmAnalytics | null>(initialRfmAnalytics || null);
const [clientAnalytics, setClientAnalytics] = useState<ClientAnalyticsItem[]>(initialClientAnalytics || []); const [clientAnalytics, setClientAnalytics] = useState<ClientAnalyticsItem[]>(initialClientAnalytics || []);
const [isLoading, setIsLoading] = useState(!initialClientAnalytics); const [isLoading, setIsLoading] = useState(!initialClientAnalytics);
const [isRfmLoading, setIsRfmLoading] = useState(!initialRfmAnalytics && Boolean(initialClientAnalytics));
// Pagination state // Pagination state
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
@@ -207,6 +208,7 @@ const Clients = () => {
if (cachedClients) setClientAnalytics(cachedClients); if (cachedClients) setClientAnalytics(cachedClients);
setRfmAnalytics(cachedRfm || null); setRfmAnalytics(cachedRfm || null);
setIsLoading(!hasCachedClients); setIsLoading(!hasCachedClients);
setIsRfmLoading(!cachedRfm && hasCachedClients);
} }
const filterOptionsPromise = fetchClientFilterOptions(dateRange, { force: true }); const filterOptionsPromise = fetchClientFilterOptions(dateRange, { force: true });
@@ -218,11 +220,13 @@ const Clients = () => {
setFilterOptions(options); setFilterOptions(options);
setClientAnalytics(clientsData); setClientAnalytics(clientsData);
setIsLoading(false); setIsLoading(false);
setIsRfmLoading(!cachedRfm);
} }
const rfmData = await rfmPromise; const rfmData = await rfmPromise;
if (isMounted) { if (isMounted) {
setRfmAnalytics(rfmData); setRfmAnalytics(rfmData);
setIsRfmLoading(false);
} }
}; };
@@ -441,6 +445,7 @@ const Clients = () => {
(sortBy === 'recent' ? 0 : 1); (sortBy === 'recent' ? 0 : 1);
const hasActiveFilters = activeFilterCount > 0; const hasActiveFilters = activeFilterCount > 0;
const isRefreshing = isLoading && clientAnalytics.length > 0; const isRefreshing = isLoading && clientAnalytics.length > 0;
const shouldShowRfmLoading = isRfmLoading && clientAnalytics.length > 0;
return ( return (
<div className="space-y-6"> <div className="space-y-6">
@@ -672,14 +677,25 @@ const Clients = () => {
</td> </td>
<td className="px-6 py-2.5 font-semibold text-zinc-900 dark:text-dark-text">{client.name}</td> <td className="px-6 py-2.5 font-semibold text-zinc-900 dark:text-dark-text">{client.name}</td>
<td className="px-6 py-2.5"> <td className="px-6 py-2.5">
{shouldShowRfmLoading ? (
<span className="skeleton inline-flex h-7 w-24 rounded-full" />
) : (
<span <span
className="inline-flex rounded-full border px-3 py-1 text-xs font-bold" className="inline-flex rounded-full border px-3 py-1 text-xs font-bold"
style={clientTypePillStyle(clientTypeStyle)} style={clientTypePillStyle(clientTypeStyle)}
> >
{client.clientType} {client.clientType}
</span> </span>
)}
</td> </td>
<td className="px-6 py-2.5"> <td className="px-6 py-2.5">
{shouldShowRfmLoading ? (
<div className="flex items-center gap-1">
{[0, 1, 2].map(item => (
<span key={`rfm-score-loading-${client.customerKey}-${item}`} className="skeleton h-6 w-6 rounded-md" />
))}
</div>
) : (
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
{client.rfmScore.split('').map((score, scoreIndex) => ( {client.rfmScore.split('').map((score, scoreIndex) => (
<span <span
@@ -690,6 +706,7 @@ const Clients = () => {
</span> </span>
))} ))}
</div> </div>
)}
</td> </td>
<td className="px-6 py-2.5 text-brand-primary font-bold">{formatCurrency(client.totalSpent)}</td> <td className="px-6 py-2.5 text-brand-primary font-bold">{formatCurrency(client.totalSpent)}</td>
<td className="px-6 py-2.5 text-zinc-700 dark:text-dark-text font-semibold">{formatCurrency(client.averageTicket)}</td> <td className="px-6 py-2.5 text-zinc-700 dark:text-dark-text font-semibold">{formatCurrency(client.averageTicket)}</td>