diff --git a/apps/web/components/ui/sonner.tsx b/apps/web/components/ui/sonner.tsx new file mode 100644 index 0000000..2865367 --- /dev/null +++ b/apps/web/components/ui/sonner.tsx @@ -0,0 +1,35 @@ +"use client" + +import { useTheme } from "next-themes" +import { Toaster as Sonner } from "sonner" + +type ToasterProps = React.ComponentProps + +const Toaster = ({ ...props }: ToasterProps) => { + const { theme = "system" } = useTheme() + + return ( + + ) +} + +export { Toaster } diff --git a/apps/web/features/tickets/components/TicketAssignment.tsx b/apps/web/features/tickets/components/TicketAssignment.tsx index 964ee20..0dd8384 100644 --- a/apps/web/features/tickets/components/TicketAssignment.tsx +++ b/apps/web/features/tickets/components/TicketAssignment.tsx @@ -6,6 +6,8 @@ import { ticketService } from '../api/tickets.api'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; +import { toast } from '@/lib/toast'; +import { MESSAGES } from '@/lib/toast/messages'; interface Props { ticketId: string; @@ -16,18 +18,18 @@ export function TicketAssignment({ ticketId, currentAssignee }: Props) { const router = useRouter(); const [isAssigning, setIsAssigning] = useState(false); const [technicianId, setTechnicianId] = useState(''); - const [error, setError] = useState(null); const handleAssign = async () => { if (!technicianId) return; setIsAssigning(true); - setError(null); try { - await ticketService.assignTicket(ticketId, technicianId); + const apiCall = ticketService.assignTicket(ticketId, technicianId); + toast.promise(apiCall, MESSAGES.TICKETS.ASSIGN); + await apiCall; setTechnicianId(''); router.refresh(); } catch (err: any) { - setError(err.message || 'Failed to assign ticket'); + // Error feedback is handled by toast } finally { setIsAssigning(false); } @@ -35,12 +37,13 @@ export function TicketAssignment({ ticketId, currentAssignee }: Props) { const handleUnassign = async () => { setIsAssigning(true); - setError(null); try { - await ticketService.unassignTicket(ticketId); + const apiCall = ticketService.unassignTicket(ticketId); + toast.promise(apiCall, MESSAGES.TICKETS.UNASSIGN); + await apiCall; router.refresh(); } catch (err: any) { - setError(err.message || 'Failed to unassign ticket'); + // Error feedback is handled by toast } finally { setIsAssigning(false); } @@ -52,12 +55,6 @@ export function TicketAssignment({ ticketId, currentAssignee }: Props) { Assignment - {error && ( -
- {error} -
- )} - {currentAssignee ? (

diff --git a/apps/web/features/tickets/components/TicketWorkflow.tsx b/apps/web/features/tickets/components/TicketWorkflow.tsx index a0b3c8e..fad3bf4 100644 --- a/apps/web/features/tickets/components/TicketWorkflow.tsx +++ b/apps/web/features/tickets/components/TicketWorkflow.tsx @@ -6,6 +6,8 @@ import { ticketService } from '../api/tickets.api'; import { TicketStatus } from '../types'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; +import { toast } from '@/lib/toast'; +import { MESSAGES } from '@/lib/toast/messages'; interface Props { ticketId: string; @@ -15,7 +17,6 @@ interface Props { export function TicketWorkflow({ ticketId, currentStatus }: Props) { const router = useRouter(); const [isUpdating, setIsUpdating] = useState(false); - const [error, setError] = useState(null); const getAvailableTransitions = () => { // This replicates the backend ALLOWED_TRANSITIONS logic temporarily for UI purposes @@ -33,12 +34,13 @@ export function TicketWorkflow({ ticketId, currentStatus }: Props) { const handleStatusChange = async (newStatus: TicketStatus) => { setIsUpdating(true); - setError(null); try { - await ticketService.updateTicketStatus(ticketId, newStatus); + const apiCall = ticketService.updateTicketStatus(ticketId, newStatus); + toast.promise(apiCall, MESSAGES.TICKETS.STATUS_UPDATE); + await apiCall; router.refresh(); } catch (err: any) { - setError(err.message || 'Failed to update status'); + // Error feedback is handled by toast } finally { setIsUpdating(false); } @@ -54,12 +56,6 @@ export function TicketWorkflow({ ticketId, currentStatus }: Props) { Workflow Actions - {error && ( -

- {error} -
- )} -
{availableTransitions.map((status) => (