111 lines
3.2 KiB
TypeScript
111 lines
3.2 KiB
TypeScript
|
|
/**
|
||
|
|
* Resources Data API Endpoint
|
||
|
|
* GET /api/data/resources - Query resources (users) from PostgreSQL
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { NextRequest, NextResponse } from 'next/server';
|
||
|
|
import postgresClient from '@/lib/services/postgres-client';
|
||
|
|
|
||
|
|
export async function GET(request: NextRequest) {
|
||
|
|
try {
|
||
|
|
const searchParams = request.nextUrl.searchParams;
|
||
|
|
const limit = parseInt(searchParams.get('limit') || '100');
|
||
|
|
const offset = parseInt(searchParams.get('offset') || '0');
|
||
|
|
const isActive = searchParams.get('isActive');
|
||
|
|
const sortBy = searchParams.get('sort');
|
||
|
|
const sortOrder = searchParams.get('order') || 'asc';
|
||
|
|
const ids = searchParams.get('ids'); // Comma-separated IDs for enrichment
|
||
|
|
|
||
|
|
// Build conditions and parameters
|
||
|
|
const conditions: string[] = [];
|
||
|
|
const params: any[] = [];
|
||
|
|
|
||
|
|
if (ids) {
|
||
|
|
// Fetch specific resources by IDs
|
||
|
|
const idArray = ids.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id));
|
||
|
|
if (idArray.length > 0) {
|
||
|
|
conditions.push(`id = ANY($${params.length + 1})`);
|
||
|
|
params.push(idArray);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isActive !== null && !ids) {
|
||
|
|
conditions.push('is_active = $' + (params.length + 1));
|
||
|
|
params.push(isActive === 'true');
|
||
|
|
}
|
||
|
|
|
||
|
|
const whereClause = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
|
||
|
|
|
||
|
|
// Build dynamic ORDER BY clause
|
||
|
|
let orderByClause = 'ORDER BY last_name ASC, first_name ASC';
|
||
|
|
if (sortBy) {
|
||
|
|
const validColumns = ['id', 'first_name', 'last_name', 'email', 'user_name', 'title', 'is_active', 'resource_type'];
|
||
|
|
if (validColumns.includes(sortBy)) {
|
||
|
|
const direction = sortOrder.toLowerCase() === 'desc' ? 'DESC' : 'ASC';
|
||
|
|
orderByClause = `ORDER BY ${sortBy} ${direction}, last_name ASC, first_name ASC`;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Query resources
|
||
|
|
const query = `
|
||
|
|
SELECT
|
||
|
|
id,
|
||
|
|
first_name,
|
||
|
|
last_name,
|
||
|
|
email,
|
||
|
|
user_name,
|
||
|
|
title,
|
||
|
|
office_phone,
|
||
|
|
mobile_phone,
|
||
|
|
office_extension,
|
||
|
|
is_active,
|
||
|
|
location_id,
|
||
|
|
resource_type,
|
||
|
|
pay_roll_identifier,
|
||
|
|
hire_date,
|
||
|
|
travel_availability_pct,
|
||
|
|
survey_resource_rating,
|
||
|
|
created_at,
|
||
|
|
updated_at,
|
||
|
|
synced_at,
|
||
|
|
is_deleted,
|
||
|
|
deleted_at
|
||
|
|
FROM resources
|
||
|
|
${whereClause}
|
||
|
|
${orderByClause}
|
||
|
|
LIMIT $${params.length + 1} OFFSET $${params.length + 2}
|
||
|
|
`;
|
||
|
|
|
||
|
|
params.push(limit, offset);
|
||
|
|
|
||
|
|
const result = await postgresClient.query(query, params);
|
||
|
|
const resources = result.rows;
|
||
|
|
|
||
|
|
// Get total count
|
||
|
|
const countQuery = `
|
||
|
|
SELECT COUNT(*) as total
|
||
|
|
FROM resources
|
||
|
|
${whereClause}
|
||
|
|
`;
|
||
|
|
|
||
|
|
const countResult = await postgresClient.query(countQuery, params.slice(0, -2));
|
||
|
|
const totalCount = parseInt(countResult.rows[0].total);
|
||
|
|
|
||
|
|
return NextResponse.json({
|
||
|
|
resources,
|
||
|
|
pagination: {
|
||
|
|
limit,
|
||
|
|
offset,
|
||
|
|
total: totalCount,
|
||
|
|
hasMore: offset + resources.length < totalCount,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Failed to fetch resources:', error);
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Failed to fetch resources' },
|
||
|
|
{ status: 500 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|