feat: agent status badge + auto workstation detection in BookingDetailPanel
- Check localhost:9000 on panel open via getIdentity() - If local agent is running → use its workstation_id directly, no picker - If agent is offline → show subtle badge 'Агент не запущен · ключи недоступны' under tabs - If agent offline but multiple server-side encoders online → still show picker Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from '../../lib/utils'
|
||||
import type { Booking, Room } from '../../types'
|
||||
import { api, type BookingGuest, type BookingGuestPayload, type GuestApiType } from '../../lib/api'
|
||||
import { getIdentity, type AgentIdentity } from '../../lib/agent'
|
||||
|
||||
const fmtDate = (iso: string) =>
|
||||
new Intl.DateTimeFormat('ru-RU', { day: 'numeric', month: 'long' }).format(new Date(iso))
|
||||
@@ -146,6 +147,12 @@ export function BookingDetailPanel({ booking, room, rooms, allBookings, slug, on
|
||||
setEarlyOpen(false)
|
||||
}, [booking.id])
|
||||
|
||||
// Проверяем локальный агент (localhost:9000) при открытии панели
|
||||
useEffect(() => {
|
||||
setAgentIdentity('loading')
|
||||
getIdentity().then(identity => setAgentIdentity(identity))
|
||||
}, [booking.id])
|
||||
|
||||
// Parse ФИО string into form fields
|
||||
const parseFio = (val: string) => {
|
||||
const parts = val.trim().split(/\s+/)
|
||||
@@ -306,6 +313,7 @@ export function BookingDetailPanel({ booking, room, rooms, allBookings, slug, on
|
||||
const [cardEncoders, setCardEncoders] = useState<Array<{ id: string; name: string }>>([])
|
||||
const [cardEncoderPickerOpen, setCardEncoderPickerOpen] = useState(false)
|
||||
const [selectedEncoderId, setSelectedEncoderId] = useState('')
|
||||
const [agentIdentity, setAgentIdentity] = useState<AgentIdentity | null | 'loading'>('loading')
|
||||
|
||||
const freeRoomsForRelocate = (rooms ?? []).filter(r =>
|
||||
r.id !== booking.roomId &&
|
||||
@@ -400,7 +408,13 @@ export function BookingDetailPanel({ booking, room, rooms, allBookings, slug, on
|
||||
const handleIssueCard = async () => {
|
||||
if (!slug || cardIssuing) return
|
||||
|
||||
// Load available encoders
|
||||
// Если локальный агент запущен — используем его рабочее место напрямую
|
||||
if (agentIdentity && agentIdentity !== 'loading' && agentIdentity.workstation_id) {
|
||||
await doIssueCard(agentIdentity.workstation_id)
|
||||
return
|
||||
}
|
||||
|
||||
// Агент не запущен — ищем онлайн-рабочие места с энкодером через сервер
|
||||
let encoders: Array<{ id: string; name: string }> = []
|
||||
try {
|
||||
const wsList = await api.workstations.list(slug)
|
||||
@@ -415,12 +429,11 @@ export function BookingDetailPanel({ booking, room, rooms, allBookings, slug, on
|
||||
}
|
||||
|
||||
if (encoders.length === 1) {
|
||||
// Auto-issue
|
||||
await doIssueCard(encoders[0].id)
|
||||
return
|
||||
}
|
||||
|
||||
// Multiple encoders — show picker
|
||||
// Несколько энкодеров — показываем выбор
|
||||
setCardEncoders(encoders)
|
||||
setSelectedEncoderId(encoders[0].id)
|
||||
setCardEncoderPickerOpen(true)
|
||||
@@ -552,6 +565,16 @@ export function BookingDetailPanel({ booking, room, rooms, allBookings, slug, on
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Статус агента — показываем только если агент не запущен */}
|
||||
{agentIdentity === null && (
|
||||
<div className="flex items-center gap-1.5 mt-2 px-1">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-slate-500 shrink-0" />
|
||||
<span className="text-[11px] text-slate-400 dark:text-slate-500">
|
||||
Агент не запущен · ключи недоступны
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Tab content */}
|
||||
|
||||
Reference in New Issue
Block a user