feat(frontend): add mid-session Copy for Ticket to navigation page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,8 @@ import { cn, safeGetItem, safeSetItem } from '@/lib/utils'
|
|||||||
import { MarkdownContent } from '@/components/ui/MarkdownContent'
|
import { MarkdownContent } from '@/components/ui/MarkdownContent'
|
||||||
import { CustomStepModal } from '@/components/step-library/CustomStepModal'
|
import { CustomStepModal } from '@/components/step-library/CustomStepModal'
|
||||||
import { PostStepActionModal, ContinuationModal, ForkTreeModal, ScratchpadSidebar, SessionOutcomeModal } from '@/components/session'
|
import { PostStepActionModal, ContinuationModal, ForkTreeModal, ScratchpadSidebar, SessionOutcomeModal } from '@/components/session'
|
||||||
import { Plus, CheckCircle, ArrowRight, Clock, Terminal, Clipboard, Check, HelpCircle } from 'lucide-react'
|
import { Plus, CheckCircle, ArrowRight, Clock, Terminal, Clipboard, Check, Copy, HelpCircle } from 'lucide-react'
|
||||||
|
import { toast } from '@/lib/toast'
|
||||||
import { Modal } from '@/components/common/Modal'
|
import { Modal } from '@/components/common/Modal'
|
||||||
|
|
||||||
interface LocationState {
|
interface LocationState {
|
||||||
@@ -45,6 +46,8 @@ export function TreeNavigationPage() {
|
|||||||
const [copiedCommand, setCopiedCommand] = useState<string | null>(null)
|
const [copiedCommand, setCopiedCommand] = useState<string | null>(null)
|
||||||
const [shortcutsModalOpen, setShortcutsModalOpen] = useState(false)
|
const [shortcutsModalOpen, setShortcutsModalOpen] = useState(false)
|
||||||
const [selectingOption, setSelectingOption] = useState<string | null>(null)
|
const [selectingOption, setSelectingOption] = useState<string | null>(null)
|
||||||
|
const [copiedForTicket, setCopiedForTicket] = useState(false)
|
||||||
|
const [isCopyingForTicket, setIsCopyingForTicket] = useState(false)
|
||||||
|
|
||||||
const handleCopyCommand = (text: string) => {
|
const handleCopyCommand = (text: string) => {
|
||||||
navigator.clipboard.writeText(text)
|
navigator.clipboard.writeText(text)
|
||||||
@@ -52,6 +55,29 @@ export function TreeNavigationPage() {
|
|||||||
setTimeout(() => setCopiedCommand(null), 2000)
|
setTimeout(() => setCopiedCommand(null), 2000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCopyForTicket = async () => {
|
||||||
|
if (!session || isCopyingForTicket) return
|
||||||
|
setIsCopyingForTicket(true)
|
||||||
|
try {
|
||||||
|
const content = await sessionsApi.export(session.id, {
|
||||||
|
format: 'psa',
|
||||||
|
include_timestamps: true,
|
||||||
|
include_tree_info: true,
|
||||||
|
})
|
||||||
|
if (content) {
|
||||||
|
await navigator.clipboard.writeText(content)
|
||||||
|
setCopiedForTicket(true)
|
||||||
|
setTimeout(() => setCopiedForTicket(false), 2000)
|
||||||
|
toast.success('Copied progress notes to clipboard')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Copy for ticket failed:', err)
|
||||||
|
toast.error('Failed to copy notes')
|
||||||
|
} finally {
|
||||||
|
setIsCopyingForTicket(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Session metadata (prefill from Repeat Last Session)
|
// Session metadata (prefill from Repeat Last Session)
|
||||||
const [ticketNumber, setTicketNumber] = useState<string>(locationState?.prefillTicketNumber || '')
|
const [ticketNumber, setTicketNumber] = useState<string>(locationState?.prefillTicketNumber || '')
|
||||||
const [clientName, setClientName] = useState<string>(locationState?.prefillClientName || '')
|
const [clientName, setClientName] = useState<string>(locationState?.prefillClientName || '')
|
||||||
@@ -549,12 +575,26 @@ export function TreeNavigationPage() {
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div className="flex items-center gap-2">
|
||||||
onClick={() => navigate('/sessions')}
|
<button
|
||||||
className="rounded-md px-3 py-1.5 text-sm text-white/50 hover:bg-white/[0.06] hover:text-white"
|
onClick={handleCopyForTicket}
|
||||||
>
|
disabled={isCopyingForTicket}
|
||||||
Exit
|
title="Copy progress notes for ticket"
|
||||||
</button>
|
className={cn(
|
||||||
|
'flex items-center gap-1.5 rounded-md border border-white/10 px-3 py-1.5 text-xs font-medium text-white/60',
|
||||||
|
'hover:bg-white/10 hover:text-white transition-colors disabled:opacity-50'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{copiedForTicket ? <Check className="h-3.5 w-3.5 text-emerald-400" /> : <Copy className="h-3.5 w-3.5" />}
|
||||||
|
{copiedForTicket ? 'Copied!' : 'Copy for Ticket'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => navigate('/sessions')}
|
||||||
|
className="rounded-md px-3 py-1.5 text-sm text-white/50 hover:bg-white/[0.06] hover:text-white"
|
||||||
|
>
|
||||||
|
Exit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Breadcrumb */}
|
{/* Breadcrumb */}
|
||||||
|
|||||||
Reference in New Issue
Block a user