Show RFV loading state in clients table
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m30s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m30s
This commit is contained in:
@@ -188,6 +188,7 @@ const Clients = () => {
|
||||
const [rfmAnalytics, setRfmAnalytics] = useState<RfmAnalytics | null>(initialRfmAnalytics || null);
|
||||
const [clientAnalytics, setClientAnalytics] = useState<ClientAnalyticsItem[]>(initialClientAnalytics || []);
|
||||
const [isLoading, setIsLoading] = useState(!initialClientAnalytics);
|
||||
const [isRfmLoading, setIsRfmLoading] = useState(!initialRfmAnalytics && Boolean(initialClientAnalytics));
|
||||
|
||||
// Pagination state
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
@@ -207,6 +208,7 @@ const Clients = () => {
|
||||
if (cachedClients) setClientAnalytics(cachedClients);
|
||||
setRfmAnalytics(cachedRfm || null);
|
||||
setIsLoading(!hasCachedClients);
|
||||
setIsRfmLoading(!cachedRfm && hasCachedClients);
|
||||
}
|
||||
|
||||
const filterOptionsPromise = fetchClientFilterOptions(dateRange, { force: true });
|
||||
@@ -218,11 +220,13 @@ const Clients = () => {
|
||||
setFilterOptions(options);
|
||||
setClientAnalytics(clientsData);
|
||||
setIsLoading(false);
|
||||
setIsRfmLoading(!cachedRfm);
|
||||
}
|
||||
|
||||
const rfmData = await rfmPromise;
|
||||
if (isMounted) {
|
||||
setRfmAnalytics(rfmData);
|
||||
setIsRfmLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -441,6 +445,7 @@ const Clients = () => {
|
||||
(sortBy === 'recent' ? 0 : 1);
|
||||
const hasActiveFilters = activeFilterCount > 0;
|
||||
const isRefreshing = isLoading && clientAnalytics.length > 0;
|
||||
const shouldShowRfmLoading = isRfmLoading && clientAnalytics.length > 0;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -672,24 +677,36 @@ const Clients = () => {
|
||||
</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">
|
||||
<span
|
||||
className="inline-flex rounded-full border px-3 py-1 text-xs font-bold"
|
||||
style={clientTypePillStyle(clientTypeStyle)}
|
||||
>
|
||||
{client.clientType}
|
||||
</span>
|
||||
{shouldShowRfmLoading ? (
|
||||
<span className="skeleton inline-flex h-7 w-24 rounded-full" />
|
||||
) : (
|
||||
<span
|
||||
className="inline-flex rounded-full border px-3 py-1 text-xs font-bold"
|
||||
style={clientTypePillStyle(clientTypeStyle)}
|
||||
>
|
||||
{client.clientType}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-6 py-2.5">
|
||||
<div className="flex items-center gap-1">
|
||||
{client.rfmScore.split('').map((score, scoreIndex) => (
|
||||
<span
|
||||
key={`${client.name}-${scoreIndex}`}
|
||||
className="inline-flex h-6 w-6 items-center justify-center rounded-md border border-dark-border bg-dark-input text-[11px] font-bold text-dark-text"
|
||||
>
|
||||
{score}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
{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">
|
||||
{client.rfmScore.split('').map((score, scoreIndex) => (
|
||||
<span
|
||||
key={`${client.name}-${scoreIndex}`}
|
||||
className="inline-flex h-6 w-6 items-center justify-center rounded-md border border-dark-border bg-dark-input text-[11px] font-bold text-dark-text"
|
||||
>
|
||||
{score}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</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>
|
||||
|
||||
Reference in New Issue
Block a user