import { NextRequest, NextResponse } from 'next/server' import { getPayload } from 'payload' import type { Where } from 'payload' import config from '@payload-config' type Locale = 'de' | 'en' | 'all' /** * Team API * * GET /api/team - Liste aller Team-Mitglieder mit Filter und Suche * * Query-Parameter: * - tenant (required): Tenant ID * - slug: Einzelnes Mitglied nach Slug * - search: Volltextsuche in Name, Rolle, Abteilung, Bio * - department: Nach Abteilung filtern * - level: Nach Hierarchie-Ebene filtern * - specialization: Nach Fachgebiet filtern * - language: Nach Sprache filtern * - featured: Nur hervorgehobene (true/false) * - limit: Maximale Anzahl (default: 50) * - page: Seite für Pagination * - sort: Sortierung (order, name, department, startDate) * - locale: Sprache (de/en) */ export async function GET(request: NextRequest) { try { const { searchParams } = new URL(request.url) // Required: Tenant const tenantId = searchParams.get('tenant') if (!tenantId) { return NextResponse.json({ error: 'tenant parameter is required' }, { status: 400 }) } const payload = await getPayload({ config }) // Optional parameters const slug = searchParams.get('slug') const search = searchParams.get('search') const department = searchParams.get('department') const level = searchParams.get('level') const specialization = searchParams.get('specialization') const language = searchParams.get('language') const featured = searchParams.get('featured') const limit = Math.min(parseInt(searchParams.get('limit') || '50'), 100) const page = parseInt(searchParams.get('page') || '1') const sort = searchParams.get('sort') || 'order' const localeParam = searchParams.get('locale') const locale: Locale = (localeParam === 'de' || localeParam === 'en') ? localeParam : 'de' // Build where clause const where: Where = { tenant: { equals: parseInt(tenantId) }, isActive: { equals: true }, } // Single member by slug if (slug) { where.slug = { equals: slug } } // Department filter if (department) { where.department = { contains: department } } // Hierarchy level filter if (level) { where.hierarchyLevel = { equals: level } } // Featured filter if (featured === 'true') { where.isFeatured = { equals: true } } // Build sort string let sortField = 'order' switch (sort) { case 'name': sortField = 'name' break case 'department': sortField = 'department' break case 'startDate': sortField = '-startDate' break case '-order': sortField = '-order' break default: sortField = 'order' } // Query team members const result = await payload.find({ collection: 'team', where: where as Where, sort: sortField, limit, page, locale, depth: 2, // Include image and reportsTo }) let members = result.docs // Post-query filters (for array fields) // Search filter (case-insensitive) if (search) { const searchLower = search.toLowerCase() members = members.filter((member) => { const nameMatch = member.name?.toLowerCase().includes(searchLower) const roleMatch = typeof member.role === 'string' && member.role.toLowerCase().includes(searchLower) const deptMatch = typeof member.department === 'string' && member.department.toLowerCase().includes(searchLower) const bioMatch = typeof member.bioShort === 'string' && member.bioShort.toLowerCase().includes(searchLower) // Search in specializations const specMatch = Array.isArray(member.specializations) && member.specializations.some( (s) => typeof s.title === 'string' && s.title.toLowerCase().includes(searchLower) ) return nameMatch || roleMatch || deptMatch || bioMatch || specMatch }) } // Specialization filter if (specialization) { const specLower = specialization.toLowerCase() members = members.filter( (member) => Array.isArray(member.specializations) && member.specializations.some( (s) => typeof s.title === 'string' && s.title.toLowerCase().includes(specLower) ) ) } // Language filter if (language) { const langLower = language.toLowerCase() members = members.filter( (member) => Array.isArray(member.languages) && member.languages.some( (l) => typeof l.language === 'string' && l.language.toLowerCase().includes(langLower) ) ) } // Get unique departments for filter dropdown const allMembers = await payload.find({ collection: 'team', where: { tenant: { equals: parseInt(tenantId) }, isActive: { equals: true }, }, limit: 1000, locale, }) const departments = [ ...new Set(allMembers.docs.map((m) => m.department).filter(Boolean)), ].sort() as string[] const specializations = [ ...new Set( allMembers.docs.flatMap((m) => Array.isArray(m.specializations) ? m.specializations.map((s) => s.title) : [] ) ), ] .filter(Boolean) .sort() as string[] const languages = [ ...new Set( allMembers.docs.flatMap((m) => Array.isArray(m.languages) ? m.languages.map((l) => l.language) : [] ) ), ] .filter(Boolean) .sort() as string[] // Single member response if (slug && members.length === 1) { return NextResponse.json({ member: members[0], filters: { departments, specializations, languages }, }) } return NextResponse.json({ members, totalDocs: result.totalDocs, totalPages: result.totalPages, page: result.page, hasNextPage: result.hasNextPage, hasPrevPage: result.hasPrevPage, filters: { departments, specializations, languages }, }) } catch (error) { console.error('Team API error:', error) return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } }