- Add seedCategories mutation (idempotent) and getBySlug query - Add ad queries: list, getByCategory, getById, search, getByHandyman - Home screen: search bar, CategoryGrid, recent ads list with real-time Convex queries and search-by-keyword - Explore screen: category filter via search param, filtered ad list, full category grid when unfiltered - AdCard component: title, category badge, location, rating stars, price range, navigation to ad detail - CategoryGrid component: 3-column emoji grid linking to filtered explore - Add CATEGORY_EMOJI map and getCategoryName() helper in constants All UI text in Macedonian. TypeScript clean, Convex functions deployed.
62 lines
1.5 KiB
TypeScript
62 lines
1.5 KiB
TypeScript
import { query } from "./_generated/server";
|
|
import { v } from "convex/values";
|
|
|
|
export const list = query({
|
|
args: {},
|
|
handler: async (ctx) => {
|
|
return await ctx.db.query("ads").order("desc").collect();
|
|
},
|
|
});
|
|
|
|
export const getByCategory = query({
|
|
args: { category: v.string() },
|
|
handler: async (ctx, args) => {
|
|
return await ctx.db
|
|
.query("ads")
|
|
.withIndex("by_category", (q) => q.eq("category", args.category))
|
|
.order("desc")
|
|
.collect();
|
|
},
|
|
});
|
|
|
|
export const getById = query({
|
|
args: { id: v.id("ads") },
|
|
handler: async (ctx, args) => {
|
|
return await ctx.db.get(args.id);
|
|
},
|
|
});
|
|
|
|
export const search = query({
|
|
args: { query: v.string(), category: v.optional(v.string()) },
|
|
handler: async (ctx, args) => {
|
|
const searchLower = args.query.toLowerCase();
|
|
|
|
let ads;
|
|
if (args.category) {
|
|
ads = await ctx.db
|
|
.query("ads")
|
|
.withIndex("by_category", (q) => q.eq("category", args.category!))
|
|
.collect();
|
|
} else {
|
|
ads = await ctx.db.query("ads").order("desc").collect();
|
|
}
|
|
|
|
return ads.filter(
|
|
(ad) =>
|
|
ad.title.toLowerCase().includes(searchLower) ||
|
|
ad.description.toLowerCase().includes(searchLower) ||
|
|
ad.location.toLowerCase().includes(searchLower)
|
|
);
|
|
},
|
|
});
|
|
|
|
export const getByHandyman = query({
|
|
args: { handymanId: v.id("users") },
|
|
handler: async (ctx, args) => {
|
|
return await ctx.db
|
|
.query("ads")
|
|
.withIndex("by_handyman", (q) => q.eq("handymanId", args.handymanId))
|
|
.order("desc")
|
|
.collect();
|
|
},
|
|
}); |