feat(psa): ticket queue dashboard with board selector and session auto-start
- Add PSABoard type + list_boards() to CW provider (cached 1h) - Extend search_tickets with assigned_to_me, unassigned, board_ids, page, page_size - New GET /integrations/psa/boards endpoint - New TicketQueue dashboard component: My Tickets / Unassigned tabs, multi-select board filter, Load more pagination, Start Session per ticket - Add TicketQueue to QuickStartPage after active sessions - FlowPilotSessionPage auto-starts with ticket context when navigated from TicketQueue (psaTicketId + psaTicket in location.state) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,8 @@ import { StatusUpdateModal } from '@/components/flowpilot/StatusUpdateModal'
|
||||
import { HandoffModal } from '@/components/session/HandoffModal'
|
||||
import { handoffsApi } from '@/api/handoffs'
|
||||
import { aiSessionsApi } from '@/api'
|
||||
import { integrationsApi } from '@/api/integrations'
|
||||
import type { PSATicketInfo } from '@/types/integrations'
|
||||
import { toast } from '@/lib/toast'
|
||||
|
||||
export default function FlowPilotSessionPage() {
|
||||
@@ -17,10 +19,13 @@ export default function FlowPilotSessionPage() {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const prefill = (location.state as { prefill?: string } | null)?.prefill || ''
|
||||
const psaTicketId = (location.state as any)?.psaTicketId as string | undefined
|
||||
const psaTicket = (location.state as any)?.psaTicket as PSATicketInfo | undefined
|
||||
const isPickup = searchParams.get('pickup') === 'true'
|
||||
const fp = useFlowPilotSession()
|
||||
const branching = useBranching()
|
||||
const prefillHandledRef = useRef(false)
|
||||
const psaTicketHandledRef = useRef(false)
|
||||
const [showOverflow, setShowOverflow] = useState(false)
|
||||
const [showResolve, setShowResolve] = useState(false)
|
||||
const [showEscalate, setShowEscalate] = useState(false)
|
||||
@@ -44,6 +49,30 @@ export default function FlowPilotSessionPage() {
|
||||
fp.startSession({ intake_type: 'free_text', intake_content: { text: prefill } })
|
||||
}
|
||||
}, [prefill, sessionId, fp.session, fp.isLoading]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Auto-start when navigating from TicketQueue with a PSA ticket
|
||||
useEffect(() => {
|
||||
if (psaTicketId && psaTicket && !psaTicketHandledRef.current && !sessionId && !fp.session && !fp.isLoading) {
|
||||
psaTicketHandledRef.current = true
|
||||
integrationsApi.getConnection().then((conn) => {
|
||||
if (conn?.id) {
|
||||
fp.startSession({
|
||||
intake_type: 'psa_ticket',
|
||||
intake_content: {
|
||||
ticket_data: {
|
||||
summary: psaTicket.summary,
|
||||
company: psaTicket.company_name,
|
||||
priority: psaTicket.priority_name,
|
||||
},
|
||||
},
|
||||
psa_ticket_id: psaTicketId,
|
||||
psa_connection_id: conn.id,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [psaTicketId, psaTicket, sessionId, fp.session, fp.isLoading]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const [pickingUp, setPickingUp] = useState(false)
|
||||
|
||||
// Load existing session if ID in URL
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useAuthStore } from '@/store/authStore'
|
||||
import { StartSessionInput } from '@/components/dashboard/StartSessionInput'
|
||||
import { PendingEscalations } from '@/components/dashboard/PendingEscalations'
|
||||
import { ActiveFlowPilotSessions } from '@/components/dashboard/ActiveFlowPilotSessions'
|
||||
import { TicketQueue } from '@/components/dashboard/TicketQueue'
|
||||
import { PerformanceCards } from '@/components/dashboard/PerformanceCards'
|
||||
import { KnowledgeBaseCards } from '@/components/dashboard/KnowledgeBaseCards'
|
||||
import { TeamSummary } from '@/components/dashboard/TeamSummary'
|
||||
@@ -59,6 +60,11 @@ export function QuickStartPage() {
|
||||
<ActiveFlowPilotSessions />
|
||||
</div>
|
||||
|
||||
{/* Ticket Queue (auto-hides if no PSA connection) */}
|
||||
<div className="mt-8">
|
||||
<TicketQueue />
|
||||
</div>
|
||||
|
||||
{/* Dashboard — always visible */}
|
||||
<div className="mt-10">
|
||||
<SectionLabel>Dashboard</SectionLabel>
|
||||
|
||||
Reference in New Issue
Block a user