diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index c9de44f..f698e7c 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -17,8 +17,8 @@ import { XIcon, } from "lucide-react"; import { formatDistanceToNow } from "date-fns"; -import { createTicket, getCustomFields, getLifecycles, getQueueCustomFields, getQueues, getTickets, getUsers, getViews, createView, deleteView, getDashboards } from "@/lib/api"; -import type { CustomField, Lifecycle, Queue, QueueCustomField, SavedView, Ticket, User } from "@/lib/types"; +import { createTicket, getCustomFields, getLifecycles, getQueueCustomFields, getQueues, getTickets, getUsers, getViews, createView, deleteView, getDashboards, getTicketTransactions, updateTicket } from "@/lib/api"; +import type { CustomField, Lifecycle, Queue, QueueCustomField, SavedView, Ticket, Transaction, User } from "@/lib/types"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -148,6 +148,7 @@ function TicketWorkbenchContent() { const [refreshing, setRefreshing] = useState(false); const [error, setError] = useState(null); const [selectedId, setSelectedId] = useState(null); + const [selectedTxs, setSelectedTxs] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [filters, setFilters] = useState([]); @@ -442,7 +443,28 @@ function TicketWorkbenchContent() { }, [clock, filters, queues, routeQueue, searchQuery, sortKey, tickets, view]); const selectedTicket = - filteredTickets.find((ticket) => ticket.id === selectedId) ?? filteredTickets[0] ?? null; + filteredTickets.find((ticket) => ticket.id === selectedId) ?? null; + + // Fetch transactions when selection changes + useEffect(() => { + if (!selectedTicket) { setSelectedTxs([]); return; } + getTicketTransactions(selectedTicket.id).then(({ data }) => setSelectedTxs(data ?? [])); + }, [selectedTicket?.id]); + + const handleQuickStatus = async (ticketId: number, newStatus: string) => { + const { data } = await updateTicket(ticketId, { status: newStatus }); + if (data) { + setTickets((prev) => prev.map((t) => (t.id === ticketId ? data.ticket : t))); + getTicketTransactions(ticketId).then(({ data: txs }) => setSelectedTxs(txs ?? [])); + } + }; + + const handleQuickAssign = async (ticketId: number) => { + const { data } = await updateTicket(ticketId, { owner_id: users[0]?.id ?? null }); + if (data) { + setTickets((prev) => prev.map((t) => (t.id === ticketId ? data.ticket : t))); + } + }; const visibleTitle = routeQueue ? queueName(queues, routeQueue) : VIEW_LABELS[view] ?? "All tickets"; @@ -776,66 +798,123 @@ function TicketWorkbenchContent() { diff --git a/web/src/components/app-shell.tsx b/web/src/components/app-shell.tsx index bb4932b..7777e06 100644 --- a/web/src/components/app-shell.tsx +++ b/web/src/components/app-shell.tsx @@ -162,8 +162,8 @@ function SidebarNav() { const views = [ { label: "All tickets", - href: "/", - param: null, + href: "/?view=all", + param: "all", count: counts.all, icon: LayoutGridIcon, },