& {
diff --git a/webui/src/components/form/index.ts b/webui/src/components/form/index.ts
index f9a268a6..0f6ffb0d 100644
--- a/webui/src/components/form/index.ts
+++ b/webui/src/components/form/index.ts
@@ -1,5 +1,6 @@
export {
Button,
+ Badge,
FormActions,
FormError,
FormField,
diff --git a/webui/src/routes/import/-route.test.tsx b/webui/src/routes/import/-route.test.tsx
index 9020992e..79d686c9 100644
--- a/webui/src/routes/import/-route.test.tsx
+++ b/webui/src/routes/import/-route.test.tsx
@@ -301,9 +301,8 @@ describe('import route', () => {
it('renders auto-import results from route search state', async () => {
renderImportRoute(['/import/auto?autoFilter=pending']);
- expect(await screen.findByText('1 review')).toBeInTheDocument();
+ expect(await screen.findByRole('button', { name: /^Needs Review\s*1$/ })).toBeInTheDocument();
expect(screen.getAllByText('Album A').length).toBeGreaterThan(0);
- expect(screen.getByText('Needs Review')).toBeInTheDocument();
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/groups'))).toBe(false);
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/suggestions'))).toBe(
false,
diff --git a/webui/src/routes/import/-ui/auto-import-tab.tsx b/webui/src/routes/import/-ui/auto-import-tab.tsx
index 13025853..63ee5f57 100644
--- a/webui/src/routes/import/-ui/auto-import-tab.tsx
+++ b/webui/src/routes/import/-ui/auto-import-tab.tsx
@@ -1,7 +1,15 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
-import { Button, OptionButton, OptionButtonGroup, RangeInput, Select, Switch } from '@/components/form/form';
+import {
+ Badge,
+ Button,
+ OptionButton,
+ OptionButtonGroup,
+ RangeInput,
+ Select,
+ Switch,
+} from '@/components/form/form';
import type {
ImportAutoFilter,
@@ -250,31 +258,13 @@ export function AutoImportPanel({
{allResults.length > 0 ? (
<>
-
-
- {counts.imported} imported
-
-
- {counts.review} review
-
-
- {counts.failed} failed
-
-
{(['all', 'pending', 'imported', 'failed'] as const).map((filter) => (
- onFilterChange(filter)}
- >
- {filter === 'pending' ? 'Needs Review' : titleCase(filter)}
+ onFilterChange(filter)}>
+ {getAutoImportFilterLabel(filter)}
+
+ {getAutoImportFilterCount(filter, counts, allResults.length)}
+
))}
@@ -555,6 +545,49 @@ function getAutoImportConfidenceClass(status: string): string {
return classes[status] ?? '';
}
+function getAutoImportFilterLabel(filter: ImportAutoFilter): string {
+ switch (filter) {
+ case 'all':
+ return 'All';
+ case 'pending':
+ return 'Needs Review';
+ case 'imported':
+ return 'Imported';
+ case 'failed':
+ return 'Failed';
+ }
+}
+
+function getAutoImportFilterCount(
+ filter: ImportAutoFilter,
+ counts: ReturnType,
+ totalCount: number,
+): number {
+ switch (filter) {
+ case 'all':
+ return totalCount;
+ case 'pending':
+ return counts.review;
+ case 'imported':
+ return counts.imported;
+ case 'failed':
+ return counts.failed;
+ }
+}
+
+function getAutoImportFilterTone(filter: ImportAutoFilter): 'neutral' | 'warning' | 'success' | 'danger' {
+ switch (filter) {
+ case 'pending':
+ return 'warning';
+ case 'imported':
+ return 'success';
+ case 'failed':
+ return 'danger';
+ case 'all':
+ return 'neutral';
+ }
+}
+
function getMethodLabel(method: string | null | undefined): string {
const labels: Record = {
tags: 'Tags',
@@ -565,10 +598,6 @@ function getMethodLabel(method: string | null | undefined): string {
return method ? labels[method] || method : '';
}
-function titleCase(value: string): string {
- return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
-}
-
async function confirmAction({
title,
message,
diff --git a/webui/src/routes/import/-ui/import-page.module.css b/webui/src/routes/import/-ui/import-page.module.css
index 5470d25d..f30e8e7a 100644
--- a/webui/src/routes/import/-ui/import-page.module.css
+++ b/webui/src/routes/import/-ui/import-page.module.css
@@ -1122,27 +1122,6 @@
animation: adlPulse 1.5s ease-in-out infinite;
}
-/* Stats summary */
-.autoImportStats {
- display: flex;
- gap: 16px;
- padding: 8px 0;
- margin-bottom: 4px;
-}
-
-.autoImportStat {
- font-size: 12px;
- color: rgba(255, 255, 255, 0.5);
- font-weight: 500;
-}
-
-.autoImportStatReview {
- color: #fbbf24;
-}
-.autoImportStatFailed {
- color: #f87171;
-}
-
/* Filter pills */
.autoImportFilters {
padding: 6px 0;