Review view: tabs per cause (mirrors /tags pill row)

Each cause now becomes a URL-driven tab instead of stacking the cards
vertically. Empty buckets are filtered out by the adapter already, so
the tab row only shows causes with hits. Active tab persists via
?tab=<cause_key>; refresh / share / back land on the same panel.

The standalone ReviewView container is no longer used (the page
renders the active CauseGroupCard directly); deleted.
This commit is contained in:
Claudio
2026-05-18 15:54:25 +00:00
parent ca9f6e6bd2
commit f9f276a986
2 changed files with 85 additions and 72 deletions

View File

@@ -1,48 +0,0 @@
<!--
Review-page body. Renders one CauseGroupCard per ReviewGroup the
adapter returned. Mirrors DuplicatesView's pending/error/empty
branching.
-->
<script lang="ts">
import type { ReviewGroup } from '$lib/services/adapters/review';
import type { PpPhoto } from '$lib/types/photoprism';
import CauseGroupCard from './CauseGroupCard.svelte';
interface Props {
groups: ReviewGroup[];
pending: boolean;
error: unknown;
onSelect?: (photo: PpPhoto) => void;
}
let { groups, pending, error, onSelect }: Props = $props();
const totalCount = $derived(groups.reduce((acc, g) => acc + g.photos.length, 0));
</script>
<div class="px-6 py-4 pb-6">
{#if pending}
<p class="text-sm text-muted-foreground">Loading review queue…</p>
{:else if error}
<p class="text-sm text-destructive">
Could not load review queue: {error instanceof Error ? error.message : 'unknown error'}
</p>
{:else if groups.length === 0}
<div class="max-w-prose space-y-2 text-sm text-muted-foreground">
<p>The review queue is empty.</p>
<p class="text-xs">
PhotoPrism's indexer flags photos with a low quality score for human review. New
arrivals with missing EXIF, low resolution, or unknown cameras will land here.
</p>
</div>
{:else}
<p class="mb-3 text-[11px] text-muted-foreground">
{totalCount} photos in {groups.length} groups · arrow keys to focus, S to approve, A
to archive, Enter to inspect
</p>
<div class="space-y-3">
{#each groups as g, i (g.cause)}
<CauseGroupCard group={g} autoFocus={i === 0} {onSelect} />
{/each}
</div>
{/if}
</div>