This commit is contained in:
shafi54 2026-01-24 16:12:50 +05:30
parent ccde89b5c8
commit 693826b34c
4 changed files with 46 additions and 6 deletions

View file

@ -37,6 +37,7 @@
"drizzle-orm": "^0.44.5", "drizzle-orm": "^0.44.5",
"expo-server-sdk": "^4.0.0", "expo-server-sdk": "^4.0.0",
"express": "^5.1.0", "express": "^5.1.0",
"fuse.js": "^7.1.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"multer": "^2.0.2", "multer": "^2.0.2",
"node-cron": "^4.2.1", "node-cron": "^4.2.1",

View file

@ -23,6 +23,7 @@ interface Product {
flashPrice: string | null; flashPrice: string | null;
deliverySlots: Array<{ id: number; deliveryTime: Date; freezeTime: Date }>; deliverySlots: Array<{ id: number; deliveryTime: Date; freezeTime: Date }>;
specialDeals: Array<{ quantity: string; price: string; validTill: Date }>; specialDeals: Array<{ quantity: string; price: string; validTill: Date }>;
productTags: string[];
} }
export async function initializeProducts(): Promise<void> { export async function initializeProducts(): Promise<void> {
@ -94,12 +95,27 @@ export async function initializeProducts(): Promise<void> {
specialDealsMap.get(deal.productId)!.push(deal); specialDealsMap.get(deal.productId)!.push(deal);
} }
// Fetch all product tags
const allProductTags = await db
.select({
productId: productTags.productId,
tagName: productTagInfo.tagName,
})
.from(productTags)
.innerJoin(productTagInfo, eq(productTags.tagId, productTagInfo.id));
const productTagsMap = new Map<number, string[]>();
for (const tag of allProductTags) {
if (!productTagsMap.has(tag.productId)) productTagsMap.set(tag.productId, []);
productTagsMap.get(tag.productId)!.push(tag.tagName);
}
// Store each product in Redis // Store each product in Redis
for (const product of productsData) { for (const product of productsData) {
const signedImages = await generateSignedUrlsFromS3Urls((product.images as string[]) || []); const signedImages = await generateSignedUrlsFromS3Urls((product.images as string[]) || []);
const store = product.storeId ? storeMap.get(product.storeId) || null : null; const store = product.storeId ? storeMap.get(product.storeId) || null : null;
const deliverySlots = deliverySlotsMap.get(product.id) || []; const deliverySlots = deliverySlotsMap.get(product.id) || [];
const specialDeals = specialDealsMap.get(product.id) || []; const specialDeals = specialDealsMap.get(product.id) || [];
const productTags = productTagsMap.get(product.id) || [];
const productObj: Product = { const productObj: Product = {
id: product.id, id: product.id,
@ -118,6 +134,7 @@ export async function initializeProducts(): Promise<void> {
flashPrice: product.flashPrice?.toString() || null, flashPrice: product.flashPrice?.toString() || null,
deliverySlots: deliverySlots.map(s => ({ id: s.id, deliveryTime: s.deliveryTime, freezeTime: s.freezeTime })), deliverySlots: deliverySlots.map(s => ({ id: s.id, deliveryTime: s.deliveryTime, freezeTime: s.freezeTime })),
specialDeals: specialDeals.map(d => ({ quantity: d.quantity.toString(), price: d.price.toString(), validTill: d.validTill })), specialDeals: specialDeals.map(d => ({ quantity: d.quantity.toString(), price: d.price.toString(), validTill: d.validTill })),
productTags: productTags,
}; };
await redisClient.set(`product:${product.id}`, JSON.stringify(productObj)); await redisClient.set(`product:${product.id}`, JSON.stringify(productObj));

View file

@ -6,6 +6,7 @@ import { generateSignedUrlsFromS3Urls, generateSignedUrlFromS3Url } from '../../
import { z } from 'zod'; import { z } from 'zod';
import { getAllProducts as getAllProductsFromCache } from '../../stores/product-store'; import { getAllProducts as getAllProductsFromCache } from '../../stores/product-store';
import { getDashboardTags as getDashboardTagsFromCache } from '../../stores/product-tag-store'; import { getDashboardTags as getDashboardTagsFromCache } from '../../stores/product-tag-store';
import Fuse from 'fuse.js';
export const getNextDeliveryDate = async (productId: number): Promise<Date | null> => { export const getNextDeliveryDate = async (productId: number): Promise<Date | null> => {
const result = await db const result = await db
@ -66,12 +67,23 @@ export const commonRouter = router({
products = products.filter(product => taggedProductIds.has(product.id)); products = products.filter(product => taggedProductIds.has(product.id));
} }
// Apply search filtering if searchQuery is provided // Apply search filtering if searchQuery is provided using Fuse.js
if (searchQuery) { if (searchQuery) {
const searchLower = searchQuery.toLowerCase(); const fuse = new Fuse(products, {
products = products.filter(product => keys: [
product.name.toLowerCase().includes(searchLower) 'name',
); 'shortDescription',
'longDescription',
'store.name', // Search in store name too
'productTags', // Search in product tags too
],
threshold: 0.3, // Adjust fuzziness (0.0 = exact match, 1.0 = match anything)
includeScore: true,
shouldSort: true,
});
const fuseResults = fuse.search(searchQuery);
products = fuseResults.map(result => result.item);
} }
// Get suspended product IDs to filter them out // Get suspended product IDs to filter them out

10
package-lock.json generated
View file

@ -167,6 +167,7 @@
"drizzle-orm": "^0.44.5", "drizzle-orm": "^0.44.5",
"expo-server-sdk": "^4.0.0", "expo-server-sdk": "^4.0.0",
"express": "^5.1.0", "express": "^5.1.0",
"fuse.js": "^7.1.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"multer": "^2.0.2", "multer": "^2.0.2",
"node-cron": "^4.2.1", "node-cron": "^4.2.1",
@ -15489,6 +15490,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/fuse.js": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz",
"integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=10"
}
},
"node_modules/generator-function": { "node_modules/generator-function": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",