From 5fc745edd3c1b1a7b7b3b99005cd694332e0f988 Mon Sep 17 00:00:00 2001 From: Maddox Date: Wed, 8 Apr 2026 18:03:41 -0400 Subject: [PATCH] =?UTF-8?q?Fix=20stats=20bar=20counts=20=E2=80=94=20use=20?= =?UTF-8?q?/api/stats=20endpoint=20instead=20of=20page=20slice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added /api/stats to backend (returns route counts + total, respects same search/category/route filters as the main query). StatsBar now shows accurate counts across all records, not just the current page. Co-Authored-By: Claude Sonnet 4.6 --- src/App.tsx | 13 +++++++++++-- src/api.ts | 7 +++++++ src/components/StatsBar.tsx | 25 +++++++++---------------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 9054f95..d393f5c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import { useState, useCallback } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Plus, LayoutGrid, Table2, ShoppingBag } from 'lucide-react' -import { fetchStores, fetchFilters, createStore, updateStore, deleteStore } from './api' +import { fetchStores, fetchFilters, fetchStats, createStore, updateStore, deleteStore } from './api' import type { Store, StoreFilters } from './types' import { StatsBar } from './components/StatsBar' import { FilterBar } from './components/FilterBar' @@ -72,6 +72,15 @@ export default function App() { staleTime: 60_000, }) + const { data: statsData } = useQuery({ + queryKey: ['stats', filters.search, filters.category, filters.route], + queryFn: () => fetchStats({ + search: filters.search, + category: filters.category, + route: filters.route, + }), + }) + const createMut = useMutation({ mutationFn: createStore, onSuccess: () => { @@ -163,7 +172,7 @@ export default function App() {
- + { return data } +export async function fetchStats(params: Record = {}): Promise<{ + auto: number; ask: number; verify: number; ignore: number; total: number +}> { + const { data } = await client.get('/stats', { params }) + return data +} + export async function createStore(payload: Omit): Promise<{ id: number }> { const { data } = await client.post('/stores', payload) return data diff --git a/src/components/StatsBar.tsx b/src/components/StatsBar.tsx index eb040b5..279d0ab 100644 --- a/src/components/StatsBar.tsx +++ b/src/components/StatsBar.tsx @@ -1,28 +1,21 @@ import { Database, Zap, HelpCircle, CheckCircle, EyeOff } from 'lucide-react' -import type { Store } from '../types' interface Props { - stores: Store[] - total: number + stats: { auto: number; ask: number; verify: number; ignore: number; total: number } | undefined } -export function StatsBar({ stores, total }: Props) { - const counts = stores.reduce( - (acc, s) => ({ ...acc, [s.route]: (acc[s.route as keyof typeof acc] ?? 0) + 1 }), - { auto: 0, ask: 0, verify: 0, ignore: 0 } as Record - ) - - const stats = [ - { label: 'Total', value: total, icon: Database, color: 'text-slate-400' }, - { label: 'Auto', value: counts.auto, icon: Zap, color: 'text-green-400' }, - { label: 'Ask', value: counts.ask, icon: HelpCircle, color: 'text-amber-400' }, - { label: 'Verify', value: counts.verify, icon: CheckCircle, color: 'text-blue-400' }, - { label: 'Ignore', value: counts.ignore, icon: EyeOff, color: 'text-slate-500' }, +export function StatsBar({ stats }: Props) { + const entries = [ + { label: 'Total', value: stats?.total ?? 0, icon: Database, color: 'text-slate-400' }, + { label: 'Auto', value: stats?.auto ?? 0, icon: Zap, color: 'text-green-400' }, + { label: 'Ask', value: stats?.ask ?? 0, icon: HelpCircle, color: 'text-amber-400' }, + { label: 'Verify', value: stats?.verify ?? 0, icon: CheckCircle, color: 'text-blue-400' }, + { label: 'Ignore', value: stats?.ignore ?? 0, icon: EyeOff, color: 'text-slate-500' }, ] return (
- {stats.map(({ label, value, icon: Icon, color }) => ( + {entries.map(({ label, value, icon: Icon, color }) => (