Waseel: driver app, dispatch, POI suggestions, map fixes

This commit is contained in:
Krikorios
2026-08-25 02:57:49 +03:00
parent 899ca93cd5
commit 1d84003e0a
50 changed files with 3625 additions and 625 deletions
+41 -34
View File
@@ -6,6 +6,7 @@ import ReactNativeModal from "react-native-modal";
import { images } from "@/constants";
import { ApiError, fetchAPI } from "@/lib/fetch";
import { useT } from "@/lib/i18n";
import { formatLBP } from "@/lib/pricing";
import { useLocationStore } from "@/store";
import type { PaymentProps } from "@/types/type";
@@ -32,6 +33,7 @@ export const Payment = ({
const [method, setMethod] = useState<PaymentMethod>("cash");
const [success, setSuccess] = useState(false);
const [processing, setProcessing] = useState(false);
const t = useT();
const fareCents = Math.round(parseFloat(amount) * 100); // in cents
@@ -66,8 +68,8 @@ export const Payment = ({
} catch (err) {
console.log("[PAYMENT]: ", err);
Alert.alert(
"Error",
"Something went wrong while booking your ride. Please try again.",
t("components.payment.alertErrorTitle"),
t("components.payment.alertErrorBody"),
);
} finally {
setProcessing(false);
@@ -138,8 +140,8 @@ export const Payment = ({
setSuccess(true);
} else {
Alert.alert(
"Payment not completed",
"Your payment was cancelled or could not be verified. Please try again.",
t("components.payment.alertPaymentNotCompletedTitle"),
t("components.payment.alertPaymentNotCompletedBody"),
);
}
} catch (err) {
@@ -149,13 +151,13 @@ export const Payment = ({
// branch every cancellation lands in the generic "something went wrong".
if (err instanceof ApiError && err.status === 400) {
Alert.alert(
"Payment not completed",
"Your payment was cancelled or could not be verified. Please try again.",
t("components.payment.alertPaymentNotCompletedTitle"),
t("components.payment.alertPaymentNotCompletedBody"),
);
} else {
Alert.alert(
"Error",
"Something went wrong while processing your payment. Please try again.",
t("components.payment.alertProcessingTitle"),
t("components.payment.alertProcessingBody"),
);
}
} finally {
@@ -166,15 +168,19 @@ export const Payment = ({
const confirm = () =>
method === "cash"
? payWithCash()
: Alert.alert("Pay by card", `Your card will be charged $${amount}.`, [
{ text: "Cancel", style: "cancel" },
{ text: "Continue", onPress: () => void payWithCard() },
]);
: Alert.alert(
t("components.payment.alertPayCardTitle"),
t("components.payment.alertPayCardBody", { amount }),
[
{ text: t("common.cancel"), style: "cancel" },
{ text: t("common.continue"), onPress: () => void payWithCard() },
],
);
return (
<>
<Text className="text-lg font-JakartaSemiBold mt-4 mb-2">
Payment Method
<Text className="text-lg font-JakartaSemiBold mt-4 mb-2 text-black dark:text-white">
{t("components.payment.paymentMethod")}
</Text>
<View className="flex flex-row gap-x-3">
@@ -182,16 +188,16 @@ export const Payment = ({
onPress={() => setMethod("cash")}
className={`flex-1 items-center py-3 rounded-xl border ${
method === "cash"
? "bg-general-600 border-primary-500"
: "bg-white border-general-700"
? "bg-general-600 dark:bg-primary-500/20 border-primary-500"
: "bg-white dark:bg-neutral-900 border-general-700 dark:border-neutral-700"
}`}
>
<Text
className={`font-JakartaMedium ${
method === "cash" ? "text-white" : "text-black"
method === "cash" ? "text-white" : "text-black dark:text-white"
}`}
>
💵 Cash
{t("components.payment.cash")}
</Text>
</TouchableOpacity>
@@ -199,16 +205,16 @@ export const Payment = ({
onPress={() => setMethod("card")}
className={`flex-1 items-center py-3 rounded-xl border ${
method === "card"
? "bg-general-600 border-primary-500"
: "bg-white border-general-700"
? "bg-general-600 dark:bg-primary-500/20 border-primary-500"
: "bg-white dark:bg-neutral-900 border-general-700 dark:border-neutral-700"
}`}
>
<Text
className={`font-JakartaMedium ${
method === "card" ? "text-white" : "text-black"
method === "card" ? "text-white" : "text-black dark:text-white"
}`}
>
💳 Card
{t("components.payment.card")}
</Text>
</TouchableOpacity>
</View>
@@ -216,10 +222,10 @@ export const Payment = ({
<CustomButton
title={
processing
? "Processing..."
? t("components.payment.processing")
: method === "cash"
? "Book ride · Pay cash to driver"
: "Confirm & Pay by Card"
? t("components.payment.bookCash")
: t("components.payment.confirmCard")
}
className="my-2 mt-4"
onPress={confirm}
@@ -230,23 +236,24 @@ export const Payment = ({
isVisible={success}
onBackdropPress={() => setSuccess(false)}
>
<View className="flex flex-col items-center justify-center bg-white p-7 rounded-2xl">
<Image source={images.check} alt="Check" className="w-28 h-28 mt-5" />
<View className="flex flex-col items-center justify-center bg-white dark:bg-neutral-900 p-7 rounded-2xl">
<Image source={images.check} alt={t("components.payment.checkAlt")} className="w-28 h-28 mt-5" />
<Text className="text-2xl text-center font-JakartaBold mt-5">
Ride Booked!
<Text className="text-2xl text-center font-JakartaBold mt-5 text-black dark:text-white">
{t("components.payment.rideBooked")}
</Text>
<Text className="text-base text-general-200 text-JakartaMedium text-center mt-3">
Thank you for your booking.{"\n"} Your reservation has been placed.
{"\n"}
<Text className="text-base text-general-200 dark:text-neutral-400 text-JakartaMedium text-center mt-3">
{t("components.payment.successBody")}
{method === "cash"
? `Please have ${formatLBP(parseFloat(amount))} ready.`
? t("components.payment.cashInstruction", {
lbp: formatLBP(parseFloat(amount)),
})
: null}
</Text>
<CustomButton
title="Back Home"
title={t("components.payment.backHome")}
onPress={() => {
setSuccess(false);
router.push("/(root)/(tabs)/home");