Skip to content

Commit 3915f06

Browse files
author
Gerome El-assaad
committed
update /api/chat/..
1 parent 61aee52 commit 3915f06

File tree

12 files changed

+381
-140
lines changed

12 files changed

+381
-140
lines changed

app/api/chat/analytics/route.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { createServerClient } from '@/lib/supabase-server'
32
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
46

57
export async function GET(request: NextRequest) {
68
try {
7-
const supabase = createServerClient()
8-
const { data: { user }, error: authError } = await supabase.auth.getUser()
9-
10-
if (authError || !user) {
11-
return NextResponse.json(
12-
{ error: 'Unauthorized' },
13-
{ status: 401 }
14-
)
15-
}
9+
const { user, error } = await authenticateUser()
10+
if (error) return error
1611

1712
// Get user chat summary
1813
const summary = await ChatPersistence.getUserSummary(user.id)
@@ -31,15 +26,8 @@ export async function GET(request: NextRequest) {
3126

3227
export async function DELETE(request: NextRequest) {
3328
try {
34-
const supabase = createServerClient()
35-
const { data: { user }, error: authError } = await supabase.auth.getUser()
36-
37-
if (authError || !user) {
38-
return NextResponse.json(
39-
{ error: 'Unauthorized' },
40-
{ status: 401 }
41-
)
42-
}
29+
const { user, error } = await authenticateUser()
30+
if (error) return error
4331

4432
const { searchParams } = new URL(request.url)
4533
const daysOld = parseInt(searchParams.get('daysOld') || '90')

app/api/chat/export/route.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { createServerClient } from '@/lib/supabase-server'
32
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
46

57
export async function GET(request: NextRequest) {
68
try {
7-
const supabase = createServerClient()
8-
const { data: { user }, error: authError } = await supabase.auth.getUser()
9-
10-
if (authError || !user) {
11-
return NextResponse.json(
12-
{ error: 'Unauthorized' },
13-
{ status: 401 }
14-
)
15-
}
9+
const { user, error } = await authenticateUser()
10+
if (error) return error
1611

1712
const { searchParams } = new URL(request.url)
1813
const format = searchParams.get('format') || 'json'
@@ -26,6 +21,9 @@ export async function GET(request: NextRequest) {
2621

2722
// Export user's chat data
2823
const { sessions, messages } = await ChatPersistence.exportUserData(user.id)
24+
25+
// Generate export date once for consistency
26+
const exportDate = new Date().toISOString().split('T')[0]
2927

3028
if (format === 'json') {
3129
const exportData = {
@@ -40,25 +38,32 @@ export async function GET(request: NextRequest) {
4038
return new NextResponse(JSON.stringify(exportData, null, 2), {
4139
headers: {
4240
'Content-Type': 'application/json',
43-
'Content-Disposition': `attachment; filename="chat-export-${user.id}-${new Date().toISOString().split('T')[0]}.json"`,
41+
'Content-Disposition': `attachment; filename="chat-export-${user.id}-${exportDate}.json"`,
4442
},
4543
})
4644
}
4745

4846
if (format === 'csv') {
47+
// Helper function to properly escape and quote CSV fields
48+
const escapeCsvField = (field: string): string => {
49+
if (!field) return '""'
50+
// Quote the field and escape any quotes within it
51+
return `"${field.replace(/"/g, '""')}"`
52+
}
53+
4954
// Convert to CSV format
5055
const csvLines = ['Session ID,Timestamp,Role,Content,Model,Template']
5156

5257
sessions.forEach(session => {
5358
const sessionMessages = messages[session.sessionId] || []
5459
sessionMessages.forEach(message => {
5560
const csvLine = [
56-
session.sessionId,
57-
message.timestamp,
58-
message.role,
59-
`"${message.content.replace(/"/g, '""')}"`, // Escape quotes
60-
message.model || '',
61-
message.template || ''
61+
escapeCsvField(session.sessionId),
62+
escapeCsvField(message.timestamp),
63+
escapeCsvField(message.role),
64+
escapeCsvField(message.content),
65+
escapeCsvField(message.model || ''),
66+
escapeCsvField(message.template || '')
6267
].join(',')
6368
csvLines.push(csvLine)
6469
})
@@ -69,7 +74,7 @@ export async function GET(request: NextRequest) {
6974
return new NextResponse(csvContent, {
7075
headers: {
7176
'Content-Type': 'text/csv',
72-
'Content-Disposition': `attachment; filename="chat-export-${user.id}-${new Date().toISOString().split('T')[0]}.csv"`,
77+
'Content-Disposition': `attachment; filename="chat-export-${user.id}-${exportDate}.csv"`,
7378
},
7479
})
7580
}

app/api/chat/search/route.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { createServerClient } from '@/lib/supabase-server'
32
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
46

57
export async function GET(request: NextRequest) {
68
try {
7-
const supabase = createServerClient()
8-
const { data: { user }, error: authError } = await supabase.auth.getUser()
9-
10-
if (authError || !user) {
11-
return NextResponse.json(
12-
{ error: 'Unauthorized' },
13-
{ status: 401 }
14-
)
15-
}
9+
const { user, error } = await authenticateUser()
10+
if (error) return error
1611

1712
const { searchParams } = new URL(request.url)
1813
const query = searchParams.get('q')

app/api/chat/sessions/[sessionId]/messages/route.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { createServerClient } from '@/lib/supabase-server'
32
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
46

57
interface RouteParams {
68
params: {
@@ -10,15 +12,8 @@ interface RouteParams {
1012

1113
export async function GET(request: NextRequest, { params }: RouteParams) {
1214
try {
13-
const supabase = createServerClient()
14-
const { data: { user }, error: authError } = await supabase.auth.getUser()
15-
16-
if (authError || !user) {
17-
return NextResponse.json(
18-
{ error: 'Unauthorized' },
19-
{ status: 401 }
20-
)
21-
}
15+
const { user, error } = await authenticateUser()
16+
if (error) return error
2217

2318
const { sessionId } = params
2419

@@ -46,15 +41,8 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
4641

4742
export async function POST(request: NextRequest, { params }: RouteParams) {
4843
try {
49-
const supabase = createServerClient()
50-
const { data: { user }, error: authError } = await supabase.auth.getUser()
51-
52-
if (authError || !user) {
53-
return NextResponse.json(
54-
{ error: 'Unauthorized' },
55-
{ status: 401 }
56-
)
57-
}
44+
const { user, error } = await authenticateUser()
45+
if (error) return error
5846

5947
const { sessionId } = params
6048
const body = await request.json()

app/api/chat/sessions/[sessionId]/route.ts

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { createServerClient } from '@/lib/supabase-server'
32
import { ChatPersistence } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
46

57
interface RouteParams {
68
params: {
@@ -10,15 +12,8 @@ interface RouteParams {
1012

1113
export async function GET(request: NextRequest, { params }: RouteParams) {
1214
try {
13-
const supabase = createServerClient()
14-
const { data: { user }, error: authError } = await supabase.auth.getUser()
15-
16-
if (authError || !user) {
17-
return NextResponse.json(
18-
{ error: 'Unauthorized' },
19-
{ status: 401 }
20-
)
21-
}
15+
const { user, error } = await authenticateUser()
16+
if (error) return error
2217

2318
const { sessionId } = params
2419

@@ -49,15 +44,8 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
4944

5045
export async function PATCH(request: NextRequest, { params }: RouteParams) {
5146
try {
52-
const supabase = createServerClient()
53-
const { data: { user }, error: authError } = await supabase.auth.getUser()
54-
55-
if (authError || !user) {
56-
return NextResponse.json(
57-
{ error: 'Unauthorized' },
58-
{ status: 401 }
59-
)
60-
}
47+
const { user, error } = await authenticateUser()
48+
if (error) return error
6149

6250
const { sessionId } = params
6351
const body = await request.json()
@@ -97,15 +85,8 @@ export async function PATCH(request: NextRequest, { params }: RouteParams) {
9785

9886
export async function DELETE(request: NextRequest, { params }: RouteParams) {
9987
try {
100-
const supabase = createServerClient()
101-
const { data: { user }, error: authError } = await supabase.auth.getUser()
102-
103-
if (authError || !user) {
104-
return NextResponse.json(
105-
{ error: 'Unauthorized' },
106-
{ status: 401 }
107-
)
108-
}
88+
const { user, error } = await authenticateUser()
89+
if (error) return error
10990

11091
const { sessionId } = params
11192

app/api/chat/sessions/route.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import { NextRequest, NextResponse } from 'next/server'
2-
import { createServerClient } from '@/lib/supabase-server'
32
import { ChatPersistence, ChatSession } from '@/lib/chat-persistence'
3+
import { authenticateUser } from '@/lib/auth-utils'
4+
5+
export const runtime = 'nodejs'
46

57
export async function GET(request: NextRequest) {
68
try {
7-
const supabase = createServerClient()
8-
const { data: { user }, error: authError } = await supabase.auth.getUser()
9-
10-
if (authError || !user) {
11-
return NextResponse.json(
12-
{ error: 'Unauthorized' },
13-
{ status: 401 }
14-
)
15-
}
9+
const { user, error } = await authenticateUser()
10+
if (error) return error
1611

1712
const { searchParams } = new URL(request.url)
1813
const limit = parseInt(searchParams.get('limit') || '50')
@@ -34,15 +29,8 @@ export async function GET(request: NextRequest) {
3429

3530
export async function POST(request: NextRequest) {
3631
try {
37-
const supabase = createServerClient()
38-
const { data: { user }, error: authError } = await supabase.auth.getUser()
39-
40-
if (authError || !user) {
41-
return NextResponse.json(
42-
{ error: 'Unauthorized' },
43-
{ status: 401 }
44-
)
45-
}
32+
const { user, error } = await authenticateUser()
33+
if (error) return error
4634

4735
const body = await request.json()
4836
const { teamId, title, model, template, initialMessage } = body

components/chat-history.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export function ChatHistory({
6161
const [searchQuery, setSearchQuery] = useState('')
6262
const [editingSession, setEditingSession] = useState<string | null>(null)
6363
const [editTitle, setEditTitle] = useState('')
64+
const [deletingSession, setDeletingSession] = useState<ChatSession | null>(null)
6465

6566
const filteredSessions = sessions.filter(session =>
6667
session.title?.toLowerCase().includes(searchQuery.toLowerCase()) ||
@@ -109,6 +110,13 @@ export function ChatHistory({
109110
setEditTitle(session.title || '')
110111
}
111112

113+
const handleDeleteConfirm = () => {
114+
if (deletingSession) {
115+
onSessionDelete(deletingSession.sessionId)
116+
setDeletingSession(null)
117+
}
118+
}
119+
112120
const SessionItem = ({ session }: { session: ChatSession }) => {
113121
const isActive = session.sessionId === currentSessionId
114122
const isEditing = editingSession === session.sessionId
@@ -178,7 +186,10 @@ export function ChatHistory({
178186
<Edit2 className="h-4 w-4 mr-2" />
179187
Rename
180188
</DropdownMenuItem>
181-
<DropdownMenuItem onClick={() => onSessionDelete(session.sessionId)}>
189+
<DropdownMenuItem
190+
onClick={() => setDeletingSession(session)}
191+
className="text-destructive focus:text-destructive"
192+
>
182193
<Trash2 className="h-4 w-4 mr-2" />
183194
Delete
184195
</DropdownMenuItem>
@@ -294,6 +305,30 @@ export function ChatHistory({
294305
</DropdownMenu>
295306
</div>
296307
</div>
308+
309+
{/* Delete Confirmation Dialog */}
310+
<AlertDialog open={!!deletingSession} onOpenChange={() => setDeletingSession(null)}>
311+
<AlertDialogContent>
312+
<AlertDialogHeader>
313+
<AlertDialogTitle>Delete Chat Session</AlertDialogTitle>
314+
<AlertDialogDescription>
315+
Are you sure you want to delete &ldquo;{deletingSession?.title || 'Untitled Chat'}&rdquo;?
316+
This action cannot be undone and will permanently delete all messages in this chat session.
317+
</AlertDialogDescription>
318+
</AlertDialogHeader>
319+
<AlertDialogFooter>
320+
<AlertDialogCancel onClick={() => setDeletingSession(null)}>
321+
Cancel
322+
</AlertDialogCancel>
323+
<AlertDialogAction
324+
onClick={handleDeleteConfirm}
325+
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
326+
>
327+
Delete
328+
</AlertDialogAction>
329+
</AlertDialogFooter>
330+
</AlertDialogContent>
331+
</AlertDialog>
297332
</div>
298333
)
299334
}

0 commit comments

Comments
 (0)