Phase 1: Station shell - /station route replaces /pos (with redirect) - Shared lock screen, activity tracking, auto-lock timer - Permission-gated tab bar (POS | Repairs | Lessons) - POSRegister embedded mode (skip lock/timer/topbar) - Sidebar navigates to /station Phase 2: Repairs station — front desk - Status bar with count badges per status group, clickable filters - Ticket queue panel with search and status filtering - Ticket detail panel with status progress, notes, photos, line items - Full stepped intake form: customer → item → problem/estimate → review - Service template quick-add for line items Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import { useState } from 'react'
|
|
import { RepairStatusBar } from './repair-status-bar'
|
|
import { RepairQueuePanel } from './repair-queue-panel'
|
|
import { RepairDetailPanel } from './repair-detail-panel'
|
|
import { RepairIntakeForm } from './repair-intake-form'
|
|
|
|
interface RepairDeskViewProps {
|
|
canEdit: boolean
|
|
}
|
|
|
|
export function RepairDeskView({ canEdit }: RepairDeskViewProps) {
|
|
const [selectedTicketId, setSelectedTicketId] = useState<string | null>(null)
|
|
const [intakeMode, setIntakeMode] = useState(false)
|
|
const [statusFilter, setStatusFilter] = useState<string[] | null>(null)
|
|
const [activeFilterLabel, setActiveFilterLabel] = useState<string | null>(null)
|
|
|
|
function handleFilterChange(statuses: string[] | null) {
|
|
setStatusFilter(statuses)
|
|
// Track which group label is active for the status bar highlight
|
|
if (!statuses) {
|
|
setActiveFilterLabel(null)
|
|
} else {
|
|
// Map statuses back to group label
|
|
const groups: Record<string, string> = {
|
|
new: 'New', in_transit: 'New', intake: 'New',
|
|
diagnosing: 'Diagnosing', pending_approval: 'Diagnosing',
|
|
approved: 'In Progress', in_progress: 'In Progress', pending_parts: 'In Progress',
|
|
ready: 'Ready',
|
|
}
|
|
setActiveFilterLabel(groups[statuses[0]] ?? null)
|
|
}
|
|
}
|
|
|
|
if (intakeMode) {
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
<RepairIntakeForm
|
|
onComplete={(ticketId) => {
|
|
setIntakeMode(false)
|
|
setSelectedTicketId(ticketId)
|
|
}}
|
|
onCancel={() => setIntakeMode(false)}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
<RepairStatusBar activeFilter={activeFilterLabel} onFilterChange={handleFilterChange} />
|
|
<div className="flex flex-1 min-h-0">
|
|
<div className="w-[35%] border-r border-border overflow-hidden">
|
|
<RepairQueuePanel
|
|
selectedTicketId={selectedTicketId}
|
|
onSelectTicket={setSelectedTicketId}
|
|
onNewIntake={() => setIntakeMode(true)}
|
|
statusFilter={statusFilter}
|
|
/>
|
|
</div>
|
|
<div className="w-[65%] overflow-hidden">
|
|
<RepairDetailPanel ticketId={selectedTicketId} canEdit={canEdit} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|