From 1c6383e5a04445a4e642b7cc1e184ca53bf8565d Mon Sep 17 00:00:00 2001 From: dtoro Date: Thu, 9 Apr 2026 20:43:19 +0200 Subject: [PATCH] feat: colored count badge on Colors sidebar entry Adds a `colored` field to /library/stats counting non-discarded photos with a color_label set, mirroring how `rated` is exposed. The Colors sidebar entry now shows the live count and refreshes through the existing LIBRARY_STATS_QUERY_KEY invalidations. Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/app/routers/library.py | 11 +++++++++++ frontend/src/components/layout/LeftSidebar.tsx | 2 +- frontend/src/services/api.ts | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/backend/app/routers/library.py b/backend/app/routers/library.py index 4fbf93a..4c1af2d 100644 --- a/backend/app/routers/library.py +++ b/backend/app/routers/library.py @@ -36,6 +36,8 @@ async def get_library_stats(db: AsyncSession = Depends(get_db)): - all_photos: non-discarded photos + videos (matches the All Photos section's default filter) - rated: non-discarded with rating >= 1 + - colored: non-discarded with a color_label set (matches the + Colors grouped view's labeled buckets) - duplicates: non-discarded with is_duplicate = true - discarded: is_discarded = true - total_size: raw bytes across every row, including discarded @@ -52,6 +54,14 @@ async def get_library_stats(db: AsyncSession = Depends(get_db)): ) ).scalar() or 0 + colored_count = ( + await db.execute( + select(func.count(Photo.id)).where( + not_discarded, Photo.color_label.is_not(None) + ) + ) + ).scalar() or 0 + duplicates_count = ( await db.execute( select(func.count(Photo.id)).where( @@ -85,6 +95,7 @@ async def get_library_stats(db: AsyncSession = Depends(get_db)): return { "all_photos": all_photos_count, "rated": rated_count, + "colored": colored_count, "duplicates": duplicates_count, "discarded": discarded_count, "total_photos": photo_count, diff --git a/frontend/src/components/layout/LeftSidebar.tsx b/frontend/src/components/layout/LeftSidebar.tsx index c27d3fb..bf36170 100644 --- a/frontend/src/components/layout/LeftSidebar.tsx +++ b/frontend/src/components/layout/LeftSidebar.tsx @@ -348,7 +348,7 @@ export function LeftSidebar({ onCollapse, onOpenSettings }: LeftSidebarProps) { { id: 'all-photos', label: 'All Photos', icon: , count: stats?.all_photos ?? 0 }, { id: 'rated', label: 'Rated', icon: , count: stats?.rated ?? 0 }, { id: 'tags', label: 'Tags', icon: , count: tagsTotalCount }, - { id: 'colors', label: 'Colors', icon: }, + { id: 'colors', label: 'Colors', icon: , count: stats?.colored ?? 0 }, { id: 'duplicates', label: 'Duplicates', icon: , count: stats?.duplicates ?? 0 }, { id: 'discarded', label: 'Discarded', icon: , count: stats?.discarded ?? 0 }, ], diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts index 5cc2a93..10e0cc0 100644 --- a/frontend/src/services/api.ts +++ b/frontend/src/services/api.ts @@ -409,6 +409,7 @@ export interface DuplicateGroupsResponse { export interface LibraryStats { all_photos: number rated: number + colored: number duplicates: number discarded: number total_photos: number