mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-28 21:07:04 -05:00
Add database reset script and update package.json for db commands; refactor middleware for CORS support and error handling in parks page
This commit is contained in:
@@ -1,110 +1,88 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { ParkStatus } from '@/types/api';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const search = searchParams.get('search')?.trim();
|
||||
const status = searchParams.get('status') as ParkStatus;
|
||||
const ownerId = searchParams.get('ownerId');
|
||||
const hasOwner = searchParams.get('hasOwner');
|
||||
const minRides = parseInt(searchParams.get('minRides') || '');
|
||||
const minCoasters = parseInt(searchParams.get('minCoasters') || '');
|
||||
const minSize = parseInt(searchParams.get('minSize') || '');
|
||||
const openingDateStart = searchParams.get('openingDateStart');
|
||||
const openingDateEnd = searchParams.get('openingDateEnd');
|
||||
|
||||
const where = {
|
||||
AND: [] as any[]
|
||||
};
|
||||
|
||||
// Search filter
|
||||
if (search) {
|
||||
where.AND.push({
|
||||
OR: [
|
||||
{ name: { contains: search, mode: 'insensitive' } },
|
||||
{ description: { contains: search, mode: 'insensitive' } },
|
||||
{ owner: { name: { contains: search, mode: 'insensitive' } } }
|
||||
]
|
||||
});
|
||||
// Test raw query first
|
||||
try {
|
||||
console.log('Testing database connection...');
|
||||
const rawResult = await prisma.$queryRaw`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'public'`;
|
||||
console.log('Available tables:', rawResult);
|
||||
} catch (connectionError) {
|
||||
console.error('Raw query test failed:', connectionError);
|
||||
throw new Error('Database connection test failed');
|
||||
}
|
||||
|
||||
// Status filter
|
||||
if (status) {
|
||||
where.AND.push({ status });
|
||||
}
|
||||
// Basic query with explicit types
|
||||
try {
|
||||
const queryResult = await prisma.$transaction(async (tx) => {
|
||||
// Count total parks
|
||||
const totalCount = await tx.park.count();
|
||||
console.log('Total parks count:', totalCount);
|
||||
|
||||
// Owner filters
|
||||
if (ownerId) {
|
||||
where.AND.push({ ownerId });
|
||||
}
|
||||
if (hasOwner !== null) {
|
||||
where.AND.push({ owner: hasOwner === 'true' ? { not: null } : null });
|
||||
}
|
||||
|
||||
// Numeric filters
|
||||
if (!isNaN(minRides)) {
|
||||
where.AND.push({ ride_count: { gte: minRides } });
|
||||
}
|
||||
if (!isNaN(minCoasters)) {
|
||||
where.AND.push({ coaster_count: { gte: minCoasters } });
|
||||
}
|
||||
if (!isNaN(minSize)) {
|
||||
where.AND.push({ size_acres: { gte: minSize } });
|
||||
}
|
||||
|
||||
// Date range filter
|
||||
if (openingDateStart || openingDateEnd) {
|
||||
const dateFilter: any = {};
|
||||
if (openingDateStart) {
|
||||
dateFilter.gte = new Date(openingDateStart);
|
||||
}
|
||||
if (openingDateEnd) {
|
||||
dateFilter.lte = new Date(openingDateEnd);
|
||||
}
|
||||
where.AND.push({ opening_date: dateFilter });
|
||||
}
|
||||
|
||||
const parks = await prisma.park.findMany({
|
||||
where: where.AND.length > 0 ? where : undefined,
|
||||
include: {
|
||||
owner: {
|
||||
// Fetch parks with minimal fields
|
||||
const parks = await tx.park.findMany({
|
||||
take: 10,
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
slug: true
|
||||
}
|
||||
},
|
||||
location: true,
|
||||
_count: {
|
||||
select: {
|
||||
rides: true
|
||||
slug: true,
|
||||
status: true,
|
||||
owner: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true
|
||||
}
|
||||
}
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
}
|
||||
} satisfies Prisma.ParkFindManyArgs);
|
||||
|
||||
return { totalCount, parks };
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: queryResult.parks,
|
||||
meta: {
|
||||
total: queryResult.totalCount
|
||||
}
|
||||
},
|
||||
orderBy: [
|
||||
{ status: 'asc' },
|
||||
{ name: 'asc' }
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
const formattedParks = parks.map(park => ({
|
||||
...park,
|
||||
ride_count: park._count.rides,
|
||||
_count: undefined
|
||||
}));
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: formattedParks
|
||||
});
|
||||
} catch (queryError) {
|
||||
if (queryError instanceof Prisma.PrismaClientKnownRequestError) {
|
||||
console.error('Known Prisma error:', {
|
||||
code: queryError.code,
|
||||
meta: queryError.meta,
|
||||
message: queryError.message
|
||||
});
|
||||
throw new Error(`Database query failed: ${queryError.code}`);
|
||||
}
|
||||
throw queryError;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in /api/parks:', error);
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: 'Failed to fetch parks'
|
||||
}, { status: 500 });
|
||||
console.error('Error in /api/parks:', {
|
||||
name: error instanceof Error ? error.name : 'Unknown',
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
stack: error instanceof Error ? error.stack : undefined
|
||||
});
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Failed to fetch parks'
|
||||
},
|
||||
{
|
||||
status: 500,
|
||||
headers: {
|
||||
'Cache-Control': 'no-store, must-revalidate',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user