import React, { useState, useEffect } from 'react'; import { motion } from 'framer-motion'; import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card"; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { useToast } from "@/components/ui/use-toast"; import { supabase } from '@/lib/supabaseClient'; import { MessageSquare, Plus, Send, Clock, CheckCircle, AlertCircle, X, ChevronDown, ChevronUp, RefreshCw } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { Separator } from '@/components/ui/separator'; const SupportTicketComponent = ({ session }) => { const { toast } = useToast(); const [tickets, setTickets] = useState([]); const [loading, setLoading] = useState(true); const [creating, setCreating] = useState(false); const [submitting, setSubmitting] = useState(false); const [expandedTicket, setExpandedTicket] = useState(null); const [newMessage, setNewMessage] = useState(''); const [newTicket, setNewTicket] = useState({ subject: '', message: '', order_id: '' }); // Mock ticket data - in a real app, this would come from Supabase const mockTickets = [ { id: 'TKT-001', subject: 'Order Delivery Delay', status: 'Open', created_at: '2023-11-15T10:30:00', updated_at: '2023-11-15T14:45:00', messages: [ { id: 1, sender: 'user', message: 'My order #ORD-001 was supposed to be delivered yesterday but I haven\'t received it yet. Can you please check the status?', timestamp: '2023-11-15T10:30:00' }, { id: 2, sender: 'support', message: 'Thank you for reaching out. I apologize for the delay. I\'ve checked your order and there seems to be a slight delay with the courier. Your package is expected to be delivered by tomorrow. We\'ll keep you updated.', timestamp: '2023-11-15T14:45:00' } ] }, { id: 'TKT-002', subject: 'Product Quality Issue', status: 'Closed', created_at: '2023-10-28T09:15:00', updated_at: '2023-10-30T11:20:00', messages: [ { id: 1, sender: 'user', message: 'I received my Garam Masala but the packaging was damaged and some of the product had spilled.', timestamp: '2023-10-28T09:15:00' }, { id: 2, sender: 'support', message: 'I\'m sorry to hear about the damaged packaging. We take product quality very seriously. Could you please send a photo of the damaged package?', timestamp: '2023-10-28T15:30:00' }, { id: 3, sender: 'user', message: 'I\'ve sent the photos to your email address.', timestamp: '2023-10-29T10:45:00' }, { id: 4, sender: 'support', message: 'Thank you for the photos. We\'ve processed a replacement order for you which will be shipped today. You should receive it within 3-5 business days. We\'ve also added a complimentary sample of our new Chat Masala as a token of apology for the inconvenience.', timestamp: '2023-10-29T14:20:00' }, { id: 5, sender: 'user', message: 'Thank you for the quick resolution! Looking forward to trying the Chat Masala.', timestamp: '2023-10-30T09:10:00' }, { id: 6, sender: 'support', message: 'You\'re welcome! We\'re glad we could resolve this to your satisfaction. Please let us know if you need anything else. Enjoy the Chat Masala!', timestamp: '2023-10-30T11:20:00' } ] } ]; useEffect(() => { // In a real app, fetch tickets from Supabase // For now, we'll use mock data const fetchTickets = async () => { try { setLoading(true); // Simulate API call delay setTimeout(() => { setTickets(mockTickets); setLoading(false); }, 1000); // In a real implementation, you would fetch from Supabase: // const { data, error } = await supabase // .from('support_tickets') // .select('*') // .eq('user_id', session.user.id) // .order('created_at', { ascending: false }); // // if (error) throw error; // setTickets(data || []); } catch (error) { console.error('Error fetching tickets:', error); toast({ title: 'Error', description: 'Failed to load support tickets', variant: 'destructive', }); } finally { setLoading(false); } }; if (session) { fetchTickets(); } }, [session, toast]); const handleCreateTicket = async (e) => { e.preventDefault(); try { setSubmitting(true); // Validate form if (!newTicket.subject || !newTicket.message) { toast({ title: 'Missing Information', description: 'Please fill in all required fields', variant: 'destructive', }); setSubmitting(false); return; } // In a real app, create ticket in Supabase // For now, simulate API call and add to local state setTimeout(() => { const newTicketObj = { id: `TKT-${Math.floor(Math.random() * 1000).toString().padStart(3, '0')}`, subject: newTicket.subject, status: 'Open', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), messages: [ { id: 1, sender: 'user', message: newTicket.message, timestamp: new Date().toISOString() } ] }; setTickets([newTicketObj, ...tickets]); setNewTicket({ subject: '', message: '', order_id: '' }); setCreating(false); setSubmitting(false); toast({ title: 'Ticket Created', description: 'Your support ticket has been successfully created', className: 'toast-success-theme', }); }, 1500); // In a real implementation: // const { data, error } = await supabase // .from('support_tickets') // .insert([{ // user_id: session.user.id, // subject: newTicket.subject, // status: 'Open', // order_id: newTicket.order_id || null // }]) // .select(); // // if (error) throw error; // // // Add initial message // const { error: messageError } = await supabase // .from('ticket_messages') // .insert([{ // ticket_id: data[0].id, // user_id: session.user.id, // message: newTicket.message, // is_from_support: false // }]); // // if (messageError) throw messageError; } catch (error) { console.error('Error creating ticket:', error); toast({ title: 'Error', description: 'Failed to create support ticket', variant: 'destructive', }); } finally { setSubmitting(false); } }; const handleSendMessage = async (ticketId) => { if (!newMessage.trim()) return; try { setSubmitting(true); // In a real app, add message to Supabase // For now, update local state setTimeout(() => { const updatedTickets = tickets.map(ticket => { if (ticket.id === ticketId) { const updatedMessages = [ ...ticket.messages, { id: ticket.messages.length + 1, sender: 'user', message: newMessage, timestamp: new Date().toISOString() } ]; return { ...ticket, messages: updatedMessages, updated_at: new Date().toISOString() }; } return ticket; }); setTickets(updatedTickets); setNewMessage(''); setSubmitting(false); // Simulate support response after 3 seconds setTimeout(() => { const updatedTicketsWithResponse = tickets.map(ticket => { if (ticket.id === ticketId) { const updatedMessages = [ ...ticket.messages, { id: ticket.messages.length + 1, sender: 'user', message: newMessage, timestamp: new Date().toISOString() }, { id: ticket.messages.length + 2, sender: 'support', message: 'Thank you for your message. Our support team will get back to you shortly.', timestamp: new Date(Date.now() + 5000).toISOString() } ]; return { ...ticket, messages: updatedMessages, updated_at: new Date(Date.now() + 5000).toISOString() }; } return ticket; }); setTickets(updatedTicketsWithResponse); }, 3000); }, 1000); // In a real implementation: // const { error } = await supabase // .from('ticket_messages') // .insert([{ // ticket_id: ticketId, // user_id: session.user.id, // message: newMessage, // is_from_support: false // }]); // // if (error) throw error; // // // Update ticket updated_at timestamp // await supabase // .from('support_tickets') // .update({ updated_at: new Date() }) // .eq('id', ticketId); } catch (error) { console.error('Error sending message:', error); toast({ title: 'Error', description: 'Failed to send message', variant: 'destructive', }); } finally { setSubmitting(false); } }; const formatDate = (dateString) => { const options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }; return new Date(dateString).toLocaleDateString('en-US', options); }; const getStatusColor = (status) => { switch (status.toLowerCase()) { case 'open': return 'bg-green-100 text-green-800'; case 'closed': return 'bg-stone-100 text-stone-800'; case 'pending': return 'bg-amber-100 text-amber-800'; default: return 'bg-blue-100 text-blue-800'; } }; const toggleTicket = (ticketId) => { setExpandedTicket(expandedTicket === ticketId ? null : ticketId); }; return (

Support Tickets

{!creating && ( )}
{creating && ( Create New Support Ticket Please provide details about your issue or question
setNewTicket({...newTicket, subject: e.target.value})} className="mt-1 bg-white border-amber-200 focus:border-amber-600" placeholder="Brief description of your issue" required />
setNewTicket({...newTicket, order_id: e.target.value})} className="mt-1 bg-white border-amber-200 focus:border-amber-600" placeholder="e.g. ORD-001" />