import { router, publicProcedure, protectedProcedure } from '@/src/trpc/trpc-index' import { commonRouter } from '@/src/trpc/apis/common-apis/common' import { db } from '@/src/db/db_index' import { keyValStore, productInfo, storeInfo } from '@/src/db/schema' import * as turf from '@turf/turf'; import { z } from 'zod'; import { mbnrGeoJson } from '@/src/lib/mbnr-geojson' import { generateUploadUrl } from '@/src/lib/s3-client' import { ApiError } from '@/src/lib/api-error' import { getAllConstValues } from '@/src/lib/const-store' import { CONST_KEYS } from '@/src/lib/const-keys' const polygon = turf.polygon(mbnrGeoJson.features[0].geometry.coordinates); export const commonApiRouter = router({ product: commonRouter, getStoresSummary: publicProcedure .query(async () => { const stores = await db.query.storeInfo.findMany({ columns: { id: true, name: true, description: true, }, }); return { stores, }; }), checkLocationInPolygon: publicProcedure .input(z.object({ lat: z.number().min(-90).max(90), lng: z.number().min(-180).max(180), })) .query(({ input }) => { try { const { lat, lng } = input; const point = turf.point([lng, lat]); // GeoJSON: [longitude, latitude] const isInside = turf.booleanPointInPolygon(point, polygon); return { isInside }; } catch (error) { throw new Error('Invalid coordinates or polygon data'); } }), generateUploadUrls: protectedProcedure .input(z.object({ contextString: z.enum(['review', 'product_info', 'store']), mimeTypes: z.array(z.string()), })) .mutation(async ({ input }): Promise<{ uploadUrls: string[] }> => { const { contextString, mimeTypes } = input; const uploadUrls: string[] = []; const keys: string[] = []; for (const mimeType of mimeTypes) { // Generate key based on context and mime type let folder: string; if (contextString === 'review') { folder = 'review-images'; } else if (contextString === 'product_info') { folder = 'product-images'; } else if (contextString === 'store') { folder = 'store-images'; } else if (contextString === 'review_response') { folder = 'review-response-images'; } else { folder = ''; } const extension = mimeType === 'image/jpeg' ? '.jpg' : mimeType === 'image/png' ? '.png' : mimeType === 'image/gif' ? '.gif' : '.jpg'; const key = `${folder}/${Date.now()}${extension}`; try { const uploadUrl = await generateUploadUrl(key, mimeType); uploadUrls.push(uploadUrl); keys.push(key); } catch (error) { console.error('Error generating upload URL:', error); throw new ApiError('Failed to generate upload URL', 500); } } return { uploadUrls }; }), healthCheck: publicProcedure .query(async () => { // Test DB connection by selecting product names // await db.select({ name: productInfo.name }).from(productInfo).limit(1); await db.select({ key: keyValStore.key }).from(keyValStore).limit(1); return { status: "ok", }; }), essentialConsts: publicProcedure .query(async () => { const consts = await getAllConstValues(); return { freeDeliveryThreshold: consts[CONST_KEYS.freeDeliveryThreshold] ?? 200, deliveryCharge: consts[CONST_KEYS.deliveryCharge] ?? 0, flashFreeDeliveryThreshold: consts[CONST_KEYS.flashFreeDeliveryThreshold] ?? 500, flashDeliveryCharge: consts[CONST_KEYS.flashDeliveryCharge] ?? 69, popularItems: consts[CONST_KEYS.popularItems] ?? '5,3,2,4,1', versionNum: consts[CONST_KEYS.versionNum] ?? '1.1.0', playStoreUrl: consts[CONST_KEYS.playStoreUrl] ?? 'https://play.google.com/store/apps/details?id=in.freshyo.app', appStoreUrl: consts[CONST_KEYS.appStoreUrl] ?? 'https://apps.apple.com/in/app/freshyo/id6756889077', webViewHtml: null, isWebviewClosable: true, isFlashDeliveryEnabled: consts[CONST_KEYS.isFlashDeliveryEnabled] ?? true, supportMobile: consts[CONST_KEYS.supportMobile] ?? '', supportEmail: consts[CONST_KEYS.supportEmail] ?? '', }; }), }); export type CommonApiRouter = typeof commonApiRouter;