Untitled
unknown
plain_text
8 months ago
25 kB
6
Indexable
import React, { useState, useRef, useEffect, useCallback } from "react";
import {
Image,
SafeAreaView,
ScrollView,
StatusBar,
Text,
TouchableOpacity,
View,
KeyboardAvoidingView,
Platform,
Modal,
} from "react-native";
import tw from "twrnc";
import { useFocusEffect } from "@react-navigation/native";
import Config from "../../config";
import { useNavigation } from "@react-navigation/native";
import { Ionicons } from "@expo/vector-icons";
import { TextInput } from "react-native-gesture-handler";
import { useSelector } from "react-redux";
import axios from "axios";
const CheckoutScreen = ({ route, visible }) => {
const navigation = useNavigation();
const [modalVisible, setModalVisible] = useState(false); // Controls offer price modal
const [selectedOption, setSelectedOption] = useState("suggested");
const [phoneNumber, setPhoneNumber] = useState("");
const token = useSelector((state) => state?.user?.token);
const [otp, setOtp] = useState(["", "", "", ""]);
const [countdown, setCountdown] = useState(59);
const { checkoutData } = route.params || {};
const [timerExpired, setTimerExpired] = useState(false);
const [focusedIndex, setFocusedIndex] = useState(null);
const [otpRequested, setOtpRequested] = useState(false);
const inputRefs = useRef([]);
const [shippingAddress, setShippingAddress] = useState(null);
const [billingAddress, setBillingAddress] = useState(null);
const addressesRef = useRef({
shipping: null,
billing: null
});
const handleOtpRequest = () => {
if (!otpRequested) {
// Call your OTP request function
setModalVisible(true);
setOtpRequested(true); // Update state to change button text
} else {
// Submit the OTP
handleSubmit();
setModalVisible(false);
}
};
const handlePhoneNumberChange = (text) => {
// Remove non-numeric characters and limit to 10 digits
const formattedText = text.replace(/\D/g, "").slice(0, 10);
setPhoneNumber(formattedText);
};
const handleBack = () => {
navigation.goBack();
};
const handleSubmit = () => {
// setModalVisible(false); // Close offer price modal
// setSubmittedModalVisible(true); // Open offer submitted modal
};
useFocusEffect(
useCallback(() => {
if (route.params?.selectedAddress && route.params?.addressType) {
const address = route.params.selectedAddress;
const addressType = route.params.addressType;
const formattedAddress = formatAddress(address);
// Update the ref for the specific address type
addressesRef.current[addressType] = formattedAddress;
// Update the state
if (addressType === 'shipping') {
setShippingAddress(formattedAddress);
} else if (addressType === 'billing') {
setBillingAddress(formattedAddress);
}
}
// If addresses are not set yet, try to use the ones from ref
if (!shippingAddress && addressesRef.current.shipping) {
setShippingAddress(addressesRef.current.shipping);
}
if (!billingAddress && addressesRef.current.billing) {
setBillingAddress(addressesRef.current.billing);
}
// If addresses are still not available, fetch from API
if (!shippingAddress && !addressesRef.current.shipping) {
fetchShippingAddress();
}
if (!billingAddress && !addressesRef.current.billing) {
fetchBillingAddress();
}
return () => { };
}, [route.params, shippingAddress, billingAddress])
);
// Split the fetch functions
const fetchShippingAddress = async () => {
if (!token) return;
try {
const response = await axios.get(`${Config.API_BASE_URL}/shippingAddress`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.data?.addresses && response.data?.addresses.length > 0) {
const formattedAddress = formatAddress(response.data.addresses[0]);
addressesRef.current.shipping = formattedAddress;
setShippingAddress(formattedAddress);
}
} catch (error) {
console.error("Failed to fetch shipping address:", error);
}
};
const fetchBillingAddress = async () => {
if (!token) return;
try {
const response = await axios.get(`${Config.API_BASE_URL}/billingAddress`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.data?.addresses && response.data?.addresses.length > 0) {
const formattedAddress = formatAddress(response.data.addresses[0]);
addressesRef.current.billing = formattedAddress;
setBillingAddress(formattedAddress);
}
} catch (error) {
console.error("Failed to fetch billing address:", error);
}
};
const formatAddress = (addressData) => {
return {
name: addressData.name || "User",
phone: addressData.phoneNumber,
address: `${addressData.address1}${addressData.address2 ? `, ${addressData.address2}` : ''}${addressData.landmark ? `, ${addressData.landmark}` : ''}`,
};
};
useEffect(() => {
if (countdown > 0) {
const timer = setTimeout(() => {
setCountdown(countdown - 1);
}, 1000);
return () => clearTimeout(timer);
} else {
setTimerExpired(true);
}
}, [countdown]);
const handleOtpChange = (value, index) => {
const newOtp = [...otp];
if (/^[0-9]?$/.test(value)) {
newOtp[index] = value;
setOtp(newOtp);
if (value && index < 3) {
inputRefs.current[index + 1].focus();
} else if (!value && index > 0) {
inputRefs.current[index - 1].focus();
}
}
};
const handleResendCode = () => {
setOtp(["", "", "", ""]);
setCountdown(59);
setTimerExpired(false);
console.log("Resending OTP code");
inputRefs.current[0].focus();
};
const handleKeyPress = (e, index) => {
if (e.nativeEvent.key === "Backspace" && !otp[index] && index > 0) {
inputRefs.current[index - 1].focus();
}
};
const handleFocus = (index) => {
setFocusedIndex(index);
};
const handleBlur = () => {
setFocusedIndex(null);
};
const promoCodeApplied = true;
const promoCode = "SAVE10";
const promoDescription = "Get 10% off on your order";
return (
<SafeAreaView style={tw`flex-1 bg-white`}>
<StatusBar backgroundColor="#FDE504" />
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={tw`flex-1`}
>
<View style={tw`bg-[#FDE504] h-[48px]`}>
<View style={tw`flex-row items-center px-4 pt-4 ml-2 `}>
<TouchableOpacity onPress={handleBack}>
<Ionicons name="chevron-back" size={24} color="black" />
</TouchableOpacity>
</View>
</View>
<View style={tw`px-5 py-3`}>
<Text style={[tw`text-base `, { fontFamily: "Karla-Bold" }]}>
Order Details
</Text>
</View>
<ScrollView
style={tw`flex-1`}
contentContainerStyle={tw`pb-4 flex-grow`}
>
<View style={tw`w-full border-b-4 border-[#FFFBE1] mb-2`} />
<View style={tw`w-full py-[22px]`}>
{/* Shipping Address Section */}
<View style={tw`flex-row justify-between px-5`}>
<Text
style={[
tw`text-center text-neutral-900 text-base leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
Shipping Address
</Text>
{shippingAddress && (
<TouchableOpacity
onPress={() => navigation.navigate("EditAddress", { type: "shipping" })}
>
<Text
style={[
tw`text-center text-neutral-900 text-[12px] leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
Change
</Text>
</TouchableOpacity>
)}
</View>
{shippingAddress ? (
<View
style={tw`h-20 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex justify-start items-start`}
>
<Text
style={[
tw`text-neutral-900 text-sm mb-2`,
{ fontFamily: "Karla-Bold" },
]}
>
Phone - {shippingAddress.phone}
</Text>
<Text
style={[
tw`text-neutral-400 text-xs `,
{ fontFamily: "Karla-Regular" },
]}
>
{shippingAddress.address}
</Text>
</View>
) : (
<TouchableOpacity
style={tw`h-20 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex-row justify-start items-center gap-[20px]`}
onPress={() => navigation.navigate("AddAddress", { type: "shipping" })}
>
<Text style={tw`text-2xl text-[#1F2125] mr-4`}>+</Text>
<Text style={tw`text-base text-black`}>
Add Shipping Address
</Text>
</TouchableOpacity>
)}
{/* Billing Address Section */}
<View style={tw`flex-row justify-between px-5`}>
<Text
style={[
tw`text-center text-neutral-900 text-base leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
Billing Address
</Text>
{billingAddress && (
<TouchableOpacity
onPress={() => navigation.navigate("EditAddress", { type: "billing" })}
>
<Text
style={[
tw`text-center text-neutral-900 text-[12px] leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
Change
</Text>
</TouchableOpacity>
)}
</View>
{billingAddress ? (
<View
style={tw`h-20 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex justify-start items-start`}
>
<Text
style={[
tw`text-neutral-900 text-sm mb-2`,
{ fontFamily: "Karla-Bold" },
]}
>
Phone - {billingAddress.phone}
</Text>
<Text
style={[
tw`text-neutral-400 text-xs `,
{ fontFamily: "Karla-Regular" },
]}
>
{billingAddress.address}
</Text>
</View>
) : (
<TouchableOpacity
style={tw`h-15 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex-row justify-start items-center gap-[20px]`}
onPress={() => navigation.navigate("AddAddress", { type: "billing" })}
>
<Text style={tw`text-3xl text-[#1F2125] mr-4`}>+</Text>
<Text
style={[
tw`text-base text-black`,
{ fontFamily: "Karla-Regular" },
]}
>
Add Billing Address
</Text>
</TouchableOpacity>
)}
<View style={tw`w-full border-b-4 border-[#FFFBE1] mb-2`} />
</View>
<View style={tw`w-full pb-[22px]`}>
<View style={tw`flex-row justify-between px-5`}>
<Text
style={[
tw`text-center text-neutral-900 text-base leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
Payment Method
</Text>
<Text
style={[
tw`text-center text-neutral-900 text-[12px] leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
See All
</Text>
</View>
<View
style={tw`h-20 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex-row justify-start items-center gap-[20px]`}
>
<View>
<Image
source={require("../../assets/checkout/mastercard.png")}
style={tw`h-7 w-10`}
/>
</View>
<View>
<Text
style={[
tw`text-neutral-900 text-sm mb-1`,
{ fontFamily: "Karla-Bold" },
]}
>
Mastercard
</Text>
<Text
style={[
tw`text-neutral-400 text-xs`,
{ fontFamily: "Karla-Regular" },
]}
>
Checked Automatically
</Text>
</View>
</View>
<View style={tw`w-full border-b-4 border-[#FFFBE1] mb-2`} />
</View>
<View style={tw`w-full pb-[22px]`}>
<View style={tw`flex-row justify-between px-5`}>
<Text
style={[
tw`text-center text-neutral-900 text-base leading-tight`,
{ fontFamily: "Karla-Bold" },
]}
>
Voucher
</Text>
</View>
<View style={tw`w-full py-[12px]`}>
{/* Promo Code Section */}
{promoCodeApplied ? (
<View
style={tw`h-15 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex-row justify-start items-center gap-[20px]`}
>
<View>
<Image
source={require("../../assets/checkout/Discount.png")}
style={tw`h-5 w-5`}
/>
</View>
<View>
<Text
style={[
tw`text-[#1F2125] text-sm mb-1`,
{ fontFamily: "Karla-Bold" },
]}
>
One promo was applied
</Text>
</View>
<View style={tw`flex-row items-center px-4 ml-12`}>
<TouchableOpacity onPress={handleBack}>
<Ionicons
name="chevron-forward"
size={24}
color="black"
/>
</TouchableOpacity>
</View>
</View>
) : (
<TouchableOpacity
style={tw`h-15 border rounded-[12px] border-gray-200 ml-[16px] mr-4 mt-[12px] mb-[22px] p-4 flex-row justify-start items-center gap-[20px]`}
onPress={() => navigation.navigate("Coupons")}
>
<Text style={tw`text-3xl text-[#1F2125]`}>+</Text>
<Text
style={[
tw`text-base text-black`,
{ fontFamily: "Karla-Regular" },
]}
>
Apply Promo Code
</Text>
</TouchableOpacity>
)}
</View>
<View>
<View style={tw`flex-row justify-between px-4 mt-[50px]`}>
<Text
style={[
tw`text-neutral-900 text-sm `,
{ fontFamily: "Karla-Regular" },
]}
>
Unit Cost
</Text>
<Text
style={[
tw`text-right text-neutral-900 text-sm leading-none`,
{ fontFamily: "Karla-Bold" },
]}
>
{checkoutData?.totalAmount || "0"} د.إ
</Text>
</View>
<View style={tw`flex-row justify-between px-4 mt-[11px]`}>
<Text
style={[
tw`text-neutral-900 text-sm `,
{ fontFamily: "Karla-Regular" },
]}
>
Qty
</Text>
<Text
style={[
tw`text-right text-neutral-900 text-sm leading-none`,
{ fontFamily: "Karla-Bold" },
]}
>
{checkoutData?.totalQuantity || "0"}
</Text>
</View>
<View style={tw`flex-row justify-between px-4 mt-[11px]`}>
<Text
style={[
tw`text-neutral-900 text-sm `,
{ fontFamily: "Karla-Regular" },
]}
>
Discount
</Text>
<Text
style={[
tw`text-right text-[#30BD75] text-sm leading-none`,
{ fontFamily: "Karla-Bold" },
]}
>
{checkoutData?.discountAmount || "0"} د.إ -
</Text>
</View>
<View style={tw`flex-row justify-between px-4 mt-[11px]`}>
<Text
style={[
tw`text-neutral-900 text-sm `,
{ fontFamily: "Karla-Regular" },
]}
>
Shipping Cost
</Text>
<Text
style={[
tw`text-right text-neutral-900 text-sm leading-none`,
{ fontFamily: "Karla-Bold" },
]}
>
20 د.إ
</Text>
</View>
<View
style={tw`border-t border-dashed border-gray-300 my-2 ml-4 mr-4 mt-[11px]`}
/>
<View style={tw`flex-row justify-between px-4 mt-[20px]`}>
<Text
style={[
tw`text-neutral-900 text-base `,
{ fontFamily: "Karla-Bold" },
]}
>
Total
</Text>
<Text
style={tw`text-right text-neutral-900 text-sm font-bold leading-none`}
>
{checkoutData?.finalTotal || "0"} د.إ
</Text>
</View>
</View>
</View>
</ScrollView>
<View style={tw`p-4`}>
<TouchableOpacity style={tw`bg-[#FDE504] p-[15px] rounded-xl`}>
<Text
style={[
tw`text-center text-[16px]`,
{ fontFamily: "Karla-Bold" },
]}
>
Checkout
</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => setModalVisible(false)}
>
<View style={tw`flex-1 justify-end`}>
<View style={tw`bg-black bg-opacity-50 absolute inset-0`} />
<View style={tw`items-center mb-4`}>
<TouchableOpacity
style={tw`bg-gray-300 rounded-full p-2 mt-2`}
onPress={() => setModalVisible(false)}
>
<Ionicons name="close" size={20} color="#000" />
</TouchableOpacity>
</View>
<View style={tw`bg-white rounded-t-[20px] p-4 mt-[22px]`}>
<View style={tw`mb-[12px]`}>
<Text style={[tw`text-[22px] text-[#070707] mb-1`, { fontFamily: "Karla-Bold" }]}>
Verify Your Phone Number
</Text>
<Text style={[tw`text-[14px] w-[328px] h-[44px]`, { fontFamily: "Karla-Regular" }]}>
To use KUKU, we need to verify your phone number. We will never
display this number publicly.
</Text>
</View>
<View
style={tw`flex-row border border-gray-200 rounded-[12px] px-4 items-center mb-5 bg-[#F7F7F7] h-[56px]`}
>
<View
style={tw`flex-row items-center pr-2 border-r border-r-gray-200`}
>
<Image
source={require("../../assets/login/uae-flag.png")}
style={tw`w-4 h-2.5 mr-1`}
/>
<Text style={[tw`text-gray-700 text-sm mr-1`, { fontFamily: "Karla-Regular" }]}>+971</Text>
<Ionicons name="chevron-down" size={12} color="#666" />
</View>
<TextInput
placeholder="Phone Number"
style={[tw`flex-1 pl-2 text-gray-700 text-base`, { fontFamily: "Karla-Regular" }]}
keyboardType="phone-pad"
placeholderTextColor="#999"
value={phoneNumber}
onChangeText={handlePhoneNumberChange}
maxLength={10} // Ensures max length of 10
/>
</View>
<View style={tw`flex-row justify-center gap-4 mb-4 mt-[16px]`}>
{otp.map((digit, index) => (
<View
key={index}
style={[
tw`w-16 h-16 border-2 rounded-lg justify-center items-center `,
{
backgroundColor: "#F7F7F7",
borderColor:
digit || focusedIndex === index ? "#FFEB3B" : "#E0E0E0",
},
]}
>
<TextInput
ref={(el) => (inputRefs.current[index] = el)}
style={[
tw`text-xl font-bold w-full h-full`,
{ textAlign: "center", textAlignVertical: "start" },
]}
keyboardType="number-pad"
maxLength={1}
value={digit}
onChangeText={(value) => handleOtpChange(value, index)}
onKeyPress={(e) => handleKeyPress(e, index)}
onFocus={() => handleFocus(index)}
onBlur={handleBlur}
selectTextOnFocus
placeholder="0"
placeholderTextColor="#e5e5e5"
/>
</View>
))}
</View>
{timerExpired ? (
<View style={tw`flex-row justify-center mb-8`}>
<Text style={[tw`text-gray-500 text-sm`, { fontFamily: "Karla-Regular" }]}>
Didn't received code?{" "}
</Text>
<TouchableOpacity onPress={handleResendCode}>
<Text style={[tw`text-gray-800 text-sm`, { fontFamily: "Karla-SemiBold" }]}>
Resend Code
</Text>
</TouchableOpacity>
</View>
) : (
<Text
style={[tw`text-center text-gray-800 w-[328px] h-[52px] mb-8`, { fontFamily: "Karla-Regular" }]}
>
You can resend code in {countdown} sec
</Text>
)}
<TouchableOpacity
style={tw`bg-[#FDE504] rounded-lg py-4 items-center mb-4 h-[56px]`}
onPress={handleOtpRequest}
>
<Text style={tw`text-karla-700 font-medium text-[16px]`}>
{otpRequested ? "Submit" : "Get OTP"}
</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</SafeAreaView>
);
};
export default CheckoutScreen;
Editor is loading...
Leave a Comment