diff --git a/app/(app)/tickets/page.tsx b/app/(app)/tickets/page.tsx index 41cc7a6..1c6cdf4 100644 --- a/app/(app)/tickets/page.tsx +++ b/app/(app)/tickets/page.tsx @@ -2,7 +2,8 @@ import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; -import { RefreshCw, Ticket, Plus, Send } from "lucide-react"; +import { RefreshCw, Ticket, Plus, Send, RotateCcw, User } from "lucide-react"; +import { useAuth } from "@/contexts/AuthContext"; import { Card, CardContent, CardHeader } from "@/components/ui/Card"; import { Table, TableHead, TableBody, TableRow, Th, Td, EmptyState } from "@/components/ui/Table"; import { Badge } from "@/components/ui/Badge"; @@ -34,11 +35,20 @@ const priorityVariant: Record = { const statusFilters = ["", "OPEN", "IN_PROGRESS", "RESOLVED", "CLOSED"]; const typeFilters = ["", "SUPPORT", "BILLING", "INSTALLATION"]; +// Previous status mapping (revert flow) +const prevStatus: Record = { + CLOSED: "RESOLVED", + RESOLVED: "IN_PROGRESS", + IN_PROGRESS: "OPEN", +}; + export default function TicketsPage() { const qc = useQueryClient(); + const { user } = useAuth(); const [search, setSearch] = useState(""); const [statusFilter, setStatusFilter] = useState(""); const [typeFilter, setTypeFilter] = useState(""); + const [assignedToMe, setAssignedToMe] = useState(false); const [page, setPage] = useState(1); const [selected, setSelected] = useState(null); const [showCreate, setShowCreate] = useState(false); @@ -46,12 +56,13 @@ export default function TicketsPage() { const [newForm, setNewForm] = useState({ subject: "", description: "", type: "SUPPORT", priority: "NORMAL", clientSearch: "", clientId: "" }); const { data, isLoading, refetch } = useQuery>({ - queryKey: ["tickets", search, statusFilter, typeFilter, page], + queryKey: ["tickets", search, statusFilter, typeFilter, assignedToMe, page], queryFn: async () => { const params = new URLSearchParams({ page: String(page), limit: "20" }); if (search) params.set("search", search); if (statusFilter) params.set("status", statusFilter); if (typeFilter) params.set("type", typeFilter); + if (assignedToMe && user?.id) params.set("assignedToId", user.id); const res = await api.get>(`/api/v1/tickets?${params}`); return res.data; }, @@ -109,6 +120,14 @@ export default function TicketsPage() { onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed to create ticket"), }); + const revertStatus = useMutation({ + mutationFn: async ({ id, status }: { id: string; status: string }) => { + await api.patch(`/api/v1/tickets/${id}`, { status }); + }, + onSuccess: () => { toast.success("Status reverted"); refetch(); refetchDetail(); qc.invalidateQueries({ queryKey: ["ticket"] }); }, + onError: (e: any) => toast.error(e.response?.data?.message ?? "Failed"), + }); + const tickets = data?.data ?? []; const total = data?.meta?.total ?? 0; const detail = ticketDetail ?? selected; @@ -150,6 +169,13 @@ export default function TicketsPage() { ))} + @@ -203,11 +229,18 @@ export default function TicketsPage() { {/* Status actions */} - {nextStatus[detail.status] && ( - - )} +
+ {nextStatus[detail.status] && ( + + )} + {prevStatus[detail.status] && ( + + )} +
{/* Comments */}