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;
|
||||
isPackaged?: boolean;
|
||||
isPackageVerified?: boolean;
|
||||
productSize: number;
|
||||
}[];
|
||||
createdAt: string;
|
||||
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 style={tw`flex-row items-center`}>
|
||||
<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>
|
||||
<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}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
|||
const displayPrice = change.price !== undefined ? change.price : product.price;
|
||||
const displayMarketPrice = change.marketPrice !== undefined ? change.marketPrice : product.marketPrice;
|
||||
const displayFlashPrice = change.flashPrice !== undefined ? change.flashPrice : product.flashPrice;
|
||||
const displayProductQuantity = change.productQuantity !== undefined ? change.productQuantity : product.productQuantity;
|
||||
|
||||
return (
|
||||
<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"
|
||||
/>
|
||||
|
||||
{/* Product name and Flash Checkbox */}
|
||||
{/* Product name and Flash Checkbox */}
|
||||
<View style={tw`flex-1 flex-row items-center`}>
|
||||
<MyText style={tw`text-base font-medium text-gray-800`} numberOfLines={1}>
|
||||
{product.name.length > 25 ? product.name.substring(0, 25) + '...' : product.name}
|
||||
|
|
@ -92,12 +93,12 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
|||
</View>
|
||||
</View>
|
||||
|
||||
{/* Second row: Prices */}
|
||||
{/* Prices and Product Size Row */}
|
||||
<View style={tw`flex-row items-center justify-between`}>
|
||||
{/* 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>
|
||||
<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>
|
||||
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||
|
|
@ -106,9 +107,9 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
|||
</View>
|
||||
|
||||
{/* 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>
|
||||
<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>
|
||||
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||
|
|
@ -117,15 +118,26 @@ const ProductItemComponent: React.FC<ProductItemProps> = ({
|
|||
</View>
|
||||
|
||||
{/* 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>
|
||||
<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>
|
||||
<TouchableOpacity onPress={() => openEditDialog(product)} style={tw`ml-1`}>
|
||||
<MaterialIcons name="edit" size={14} color="#6b7280" />
|
||||
</TouchableOpacity>
|
||||
</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>
|
||||
);
|
||||
|
|
@ -135,6 +147,7 @@ interface PendingChange {
|
|||
price?: number;
|
||||
marketPrice?: number | null;
|
||||
flashPrice?: number | null;
|
||||
productQuantity?: number | null;
|
||||
isFlashAvailable?: boolean;
|
||||
}
|
||||
|
||||
|
|
@ -144,6 +157,7 @@ interface EditDialogState {
|
|||
tempPrice: string;
|
||||
tempMarketPrice: string;
|
||||
tempFlashPrice: string;
|
||||
tempProductQuantity: string;
|
||||
}
|
||||
|
||||
export default function PricesOverview() {
|
||||
|
|
@ -156,6 +170,7 @@ export default function PricesOverview() {
|
|||
tempPrice: "",
|
||||
tempMarketPrice: "",
|
||||
tempFlashPrice: "",
|
||||
tempProductQuantity: "",
|
||||
});
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
|
||||
|
|
@ -211,6 +226,7 @@ export default function PricesOverview() {
|
|||
tempPrice: (change.price ?? product.price)?.toString() || "",
|
||||
tempMarketPrice: (change.marketPrice ?? product.marketPrice)?.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 marketPrice = editDialog.tempMarketPrice ? parseFloat(editDialog.tempMarketPrice) : null;
|
||||
const flashPrice = editDialog.tempFlashPrice ? parseFloat(editDialog.tempFlashPrice) : null;
|
||||
const productQuantity = editDialog.tempProductQuantity ? parseFloat(editDialog.tempProductQuantity) : null;
|
||||
|
||||
if (isNaN(price) || price <= 0) {
|
||||
Alert.alert("Error", "Please enter a valid price");
|
||||
|
|
@ -235,16 +252,22 @@ export default function PricesOverview() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (editDialog.tempProductQuantity && (isNaN(productQuantity!) || productQuantity! <= 0)) {
|
||||
Alert.alert("Error", "Please enter a valid product size");
|
||||
return;
|
||||
}
|
||||
|
||||
setPendingChanges(prev => ({
|
||||
...prev,
|
||||
[editDialog.product.id]: {
|
||||
price: price !== editDialog.product.price ? price : undefined,
|
||||
marketPrice: marketPrice !== editDialog.product.marketPrice ? marketPrice : 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
|
||||
|
|
@ -254,6 +277,7 @@ export default function PricesOverview() {
|
|||
if (change.price !== undefined) update.price = change.price;
|
||||
if (change.marketPrice !== undefined) update.marketPrice = change.marketPrice;
|
||||
if (change.flashPrice !== undefined) update.flashPrice = change.flashPrice;
|
||||
if (change.productQuantity !== undefined) update.productQuantity = change.productQuantity;
|
||||
if (change.isFlashAvailable !== undefined) update.isFlashAvailable = change.isFlashAvailable;
|
||||
return update;
|
||||
});
|
||||
|
|
@ -351,7 +375,7 @@ export default function PricesOverview() {
|
|||
)}
|
||||
|
||||
{/* 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`}>
|
||||
<MyText style={tw`text-lg font-bold mb-4`}>{editDialog.product?.name}</MyText>
|
||||
|
||||
|
|
@ -388,6 +412,17 @@ export default function PricesOverview() {
|
|||
/>
|
||||
</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
|
||||
style={tw`bg-blue-600 py-3 rounded-md items-center`}
|
||||
onPress={saveEditDialog}
|
||||
|
|
|
|||
|
|
@ -775,6 +775,7 @@ export const orderRouter = router({
|
|||
amount:
|
||||
parseFloat(item.quantity) * parseFloat(item.price.toString()),
|
||||
unit: item.product.unit?.shortNotation || "",
|
||||
productSize: item.product.productQuantity,
|
||||
isPackaged: item.is_packaged,
|
||||
isPackageVerified: item.is_package_verified,
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -143,10 +143,22 @@ export default function Dashboard() {
|
|||
const initialBatchRaw = products;
|
||||
|
||||
// Filter to include only products with available slots
|
||||
const initialBatch = initialBatchRaw.filter(product => {
|
||||
const slot = getQuickestSlot(product.id);
|
||||
return slot !== null && slot !== undefined && !product.isOutOfStock;
|
||||
});
|
||||
// const initialBatch = initialBatchRaw.filter(product => {
|
||||
// const slot = getQuickestSlot(product.id);
|
||||
// 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);
|
||||
setHasMore(products.length > 10);
|
||||
|
|
@ -593,6 +605,9 @@ export default function Dashboard() {
|
|||
/>
|
||||
</View>
|
||||
)}
|
||||
initialNumToRender={4}
|
||||
maxToRenderPerBatch={4}
|
||||
windowSize={4}
|
||||
// onEndReached={() => {
|
||||
// if (!isLoadingMore && hasMore) {
|
||||
// loadMoreProducts();
|
||||
|
|
|
|||
|
|
@ -350,10 +350,12 @@ export function SlotProducts({ slotId:slotIdParent, storeId:storeIdParent, baseU
|
|||
|
||||
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) => {
|
||||
setIsLoadingDialogOpen(true);
|
||||
// console.log({productId})
|
||||
|
||||
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
|
||||
useEffect(() => {
|
||||
const cartSlotIds = cartData?.items.reduce((acc,item) => {
|
||||
acc[item.id] = item.slotId;
|
||||
return acc;
|
||||
}, {} as Record<number, number>);
|
||||
if (cartItems.length > 0) {
|
||||
const newSelectedSlots = { ...selectedSlots };
|
||||
|
||||
cartItems.forEach(item => {
|
||||
const existingSlotId = selectedSlots[item.id];
|
||||
// const existingSlotId = selectedSlots[item.id];
|
||||
const existingSlotId = cartSlotIds ? cartSlotIds[item.id] : undefined;
|
||||
|
||||
if (isFlashDelivery) {
|
||||
newSelectedSlots[item.id] = 0;
|
||||
|
|
@ -325,6 +330,8 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
|
|||
);
|
||||
|
||||
if (upcomingSlots.length > 0) {
|
||||
console.log({upcomingSlots, existingSlotId, cartSlotIds})
|
||||
|
||||
if (existingSlotId) {
|
||||
const slotStillValid = upcomingSlots.some(slot => slot.id === existingSlotId);
|
||||
if (slotStillValid) {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ const addToLocalCart = async (productId: number, quantity: number, slotId?: numb
|
|||
items.push(cartItem);
|
||||
}
|
||||
|
||||
console.log({items})
|
||||
|
||||
await saveLocalCart(items, cartType);
|
||||
return items;
|
||||
};
|
||||
|
|
@ -301,6 +303,8 @@ export function useAddToCart(options?: {
|
|||
|
||||
const addToCart = (productId: number, quantity = 1, slotId?: number, onSettled?: (data: any, error: any) => void) => {
|
||||
|
||||
// console.log({productId, quantity, slotId})
|
||||
|
||||
if (slotId == null) {
|
||||
throw new Error('slotId is required for adding to cart');
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue