145 lines
5.5 KiB
TypeScript
145 lines
5.5 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
||
import prisma from '../../../lib/prisma'
|
||
import { MOCK_BUSINESSES } from '../../../lib/mockData'
|
||
|
||
// GET /api/businesses — List all businesses (Mock + DB)
|
||
export async function GET(request: NextRequest) {
|
||
try {
|
||
const { searchParams } = new URL(request.url)
|
||
const category = searchParams.get('category')
|
||
const q = searchParams.get('q')?.toLowerCase()
|
||
const featured = searchParams.get('featured')
|
||
|
||
// 1. Fetch from Database
|
||
const where: any = {}
|
||
if (category && category !== 'All') where.category = category
|
||
if (featured === 'true') where.isFeatured = true
|
||
if (q) {
|
||
where.OR = [
|
||
{ name: { contains: q, mode: 'insensitive' } },
|
||
{ description: { contains: q, mode: 'insensitive' } },
|
||
// Simplified tags check
|
||
{ tags: { has: q } }
|
||
]
|
||
}
|
||
|
||
const dbBusinesses = await prisma.business.findMany({
|
||
where,
|
||
include: { owner: true, offers: true },
|
||
orderBy: { createdAt: 'desc' },
|
||
})
|
||
|
||
// 2. Filter Mock Businesses
|
||
const filteredMocks = MOCK_BUSINESSES.filter(biz => {
|
||
// Category filter
|
||
if (category && category !== 'All' && biz.category !== category) return false;
|
||
|
||
// Featured filter
|
||
if (featured === 'true' && !biz.isFeatured) return false;
|
||
|
||
// Search query filter
|
||
if (q) {
|
||
const matches =
|
||
biz.name.toLowerCase().includes(q) ||
|
||
biz.description.toLowerCase().includes(q) ||
|
||
biz.tags.some(t => t.toLowerCase().includes(q));
|
||
if (!matches) return false;
|
||
}
|
||
|
||
return true;
|
||
});
|
||
|
||
// 3. Combine and return
|
||
// Prioritize DB entries over mocks to show user-created data first
|
||
const combined = [...dbBusinesses, ...filteredMocks];
|
||
|
||
return NextResponse.json(combined)
|
||
} catch (error) {
|
||
console.error('GET /api/businesses error:', error)
|
||
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 })
|
||
}
|
||
}
|
||
|
||
export async function POST(request: NextRequest) {
|
||
try {
|
||
const body = await request.json()
|
||
const headerUserId = request.headers.get('x-user-id')
|
||
const { ownerId: bodyOwnerId, ...data } = body
|
||
|
||
const ownerId = bodyOwnerId || headerUserId
|
||
|
||
if (!ownerId) {
|
||
return NextResponse.json({ error: 'ownerId est requis (via body ou x-user-id header)' }, { status: 400 })
|
||
}
|
||
|
||
// 1. Sanitize data - ONLY pass fields that exist in the Prisma Business model
|
||
// We must exclude 'id', 'offers', 'owner', 'createdAt', 'updatedAt' from the data object
|
||
const cleanData: any = {
|
||
name: data.name || "Nouvelle Entreprise",
|
||
slug: data.slug || null,
|
||
category: data.category || "Autre",
|
||
location: data.location || "Ma Ville",
|
||
description: data.description || "",
|
||
logoUrl: data.logoUrl || "https://picsum.photos/200/200?random=default",
|
||
videoUrl: data.videoUrl || null,
|
||
contactEmail: data.contactEmail || "",
|
||
contactPhone: data.contactPhone || null,
|
||
socialLinks: data.socialLinks || {},
|
||
verified: data.verified ?? false,
|
||
viewCount: data.viewCount ?? 0,
|
||
rating: data.rating ?? 0,
|
||
tags: Array.isArray(data.tags) ? data.tags : [],
|
||
isFeatured: data.isFeatured ?? false,
|
||
founderName: data.founderName || null,
|
||
founderImageUrl: data.founderImageUrl || null,
|
||
keyMetric: data.keyMetric || null,
|
||
}
|
||
|
||
// 2. Slug Uniqueness Check
|
||
if (cleanData.slug) {
|
||
const slugConflict = await prisma.business.findFirst({
|
||
where: {
|
||
slug: cleanData.slug,
|
||
NOT: { ownerId: ownerId } // Important: allow the owner to keep their own slug
|
||
}
|
||
});
|
||
if (slugConflict) {
|
||
return NextResponse.json({
|
||
error: `Le lien personnalisé "${cleanData.slug}" est déjà utilisé par une autre entreprise. Veuillez en choisir un autre.`
|
||
}, { status: 400 });
|
||
}
|
||
}
|
||
|
||
let business;
|
||
const existing = await prisma.business.findFirst({
|
||
where: { ownerId: ownerId }
|
||
});
|
||
|
||
console.log('Upserting business for ownerId:', ownerId, 'Existing:', !!existing);
|
||
|
||
if (existing) {
|
||
// When updating, we use the sanitized cleanData and the existing record's id
|
||
business = await prisma.business.update({
|
||
where: { id: existing.id },
|
||
data: cleanData,
|
||
include: { owner: true }
|
||
});
|
||
} else {
|
||
// When creating, we add the ownerId to the sanitized cleanData
|
||
business = await prisma.business.create({
|
||
data: {
|
||
...cleanData,
|
||
ownerId: ownerId
|
||
},
|
||
include: { owner: true }
|
||
});
|
||
}
|
||
|
||
console.log('Business saved successfully:', business.id);
|
||
return NextResponse.json(business, { status: 200 })
|
||
} catch (error) {
|
||
console.error('POST /api/businesses error:', error)
|
||
return NextResponse.json({ error: 'Erreur lors de l’enregistrement' }, { status: 500 })
|
||
}
|
||
}
|