enh
This commit is contained in:
parent
4e54a8c6ee
commit
d8271dd502
7 changed files with 82 additions and 17 deletions
|
|
@ -66,6 +66,7 @@ interface OrderType {
|
||||||
unit: string;
|
unit: string;
|
||||||
isPackaged?: boolean;
|
isPackaged?: boolean;
|
||||||
isPackageVerified?: boolean;
|
isPackageVerified?: boolean;
|
||||||
|
productSize: number;
|
||||||
}[];
|
}[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
deliveryTime: string | null;
|
deliveryTime: string | null;
|
||||||
|
|
@ -437,7 +438,7 @@ const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void }
|
||||||
<View key={idx} style={tw`py-2 border-b border-gray-50 last:border-0`}>
|
<View key={idx} style={tw`py-2 border-b border-gray-50 last:border-0`}>
|
||||||
<View style={tw`flex-row items-center`}>
|
<View style={tw`flex-row items-center`}>
|
||||||
<View style={tw`bg-gray-100 px-2 py-1 rounded items-center justify-center mr-2`}>
|
<View style={tw`bg-gray-100 px-2 py-1 rounded items-center justify-center mr-2`}>
|
||||||
<MyText style={tw`text-xs font-bold text-gray-600`}>{item.quantity} {item.unit}</MyText>
|
<MyText style={tw`text-xs font-bold text-gray-600`}>{item.quantity * item.productSize } {item.unit}</MyText>
|
||||||
</View>
|
</View>
|
||||||
<MyText style={tw`text-sm text-gray-800 flex-1`} numberOfLines={1} ellipsizeMode="tail">
|
<MyText style={tw`text-sm text-gray-800 flex-1`} numberOfLines={1} ellipsizeMode="tail">
|
||||||
{item.name.length > 30 ? `${item.name.substring(0, 30)}...` : item.name}
|
{item.name.length > 30 ? `${item.name.substring(0, 30)}...` : item.name}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
||||||
const displayPrice = change.price !== undefined ? change.price : product.price;
|
const displayPrice = change.price !== undefined ? change.price : product.price;
|
||||||
const displayMarketPrice = change.marketPrice !== undefined ? change.marketPrice : product.marketPrice;
|
const displayMarketPrice = change.marketPrice !== undefined ? change.marketPrice : product.marketPrice;
|
||||||
const displayFlashPrice = change.flashPrice !== undefined ? change.flashPrice : product.flashPrice;
|
const displayFlashPrice = change.flashPrice !== undefined ? change.flashPrice : product.flashPrice;
|
||||||
|
const displayProductQuantity = change.productQuantity !== undefined ? change.productQuantity : product.productQuantity;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={tw`bg-white p-4 mb-3 rounded-xl border border-gray-200 shadow-sm`}>
|
<View style={tw`bg-white p-4 mb-3 rounded-xl border border-gray-200 shadow-sm`}>
|
||||||
|
|
@ -67,7 +68,7 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
||||||
resizeMode="cover"
|
resizeMode="cover"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Product name and Flash Checkbox */}
|
{/* Product name and Flash Checkbox */}
|
||||||
<View style={tw`flex-1 flex-row items-center`}>
|
<View style={tw`flex-1 flex-row items-center`}>
|
||||||
<MyText style={tw`text-base font-medium text-gray-800`} numberOfLines={1}>
|
<MyText style={tw`text-base font-medium text-gray-800`} numberOfLines={1}>
|
||||||
{product.name.length > 25 ? product.name.substring(0, 25) + '...' : product.name}
|
{product.name.length > 25 ? product.name.substring(0, 25) + '...' : product.name}
|
||||||
|
|
@ -92,12 +93,12 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Second row: Prices */}
|
{/* Prices and Product Size Row */}
|
||||||
<View style={tw`flex-row items-center justify-between`}>
|
<View style={tw`flex-row items-center justify-between`}>
|
||||||
{/* Our Price */}
|
{/* Our Price */}
|
||||||
<View style={tw`items-center flex-1`}>
|
<View style={tw`items-center`}>
|
||||||
<MyText style={tw`text-xs text-gray-500 mb-1`}>Our Price</MyText>
|
<MyText style={tw`text-xs text-gray-500 mb-1`}>Our Price</MyText>
|
||||||
<View style={tw`flex-row items-center justify-center`}>
|
<View style={tw`flex-row items-center`}>
|
||||||
<MyText style={tw`text-sm font-bold text-green-600`}>₹{displayPrice}</MyText>
|
<MyText style={tw`text-sm font-bold text-green-600`}>₹{displayPrice}</MyText>
|
||||||
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||||
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||||
|
|
@ -106,9 +107,9 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Market Price */}
|
{/* Market Price */}
|
||||||
<View style={tw`items-center flex-1`}>
|
<View style={tw`items-center`}>
|
||||||
<MyText style={tw`text-xs text-gray-500 mb-1`}>Market Price</MyText>
|
<MyText style={tw`text-xs text-gray-500 mb-1`}>Market Price</MyText>
|
||||||
<View style={tw`flex-row items-center justify-center`}>
|
<View style={tw`flex-row items-center`}>
|
||||||
<MyText style={tw`text-sm text-gray-600`}>{displayMarketPrice ? `₹${displayMarketPrice}` : "N/A"}</MyText>
|
<MyText style={tw`text-sm text-gray-600`}>{displayMarketPrice ? `₹${displayMarketPrice}` : "N/A"}</MyText>
|
||||||
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||||
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||||
|
|
@ -117,15 +118,26 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Flash Price */}
|
{/* Flash Price */}
|
||||||
<View style={tw`items-center flex-1`}>
|
<View style={tw`items-center`}>
|
||||||
<MyText style={tw`text-xs text-gray-500 mb-1`}>Flash Price</MyText>
|
<MyText style={tw`text-xs text-gray-500 mb-1`}>Flash Price</MyText>
|
||||||
<View style={tw`flex-row items-center justify-center`}>
|
<View style={tw`flex-row items-center`}>
|
||||||
<MyText style={tw`text-sm text-orange-600`}>{displayFlashPrice ? `₹${displayFlashPrice}` : "N/A"}</MyText>
|
<MyText style={tw`text-sm text-orange-600`}>{displayFlashPrice ? `₹${displayFlashPrice}` : "N/A"}</MyText>
|
||||||
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||||
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* Product Size */}
|
||||||
|
<View style={tw`items-center`}>
|
||||||
|
<MyText style={tw`text-xs text-gray-500 mb-1`}>Size</MyText>
|
||||||
|
<View style={tw`flex-row items-center`}>
|
||||||
|
<MyText style={tw`text-sm text-blue-600`}>{displayProductQuantity ? `${displayProductQuantity}${product.unit.shortNotation || ''}` : "N/A"}</MyText>
|
||||||
|
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||||
|
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
@ -135,6 +147,7 @@ interface PendingChange {
|
||||||
price?: number;
|
price?: number;
|
||||||
marketPrice?: number | null;
|
marketPrice?: number | null;
|
||||||
flashPrice?: number | null;
|
flashPrice?: number | null;
|
||||||
|
productQuantity?: number | null;
|
||||||
isFlashAvailable?: boolean;
|
isFlashAvailable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,6 +157,7 @@ interface EditDialogState {
|
||||||
tempPrice: string;
|
tempPrice: string;
|
||||||
tempMarketPrice: string;
|
tempMarketPrice: string;
|
||||||
tempFlashPrice: string;
|
tempFlashPrice: string;
|
||||||
|
tempProductQuantity: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PricesOverview() {
|
export default function PricesOverview() {
|
||||||
|
|
@ -156,6 +170,7 @@ export default function PricesOverview() {
|
||||||
tempPrice: "",
|
tempPrice: "",
|
||||||
tempMarketPrice: "",
|
tempMarketPrice: "",
|
||||||
tempFlashPrice: "",
|
tempFlashPrice: "",
|
||||||
|
tempProductQuantity: "",
|
||||||
});
|
});
|
||||||
const [showMenu, setShowMenu] = useState(false);
|
const [showMenu, setShowMenu] = useState(false);
|
||||||
|
|
||||||
|
|
@ -211,6 +226,7 @@ export default function PricesOverview() {
|
||||||
tempPrice: (change.price ?? product.price)?.toString() || "",
|
tempPrice: (change.price ?? product.price)?.toString() || "",
|
||||||
tempMarketPrice: (change.marketPrice ?? product.marketPrice)?.toString() || "",
|
tempMarketPrice: (change.marketPrice ?? product.marketPrice)?.toString() || "",
|
||||||
tempFlashPrice: (change.flashPrice ?? product.flashPrice)?.toString() || "",
|
tempFlashPrice: (change.flashPrice ?? product.flashPrice)?.toString() || "",
|
||||||
|
tempProductQuantity: (change.productQuantity ?? product.productQuantity)?.toString() || "",
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -219,6 +235,7 @@ export default function PricesOverview() {
|
||||||
const price = parseFloat(editDialog.tempPrice);
|
const price = parseFloat(editDialog.tempPrice);
|
||||||
const marketPrice = editDialog.tempMarketPrice ? parseFloat(editDialog.tempMarketPrice) : null;
|
const marketPrice = editDialog.tempMarketPrice ? parseFloat(editDialog.tempMarketPrice) : null;
|
||||||
const flashPrice = editDialog.tempFlashPrice ? parseFloat(editDialog.tempFlashPrice) : null;
|
const flashPrice = editDialog.tempFlashPrice ? parseFloat(editDialog.tempFlashPrice) : null;
|
||||||
|
const productQuantity = editDialog.tempProductQuantity ? parseFloat(editDialog.tempProductQuantity) : null;
|
||||||
|
|
||||||
if (isNaN(price) || price <= 0) {
|
if (isNaN(price) || price <= 0) {
|
||||||
Alert.alert("Error", "Please enter a valid price");
|
Alert.alert("Error", "Please enter a valid price");
|
||||||
|
|
@ -235,16 +252,22 @@ export default function PricesOverview() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editDialog.tempProductQuantity && (isNaN(productQuantity!) || productQuantity! <= 0)) {
|
||||||
|
Alert.alert("Error", "Please enter a valid product size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setPendingChanges(prev => ({
|
setPendingChanges(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
[editDialog.product.id]: {
|
[editDialog.product.id]: {
|
||||||
price: price !== editDialog.product.price ? price : undefined,
|
price: price !== editDialog.product.price ? price : undefined,
|
||||||
marketPrice: marketPrice !== editDialog.product.marketPrice ? marketPrice : undefined,
|
marketPrice: marketPrice !== editDialog.product.marketPrice ? marketPrice : undefined,
|
||||||
flashPrice: flashPrice !== editDialog.product.flashPrice ? flashPrice : undefined,
|
flashPrice: flashPrice !== editDialog.product.flashPrice ? flashPrice : undefined,
|
||||||
|
productQuantity: productQuantity !== editDialog.product.productQuantity ? productQuantity : undefined,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setEditDialog({ open: false, product: null, tempPrice: "", tempMarketPrice: "", tempFlashPrice: "" });
|
setEditDialog({ open: false, product: null, tempPrice: "", tempMarketPrice: "", tempFlashPrice: "", tempProductQuantity: "" });
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle save all changes
|
// Handle save all changes
|
||||||
|
|
@ -254,6 +277,7 @@ export default function PricesOverview() {
|
||||||
if (change.price !== undefined) update.price = change.price;
|
if (change.price !== undefined) update.price = change.price;
|
||||||
if (change.marketPrice !== undefined) update.marketPrice = change.marketPrice;
|
if (change.marketPrice !== undefined) update.marketPrice = change.marketPrice;
|
||||||
if (change.flashPrice !== undefined) update.flashPrice = change.flashPrice;
|
if (change.flashPrice !== undefined) update.flashPrice = change.flashPrice;
|
||||||
|
if (change.productQuantity !== undefined) update.productQuantity = change.productQuantity;
|
||||||
if (change.isFlashAvailable !== undefined) update.isFlashAvailable = change.isFlashAvailable;
|
if (change.isFlashAvailable !== undefined) update.isFlashAvailable = change.isFlashAvailable;
|
||||||
return update;
|
return update;
|
||||||
});
|
});
|
||||||
|
|
@ -351,7 +375,7 @@ export default function PricesOverview() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Edit Dialog */}
|
{/* Edit Dialog */}
|
||||||
<BottomDialog open={editDialog.open} onClose={() => setEditDialog({ ...editDialog, open: false, tempFlashPrice: "" })}>
|
<BottomDialog open={editDialog.open} onClose={() => setEditDialog({ ...editDialog, open: false, tempFlashPrice: "", tempMarketPrice: "", tempPrice: "", tempProductQuantity: "" })}>
|
||||||
<View style={tw`p-4`}>
|
<View style={tw`p-4`}>
|
||||||
<MyText style={tw`text-lg font-bold mb-4`}>{editDialog.product?.name}</MyText>
|
<MyText style={tw`text-lg font-bold mb-4`}>{editDialog.product?.name}</MyText>
|
||||||
|
|
||||||
|
|
@ -388,6 +412,17 @@ export default function PricesOverview() {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<View style={tw`mb-4`}>
|
||||||
|
<MyText style={tw`text-sm font-medium mb-1`}>Product Size</MyText>
|
||||||
|
<TextInput
|
||||||
|
style={tw`border border-gray-300 rounded-md px-3 py-2`}
|
||||||
|
value={editDialog.tempProductQuantity}
|
||||||
|
onChangeText={(text) => setEditDialog({ ...editDialog, tempProductQuantity: text })}
|
||||||
|
keyboardType="decimal-pad"
|
||||||
|
placeholder="Enter product size"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={tw`bg-blue-600 py-3 rounded-md items-center`}
|
style={tw`bg-blue-600 py-3 rounded-md items-center`}
|
||||||
onPress={saveEditDialog}
|
onPress={saveEditDialog}
|
||||||
|
|
|
||||||
|
|
@ -775,6 +775,7 @@ export const orderRouter = router({
|
||||||
amount:
|
amount:
|
||||||
parseFloat(item.quantity) * parseFloat(item.price.toString()),
|
parseFloat(item.quantity) * parseFloat(item.price.toString()),
|
||||||
unit: item.product.unit?.shortNotation || "",
|
unit: item.product.unit?.shortNotation || "",
|
||||||
|
productSize: item.product.productQuantity,
|
||||||
isPackaged: item.is_packaged,
|
isPackaged: item.is_packaged,
|
||||||
isPackageVerified: item.is_package_verified,
|
isPackageVerified: item.is_package_verified,
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -143,10 +143,22 @@ export default function Dashboard() {
|
||||||
const initialBatchRaw = products;
|
const initialBatchRaw = products;
|
||||||
|
|
||||||
// Filter to include only products with available slots
|
// Filter to include only products with available slots
|
||||||
const initialBatch = initialBatchRaw.filter(product => {
|
// const initialBatch = initialBatchRaw.filter(product => {
|
||||||
const slot = getQuickestSlot(product.id);
|
// const slot = getQuickestSlot(product.id);
|
||||||
return slot !== null && slot !== undefined && !product.isOutOfStock;
|
// return !product.isOutOfStock;
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
const initialBatch = initialBatchRaw.sort((a, b) => {
|
||||||
|
const slotA = getQuickestSlot(a.id);
|
||||||
|
const slotB = getQuickestSlot(b.id);
|
||||||
|
|
||||||
|
if (slotA && !slotB) return -1;
|
||||||
|
if (!slotA && slotB) return 1;
|
||||||
|
|
||||||
|
if(a.isOutOfStock && !b.isOutOfStock) return 1;
|
||||||
|
if(!a.isOutOfStock && b.isOutOfStock) return -1;
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
|
||||||
setDisplayedProducts(initialBatch);
|
setDisplayedProducts(initialBatch);
|
||||||
setHasMore(products.length > 10);
|
setHasMore(products.length > 10);
|
||||||
|
|
@ -593,6 +605,9 @@ export default function Dashboard() {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
initialNumToRender={4}
|
||||||
|
maxToRenderPerBatch={4}
|
||||||
|
windowSize={4}
|
||||||
// onEndReached={() => {
|
// onEndReached={() => {
|
||||||
// if (!isLoadingMore && hasMore) {
|
// if (!isLoadingMore && hasMore) {
|
||||||
// loadMoreProducts();
|
// loadMoreProducts();
|
||||||
|
|
|
||||||
|
|
@ -350,10 +350,12 @@ export function SlotProducts({ slotId:slotIdParent, storeId:storeIdParent, baseU
|
||||||
|
|
||||||
const productsQuery = trpc.user.product.getAllProductsSummary.useQuery();
|
const productsQuery = trpc.user.product.getAllProductsSummary.useQuery();
|
||||||
|
|
||||||
const { addToCart = () => { } } = useAddToCart({ showSuccessAlert: false, showErrorAlert: false, refetchCart: true }, "flash") || {};
|
const { addToCart = () => { } } = useAddToCart({ showSuccessAlert: false, showErrorAlert: false, refetchCart: true }, "regular") || {};
|
||||||
|
|
||||||
const handleAddToCart = (productId: number) => {
|
const handleAddToCart = (productId: number) => {
|
||||||
setIsLoadingDialogOpen(true);
|
setIsLoadingDialogOpen(true);
|
||||||
|
// console.log({productId})
|
||||||
|
|
||||||
addToCart(productId, 1, slotId || 0, () => setIsLoadingDialogOpen(false));
|
addToCart(productId, 1, slotId || 0, () => setIsLoadingDialogOpen(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,11 +305,16 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
|
||||||
|
|
||||||
// Auto-select delivery slots for each cart item
|
// Auto-select delivery slots for each cart item
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const cartSlotIds = cartData?.items.reduce((acc,item) => {
|
||||||
|
acc[item.id] = item.slotId;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<number, number>);
|
||||||
if (cartItems.length > 0) {
|
if (cartItems.length > 0) {
|
||||||
const newSelectedSlots = { ...selectedSlots };
|
const newSelectedSlots = { ...selectedSlots };
|
||||||
|
|
||||||
cartItems.forEach(item => {
|
cartItems.forEach(item => {
|
||||||
const existingSlotId = selectedSlots[item.id];
|
// const existingSlotId = selectedSlots[item.id];
|
||||||
|
const existingSlotId = cartSlotIds ? cartSlotIds[item.id] : undefined;
|
||||||
|
|
||||||
if (isFlashDelivery) {
|
if (isFlashDelivery) {
|
||||||
newSelectedSlots[item.id] = 0;
|
newSelectedSlots[item.id] = 0;
|
||||||
|
|
@ -325,6 +330,8 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (upcomingSlots.length > 0) {
|
if (upcomingSlots.length > 0) {
|
||||||
|
console.log({upcomingSlots, existingSlotId, cartSlotIds})
|
||||||
|
|
||||||
if (existingSlotId) {
|
if (existingSlotId) {
|
||||||
const slotStillValid = upcomingSlots.some(slot => slot.id === existingSlotId);
|
const slotStillValid = upcomingSlots.some(slot => slot.id === existingSlotId);
|
||||||
if (slotStillValid) {
|
if (slotStillValid) {
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ const addToLocalCart = async (productId: number, quantity: number, slotId?: numb
|
||||||
items.push(cartItem);
|
items.push(cartItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log({items})
|
||||||
|
|
||||||
await saveLocalCart(items, cartType);
|
await saveLocalCart(items, cartType);
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
@ -301,6 +303,8 @@ export function useAddToCart(options?: {
|
||||||
|
|
||||||
const addToCart = (productId: number, quantity = 1, slotId?: number, onSettled?: (data: any, error: any) => void) => {
|
const addToCart = (productId: number, quantity = 1, slotId?: number, onSettled?: (data: any, error: any) => void) => {
|
||||||
|
|
||||||
|
// console.log({productId, quantity, slotId})
|
||||||
|
|
||||||
if (slotId == null) {
|
if (slotId == null) {
|
||||||
throw new Error('slotId is required for adding to cart');
|
throw new Error('slotId is required for adding to cart');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue