This commit is contained in:
@@ -78,6 +78,8 @@ export function createListingRepository(db) {
|
||||
setName,
|
||||
eventName,
|
||||
tag,
|
||||
status,
|
||||
newlyAdded = false,
|
||||
minPriceMinor,
|
||||
maxPriceMinor,
|
||||
page = 1,
|
||||
@@ -89,16 +91,26 @@ export function createListingRepository(db) {
|
||||
const conditions = [
|
||||
inArray(
|
||||
listings.status,
|
||||
includeSold
|
||||
? ["AVAILABLE", "PENDING", "CLOSED"]
|
||||
: ["AVAILABLE", "PENDING"],
|
||||
status === "SOLD"
|
||||
? ["CLOSED"]
|
||||
: status === "PENDING"
|
||||
? ["PENDING"]
|
||||
: status === "AVAILABLE"
|
||||
? ["AVAILABLE"]
|
||||
: includeSold
|
||||
? ["AVAILABLE", "PENDING", "CLOSED"]
|
||||
: ["AVAILABLE", "PENDING"],
|
||||
),
|
||||
inArray(
|
||||
inventoryItems.status,
|
||||
includeSold ? ["ACTIVE", "SOLD"] : ["ACTIVE"],
|
||||
status === "SOLD" ? ["SOLD"] : includeSold || status === "ALL" ? ["ACTIVE", "SOLD"] : ["ACTIVE"],
|
||||
),
|
||||
];
|
||||
|
||||
if (newlyAdded) {
|
||||
conditions.push(sql`${inventoryItems.createdAt} >= NOW() - INTERVAL '30 days'`);
|
||||
}
|
||||
|
||||
if (typeof category === "string" && category.trim().length > 0) {
|
||||
conditions.push(eq(products.categoryId, category));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ export function createSearchQuery({
|
||||
setName,
|
||||
eventName,
|
||||
tag,
|
||||
status,
|
||||
newlyAdded = false,
|
||||
minPriceMinor,
|
||||
maxPriceMinor,
|
||||
page = 1,
|
||||
@@ -39,6 +41,10 @@ export function createSearchQuery({
|
||||
throw new Error("limit must be between 1 and 100");
|
||||
}
|
||||
|
||||
if (status && !["AVAILABLE", "PENDING", "SOLD", "ALL"].includes(status)) {
|
||||
throw new Error("status must be AVAILABLE, PENDING, SOLD, or ALL");
|
||||
}
|
||||
|
||||
if (
|
||||
typeof minPriceMinor !== "undefined" &&
|
||||
(!Number.isInteger(minPriceMinor) || minPriceMinor < 0)
|
||||
@@ -87,6 +93,8 @@ export function createSearchQuery({
|
||||
page,
|
||||
limit,
|
||||
includeSold,
|
||||
...(status ? { status } : {}),
|
||||
...(newlyAdded ? { newlyAdded: true } : {}),
|
||||
...(sort !== "recent" ? { sort } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ export async function registerPublicSearchRoutes(app, options) {
|
||||
setName: request.query.setName,
|
||||
eventName: request.query.eventName,
|
||||
tag: request.query.tag,
|
||||
status: request.query.status,
|
||||
newlyAdded: request.query.newlyAdded === "true" || request.query.newlyAdded === true,
|
||||
minPriceMinor: coerceNumber(
|
||||
request.query.minPriceMinor,
|
||||
"minPriceMinor",
|
||||
|
||||
@@ -72,6 +72,13 @@ test("accepts only the supported public search sort values", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("accepts public status and newly-added filters", () => {
|
||||
const query = createSearchQuery({ status: "SOLD", newlyAdded: true });
|
||||
assert.equal(query.status, "SOLD");
|
||||
assert.equal(query.newlyAdded, true);
|
||||
assert.throws(() => createSearchQuery({ status: "UNKNOWN" }), /status must be/);
|
||||
});
|
||||
|
||||
test("normalizes whitespace and punctuation in free-text search terms", () => {
|
||||
assert.equal(
|
||||
normalizeSearchQuery(" Pikachu #199 / holo "),
|
||||
|
||||
@@ -15,6 +15,8 @@ test("returns public search results with pagination metadata", async (testContex
|
||||
assert.equal(filters.setName, "SV151");
|
||||
assert.equal(filters.eventName, "Worlds");
|
||||
assert.equal(filters.tag, "binder");
|
||||
assert.equal(filters.status, "SOLD");
|
||||
assert.equal(filters.newlyAdded, true);
|
||||
return {
|
||||
items: [{ id: "listing-1", status: "CLOSED" }],
|
||||
pagination: { page: 2, limit: 5, total: 6, totalPages: 2 },
|
||||
@@ -26,7 +28,7 @@ test("returns public search results with pagination metadata", async (testContex
|
||||
|
||||
const response = await app.inject({
|
||||
method: "GET",
|
||||
url: "/api/v1/public/search?query=charizard&page=2&limit=5&includeSold=true&sort=price_low&conditionId=condition-1&setName=SV151&eventName=Worlds&tag=binder",
|
||||
url: "/api/v1/public/search?query=charizard&page=2&limit=5&includeSold=true&sort=price_low&conditionId=condition-1&setName=SV151&eventName=Worlds&tag=binder&status=SOLD&newlyAdded=true",
|
||||
});
|
||||
|
||||
assert.equal(response.statusCode, 200);
|
||||
|
||||
Reference in New Issue
Block a user