enh
This commit is contained in:
parent
01f6b88392
commit
286e6aabcb
11 changed files with 209 additions and 101 deletions
30
apps/backend/src/lib/flash-delivery-cron.ts
Normal file
30
apps/backend/src/lib/flash-delivery-cron.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { toggleKeyVal } from '@/src/dbService'
|
||||||
|
import { CONST_KEYS } from '@/src/lib/const-keys'
|
||||||
|
import { computeConstants } from '@/src/lib/const-store'
|
||||||
|
import { ensureWorkerInit } from '@/src/lib/worker-init'
|
||||||
|
|
||||||
|
|
||||||
|
const CRON_TURN_OFF_FLASH_DELIVERY = '0 16 * * *' // 9:30 PM IST
|
||||||
|
const CRON_TURN_ON_FLASH_DELIVERY = '0 1 * * *' // 6:30 PM IST
|
||||||
|
|
||||||
|
export async function runFlashDeliveryToggleCron(params: {
|
||||||
|
cron: string
|
||||||
|
env: any
|
||||||
|
}) {
|
||||||
|
console.log('from the cron job top level')
|
||||||
|
const { cron, env } = params
|
||||||
|
|
||||||
|
// Ensure DB bindings are initialized for this worker invocation
|
||||||
|
ensureWorkerInit(env)
|
||||||
|
|
||||||
|
if (cron !== CRON_TURN_OFF_FLASH_DELIVERY && cron !== CRON_TURN_ON_FLASH_DELIVERY) {
|
||||||
|
console.log('flash delivery cron: ignoring unknown cron', cron)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const enabled = cron === CRON_TURN_ON_FLASH_DELIVERY
|
||||||
|
console.log('flash delivery cron: toggling isFlashDeliveryEnabled', { cron, enabled })
|
||||||
|
|
||||||
|
await toggleKeyVal(CONST_KEYS.isFlashDeliveryEnabled, enabled)
|
||||||
|
await computeConstants()
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { sendAdminNotification } from '@/src/lib/notif-job'
|
import { sendAdminNotification } from '@/src/lib/notif-job'
|
||||||
import { handleOrderCancelled, handleOrderPlaced } from '@/src/lib/post-order-handler'
|
import { handleOrderCancelled, handleOrderPlaced } from '@/src/lib/post-order-handler'
|
||||||
|
|
||||||
export const handleNotifQueue = (batch: any) => {
|
export const handleNotifQueue =async (batch: any) => {
|
||||||
batch.messages.forEach((message: any) => {
|
console.log('notif batch,', {batch})
|
||||||
|
batch.messages.forEach(async (message: any) => {
|
||||||
const body = message?.body
|
const body = message?.body
|
||||||
if (!body) {
|
if (!body) {
|
||||||
console.log('notif_queue message received with empty body')
|
console.log('notif_queue message received with empty body')
|
||||||
|
|
@ -10,7 +11,7 @@ export const handleNotifQueue = (batch: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.name === 'send-admin-notification' && body.jobData?.token) {
|
if (body.name === 'send-admin-notification' && body.jobData?.token) {
|
||||||
void sendAdminNotification({
|
await sendAdminNotification({
|
||||||
token: body.jobData.token,
|
token: body.jobData.token,
|
||||||
title: body.jobData.title,
|
title: body.jobData.title,
|
||||||
body: body.jobData.body,
|
body: body.jobData.body,
|
||||||
|
|
@ -19,7 +20,7 @@ export const handleNotifQueue = (batch: any) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('notif_queue message received', body)
|
// console.log('notif_queue', body)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,8 @@ export const userRouter = {
|
||||||
tokens = userTokens.map(t => t.token);
|
tokens = userTokens.map(t => t.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tokens = ['ExponentPushToken[w4KTsLKnnp8SbURdl5-Q6x]', 'ExponentPushToken[81Io9TG3Qg0s3N0V8L86T-]', 'ExponentPushToken[YJRSQmMUEUbaI2VCZLaoN_]', 'ExponentPushToken[LQZgYkFG_3CweaUbv0fBKJ]']
|
||||||
|
|
||||||
// Queue one job per token
|
// Queue one job per token
|
||||||
let queuedCount = 0;
|
let queuedCount = 0;
|
||||||
for (const token of tokens) {
|
for (const token of tokens) {
|
||||||
|
|
@ -253,6 +255,14 @@ export const userRouter = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
// await queueDataPusher.pushNotifQueue({
|
||||||
|
// jobData: {
|
||||||
|
// token,
|
||||||
|
// title,
|
||||||
|
// body: text,
|
||||||
|
// imageUrl: imageUrl || null,
|
||||||
|
// }
|
||||||
|
// })
|
||||||
queuedCount++;
|
queuedCount++;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to queue notification for token:`, error);
|
console.error(`Failed to queue notification for token:`, error);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import type {
|
||||||
import { CacheCreator } from './src/jobs/cache-creator'
|
import { CacheCreator } from './src/jobs/cache-creator'
|
||||||
import { createApp } from './src/app'
|
import { createApp } from './src/app'
|
||||||
import { ensureWorkerInit } from './src/lib/worker-init'
|
import { ensureWorkerInit } from './src/lib/worker-init'
|
||||||
|
import { runFlashDeliveryToggleCron } from './src/lib/flash-delivery-cron'
|
||||||
import {
|
import {
|
||||||
handleNotifQueue,
|
handleNotifQueue,
|
||||||
handleOrderPlacedQueue,
|
handleOrderPlacedQueue,
|
||||||
|
|
@ -58,7 +59,7 @@ export default {
|
||||||
ensureWorkerInit(env)
|
ensureWorkerInit(env)
|
||||||
console.log('from the queue handler')
|
console.log('from the queue handler')
|
||||||
if (batch?.queue === env.NOTIF_QUEUE_NAME) {
|
if (batch?.queue === env.NOTIF_QUEUE_NAME) {
|
||||||
handleNotifQueue(batch)
|
await handleNotifQueue(batch)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,4 +75,15 @@ export default {
|
||||||
|
|
||||||
handleNotifQueue(batch)
|
handleNotifQueue(batch)
|
||||||
},
|
},
|
||||||
|
async scheduled(
|
||||||
|
event: any,
|
||||||
|
env: Record<string, string> & {
|
||||||
|
DB?: D1Database
|
||||||
|
},
|
||||||
|
ctx: ExecutionContext
|
||||||
|
) {
|
||||||
|
console.log('from the cron trigger first func');
|
||||||
|
await runFlashDeliveryToggleCron({cron: event.cron, env});
|
||||||
|
// ctx.waitUntil(runFlashDeliveryToggleCron({ cron: event.cron, env }))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,5 +92,12 @@ DELIVERY_CHARGE = "20"
|
||||||
TELEGRAM_BOT_TOKEN = "8410461852:AAGXQCwRPFbndqwTgLJh8kYxST4Z0vgh72U"
|
TELEGRAM_BOT_TOKEN = "8410461852:AAGXQCwRPFbndqwTgLJh8kYxST4Z0vgh72U"
|
||||||
TELEGRAM_CHAT_IDS = "5147760058"
|
TELEGRAM_CHAT_IDS = "5147760058"
|
||||||
|
|
||||||
|
[triggers]
|
||||||
|
#crons = ["* * * * *"]
|
||||||
|
crons = [
|
||||||
|
"30 18 * * *", # 12:00 AM IST
|
||||||
|
"35 18 * * *" # 12:05 AM IST
|
||||||
|
]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
upload_source_maps = true
|
upload_source_maps = true
|
||||||
|
|
|
||||||
|
|
@ -92,5 +92,10 @@ TELEGRAM_BOT_TOKEN = "8410461852:AAGXQCwRPFbndqwTgLJh8kYxST4Z0vgh72U"
|
||||||
# TELEGRAM_CHAT_IDS = "5147760058"
|
# TELEGRAM_CHAT_IDS = "5147760058"
|
||||||
TELEGRAM_CHAT_IDS = "-5075171894"
|
TELEGRAM_CHAT_IDS = "-5075171894"
|
||||||
|
|
||||||
|
[triggers]
|
||||||
|
crons = ["0 16 * * *", "0 1 * * *"]
|
||||||
|
# crons = ["* * * * *"]
|
||||||
|
# crons = ["7 18 * * *", "10 18 * * *"]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
upload_source_maps = true
|
upload_source_maps = true
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ app.use(express.static(path.join(__dirname, 'public')));
|
||||||
// Home route
|
// Home route
|
||||||
app.get('/', (_, res) => {
|
app.get('/', (_, res) => {
|
||||||
res.render('index', {
|
res.render('index', {
|
||||||
title: 'Freshyo - Freshness Redefined',
|
title: 'Freshyo - Delivering Freshness',
|
||||||
year: new Date().getFullYear()
|
year: new Date().getFullYear()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ export default function AddToCartDialog() {
|
||||||
const { data: cartData } = useGetCart();
|
const { data: cartData } = useGetCart();
|
||||||
const { data: constsData } = useGetEssentialConsts();
|
const { data: constsData } = useGetEssentialConsts();
|
||||||
const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap);
|
const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap);
|
||||||
// const isFlashDeliveryEnabled = constsData?.isFlashDeliveryEnabled === true;
|
const isFlashDeliveryEnabled = constsData?.isFlashDeliveryEnabled === true;
|
||||||
const isFlashDeliveryEnabled = true;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,10 @@ export const Route = createRootRoute({
|
||||||
},
|
},
|
||||||
{ title: 'Freshyo - Fresh Meat Delivery' },
|
{ title: 'Freshyo - Fresh Meat Delivery' },
|
||||||
],
|
],
|
||||||
links: [{ rel: 'stylesheet', href: appCss }],
|
links: [
|
||||||
|
{ rel: 'stylesheet', href: appCss },
|
||||||
|
{ rel: 'icon', type: 'image/png', href: '/favicon.png' },
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
shellComponent: RootDocument,
|
shellComponent: RootDocument,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import { ProductCard } from '../components/ProductCard'
|
||||||
import AddToCartDialog from '../components/AddToCartDialog'
|
import AddToCartDialog from '../components/AddToCartDialog'
|
||||||
import { useProductSlotIdentifier } from '../hooks/useProductSlotIdentifier'
|
import { useProductSlotIdentifier } from '../hooks/useProductSlotIdentifier'
|
||||||
import { usePopulateCentralStores } from '../hooks/usePopulateCentralStores'
|
import { usePopulateCentralStores } from '../hooks/usePopulateCentralStores'
|
||||||
import { Store, ImageOff } from 'lucide-react'
|
import { Store, ImageOff, Loader2 } from 'lucide-react'
|
||||||
|
|
||||||
// Scroll Indicator Component
|
// Scroll Indicator Component
|
||||||
function ScrollIndicator({
|
function ScrollIndicator({
|
||||||
|
|
@ -75,13 +75,32 @@ function ScrollIndicator({
|
||||||
|
|
||||||
export const Route = createFileRoute('/home/')({ component: HomePage })
|
export const Route = createFileRoute('/home/')({ component: HomePage })
|
||||||
|
|
||||||
|
// Section Spinner Component
|
||||||
|
function SectionSpinner({ label }: { label?: string }) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center py-10">
|
||||||
|
<Loader2 className="h-8 w-8 animate-spin text-brand-500" />
|
||||||
|
{label && (
|
||||||
|
<p className="mt-2 text-sm text-gray-500">{label}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function HomePage() {
|
function HomePage() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { data: productsData } = useAllProducts()
|
const { data: productsData, isLoading: isProductsLoading } = useAllProducts()
|
||||||
const { data: storesData } = useStores()
|
const { data: storesData, isLoading: isStoresLoading } = useStores()
|
||||||
const { data: bannersData } = useBanners()
|
const { data: bannersData } = useBanners()
|
||||||
const { data: slotsData } = useSlots()
|
const { data: slotsData, isLoading: isSlotsLoading } = useSlots()
|
||||||
const { data: essentialConsts } = useGetEssentialConsts()
|
const { data: essentialConsts, isLoading: isEssentialConstsLoading } = useGetEssentialConsts()
|
||||||
|
|
||||||
|
// Handle bootstrapping: products/stores/slots are disabled until essentialConsts provides cacheUrl
|
||||||
|
const isBootstrapping = isEssentialConstsLoading
|
||||||
|
|
||||||
|
const storesLoading = isBootstrapping || isStoresLoading
|
||||||
|
const productsLoading = isBootstrapping || isProductsLoading
|
||||||
|
const slotsLoading = isBootstrapping || isSlotsLoading
|
||||||
const { setAddedToCartProduct } = useCartStore()
|
const { setAddedToCartProduct } = useCartStore()
|
||||||
const { getQuickestSlot } = useProductSlotIdentifier()
|
const { getQuickestSlot } = useProductSlotIdentifier()
|
||||||
const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap)
|
const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap)
|
||||||
|
|
@ -201,18 +220,20 @@ function HomePage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stores Section */}
|
{/* Stores Section */}
|
||||||
{stores.length > 0 && (
|
<div className="mb-6">
|
||||||
<div className="mb-6">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div>
|
||||||
<div>
|
<p className="font-bold text-xl text-gray-900">
|
||||||
<p className="font-bold text-xl text-gray-900">
|
Our Stores
|
||||||
Our Stores
|
</p>
|
||||||
</p>
|
<p className="mt-0.5 text-xs text-gray-500">
|
||||||
<p className="mt-0.5 text-xs text-gray-500">
|
Fresh from our locations
|
||||||
Fresh from our locations
|
</p>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{storesLoading ? (
|
||||||
|
<SectionSpinner label="Loading stores..." />
|
||||||
|
) : (
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{stores.map((store: any) => (
|
{stores.map((store: any) => (
|
||||||
<div key={store.id}>
|
<div key={store.id}>
|
||||||
|
|
@ -228,70 +249,78 @@ function HomePage() {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
{/* Popular Items Section */}
|
{/* Popular Items Section */}
|
||||||
{popularProducts.length > 0 && (
|
<div className="mb-6">
|
||||||
<div className="mb-6">
|
<div className="mb-4">
|
||||||
<div className="mb-4">
|
<p className="font-bold text-xl text-gray-900">
|
||||||
<p className="font-bold text-xl text-gray-900">
|
Popular Items
|
||||||
Popular Items
|
</p>
|
||||||
</p>
|
<p className="mt-0.5 text-sm text-gray-500">
|
||||||
<p className="mt-0.5 text-sm text-gray-500">
|
Trending fresh picks just for you
|
||||||
Trending fresh picks just for you
|
</p>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
ref={popularScrollRef}
|
|
||||||
className="scrollbar-hide -mx-4 flex gap-4 overflow-x-auto px-4 pb-2"
|
|
||||||
>
|
|
||||||
{popularProducts.map((product) => (
|
|
||||||
<div key={product.id} className="w-40 shrink-0">
|
|
||||||
<ProductCard
|
|
||||||
item={product}
|
|
||||||
onPress={() => handleProductPress(product.id)}
|
|
||||||
showDeliveryInfo={false}
|
|
||||||
miniView={true}
|
|
||||||
useAddToCartDialog={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<ScrollIndicator
|
|
||||||
containerRef={popularScrollRef}
|
|
||||||
itemCount={popularProducts.length}
|
|
||||||
itemWidth={160}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{productsLoading ? (
|
||||||
|
<SectionSpinner label="Loading popular items..." />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
ref={popularScrollRef}
|
||||||
|
className="scrollbar-hide -mx-4 flex gap-4 overflow-x-auto px-4 pb-2"
|
||||||
|
>
|
||||||
|
{popularProducts.map((product) => (
|
||||||
|
<div key={product.id} className="w-40 shrink-0">
|
||||||
|
<ProductCard
|
||||||
|
item={product}
|
||||||
|
onPress={() => handleProductPress(product.id)}
|
||||||
|
showDeliveryInfo={false}
|
||||||
|
miniView={true}
|
||||||
|
useAddToCartDialog={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<ScrollIndicator
|
||||||
|
containerRef={popularScrollRef}
|
||||||
|
itemCount={popularProducts.length}
|
||||||
|
itemWidth={160}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Upcoming Delivery Slots Section */}
|
{/* Upcoming Delivery Slots Section */}
|
||||||
{sortedSlots.length > 0 && (
|
<div className="mb-6">
|
||||||
<div className="mb-6">
|
<div className="mb-4">
|
||||||
<div className="mb-4">
|
<p className="font-bold text-xl text-gray-900">
|
||||||
<p className="font-bold text-xl text-gray-900">
|
Upcoming Delivery Slots
|
||||||
Upcoming Delivery Slots
|
</p>
|
||||||
</p>
|
<p className="mt-0.5 text-sm text-gray-500">
|
||||||
<p className="mt-0.5 text-sm text-gray-500">
|
Plan your fresh deliveries ahead
|
||||||
Plan your fresh deliveries ahead
|
</p>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
ref={slotsScrollRef}
|
|
||||||
className="scrollbar-hide -mx-4 flex gap-4 overflow-x-auto px-4 pb-2"
|
|
||||||
>
|
|
||||||
{sortedSlots.slice(0, 5).map((slot) => (
|
|
||||||
<SlotCard key={slot.id} slot={slot} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<ScrollIndicator
|
|
||||||
containerRef={slotsScrollRef}
|
|
||||||
itemCount={sortedSlots.slice(0, 5).length}
|
|
||||||
itemWidth={280}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{slotsLoading ? (
|
||||||
|
<SectionSpinner label="Loading slots..." />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
ref={slotsScrollRef}
|
||||||
|
className="scrollbar-hide -mx-4 flex gap-4 overflow-x-auto px-4 pb-2"
|
||||||
|
>
|
||||||
|
{sortedSlots.slice(0, 5).map((slot) => (
|
||||||
|
<SlotCard key={slot.id} slot={slot} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<ScrollIndicator
|
||||||
|
containerRef={slotsScrollRef}
|
||||||
|
itemCount={sortedSlots.slice(0, 5).length}
|
||||||
|
itemWidth={280}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* All Products Section */}
|
{/* All Products Section */}
|
||||||
<div className="rounded-t-3xl bg-white pt-4">
|
<div className="rounded-t-3xl bg-white pt-4">
|
||||||
|
|
@ -304,23 +333,20 @@ function HomePage() {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Responsive Grid for Products - 2 columns on mobile */}
|
{productsLoading ? (
|
||||||
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-4">
|
<SectionSpinner label="Loading products..." />
|
||||||
{sortedProducts.map((product) => (
|
) : (
|
||||||
<ProductCard
|
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-4">
|
||||||
key={product.id}
|
{sortedProducts.map((product) => (
|
||||||
item={product}
|
<ProductCard
|
||||||
onPress={() => handleProductPress(product.id)}
|
key={product.id}
|
||||||
showDeliveryInfo={true}
|
item={product}
|
||||||
miniView={false}
|
onPress={() => handleProductPress(product.id)}
|
||||||
useAddToCartDialog={true}
|
showDeliveryInfo={true}
|
||||||
/>
|
miniView={false}
|
||||||
))}
|
useAddToCartDialog={true}
|
||||||
</div>
|
/>
|
||||||
|
))}
|
||||||
{sortedProducts.length === 0 && (
|
|
||||||
<div className="py-8 text-center">
|
|
||||||
<p className="text-gray-500">No products available</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
payments,
|
payments,
|
||||||
refunds,
|
refunds,
|
||||||
} from '../db/schema'
|
} from '../db/schema'
|
||||||
import { and, desc, eq, inArray, lt, SQL } from 'drizzle-orm'
|
import { and, desc, eq, gt, inArray, lt, SQL } from 'drizzle-orm'
|
||||||
import type {
|
import type {
|
||||||
AdminOrderDetails,
|
AdminOrderDetails,
|
||||||
AdminOrderRow,
|
AdminOrderRow,
|
||||||
|
|
@ -450,8 +450,22 @@ export async function getAllOrders(input: GetAllOrdersInput): Promise<AdminGetAl
|
||||||
} = input
|
} = input
|
||||||
|
|
||||||
let whereCondition: SQL<unknown> | undefined = undefined
|
let whereCondition: SQL<unknown> | undefined = undefined
|
||||||
|
|
||||||
|
if(!cursor) {
|
||||||
|
// Get max order ID for initial pagination
|
||||||
|
const [maxOrder] = await db
|
||||||
|
.select()
|
||||||
|
.from(orders)
|
||||||
|
.orderBy(desc(orders.id))
|
||||||
|
.limit(1)
|
||||||
|
|
||||||
|
const maxId = maxOrder?.id ?? 0
|
||||||
|
const threshold = maxId - limit - 5
|
||||||
|
whereCondition = and(whereCondition, gt(orders.id, threshold))
|
||||||
|
}
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
whereCondition = and(whereCondition, lt(orders.id, cursor))
|
whereCondition = and(whereCondition, lt(orders.id, cursor))
|
||||||
|
whereCondition = and(whereCondition, gt(orders.id, cursor-limit-5))
|
||||||
}
|
}
|
||||||
if (slotId) {
|
if (slotId) {
|
||||||
whereCondition = and(whereCondition, eq(orders.slotId, slotId))
|
whereCondition = and(whereCondition, eq(orders.slotId, slotId))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue