Skip to content

Commit 849e7bc

Browse files
committed
feat(support): Enhance ticket status update with email notifications
- Add email notification when support ticket status changes - Retrieve user profile to personalize status update email - Implement email generation for ticket status transitions - Add error handling for email sending process - Improve status update API endpoint with more robust logic - Ensure email notifications are sent without blocking request processing
1 parent b1e31ea commit 849e7bc

File tree

1 file changed

+54
-8
lines changed
  • app/api/admin/support/tickets/[id]

1 file changed

+54
-8
lines changed

app/api/admin/support/tickets/[id]/route.ts

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NextRequest, NextResponse } from 'next/server'
22
import { createClient } from '@/lib/supabase/server'
3+
import { sendEmail, getStatusUpdateEmail } from '@/lib/email/support-emails'
34

45
// GET single ticket
56
export async function GET(
@@ -108,34 +109,79 @@ export async function PATCH(
108109
return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
109110
}
110111

111-
const { status } = await request.json()
112+
const { status: newStatus } = await request.json()
112113

113-
if (!status) {
114+
if (!newStatus) {
114115
return NextResponse.json({ error: 'Status is required' }, { status: 400 })
115116
}
116117

117118
const validStatuses = ['open', 'in_progress', 'resolved', 'closed']
118-
if (!validStatuses.includes(status)) {
119+
if (!validStatuses.includes(newStatus)) {
119120
return NextResponse.json({ error: 'Invalid status' }, { status: 400 })
120121
}
121122

123+
// Get current ticket to check old status
124+
const { data: currentTicket, error: currentTicketError } = await supabase
125+
.from('support_tickets')
126+
.select('status, user_id, subject')
127+
.eq('id', id)
128+
.single()
129+
130+
if (currentTicketError) {
131+
console.error('Error fetching current ticket:', currentTicketError)
132+
return NextResponse.json({ error: 'Ticket not found' }, { status: 404 })
133+
}
134+
135+
const oldStatus = currentTicket.status
136+
122137
// Update ticket status
123-
const { data: ticket, error } = await supabase
138+
const { data: updatedTicket, error: updateError } = await supabase
124139
.from('support_tickets')
125140
.update({
126-
status,
141+
status: newStatus,
127142
updated_at: new Date().toISOString()
128143
})
129144
.eq('id', id)
130145
.select()
131146
.single()
132147

133-
if (error) {
134-
console.error('Error updating ticket:', error)
148+
if (updateError) {
149+
console.error('Error updating ticket:', updateError)
135150
return NextResponse.json({ error: 'Failed to update ticket' }, { status: 500 })
136151
}
137152

138-
return NextResponse.json({ ticket, success: true })
153+
// Send email notification if status has changed
154+
if (newStatus !== oldStatus) {
155+
try {
156+
const { data: userProfile } = await supabase
157+
.from('profiles')
158+
.select('email, first_name')
159+
.eq('id', currentTicket.user_id)
160+
.single()
161+
162+
if (userProfile?.email) {
163+
const userName = userProfile.first_name || 'User'
164+
const { subject, html } = getStatusUpdateEmail({
165+
userName,
166+
ticketId: id,
167+
subject: currentTicket.subject,
168+
oldStatus,
169+
newStatus,
170+
})
171+
172+
await sendEmail({
173+
to: userProfile.email,
174+
subject,
175+
html,
176+
})
177+
}
178+
} catch (emailError) {
179+
console.error('Failed to send status update email:', emailError)
180+
// Do not fail the request if email fails, just log it
181+
}
182+
}
183+
184+
return NextResponse.json({ ticket: updatedTicket, success: true })
139185
} catch (error) {
140186
console.error('Error in PATCH ticket:', error)
141187
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })

0 commit comments

Comments
 (0)