enh
This commit is contained in:
parent
d4afa75eaf
commit
10d13408d3
3 changed files with 148 additions and 108 deletions
|
|
@ -36,21 +36,32 @@ interface FloatingCartBarProps {
|
|||
}
|
||||
|
||||
// Smart time window formatting function
|
||||
const formatTimeRange = (deliveryTime: string) => {
|
||||
const time = dayjs(deliveryTime);
|
||||
const endTime = time.add(1, 'hour');
|
||||
const startPeriod = time.format('A');
|
||||
const endPeriod = endTime.format('A');
|
||||
const formatTimeRange = (deliveryTime: string) => {
|
||||
const time = dayjs(deliveryTime);
|
||||
const endTime = time.add(1, 'hour');
|
||||
const startPeriod = time.format('A');
|
||||
const endPeriod = endTime.format('A');
|
||||
|
||||
let timeRange;
|
||||
if (startPeriod === endPeriod) {
|
||||
timeRange = `${time.format('h')}-${endTime.format('h')} ${startPeriod}`;
|
||||
} else {
|
||||
timeRange = `${time.format('h:mm')} ${startPeriod} - ${endTime.format('h:mm')} ${endPeriod}`;
|
||||
}
|
||||
let timeRange;
|
||||
if (startPeriod === endPeriod) {
|
||||
timeRange = `${time.format('h')}-${endTime.format('h')} ${startPeriod}`;
|
||||
} else {
|
||||
timeRange = `${time.format('h:mm')} ${startPeriod} - ${endTime.format('h:mm')} ${endPeriod}`;
|
||||
}
|
||||
|
||||
return `${time.format('ddd, DD MMM ')}${timeRange}`;
|
||||
};
|
||||
return `${time.format('ddd, DD MMM ')}${timeRange}`;
|
||||
};
|
||||
|
||||
// Product name component with quantity
|
||||
const ProductNameWithQuantity = ({ name, productQuantity, unitNotation }: { name: string; productQuantity: number; unitNotation: string }) => {
|
||||
const truncatedName = name.length > 25 ? name.substring(0, 25) + '...' : name;
|
||||
const unit = unitNotation ? ` ${unitNotation}` : '';
|
||||
return (
|
||||
<MyText style={tw`text-slate-900 font-extrabold text-sm flex-1`} numberOfLines={1}>
|
||||
{truncatedName} <MyText style={tw`text-slate-500 font-medium text-xs`}>({productQuantity}{unit})</MyText>
|
||||
</MyText>
|
||||
);
|
||||
};
|
||||
|
||||
const FloatingCartBar: React.FC<FloatingCartBarProps> = ({
|
||||
isFlashDelivery = false,
|
||||
|
|
@ -252,9 +263,11 @@ useEffect(() => {
|
|||
|
||||
<View style={tw`flex-1 ml-4`}>
|
||||
<View style={tw`flex-row items-center justify-between mb-1`}>
|
||||
<MyText style={tw`text-slate-900 font-extrabold text-sm flex-1`} numberOfLines={1}>
|
||||
{item.product.name.length > 30 ? item.product.name.substring(0, 30) + '...' : item.product.name}
|
||||
</MyText>
|
||||
<ProductNameWithQuantity
|
||||
name={item.product.name}
|
||||
productQuantity={item.product.productQuantity}
|
||||
unitNotation={item.product.unitNotation}
|
||||
/>
|
||||
<MiniQuantifier
|
||||
value={quantities[item.id] || item.quantity}
|
||||
onChange={(value) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
|||
import { useCartStore } from '@/src/store/cartStore';
|
||||
import { useFlashCartStore } from '@/src/store/flashCartStore';
|
||||
import { trpc } from '@/src/trpc-client';
|
||||
import { useAddToCart, useGetCart, useUpdateCartItem } from '@/hooks/cart-query-hooks';
|
||||
import { useAddToCart, useGetCart, useUpdateCartItem, useRemoveFromCart } from '@/hooks/cart-query-hooks';
|
||||
import { useGetEssentialConsts } from '@/src/api-hooks/essential-consts.api';
|
||||
import dayjs from 'dayjs';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
|
@ -17,15 +17,15 @@ export default function AddToCartDialog() {
|
|||
const [quantity, setQuantity] = useState(1);
|
||||
const [selectedSlotId, setSelectedSlotId] = useState<number | null>(null);
|
||||
const [selectedFlashDelivery, setSelectedFlashDelivery] = useState(false);
|
||||
|
||||
|
||||
const { data: slotsData } = trpc.user.slots.getSlotsWithProducts.useQuery();
|
||||
const { data: cartData } = useGetCart();
|
||||
const { data: constsData } = useGetEssentialConsts();
|
||||
// const isFlashDeliveryEnabled = constsData?.isFlashDeliveryEnabled === true;
|
||||
const isFlashDeliveryEnabled = true;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const addToCart = useAddToCart({
|
||||
showSuccessAlert: false,
|
||||
showErrorAlert: false,
|
||||
|
|
@ -38,8 +38,14 @@ export default function AddToCartDialog() {
|
|||
refetchCart: true,
|
||||
});
|
||||
|
||||
const removeFromCart = useRemoveFromCart({
|
||||
showSuccessAlert: false,
|
||||
showErrorAlert: false,
|
||||
refetchCart: true,
|
||||
});
|
||||
|
||||
const isOpen = !!addedToCartProduct;
|
||||
|
||||
|
||||
|
||||
const product = addedToCartProduct?.product;
|
||||
|
||||
|
|
@ -49,10 +55,10 @@ export default function AddToCartDialog() {
|
|||
if (isOpen && product) {
|
||||
const cartItem = cartData?.items?.find((item: any) => item.productId === product.id);
|
||||
const cartQuantity = cartItem?.quantity || 0;
|
||||
|
||||
|
||||
// Set quantity: 0 → 1, >1 → keep as is
|
||||
setQuantity(cartQuantity === 0 ? 1 : cartQuantity);
|
||||
|
||||
|
||||
if (cartItem?.slotId) {
|
||||
setSelectedSlotId(cartItem.slotId);
|
||||
} else {
|
||||
|
|
@ -64,11 +70,11 @@ export default function AddToCartDialog() {
|
|||
const { slotMap, productSlotIdsMap } = useMemo(() => {
|
||||
const slotMap: Record<number, any> = {};
|
||||
const productSlotIdsMap: Record<number, number[]> = {};
|
||||
|
||||
|
||||
if (slotsData?.slots) {
|
||||
slotsData.slots.forEach((slot: any) => {
|
||||
slotMap[slot.id] = slot;
|
||||
|
||||
|
||||
slot.products?.forEach((p: any) => {
|
||||
if (!productSlotIdsMap[p.id]) {
|
||||
productSlotIdsMap[p.id] = [];
|
||||
|
|
@ -77,12 +83,12 @@ export default function AddToCartDialog() {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return { slotMap, productSlotIdsMap };
|
||||
}, [slotsData]);
|
||||
|
||||
const availableSlotIds = productSlotIdsMap[product?.id] || [];
|
||||
|
||||
|
||||
const availableSlots = availableSlotIds
|
||||
.map((slotId) => slotMap[slotId])
|
||||
.filter(Boolean);
|
||||
|
|
@ -91,7 +97,7 @@ export default function AddToCartDialog() {
|
|||
const cartItem = cartData?.items?.find((item: any) => item.productId === product?.id);
|
||||
|
||||
// Determine if updating existing item (quantity > 1 means it's an update)
|
||||
const isUpdate = (cartItem?.quantity || 0) > 1;
|
||||
const isUpdate = (cartItem?.quantity || 0) >= 1;
|
||||
|
||||
// Check if flash delivery option should be shown
|
||||
const showFlashOption = product?.isFlashAvailable === true && isFlashDeliveryEnabled;
|
||||
|
|
@ -122,99 +128,120 @@ export default function AddToCartDialog() {
|
|||
return (
|
||||
<BottomDialog open={isOpen} onClose={clearAddedToCartProduct}>
|
||||
<SafeAreaView>
|
||||
<View style={tw`p-6 max-h-[650px]`}>
|
||||
<View style={tw`flex-row items-center mb-2`}>
|
||||
<View style={tw`w-10 h-10 bg-blue-50 rounded-full items-center justify-center mr-3`}>
|
||||
<MaterialIcons name="schedule" size={20} color="#3B82F6" />
|
||||
<View style={tw`p-6 max-h-[650px]`}>
|
||||
<View style={tw`flex-row items-center mb-2`}>
|
||||
<View style={tw`w-10 h-10 bg-blue-50 rounded-full items-center justify-center mr-3`}>
|
||||
<MaterialIcons name="schedule" size={20} color="#3B82F6" />
|
||||
</View>
|
||||
<View>
|
||||
<MyText style={tw`text-xl font-bold text-gray-900`}>Select Delivery Slot</MyText>
|
||||
{product?.name && (
|
||||
<MyText style={tw`text-sm text-gray-500`}>
|
||||
{product.name} ({product.productQuantity}{product.unitNotation ? ` ${product.unitNotation}` : ''})
|
||||
</MyText>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
<View>
|
||||
<MyText style={tw`text-xl font-bold text-gray-900`}>Select Delivery Slot</MyText>
|
||||
{product?.name && (
|
||||
<MyText style={tw`text-sm text-gray-500`}>{product.name}</MyText>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{availableSlots.map((slot: any) => (
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{availableSlots.map((slot: any) => (
|
||||
<MyTouchableOpacity
|
||||
key={slot.id}
|
||||
style={tw`flex-row items-start mb-4 bg-gray-50 p-4 rounded-xl border border-gray-100 ${selectedSlotId === slot.id ? 'border-brand500' : 'border-gray-100'
|
||||
}`}
|
||||
onPress={() => {
|
||||
setSelectedSlotId(slot.id);
|
||||
setSelectedFlashDelivery(false);
|
||||
}}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="local-shipping" size={20} color="#3B82F6" style={tw`mt-0.5`} />
|
||||
<View style={tw`ml-3 flex-1`}>
|
||||
<MyText style={tw`text-gray-900 font-bold text-base`}>
|
||||
{dayjs(slot.deliveryTime).format('ddd, DD MMM • h:mm A')}
|
||||
</MyText>
|
||||
</View>
|
||||
{selectedSlotId === slot.id ? (
|
||||
<MaterialIcons name="check-circle" size={24} color="#3B82F6" style={tw`mt-0.5`} />
|
||||
) : (
|
||||
<MaterialIcons name="check-box-outline-blank" size={24} color="#9CA3AF" style={tw`mt-0.5`} />
|
||||
)}
|
||||
</MyTouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
|
||||
{showFlashOption && (
|
||||
<MyTouchableOpacity
|
||||
key={slot.id}
|
||||
style={tw`flex-row items-start mb-4 bg-gray-50 p-4 rounded-xl border border-gray-100 ${
|
||||
selectedSlotId === slot.id ? 'border-brand500' : 'border-gray-100'
|
||||
}`}
|
||||
key="flash-delivery"
|
||||
style={tw`flex-row items-center mb-4 bg-pink-50 p-4 rounded-xl border ${selectedFlashDelivery ? 'border-pink-500' : 'border-pink-200'
|
||||
}`}
|
||||
onPress={() => {
|
||||
setSelectedSlotId(slot.id);
|
||||
setSelectedFlashDelivery(false);
|
||||
setSelectedFlashDelivery(true);
|
||||
setSelectedSlotId(null);
|
||||
}}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="local-shipping" size={20} color="#3B82F6" style={tw`mt-0.5`} />
|
||||
<MaterialIcons name="bolt" size={20} color="#f81260" />
|
||||
<View style={tw`ml-3 flex-1`}>
|
||||
<MyText style={tw`text-gray-900 font-bold text-base`}>
|
||||
{dayjs(slot.deliveryTime).format('ddd, DD MMM • h:mm A')}
|
||||
</MyText>
|
||||
<MyText style={tw`text-gray-900 font-bold text-base`}>1 hr Delivery</MyText>
|
||||
</View>
|
||||
{selectedSlotId === slot.id ? (
|
||||
<MaterialIcons name="check-circle" size={24} color="#3B82F6" style={tw`mt-0.5`} />
|
||||
{selectedFlashDelivery ? (
|
||||
<MaterialIcons name="check-circle" size={24} color="#f81260" />
|
||||
) : (
|
||||
<MaterialIcons name="check-box-outline-blank" size={24} color="#9CA3AF" style={tw`mt-0.5`} />
|
||||
<MaterialIcons name="check-box-outline-blank" size={24} color="#f81260" />
|
||||
)}
|
||||
</MyTouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
)}
|
||||
|
||||
{showFlashOption && (
|
||||
<MyTouchableOpacity
|
||||
key="flash-delivery"
|
||||
style={tw`flex-row items-center mb-4 bg-pink-50 p-4 rounded-xl border ${
|
||||
selectedFlashDelivery ? 'border-pink-500' : 'border-pink-200'
|
||||
}`}
|
||||
onPress={() => {
|
||||
setSelectedFlashDelivery(true);
|
||||
setSelectedSlotId(null);
|
||||
}}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="bolt" size={20} color="#f81260" />
|
||||
<View style={tw`ml-3 flex-1`}>
|
||||
<MyText style={tw`text-gray-900 font-bold text-base`}>1 hr Delivery</MyText>
|
||||
<View style={tw`mt-4`}>
|
||||
<MyText style={tw`text-sm font-bold text-gray-900 mb-2`}>Quantity</MyText>
|
||||
<View style={tw`flex-row items-center`}>
|
||||
<View style={tw`flex-1`}>
|
||||
<Quantifier
|
||||
value={quantity}
|
||||
setValue={setQuantity}
|
||||
step={1}
|
||||
unit={product.unitNotation}
|
||||
/>
|
||||
</View>
|
||||
{isUpdate && (
|
||||
<MyTouchableOpacity
|
||||
onPress={() => {
|
||||
if (cartItem?.id) {
|
||||
removeFromCart.mutate(
|
||||
{ itemId: cartItem.id },
|
||||
{ onSuccess: () => clearAddedToCartProduct() }
|
||||
);
|
||||
} else {
|
||||
clearAddedToCartProduct();
|
||||
}
|
||||
}}
|
||||
style={tw`p-2 ml-3 bg-red-50 rounded-lg border border-red-200`}
|
||||
>
|
||||
<MaterialIcons name="delete-outline" size={24} color="#EF4444" />
|
||||
</MyTouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
{selectedFlashDelivery ? (
|
||||
<MaterialIcons name="check-circle" size={24} color="#f81260" />
|
||||
) : (
|
||||
<MaterialIcons name="check-box-outline-blank" size={24} color="#f81260" />
|
||||
)}
|
||||
</MyTouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={tw`mt-4`}>
|
||||
<MyText style={tw`text-sm font-bold text-gray-900 mb-2`}>Quantity</MyText>
|
||||
<Quantifier
|
||||
value={quantity}
|
||||
setValue={setQuantity}
|
||||
step={product.incrementStep}
|
||||
unit={product.unitNotation}
|
||||
/>
|
||||
<View style={tw`flex-row gap-3 mt-4 pb-12`}>
|
||||
<MyTouchableOpacity
|
||||
style={tw`flex-1 bg-brand500 py-3.5 rounded-xl items-center ${(!selectedSlotId && !selectedFlashDelivery) ? 'opacity-50' : ''}`}
|
||||
onPress={handleAddToCart}
|
||||
disabled={(addToCart.isLoading || updateCartItem.isLoading) || (!selectedSlotId && !selectedFlashDelivery)}
|
||||
>
|
||||
<MyText style={tw`text-white font-bold`}>
|
||||
{addToCart.isLoading || updateCartItem.isLoading ? (isUpdate ? 'Updating...' : 'Adding...') : (isUpdate ? 'Update Item' : 'Add to Cart')}
|
||||
</MyText>
|
||||
</MyTouchableOpacity>
|
||||
<MyTouchableOpacity
|
||||
style={tw`flex-1 bg-gray-100 py-3.5 rounded-xl items-center`}
|
||||
onPress={clearAddedToCartProduct}
|
||||
>
|
||||
<MyText style={tw`text-gray-700 font-bold`}>Cancel</MyText>
|
||||
</MyTouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={tw`flex-row gap-3 mt-4 pb-12`}>
|
||||
<MyTouchableOpacity
|
||||
style={tw`flex-1 bg-brand500 py-3.5 rounded-xl items-center ${(!selectedSlotId && !selectedFlashDelivery) ? 'opacity-50' : ''}`}
|
||||
onPress={handleAddToCart}
|
||||
disabled={(addToCart.isLoading || updateCartItem.isLoading) || (!selectedSlotId && !selectedFlashDelivery)}
|
||||
>
|
||||
<MyText style={tw`text-white font-bold`}>
|
||||
{addToCart.isLoading || updateCartItem.isLoading ? (isUpdate ? 'Updating...' : 'Adding...') : (isUpdate ? 'Update Item' : 'Add to Cart')}
|
||||
</MyText>
|
||||
</MyTouchableOpacity>
|
||||
<MyTouchableOpacity
|
||||
style={tw`flex-1 bg-gray-100 py-3.5 rounded-xl items-center`}
|
||||
onPress={clearAddedToCartProduct}
|
||||
>
|
||||
<MyText style={tw`text-gray-700 font-bold`}>Cancel</MyText>
|
||||
</MyTouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</BottomDialog>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ const isDevMode = Constants.executionEnvironment !== "standalone";
|
|||
// const BASE_API_URL = API_URL;
|
||||
// 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.3:4000';
|
||||
// let BASE_API_URL = "https://mf.freshyo.in";
|
||||
// const BASE_API_URL = 'http://192.168.1.3:4000';
|
||||
let BASE_API_URL = "https://mf.freshyo.in";
|
||||
// let BASE_API_URL = 'http://192.168.100.104:4000';
|
||||
// let BASE_API_URL = 'http://192.168.29.176:4000';
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue