Merge pull request 'test' (#2) from test into main

Reviewed-on: #2
This commit is contained in:
shafi 2026-03-09 17:30:04 +00:00
commit e5f80c9237
10 changed files with 85 additions and 56 deletions

View file

@ -103,6 +103,18 @@ export function OrderOptionsMenu({
}
};
const handleOpenInMaps = () => {
if (order.latitude && order.longitude) {
const url = `https://www.google.com/maps/search/?api=1&query=${order.latitude},${order.longitude}`;
Linking.openURL(url);
} else {
Alert.alert('No location coordinates available');
}
};
const hasCoordinates = order.latitude !== null && order.latitude !== undefined &&
order.longitude !== null && order.longitude !== undefined;
return (
<BottomDialog open={open} onClose={onClose}>
<View style={{ maxHeight: SCREEN_HEIGHT * 0.7 }}>
@ -257,6 +269,29 @@ export function OrderOptionsMenu({
<MaterialIcons name="chevron-right" size={24} color="#9ca3af" style={tw`ml-auto`} />
</TouchableOpacity>
{hasCoordinates && (
<TouchableOpacity
style={tw`flex-row items-center p-4 bg-white border border-gray-100 rounded-xl mb-3 shadow-sm`}
onPress={() => {
handleOpenInMaps();
onClose();
}}
>
<View style={tw`w-10 h-10 rounded-full bg-blue-50 items-center justify-center mr-4`}>
<MaterialIcons name="map" size={20} color="#2563eb" />
</View>
<View>
<MyText style={tw`font-semibold text-gray-800 text-base`}>
Open in Maps
</MyText>
<MyText style={tw`text-gray-500 text-xs`}>
View delivery location on Google Maps
</MyText>
</View>
<MaterialIcons name="chevron-right" size={24} color="#9ca3af" style={tw`ml-auto`} />
</TouchableOpacity>
)}
<TouchableOpacity
style={tw`flex-row items-center p-4 bg-white border border-gray-100 rounded-xl mb-3 shadow-sm`}
onPress={() => {

View file

@ -10,6 +10,8 @@ import {
refunds,
coupons,
couponUsage,
complaints,
payments,
} from "@/src/db/schema";
import { eq, and, gte, lt, desc, SQL, inArray } from "drizzle-orm";
import dayjs from "dayjs";
@ -1001,3 +1003,16 @@ export const orderRouter = router({
// {"id": "order_Rhh00qJNdjUp8o", "notes": {"retry": "true", "customerOrderId": "14"}, "amount": 21000, "entity": "order", "status": "created", "receipt": "order_14_retry", "attempts": 0, "currency": "INR", "offer_id": null, "signature": "6df20655021f1d6841340f2a2ef2ef9378cb3d43495ab09e85f08aea1a851583", "amount_due": 21000, "created_at": 1763575791, "payment_id": "pay_Rhh15cLL28YM7j", "amount_paid": 0}
type RefundStatus = "success" | "pending" | "failed" | "none" | "na";
export async function deleteOrderById(orderId: number): Promise<void> {
await db.transaction(async (tx) => {
await tx.delete(orderItems).where(eq(orderItems.orderId, orderId));
await tx.delete(orderStatus).where(eq(orderStatus.orderId, orderId));
await tx.delete(payments).where(eq(payments.orderId, orderId));
await tx.delete(refunds).where(eq(refunds.orderId, orderId));
await tx.delete(couponUsage).where(eq(couponUsage.orderId, orderId));
await tx.delete(complaints).where(eq(complaints.orderId, orderId));
await tx.delete(orders).where(eq(orders.id, orderId));
});
}

View file

@ -5,7 +5,7 @@ import { productInfo, units, productSlots, deliverySlotInfo, specialDeals, store
import { claimUploadUrl, extractKeyFromPresignedUrl, scaffoldAssetUrl } from '@/src/lib/s3-client';
import { ApiError } from '@/src/lib/api-error';
import { eq, and, gt, sql, inArray, desc } from 'drizzle-orm';
import { getProductById as getProductByIdFromCache, getAllProducts as getAllProductsFromCache } from '@/src/stores/product-store';
import { getProductById as getProductByIdFromCache } from '@/src/stores/product-store';
import dayjs from 'dayjs';
// Uniform Product Type
@ -246,20 +246,4 @@ export const productRouter = router({
return { success: true, review: newReview };
}),
getAllProductsSummary: publicProcedure
.query(async (): Promise<Product[]> => {
// Get all products from cache
const allCachedProducts = await getAllProductsFromCache();
// Transform the cached products to match the expected summary format
// (with empty deliverySlots and specialDeals arrays for summary view)
const transformedProducts = allCachedProducts.map(product => ({
...product,
deliverySlots: [], // Empty for summary view
specialDeals: [], // Empty for summary view
}));
return transformedProducts;
}),
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -54,13 +54,13 @@ const PaymentAndOrderComponent: React.FC<PaymentAndOrderProps> = ({
queryClient.invalidateQueries({ queryKey: [`local-cart-${cartType}`] });
};
const { data: productsData } = trpc.user.product.getAllProductsSummary.useQuery();
const { data: productsData } = trpc.common.product.getAllProductsSummary.useQuery({});
// Memoized flash-eligible product IDs
const flashEligibleProductIds = useMemo(() => {
if (!productsData) return new Set<number>();
if (!productsData?.products) return new Set<number>();
return new Set(
productsData
productsData.products
.filter((product: any) => product.isFlashAvailable)
.map((product: any) => product.id)
);
@ -397,4 +397,4 @@ const PaymentAndOrderComponent: React.FC<PaymentAndOrderProps> = ({
);
};
export default PaymentAndOrderComponent;
export default PaymentAndOrderComponent;

View file

@ -348,7 +348,7 @@ export function SlotProducts({ slotId:slotIdParent, storeId:storeIdParent, baseU
const slotQuery = trpc.user.slots.getSlotById.useQuery({ slotId: slotId! }, { enabled: !!slotId });
const productsQuery = trpc.user.product.getAllProductsSummary.useQuery();
const productsQuery = trpc.common.product.getAllProductsSummary.useQuery({});
const { addToCart = () => { } } = useAddToCart({ showSuccessAlert: false, showErrorAlert: false, refetchCart: true }, "regular") || {};
@ -401,8 +401,8 @@ export function SlotProducts({ slotId:slotIdParent, storeId:storeIdParent, baseU
const slotProductIds = new Set(slotQuery.data.products?.map((p: any) => p.id) || []);
const filteredProducts: any[] = storeIdNum
? productsQuery?.data?.filter(p =>
p.store?.id === storeIdNum && slotProductIds.has(p.id)
? productsQuery?.data?.products?.filter(p =>
p.storeId === storeIdNum && slotProductIds.has(p.id)
) || []
: slotQuery.data.products;
@ -448,7 +448,7 @@ export function FlashDeliveryProducts({ storeId:storeIdParent, baseUrl, onProduc
const storeId = storeIdParent;
const storeIdNum = storeId;
const productsQuery = trpc.user.product.getAllProductsSummary.useQuery();
const productsQuery = trpc.common.product.getAllProductsSummary.useQuery({});
const { addToCart = () => { } } = useAddToCart({ showSuccessAlert: false, showErrorAlert: false, refetchCart: true }, "flash") || {};
@ -489,14 +489,14 @@ export function FlashDeliveryProducts({ storeId:storeIdParent, baseUrl, onProduc
let flashProducts: any[] = [];
if (storeIdNum) {
// Filter by store, flash availability, and stock status
flashProducts = productsQuery?.data?.filter(p =>
p.store?.id === storeIdNum &&
flashProducts = productsQuery?.data?.products?.filter(p =>
p.storeId === storeIdNum &&
p.isFlashAvailable &&
!p.isOutOfStock
) || [];
} else {
// Show all flash-available products that are in stock
flashProducts = productsQuery?.data?.filter(p =>
flashProducts = productsQuery?.data?.products?.filter(p =>
p.isFlashAvailable &&
!p.isOutOfStock
) || [];
@ -533,4 +533,4 @@ export function FlashDeliveryProducts({ storeId:storeIdParent, baseUrl, onProduc
/>
</View>
);
}
}

View file

@ -80,16 +80,16 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
const { data: couponsRaw, error: couponsError } = trpc.user.coupon.getEligible.useQuery();
const { data: constsData } = useGetEssentialConsts();
const { data: productsData } = trpc.user.product.getAllProductsSummary.useQuery();
const { data: productsData } = trpc.common.product.getAllProductsSummary.useQuery({});
const cartItems = cartData?.items || [];
// Memoized flash-eligible product IDs
const flashEligibleProductIds = useMemo(() => {
if (!productsData) return new Set<number>();
if (!productsData?.products) return new Set<number>();
return new Set(
productsData
productsData.products
.filter((product: any) => product.isFlashAvailable)
.map((product: any) => product.id)
);

View file

@ -35,7 +35,7 @@ const CheckoutPage: React.FC<CheckoutPageProps> = ({ isFlashDelivery = false })
const { data: addresses, refetch: refetchAddresses } = trpc.user.address.getUserAddresses.useQuery();
const { data: slotsData, refetch: refetchSlots } = trpc.user.slots.getSlots.useQuery();
const { data: constsData } = useGetEssentialConsts();
const { data: productsData } = trpc.user.product.getAllProductsSummary.useQuery();
const { data: productsData } = trpc.common.product.getAllProductsSummary.useQuery({});
useMarkDataFetchers(() => {
refetchCart();
@ -53,9 +53,9 @@ const CheckoutPage: React.FC<CheckoutPageProps> = ({ isFlashDelivery = false })
// Memoized flash-eligible product IDs
const flashEligibleProductIds = useMemo(() => {
if (!productsData) return new Set<number>();
if (!productsData?.products) return new Set<number>();
return new Set(
productsData
productsData.products
.filter((product: any) => product.isFlashAvailable)
.map((product: any) => product.id)
);
@ -273,4 +273,4 @@ const CheckoutPage: React.FC<CheckoutPageProps> = ({ isFlashDelivery = false })
);
};
export default CheckoutPage;
export default CheckoutPage;

View file

@ -24,21 +24,8 @@ interface LocalCartItem {
interface ProductSummary {
id: number;
name: string;
shortDescription?: string | null;
longDescription?: string | null;
price: string;
marketPrice?: string | null;
unitNotation: string;
images: string[];
isOutOfStock: boolean;
store?: { id: number; name: string; description?: string | null } | null;
incrementStep: number;
productQuantity: number;
isFlashAvailable: boolean;
flashPrice?: string | null;
deliverySlots: Array<{ id: number; deliveryTime: Date; freezeTime: Date }>;
specialDeals: Array<{ quantity: string; price: string; validTill: Date }>;
}
interface CartItem {
@ -146,15 +133,23 @@ export function useGetCart(options?: {
};
} else {
const { data: products } = trpc.user.product.getAllProductsSummary.useQuery();
const { data: products } = trpc.common.product.getAllProductsSummary.useQuery({});
const query = useQuery({
queryKey: [`local-cart-${cartType}`],
queryFn: async () => {
const cartItems = await getLocalCart(cartType);
// const productMap = Object.fromEntries(products?.map((p: ProductSummary) => [p.id, p]) || []);
const productMap = Object.fromEntries(products?.map((p) => [p.id, p]) || []);
const productMap = Object.fromEntries(
products?.products?.map((p) => [
p.id,
{
...p,
price: String(p.price),
marketPrice: p.marketPrice === null || p.marketPrice === undefined ? null : String(p.marketPrice),
} as ProductSummary,
]) || []
);
const items: CartItem[] = cartItems.map(cartItem => {
const product = productMap[cartItem.productId];
@ -507,4 +502,4 @@ export function useRemoveFromCart(options?: {
}
// Export clear cart function for direct use
export { clearLocalCart };
export { clearLocalCart };

View file

@ -64,9 +64,9 @@ const isDevMode = Constants.executionEnvironment !== "standalone";
// const BASE_API_URL = 'http://10.0.2.2:4000';
// const BASE_API_URL = 'http://192.168.100.101:4000';
// const BASE_API_URL = 'http://192.168.1.5:4000';
// let BASE_API_URL = "https://mf.freshyo.in";
let BASE_API_URL = "https://freshyo.technocracy.ovh";
// let BASE_API_URL = 'http://192.168.100.104:4000';
let BASE_API_URL = "https://mf.freshyo.in";
// let BASE_API_URL = "https://freshyo.technocracy.ovh";
// let BASE_API_URL = 'http://192.168.100.107:4000';
// let BASE_API_URL = 'http://192.168.29.176:4000';
// if(isDevMode) {