From 2e90c36de7cd0834f25d155fc69d5016fb3313c7 Mon Sep 17 00:00:00 2001 From: shafi54 <108669266+shafi-aviz@users.noreply.github.com> Date: Tue, 15 Sep 2026 19:14:48 +0530 Subject: [PATCH] enh --- apps/user-ui/hooks/cart-query-hooks.tsx | 45 +++++++++++++++++++ .../components/CentralStoreInitializer.tsx | 2 + change-log.txt | 23 ++++++++++ 3 files changed, 70 insertions(+) diff --git a/apps/user-ui/hooks/cart-query-hooks.tsx b/apps/user-ui/hooks/cart-query-hooks.tsx index fddbf6f..ebbfa4d 100644 --- a/apps/user-ui/hooks/cart-query-hooks.tsx +++ b/apps/user-ui/hooks/cart-query-hooks.tsx @@ -1,6 +1,8 @@ import { useCentralProductStore } from '@/src/store/centralProductStore'; import { useCentralSlotStore } from '@/src/store/centralSlotStore'; import { Alert } from 'react-native'; +import { useEffect, useRef } from 'react'; +import dayjs from 'dayjs'; import { useQuery, useMutation, useQueryClient, UseQueryResult, UseMutationResult } from '@tanstack/react-query'; import type { CartData as SharedCartData, ProductSummaryCore } from '@packages/shared'; import { StorageServiceCasual } from 'common-ui/src/services/StorageServiceCasual'; @@ -244,6 +246,49 @@ export function useGetCart(options: UseGetCartOptions = {}, cartType: CartType = }; } +export function useReconcileCartSlots() { + const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap); + const isSlotsLoaded = useCentralSlotStore((state) => state.isSlotsLoaded); + const queryClient = useQueryClient(); + const hasRun = useRef(false); + + useEffect(() => { + if (!isSlotsLoaded || hasRun.current) return; + hasRun.current = true; + + (async () => { + const items = await getLocalCart("regular"); + if (items.length === 0) return; + + let changed = false; + const nextItems: LocalCartItem[] = []; + + for (const item of items) { + const validSlots = productSlotsMap[item.skuId]?.slots ?? []; + + if (validSlots.some((slot) => slot.id === item.slotId)) { + nextItems.push(item); + continue; + } + + const nearestSlot = [...validSlots].sort( + (a, b) => dayjs(a.deliveryTime).valueOf() - dayjs(b.deliveryTime).valueOf() + )[0]; + + if (nearestSlot) { + nextItems.push({ ...item, slotId: nearestSlot.id }); + } + changed = true; + } + + if (changed) { + await saveLocalCart(nextItems, "regular"); + queryClient.invalidateQueries({ queryKey: ["local-cart-regular"] }); + } + })(); + }, [isSlotsLoaded, productSlotsMap, queryClient]); +} + export function useAddToCart(options: MutationOptions = {}, cartType: CartType = "regular"): UseAddToCartReturn { const queryClient = useQueryClient(); diff --git a/apps/user-ui/src/components/CentralStoreInitializer.tsx b/apps/user-ui/src/components/CentralStoreInitializer.tsx index 312a7e6..ead3408 100644 --- a/apps/user-ui/src/components/CentralStoreInitializer.tsx +++ b/apps/user-ui/src/components/CentralStoreInitializer.tsx @@ -1,11 +1,13 @@ import React from 'react'; import { useInitializeCentralSlotStore } from '@/src/store/centralSlotStore'; import { useInitializeCentralProductStore } from '@/src/store/centralProductStore'; +import { useReconcileCartSlots } from '@/hooks/cart-query-hooks'; import type { ReactParentComponent } from '@packages/shared'; export default function CentralStoreInitializer({ children }: ReactParentComponent) { useInitializeCentralSlotStore(); useInitializeCentralProductStore(); + useReconcileCartSlots(); return <>{children}; } diff --git a/change-log.txt b/change-log.txt index 3283569..64ecf78 100644 --- a/change-log.txt +++ b/change-log.txt @@ -2054,3 +2054,26 @@ index 1) instead of by placeholder: +- tapOn: +- id: "variant-1-price" - inputText: "999" + +[2026-09-15 18:38:49] Reconcile regular cart slots on app startup. + +Behavior: on launch, for each item in local `cart_items`, if its stored slotId is still a valid +slot for that SKU, keep it; otherwise move it to the nearest valid slot (earliest deliveryTime); +if the SKU has no valid slots, drop the item. Silent, regular cart only, runs once per launch. + +=== apps/user-ui/hooks/cart-query-hooks.tsx === +- import: + useEffect, useRef from 'react' +- import: + dayjs from 'dayjs' +- new export useReconcileCartSlots(): + reads productSlotsMap + isSlotsLoaded from useCentralSlotStore, guarded by useRef so it runs + once per app launch; reads getLocalCart('regular'), and for each item: + validSlots = productSlotsMap[item.skuId]?.slots ?? [] + if validSlots.some(s => s.id === item.slotId) -> keep item + else nearest = validSlots sorted by deliveryTime asc, take [0] + nearest ? item.slotId = nearest.id : drop item + if anything changed -> saveLocalCart(next, 'regular') and + queryClient.invalidateQueries({ queryKey: ['local-cart-regular'] }) + +=== apps/user-ui/src/components/CentralStoreInitializer.tsx === +- import: + useReconcileCartSlots from '@/hooks/cart-query-hooks' +- call useReconcileCartSlots() alongside existing store initializers.