initial commit
This commit is contained in:
142
app/api/topics/route.ts
Normal file
142
app/api/topics/route.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import connectDB from '@/lib/mongodb'
|
||||
import TopicModel, { transformToTopics } from '@/models/topic'
|
||||
import { authMiddleware } from '@/lib/auth-middleware'
|
||||
import { ZodError } from 'zod'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
await connectDB()
|
||||
const searchParams = request.nextUrl.searchParams
|
||||
const page = parseInt(searchParams.get('page') || '1')
|
||||
const limit = parseInt(searchParams.get('limit') || '10')
|
||||
const search = searchParams.get('q') || ''
|
||||
const tag = searchParams.get('tag') || ''
|
||||
const authorId = searchParams.get('authorId') || '' // For filtering by user's topics
|
||||
const includeDrafts = searchParams.get('includeDrafts') === 'true' // For user's own topics
|
||||
const fetchAll = searchParams.get('fetchAll') // Admin panel support
|
||||
const skip = (page - 1) * limit
|
||||
|
||||
// Build query based on parameters
|
||||
const query: any = {}
|
||||
|
||||
// Authentication check for private operations (drafts or admin)
|
||||
let user = null
|
||||
try {
|
||||
user = await authMiddleware(request)
|
||||
} catch (error) {
|
||||
// Non-authenticated request - that's okay for public topic listing
|
||||
}
|
||||
|
||||
// If requesting user's own topics with drafts, verify authentication
|
||||
if (includeDrafts && !user) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: { message: 'Authentication required to view drafts', code: 'AUTH_REQUIRED' },
|
||||
},
|
||||
{ status: 401 }
|
||||
)
|
||||
}
|
||||
|
||||
// Filter by author if specified
|
||||
if (authorId) {
|
||||
query.authorId = authorId
|
||||
}
|
||||
|
||||
// Handle draft filtering
|
||||
if (fetchAll === 'true') {
|
||||
// Admin panel - show all posts (drafts and published)
|
||||
// No draft filtering applied
|
||||
} else if (includeDrafts && user && (authorId === user.id || !authorId)) {
|
||||
// User requesting their own topics (including drafts)
|
||||
if (!authorId) {
|
||||
query.authorId = user.id
|
||||
}
|
||||
} else {
|
||||
// Public topic listing - only published topics
|
||||
query.isDraft = false
|
||||
}
|
||||
|
||||
// Search functionality
|
||||
if (search) {
|
||||
query.$or = [
|
||||
{ title: { $regex: search, $options: 'i' } },
|
||||
{ excerpt: { $regex: search, $options: 'i' } },
|
||||
{ content: { $regex: search, $options: 'i' } },
|
||||
]
|
||||
}
|
||||
|
||||
// Filter by tag
|
||||
if (tag) {
|
||||
query['tags.name'] = { $regex: new RegExp(tag, 'i') }
|
||||
}
|
||||
|
||||
// Get total count with same filters
|
||||
const totalTopics = await TopicModel.countDocuments(query)
|
||||
|
||||
// Get paginated topics sorted by publishedAt
|
||||
const topics = await TopicModel.find(query)
|
||||
.sort({ publishedAt: -1 })
|
||||
.skip(skip)
|
||||
.limit(limit)
|
||||
.lean()
|
||||
|
||||
if (!topics || topics.length === 0) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
data: [],
|
||||
pagination: {
|
||||
total: 0,
|
||||
page,
|
||||
limit,
|
||||
totalPages: 0,
|
||||
},
|
||||
},
|
||||
{ status: 200 }
|
||||
)
|
||||
}
|
||||
|
||||
// Transform the topics using our utility function
|
||||
const transformedTopics = transformToTopics(topics)
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
data: transformedTopics,
|
||||
pagination: {
|
||||
total: totalTopics,
|
||||
page,
|
||||
limit,
|
||||
totalPages: Math.ceil(totalTopics / limit),
|
||||
},
|
||||
},
|
||||
{ status: 200 }
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('Error fetching topics:', error)
|
||||
|
||||
if (error instanceof ZodError) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Data validation failed',
|
||||
code: 'VALIDATION_ERROR',
|
||||
details: error.issues,
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: { message: 'Failed to fetch topics', code: 'SERVER_ERROR' },
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user