Files
falah-mobile/src/app/api/souq/listings/route.ts
T

183 lines
4.9 KiB
TypeScript
Raw Normal View History

import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireAuth } from "@/lib/auth";
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const category = searchParams.get("category");
const search = searchParams.get("search");
const featured = searchParams.get("featured");
const sellerId = searchParams.get("sellerId");
const minPrice = searchParams.get("minPrice");
const maxPrice = searchParams.get("maxPrice");
const sortBy = searchParams.get("sortBy");
const deliveryDays = searchParams.get("deliveryDays");
const page = parseInt(searchParams.get("page") || "1", 10);
const limit = parseInt(searchParams.get("limit") || "20", 10);
const skip = (page - 1) * limit;
const where: Record<string, unknown> = {};
// Only return active listings by default
where.status = "active";
if (category) {
where.category = category;
}
if (search) {
where.OR = [
{ title: { contains: search } },
{ description: { contains: search } },
];
}
if (featured === "true") {
where.featured = true;
}
if (sellerId) {
where.sellerId = sellerId;
}
// Price range filter
if (minPrice || maxPrice) {
const priceFilter: Record<string, number> = {};
if (minPrice) priceFilter.gte = parseInt(minPrice, 10);
if (maxPrice) priceFilter.lte = parseInt(maxPrice, 10);
where.priceFlh = priceFilter;
}
// Delivery days filter
if (deliveryDays) {
where.deliveryDays = { lte: parseInt(deliveryDays, 10) };
}
// Build orderBy based on sortBy
let orderBy: Record<string, unknown>[];
switch (sortBy) {
case "price_asc":
orderBy = [{ priceFlh: "asc" }, { featured: "desc" }, { createdAt: "desc" }];
break;
case "price_desc":
orderBy = [{ priceFlh: "desc" }, { featured: "desc" }, { createdAt: "desc" }];
break;
case "rating":
orderBy = [{ rating: "desc" }, { featured: "desc" }, { createdAt: "desc" }];
break;
case "popular":
orderBy = [{ salesCount: "desc" }, { featured: "desc" }, { createdAt: "desc" }];
break;
case "newest":
orderBy = [{ createdAt: "desc" }, { featured: "desc" }];
break;
default:
orderBy = [{ featured: "desc" }, { createdAt: "desc" }];
break;
}
const [listings, total] = await Promise.all([
prisma.listing.findMany({
where,
include: {
seller: {
select: { id: true, name: true, email: true, avatar: true },
},
},
orderBy,
skip,
take: limit,
}),
prisma.listing.count({ where }),
]);
return NextResponse.json({
listings,
pagination: {
page,
limit,
total,
totalPages: Math.ceil(total / limit),
},
});
} catch (error) {
console.error("GET /api/souq/listings error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
try {
const auth = await requireAuth(request);
if (!auth) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const user = await prisma.user.findUnique({ where: { id: auth.userId } });
if (!user) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
const {
title,
description,
category,
subcategory,
priceFlh,
packages,
tags,
images,
deliveryDays,
fileType,
} = await request.json();
if (!title || !description || !category || !priceFlh) {
return NextResponse.json(
{ error: "Missing required fields: title, description, category, priceFlh" },
{ status: 400 }
);
}
if (typeof priceFlh !== "number" || priceFlh < 0) {
return NextResponse.json(
{ error: "priceFlh must be a non-negative number" },
{ status: 400 }
);
}
const listing = await prisma.listing.create({
data: {
title,
description,
category,
subcategory: subcategory || null,
priceFlh,
packages: packages ? JSON.stringify(packages) : null,
tags: tags ? JSON.stringify(tags) : null,
images: images ? JSON.stringify(images) : null,
deliveryDays: deliveryDays || null,
fileType: fileType || null,
sellerId: user.id,
status: "active",
},
include: {
seller: {
select: { id: true, name: true, email: true, avatar: true },
},
},
});
return NextResponse.json({ listing }, { status: 201 });
} catch (error) {
console.error("POST /api/souq/listings error:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}