Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 25s
CI / test-go-edu-search (push) Successful in 25s
CI / test-python-klausur (push) Failing after 1m53s
CI / test-python-agent-core (push) Successful in 15s
CI / test-nodejs-website (push) Successful in 17s
Step components (Deskew, Dewarp, Crop, Orientation) had local state guards that prevented reloading when sessionId changed via sub-session tab clicks. Added useEffect reset hooks that clear all local state when sessionId changes, allowing the component to properly reload the new session's data. Also renamed "Box N" to "Seite N" in BoxSessionTabs per user feedback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
69 lines
2.4 KiB
TypeScript
69 lines
2.4 KiB
TypeScript
'use client'
|
|
|
|
import type { SubSession } from '@/app/(admin)/ai/ocr-pipeline/types'
|
|
|
|
interface BoxSessionTabsProps {
|
|
parentSessionId: string
|
|
subSessions: SubSession[]
|
|
activeSessionId: string
|
|
onSessionChange: (sessionId: string) => void
|
|
}
|
|
|
|
const STATUS_ICONS: Record<string, string> = {
|
|
pending: '\u23F3', // hourglass
|
|
processing: '\uD83D\uDD04', // arrows
|
|
completed: '\u2713', // checkmark
|
|
}
|
|
|
|
function getStatusIcon(sub: SubSession): string {
|
|
if (sub.status === 'completed' || (sub.current_step && sub.current_step >= 9)) return STATUS_ICONS.completed
|
|
if (sub.current_step && sub.current_step > 1) return STATUS_ICONS.processing
|
|
return STATUS_ICONS.pending
|
|
}
|
|
|
|
export function BoxSessionTabs({ parentSessionId, subSessions, activeSessionId, onSessionChange }: BoxSessionTabsProps) {
|
|
if (subSessions.length === 0) return null
|
|
|
|
const isParentActive = activeSessionId === parentSessionId
|
|
|
|
return (
|
|
<div className="flex items-center gap-1.5 px-1 py-1.5 bg-gray-50 dark:bg-gray-800/50 rounded-xl border border-gray-200 dark:border-gray-700">
|
|
{/* Main session tab */}
|
|
<button
|
|
onClick={() => onSessionChange(parentSessionId)}
|
|
className={`px-3 py-1.5 rounded-lg text-xs font-medium transition-colors ${
|
|
isParentActive
|
|
? 'bg-white dark:bg-gray-700 text-teal-700 dark:text-teal-400 shadow-sm ring-1 ring-teal-300 dark:ring-teal-600'
|
|
: 'text-gray-500 dark:text-gray-400 hover:bg-white/50 dark:hover:bg-gray-700/50'
|
|
}`}
|
|
>
|
|
Hauptseite
|
|
</button>
|
|
|
|
<div className="w-px h-5 bg-gray-200 dark:bg-gray-700" />
|
|
|
|
{/* Sub-session tabs */}
|
|
{subSessions.map((sub) => {
|
|
const isActive = activeSessionId === sub.id
|
|
const icon = getStatusIcon(sub)
|
|
|
|
return (
|
|
<button
|
|
key={sub.id}
|
|
onClick={() => onSessionChange(sub.id)}
|
|
className={`px-3 py-1.5 rounded-lg text-xs font-medium transition-colors ${
|
|
isActive
|
|
? 'bg-white dark:bg-gray-700 text-teal-700 dark:text-teal-400 shadow-sm ring-1 ring-teal-300 dark:ring-teal-600'
|
|
: 'text-gray-500 dark:text-gray-400 hover:bg-white/50 dark:hover:bg-gray-700/50'
|
|
}`}
|
|
title={sub.name}
|
|
>
|
|
<span className="mr-1">{icon}</span>
|
|
Seite {sub.box_index + 1}
|
|
</button>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
}
|