enh
This commit is contained in:
parent
360289d3c6
commit
d9a61818de
9 changed files with 33 additions and 40 deletions
|
|
@ -302,7 +302,7 @@ export default function DeliverySequences() {
|
||||||
// Auto-select first slot if no slotId provided
|
// Auto-select first slot if no slotId provided
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!slotId && slotsData?.slots && slotsData.slots.length > 0) {
|
if (!slotId && slotsData?.slots && slotsData.slots.length > 0) {
|
||||||
router.replace(`/manage-orders/delivery-sequences?slotId=${slotsData.slots[0].id}`);
|
router.replace(`/(drawer)/dashboard/manage-orders/delivery-sequences?slotId=${slotsData.slots[0].id}`);
|
||||||
}
|
}
|
||||||
}, [slotId, slotsData, router]);
|
}, [slotId, slotsData, router]);
|
||||||
|
|
||||||
|
|
@ -505,7 +505,7 @@ export default function DeliverySequences() {
|
||||||
value={selectedSlotId || ""}
|
value={selectedSlotId || ""}
|
||||||
onValueChange={(val) => {
|
onValueChange={(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
router.replace(`/manage-orders/delivery-sequences?slotId=${val}`);
|
router.replace(`/(drawer)/dashboard/manage-orders/delivery-sequences?slotId=${val}`);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
placeholder="Select slot"
|
placeholder="Select slot"
|
||||||
|
|
@ -726,7 +726,7 @@ export default function DeliverySequences() {
|
||||||
}}
|
}}
|
||||||
onViewDetails={() => {
|
onViewDetails={() => {
|
||||||
if (selectedOrder) {
|
if (selectedOrder) {
|
||||||
router.push(`/manage-orders/order-details/${selectedOrder.id}`);
|
router.push(`/(drawer)/dashboard/manage-orders/order-details/${selectedOrder.id}`);
|
||||||
}
|
}
|
||||||
setShowOrderMenu(false);
|
setShowOrderMenu(false);
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -105,12 +105,12 @@ const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void }
|
||||||
const updateItemPackagingMutation = trpc.admin.order.updateOrderItemPackaging.useMutation();
|
const updateItemPackagingMutation = trpc.admin.order.updateOrderItemPackaging.useMutation();
|
||||||
|
|
||||||
const handleOrderPress = () => {
|
const handleOrderPress = () => {
|
||||||
router.push(`/manage-orders/order-details/${order.orderId}` as any);
|
router.push(`/(drawer)/dashboard/manage-orders/order-details/${order.orderId}` as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuOption = () => {
|
const handleMenuOption = () => {
|
||||||
setMenuOpen(false);
|
setMenuOpen(false);
|
||||||
router.push(`/manage-orders/order-details/${order.orderId}` as any);
|
router.push(`/(drawer)/dashboard/manage-orders/order-details/${order.orderId}` as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMarkPackaged = (isPackaged: boolean) => {
|
const handleMarkPackaged = (isPackaged: boolean) => {
|
||||||
|
|
|
||||||
|
|
@ -419,7 +419,7 @@ export default function PricesOverview() {
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={tw`flex-row items-center p-4 bg-gray-50 rounded-lg`}
|
style={tw`flex-row items-center p-4 bg-gray-50 rounded-lg`}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push('/rebalance-orders' as any);
|
router.push('/(drawer)/dashboard/rebalance-orders' as any);
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -95,11 +95,11 @@ export default function ProductTags() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddNewTag = () => {
|
const handleAddNewTag = () => {
|
||||||
router.push('/product-tags/add');
|
router.push('/(drawer)/dashboard/product-tags/add');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOrderTags = () => {
|
const handleOrderTags = () => {
|
||||||
router.push('/product-tags/order');
|
router.push('/(drawer)/dashboard/product-tags/order');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ const SlotItemComponent: React.FC<SlotItemProps> = ({
|
||||||
</View>
|
</View>
|
||||||
<View style={tw`flex-row items-center`}>
|
<View style={tw`flex-row items-center`}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => router.push(`/slots/edit/${slot.id}` as any)}
|
onPress={() => router.push(`/(drawer)/dashboard/slots/edit/${slot.id}` as any)}
|
||||||
style={tw`px-3 py-1 rounded-full bg-pink2 mr-2`}
|
style={tw`px-3 py-1 rounded-full bg-pink2 mr-2`}
|
||||||
>
|
>
|
||||||
<View style={tw`flex-row items-center`}>
|
<View style={tw`flex-row items-center`}>
|
||||||
|
|
@ -147,7 +147,7 @@ const SlotItemComponent: React.FC<SlotItemProps> = ({
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setMenuOpen(false);
|
setMenuOpen(false);
|
||||||
router.push(`/slots/add?baseslot=${slot.id}` as any);
|
router.push(`/(drawer)/dashboard/slots/add?baseslot=${slot.id}` as any);
|
||||||
}}
|
}}
|
||||||
style={tw`py-4 border-b border-gray-200`}
|
style={tw`py-4 border-b border-gray-200`}
|
||||||
>
|
>
|
||||||
|
|
@ -277,7 +277,7 @@ export default function Slots() {
|
||||||
<MyTouchableOpacity
|
<MyTouchableOpacity
|
||||||
testID="add-slot-fab"
|
testID="add-slot-fab"
|
||||||
accessibilityLabel="add-slot-fab"
|
accessibilityLabel="add-slot-fab"
|
||||||
onPress={() => router.push('/slots/add' as any)}
|
onPress={() => router.push('/(drawer)/dashboard/slots/add' as any)}
|
||||||
activeOpacity={0.95}
|
activeOpacity={0.95}
|
||||||
style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }}
|
style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ export default function SlotDetails() {
|
||||||
|
|
||||||
{/* FAB for Edit Slot */}
|
{/* FAB for Edit Slot */}
|
||||||
<MyTouchableOpacity
|
<MyTouchableOpacity
|
||||||
onPress={() => router.push(`/slots/edit/${slot.id}` as any)}
|
onPress={() => router.push(`/(drawer)/dashboard/slots/edit/${slot.id}` as any)}
|
||||||
activeOpacity={0.95}
|
activeOpacity={0.95}
|
||||||
style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }}
|
style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ export const TagMenu: React.FC<TagMenuProps> = ({
|
||||||
|
|
||||||
const handleEditTag = () => {
|
const handleEditTag = () => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
router.push(`/product-tags/edit?tagId=${tagId}`);
|
router.push(`/(drawer)/dashboard/product-tags/edit?tagId=${tagId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteTag = () => {
|
const handleDeleteTag = () => {
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,16 @@ import { router, protectedProcedure } from '@/src/trpc/trpc-index'
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { computeConstants } from '@/src/lib/const-store'
|
import { computeConstants } from '@/src/lib/const-store'
|
||||||
import { CONST_KEYS } from '@/src/lib/const-keys'
|
import { CONST_KEYS } from '@/src/lib/const-keys'
|
||||||
|
import { scheduleStoreInitialization } from '@/src/stores/store-initializer'
|
||||||
import { getAllConstants as getAllConstantsFromDb, upsertConstants as upsertConstantsInDb } from '@/src/dbService'
|
import { getAllConstants as getAllConstantsFromDb, upsertConstants as upsertConstantsInDb } from '@/src/dbService'
|
||||||
import type { Constant, ConstantUpdateResult } from '@packages/shared'
|
import type { Constant, ConstantUpdateResult } from '@packages/shared'
|
||||||
|
|
||||||
|
// Constants that are baked into the versioned cache files (products.json etc.)
|
||||||
|
// — changing them requires regenerating the cache so the user app picks it up.
|
||||||
|
const CACHE_AFFECTING_KEYS: string[] = [
|
||||||
|
CONST_KEYS.tagsOrder,
|
||||||
|
]
|
||||||
|
|
||||||
export const constRouter = router({
|
export const constRouter = router({
|
||||||
getConstants: protectedProcedure
|
getConstants: protectedProcedure
|
||||||
.query(async (): Promise<Constant[]> => {
|
.query(async (): Promise<Constant[]> => {
|
||||||
|
|
@ -64,6 +71,13 @@ export const constRouter = router({
|
||||||
// Refresh all constants in Redis after database update
|
// Refresh all constants in Redis after database update
|
||||||
await computeConstants();
|
await computeConstants();
|
||||||
|
|
||||||
|
// Constants like tagsOrder are baked into the versioned cache files.
|
||||||
|
// Regenerate the cache (bumps cacheVersion) so the user app fetches the
|
||||||
|
// new data (e.g., the new tab order on the home page).
|
||||||
|
if (constants.some((c) => CACHE_AFFECTING_KEYS.includes(c.key))) {
|
||||||
|
await scheduleStoreInitialization()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
updatedCount: constants.length,
|
updatedCount: constants.length,
|
||||||
|
|
|
||||||
|
|
@ -593,35 +593,14 @@ export default function Dashboard() {
|
||||||
productById.set(product.id, product);
|
productById.set(product.id, product);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tag.productIds is already in the admin-curated order (backend sorts by sortOrder).
|
// Respect the admin-curated order — tag.productIds is already ordered by
|
||||||
const orderedIds = (tag.productIds || []).filter((id: number) => productById.has(id));
|
// the tag's sortOrder (backend reorders it when building the cache).
|
||||||
const ordered: any[] = [];
|
map[tag.id] = (tag.productIds || [])
|
||||||
const rest: any[] = [];
|
.map((id: number) => productById.get(id))
|
||||||
for (const id of orderedIds) {
|
.filter(Boolean) as any[];
|
||||||
const product = productById.get(id);
|
|
||||||
const isOutOfStock = Boolean(productSlotsMap[id]?.isOutOfStock) || !getQuickestSlot(id);
|
|
||||||
if (isOutOfStock) rest.push(product);
|
|
||||||
else ordered.push(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Products in the tag's productIds but not in the curated order (added later) — availability sort.
|
|
||||||
const seen = new Set(orderedIds);
|
|
||||||
const extra = products
|
|
||||||
.filter((product: any) => (tag.productIds?.includes(product.id) ?? false) && !seen.has(product.id))
|
|
||||||
.sort((a: any, b: any) => {
|
|
||||||
const slotA = getQuickestSlot(a.id)
|
|
||||||
const slotB = getQuickestSlot(b.id)
|
|
||||||
const aOutOfStock = Boolean(productSlotsMap[a.id]?.isOutOfStock) || !slotA
|
|
||||||
const bOutOfStock = Boolean(productSlotsMap[b.id]?.isOutOfStock) || !slotB
|
|
||||||
if (aOutOfStock && !bOutOfStock) return 1
|
|
||||||
if (!aOutOfStock && bOutOfStock) return -1
|
|
||||||
return 0
|
|
||||||
});
|
|
||||||
|
|
||||||
map[tag.id] = [...ordered, ...rest, ...extra];
|
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}, [dashboardTags, products, getQuickestSlot, productSlotsMap]);
|
}, [dashboardTags, products]);
|
||||||
|
|
||||||
const handleRefresh = useCallback(async () => {
|
const handleRefresh = useCallback(async () => {
|
||||||
setIsRefreshing(true);
|
setIsRefreshing(true);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue