Fix UI issues
parent
b4e9521630
commit
45d2f6a481
|
|
@ -232,7 +232,7 @@ export default function HomeScreen() {
|
|||
? "warning"
|
||||
: "danger"
|
||||
}
|
||||
message={daysLeftToPayEmiText}
|
||||
message={`${daysLeftToPayEmi} ${t("home.days-left-to-pay-emi")}`}
|
||||
subMessage={t("home.pay-now")}
|
||||
redirectPath="/(tabs)/payments"
|
||||
/>
|
||||
|
|
@ -258,8 +258,7 @@ export default function HomeScreen() {
|
|||
unit={t("home.km")}
|
||||
/>
|
||||
</View>
|
||||
{due_amount && (
|
||||
<>
|
||||
{due_amount && due_amount > 0 ? (
|
||||
<PaymentDueCard
|
||||
label={t("home.payment-due")}
|
||||
amount={due_amount}
|
||||
|
|
@ -267,19 +266,21 @@ export default function HomeScreen() {
|
|||
router.push("/payments/selectAmount");
|
||||
}}
|
||||
/>
|
||||
|
||||
) : due_amount == 0 ? (
|
||||
<EMINotification
|
||||
message="Payment Complete"
|
||||
actionText="View Details"
|
||||
message={`${t("home.payment-complete")}`}
|
||||
actionText={`${t("home.view-details")}`}
|
||||
onActionPress={() => router.push("/(tabs)/payments")}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
<View style={styles.map}>
|
||||
{loading ? (
|
||||
<View style={styles.errorContainer}>
|
||||
<LocationOff />
|
||||
<Text style={styles.errorText}>Fetching Location...</Text>
|
||||
<Text style={styles.errorText}>
|
||||
{t("home.fetching-location")}
|
||||
</Text>
|
||||
</View>
|
||||
) : lat != null && lon != null && !(lat == 0 && lon == 0) ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -49,19 +49,23 @@ const BatteryDetails = () => {
|
|||
(remaining % (30.44 * 24 * 60 * 60 * 1000)) / (24 * 60 * 60 * 1000)
|
||||
);
|
||||
|
||||
durationText = (() => {
|
||||
const parts: string[] = [];
|
||||
|
||||
if (yearsLeft > 0) {
|
||||
parts.push(`${yearsLeft} year${yearsLeft !== 1 ? "s" : ""}`);
|
||||
}
|
||||
if (monthsLeft > 0) {
|
||||
parts.push(`${monthsLeft} month${monthsLeft !== 1 ? "s" : ""}`);
|
||||
}
|
||||
if (daysLeft > 0 || parts.length === 0) {
|
||||
parts.push(`${daysLeft} day${daysLeft !== 1 ? "s" : ""}`);
|
||||
parts.push(`${yearsLeft} ${t("home.year")}`);
|
||||
}
|
||||
|
||||
durationText = parts.join(", ");
|
||||
if (monthsLeft > 0) {
|
||||
parts.push(`${monthsLeft} ${t("home.month")}`);
|
||||
}
|
||||
|
||||
if (daysLeft > 0 || parts.length === 0) {
|
||||
parts.push(`${daysLeft} ${t("home.day")}`);
|
||||
}
|
||||
|
||||
return parts.join(", ");
|
||||
})();
|
||||
}
|
||||
|
||||
const formatDate = (date?: Date | null): string =>
|
||||
|
|
|
|||
|
|
@ -169,7 +169,9 @@ export default function PaymentsTabScreen() {
|
|||
} catch (err) {
|
||||
console.error("Error fetching EMI details:", err);
|
||||
const errorMessage =
|
||||
err instanceof Error ? err.message : "Something went wrong";
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: `${t("service.something-went-wrong")}`;
|
||||
showSnackbar(errorMessage, "error");
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
|
|
@ -255,7 +257,7 @@ export default function PaymentsTabScreen() {
|
|||
</Pressable>
|
||||
<View>
|
||||
<ProfileImage
|
||||
username={data?.name || "User"}
|
||||
username={data?.name || "--"}
|
||||
onClick={() => router.push("/user/profile")}
|
||||
textSize={20}
|
||||
boxSize={40}
|
||||
|
|
@ -268,6 +270,7 @@ export default function PaymentsTabScreen() {
|
|||
|
||||
// Format currency
|
||||
const formatCurrency = (amount: number) => {
|
||||
console.log(amount, "amount format current");
|
||||
return `₹${amount.toLocaleString()}`;
|
||||
};
|
||||
|
||||
|
|
@ -337,7 +340,9 @@ export default function PaymentsTabScreen() {
|
|||
} catch (err) {
|
||||
console.error("Error fetching payment history:", err);
|
||||
const errorMessage =
|
||||
err instanceof Error ? err.message : "Something went wrong";
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: `${t("service.something-went-wrong")}`;
|
||||
showSnackbar(errorMessage, "error");
|
||||
} finally {
|
||||
if (isLoadMore) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { BASE_URL } from "@/constants/config";
|
|||
import { Overlay } from "@/components/common/Overlay";
|
||||
import CrossIcon from "@/assets/icons/close_white.svg";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import CalendarIcon from "@/assets/icons/calendar.svg";
|
||||
|
||||
interface FormValues {
|
||||
serviceType: string | null;
|
||||
|
|
@ -173,17 +174,14 @@ export default function ServiceFormScreen(): JSX.Element {
|
|||
|
||||
console.log("Submission successful:", response.data);
|
||||
|
||||
actions.resetForm();
|
||||
showSnackbar(
|
||||
`${t("service.service-request-success")}`,
|
||||
"success"
|
||||
);
|
||||
actions.resetForm();
|
||||
} catch (error: any) {
|
||||
console.error("Error during submission:", error);
|
||||
showSnackbar(
|
||||
error.message || `${t("service.something-went-wrong")}`,
|
||||
"error"
|
||||
);
|
||||
showSnackbar(`${t("service.something-went-wrong")}`, "error");
|
||||
} finally {
|
||||
actions.setSubmitting(false);
|
||||
}
|
||||
|
|
@ -269,8 +267,11 @@ export default function ServiceFormScreen(): JSX.Element {
|
|||
style={styles.inputBoxDate}
|
||||
>
|
||||
<Text style={styles.dateText}>
|
||||
{values.date && values.date.toLocaleString()}
|
||||
{values.date
|
||||
? values.date.toLocaleString()
|
||||
: `${t("service.select")}`}
|
||||
</Text>
|
||||
<CalendarIcon width={20} height={20} />
|
||||
</TouchableOpacity>
|
||||
{touched.date && errors.date && (
|
||||
<Text style={styles.error}>{`${errors.date}`}</Text>
|
||||
|
|
|
|||
|
|
@ -114,9 +114,11 @@ export default function WelcomeScreen() {
|
|||
<View style={styles.bottomSection}>
|
||||
<View style={styles.contactContainer}>
|
||||
<View style={{ flexDirection: "row" }}>
|
||||
<Text>For any queries, </Text>
|
||||
<Text>{t("onboarding.for-any-queries")}</Text>
|
||||
<TouchableOpacity onPress={makePhoneCall}>
|
||||
<Text style={styles.link}>contact us.</Text>
|
||||
<Text style={styles.link}>
|
||||
{t("onboarding.contact-us")}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import CheckCircle from "@/assets/icons/check_circle.svg";
|
|||
import Pending from "@/assets/icons/pending.svg";
|
||||
import Failed from "@/assets/icons/cancel.svg";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const PaymentConfirmationScreen = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -86,10 +87,10 @@ const PaymentConfirmationScreen = () => {
|
|||
const displayValue = (value: any) => {
|
||||
return value ? String(value) : "--";
|
||||
};
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Header title="Payment Status" />
|
||||
<Header title={`${t("payment.payment-status")}`} />
|
||||
|
||||
<View style={styles.contentFrame}>
|
||||
<View style={styles.qrFrame}>
|
||||
|
|
@ -112,37 +113,49 @@ const PaymentConfirmationScreen = () => {
|
|||
<View style={styles.divider} />
|
||||
|
||||
<View style={styles.transactionContainer}>
|
||||
<Text style={styles.sectionHeader}>Transaction Details</Text>
|
||||
<Text style={styles.sectionHeader}>{`${t(
|
||||
"payment.transaction-details"
|
||||
)}`}</Text>
|
||||
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.detailLabel}>Payment mode</Text>
|
||||
<Text style={styles.detailLabel}>{`${t(
|
||||
"payment.payment-mode"
|
||||
)}`}</Text>
|
||||
<Text style={styles.detailValue}>
|
||||
{displayValue(paymentOrder?.payment_mode?.[0])}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.detailLabel}>Paid to</Text>
|
||||
<Text style={styles.detailLabel}>{`${t(
|
||||
"payment.paid-to"
|
||||
)}`}</Text>
|
||||
<Text style={styles.detailValue}>
|
||||
{displayValue(paymentOrder?.upi_handle)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.detailLabel}>Paid by</Text>
|
||||
<Text style={styles.detailLabel}>{`${t(
|
||||
"payment.paid-by"
|
||||
)}`}</Text>
|
||||
<Text style={styles.detailValue}>
|
||||
{displayValue(paymentOrder?.paid_by_upi_handle)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.detailLabel}>Order ID</Text>
|
||||
<Text style={styles.detailLabel}>{`${t(
|
||||
"payment.order-id"
|
||||
)}`}</Text>
|
||||
<Text style={styles.detailValue}>
|
||||
{displayValue(paymentOrder?.order_id)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.detailRow}>
|
||||
<Text style={styles.detailLabel}>Transaction ID</Text>
|
||||
<Text style={styles.detailLabel}>{`${t(
|
||||
"payment.transaction-id"
|
||||
)}`}</Text>
|
||||
<Text style={styles.detailValue}>
|
||||
{displayValue(
|
||||
paymentOrder?.transaction_id ||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import SuccessIcon from "@/assets/icons/check_circle.svg";
|
|||
import FailureIcon from "@/assets/icons/cancel.svg";
|
||||
import PendingIcon from "@/assets/icons/pending.svg";
|
||||
import Header from "@/components/common/Header";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface TransactionDetailData {
|
||||
id: number;
|
||||
|
|
@ -61,6 +62,8 @@ export default function TransactionDetailScreen() {
|
|||
fetchTransactionDetail();
|
||||
}, [paymentId]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const fetchTransactionDetail = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
|
@ -78,7 +81,9 @@ export default function TransactionDetailScreen() {
|
|||
} catch (err) {
|
||||
console.error("Error fetching transaction details:", err);
|
||||
const errorMessage =
|
||||
err instanceof Error ? err.message : "Something went wrong";
|
||||
err instanceof Error
|
||||
? err.message
|
||||
: `${t("service.something-went-wrong")}`;
|
||||
showSnackbar(errorMessage, "error");
|
||||
router.back();
|
||||
} finally {
|
||||
|
|
@ -132,7 +137,10 @@ export default function TransactionDetailScreen() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Header title="Transaction Details" showBackButton={true} />
|
||||
<Header
|
||||
title={`${t("payment.transaction-details")}`}
|
||||
showBackButton={true}
|
||||
/>
|
||||
{isLoading ? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color="#00BE88" />
|
||||
|
|
@ -160,30 +168,32 @@ export default function TransactionDetailScreen() {
|
|||
|
||||
<View style={styles.divider} />
|
||||
<View style={styles.detailsCard}>
|
||||
<Text style={styles.detailsTitle}>Transaction Details</Text>
|
||||
<Text style={styles.detailsTitle}>
|
||||
{`${t("payment.transaction-details")}`}
|
||||
</Text>
|
||||
|
||||
<DetailRow
|
||||
label="Payment mode"
|
||||
label={`${t("payment.payment-mode")}`}
|
||||
value={transactionData.payment_mode.join(", ") || "--"}
|
||||
/>
|
||||
|
||||
<DetailRow
|
||||
label="Paid to"
|
||||
label={`${t("payment.paid-to")}`}
|
||||
value={transactionData.upi_handle || "--"}
|
||||
/>
|
||||
|
||||
<DetailRow
|
||||
label="Paid by"
|
||||
label={`${t("payment.paid-by")}`}
|
||||
value={transactionData.paid_by_upi_handle || "--"}
|
||||
/>
|
||||
|
||||
<DetailRow
|
||||
label="Order ID"
|
||||
label={`${t("payment.order-id")}`}
|
||||
value={transactionData.order_id || "--"}
|
||||
/>
|
||||
|
||||
<DetailRow
|
||||
label="Transaction ID"
|
||||
label={`${t("payment.transaction-id")}`}
|
||||
value={transactionData.transaction_order_id || "--"}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import {
|
|||
Text,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
SafeAreaView,
|
||||
Alert,
|
||||
Share,
|
||||
Linking,
|
||||
BackHandler,
|
||||
ScrollView,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import * as MediaLibrary from "expo-media-library";
|
||||
|
|
@ -22,58 +22,41 @@ import Header from "@/components/common/Header";
|
|||
import ShareIcon from "@/assets/icons/share.svg";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { useSnackbar } from "@/contexts/Snackbar";
|
||||
|
||||
import DownloadIcon from "@/assets/icons/download.svg";
|
||||
import { payments } from "@/constants/config";
|
||||
import { useRouter } from "expo-router";
|
||||
import { useFocusEffect, useRouter } from "expo-router";
|
||||
import { useSocket } from "@/contexts/SocketContext";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const { height: screenHeight } = Dimensions.get("window");
|
||||
|
||||
const UpiPaymentScreen = () => {
|
||||
const dispatch = useDispatch();
|
||||
//paymentorder.amount is undefined
|
||||
console.log("inside payemi ✅✅");
|
||||
useEffect(() => {
|
||||
console.log("inside pay emi useeffect 🔥🔥🔥🔥🔥");
|
||||
}, []);
|
||||
const paymentOrder = useSelector(
|
||||
(state: RootState) => state.payments.paymentOrder
|
||||
);
|
||||
|
||||
const router = useRouter();
|
||||
const { onPaymentConfirmation, offPaymentConfirmation, disconnect } =
|
||||
useSocket();
|
||||
|
||||
const { showSnackbar } = useSnackbar();
|
||||
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
useEffect(() => {
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
let backPressCount = 0;
|
||||
let backPressTimer: NodeJS.Timeout | null = null;
|
||||
const handlePaymentConfirmation = (data: any) => {
|
||||
console.log("Payment confirmation received:", data);
|
||||
|
||||
dispatch(
|
||||
setPaymentOrder({
|
||||
...paymentOrder,
|
||||
...data,
|
||||
})
|
||||
);
|
||||
|
||||
offPaymentConfirmation();
|
||||
disconnect();
|
||||
|
||||
router.replace("/payments/Confirmation");
|
||||
};
|
||||
|
||||
onPaymentConfirmation(handlePaymentConfirmation);
|
||||
|
||||
const backAction = () => {
|
||||
if (backPressCount === 0) {
|
||||
backPressCount++;
|
||||
console.log("Press back again to cancel payment");
|
||||
showSnackbar("Press back again to cancel payment", "success");
|
||||
|
||||
showSnackbar("Press back again to cancel payment", "info");
|
||||
backPressTimer = setTimeout(() => {
|
||||
backPressCount = 0;
|
||||
}, 2000);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if (backPressTimer) clearTimeout(backPressTimer);
|
||||
|
|
@ -83,18 +66,41 @@ const UpiPaymentScreen = () => {
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const backHandler = BackHandler.addEventListener(
|
||||
"hardwareBackPress",
|
||||
backAction
|
||||
);
|
||||
// ✅ Cleanup when screen loses focus
|
||||
return () => {
|
||||
offPaymentConfirmation();
|
||||
if (backPressTimer) clearTimeout(backPressTimer);
|
||||
backHandler.remove();
|
||||
};
|
||||
}, [onPaymentConfirmation, offPaymentConfirmation, router]);
|
||||
}, [offPaymentConfirmation, disconnect, router])
|
||||
);
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
const handlePaymentConfirmation = (data: any) => {
|
||||
dispatch(setPaymentOrder({ ...paymentOrder, ...data }));
|
||||
offPaymentConfirmation();
|
||||
disconnect();
|
||||
router.replace("/payments/Confirmation");
|
||||
};
|
||||
onPaymentConfirmation(handlePaymentConfirmation);
|
||||
return () => {
|
||||
offPaymentConfirmation();
|
||||
};
|
||||
}, [
|
||||
paymentOrder,
|
||||
onPaymentConfirmation,
|
||||
offPaymentConfirmation,
|
||||
disconnect,
|
||||
router,
|
||||
])
|
||||
);
|
||||
|
||||
const formatAmount = (amount: number): string => {
|
||||
if (amount == null || amount == undefined) return `₹${0}`;
|
||||
return `₹${amount.toLocaleString("en-IN")}`;
|
||||
};
|
||||
|
||||
|
|
@ -104,14 +110,8 @@ const UpiPaymentScreen = () => {
|
|||
return currentDate > expiryDate;
|
||||
};
|
||||
|
||||
const getExpiryTime = (): string => {
|
||||
const expiryDate = new Date(paymentOrder.expiry_date);
|
||||
return expiryDate.toLocaleString("en-IN");
|
||||
};
|
||||
|
||||
const getUpiUrl = (): string => {
|
||||
const upiString = paymentOrder.payment_link;
|
||||
|
||||
const upiMatch = upiString.match(/upi_string=([^&]+)/);
|
||||
if (upiMatch) {
|
||||
return decodeURIComponent(upiMatch[1]);
|
||||
|
|
@ -125,14 +125,10 @@ const UpiPaymentScreen = () => {
|
|||
showSnackbar(payments.LINK_EXPIRED, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const upiUrl = getUpiUrl();
|
||||
console.log("Opening UPI URL:", upiUrl);
|
||||
|
||||
dispatch(updatePaymentStatus("processing"));
|
||||
|
||||
const canOpenUrl = await Linking.canOpenURL(upiUrl);
|
||||
|
||||
if (canOpenUrl) {
|
||||
await Linking.openURL(upiUrl);
|
||||
} else {
|
||||
|
|
@ -169,14 +165,12 @@ const UpiPaymentScreen = () => {
|
|||
showSnackbar("Please grant permission to save images", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const fileUri =
|
||||
FileSystem.documentDirectory + `qr-${paymentOrder.order_id}.png`;
|
||||
const downloadResult = await FileSystem.downloadAsync(
|
||||
paymentOrder.qr_code_url,
|
||||
fileUri
|
||||
);
|
||||
|
||||
if (downloadResult.status === 200) {
|
||||
const asset = await MediaLibrary.createAssetAsync(downloadResult.uri);
|
||||
await MediaLibrary.createAlbumAsync("Payment QR Codes", asset, false);
|
||||
|
|
@ -190,15 +184,19 @@ const UpiPaymentScreen = () => {
|
|||
};
|
||||
|
||||
function handlePaymentDone() {
|
||||
router.push("/(tabs)/payments");
|
||||
router.navigate("/(tabs)/payments");
|
||||
}
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.container}>
|
||||
<Header title="Pay EMI" showBackButton={false} />
|
||||
|
||||
<View style={styles.container}>
|
||||
<Header title={t("payment.pay-emi")} showBackButton={false} />
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
<View style={styles.content}>
|
||||
<View style={styles.qrFrame}>
|
||||
<View style={styles.amountSection}>
|
||||
|
|
@ -209,7 +207,6 @@ const UpiPaymentScreen = () => {
|
|||
{formatAmount(paymentOrder?.amount)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.qrCodeContainer}>
|
||||
<Image
|
||||
source={{ uri: paymentOrder?.qr_code_url }}
|
||||
|
|
@ -217,15 +214,16 @@ const UpiPaymentScreen = () => {
|
|||
contentFit="contain"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.buttonsContainer}>
|
||||
<TouchableOpacity onPress={shareQR} style={styles.secondaryButton}>
|
||||
<TouchableOpacity
|
||||
onPress={shareQR}
|
||||
style={styles.secondaryButton}
|
||||
>
|
||||
<ShareIcon />
|
||||
<Text style={styles.secondaryButtonText}>
|
||||
{t("payment.share-qr")}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={downloadQR}
|
||||
style={styles.secondaryButton}
|
||||
|
|
@ -245,6 +243,7 @@ const UpiPaymentScreen = () => {
|
|||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View style={[styles.confirm, { marginBottom: insets.bottom }]}>
|
||||
<Text style={styles.confirmTitle}>
|
||||
{t("payment.confirm-payment")}
|
||||
|
|
@ -258,10 +257,41 @@ const UpiPaymentScreen = () => {
|
|||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: "#F3F5F8",
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollContent: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 16,
|
||||
justifyContent: "space-between",
|
||||
minHeight: screenHeight * 0.8, // Ensures minimum height for space-between to work
|
||||
},
|
||||
qrFrame: {
|
||||
backgroundColor: "#FCFCFC",
|
||||
borderRadius: 8,
|
||||
padding: 16,
|
||||
alignItems: "center",
|
||||
},
|
||||
confirm: {
|
||||
padding: 16,
|
||||
flexDirection: "column",
|
||||
backgroundColor: "#FCFCFC",
|
||||
gap: 16,
|
||||
borderRadius: 8,
|
||||
},
|
||||
doneText: {
|
||||
textAlign: "center",
|
||||
fontWeight: "500",
|
||||
|
|
@ -272,6 +302,7 @@ const styles = StyleSheet.create({
|
|||
padding: 16,
|
||||
borderWidth: 1,
|
||||
borderColor: "#DCE1E9",
|
||||
borderRadius: 4,
|
||||
},
|
||||
confirmTitle: {
|
||||
fontWeight: "400",
|
||||
|
|
@ -279,16 +310,6 @@ const styles = StyleSheet.create({
|
|||
lineHeight: 14,
|
||||
color: "#252A34",
|
||||
},
|
||||
confirm: {
|
||||
padding: 16,
|
||||
flexDirection: "column",
|
||||
backgroundColor: "#FCFCFC",
|
||||
gap: 16,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: "#F3F5F8",
|
||||
},
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
|
|
@ -315,19 +336,6 @@ const styles = StyleSheet.create({
|
|||
fontWeight: "600",
|
||||
color: "#253342",
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 16,
|
||||
justifyContent: "space-between",
|
||||
},
|
||||
qrFrame: {
|
||||
backgroundColor: "#FCFCFC",
|
||||
borderRadius: 8,
|
||||
padding: 16,
|
||||
alignItems: "center",
|
||||
marginTop: 16,
|
||||
},
|
||||
amountSection: {
|
||||
alignItems: "center",
|
||||
marginBottom: 16,
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ const SelectAmountScreen = () => {
|
|||
};
|
||||
}, []);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
console.log(
|
||||
|
|
@ -146,7 +148,7 @@ const SelectAmountScreen = () => {
|
|||
}
|
||||
} catch (err) {
|
||||
console.error(err, "Error in creating order.");
|
||||
showSnackbar("Something went wrong.", "error");
|
||||
showSnackbar(`${t("service.something-went-wrong")}`, "error");
|
||||
} finally {
|
||||
setIsFetching(false);
|
||||
}
|
||||
|
|
@ -204,7 +206,7 @@ const SelectAmountScreen = () => {
|
|||
return values.customAmount ? parseFloat(values.customAmount) : 0;
|
||||
};
|
||||
|
||||
const paymentAmount = getPaymentAmount();
|
||||
const paymentAmount = getPaymentAmount() || 0;
|
||||
|
||||
const isButtonEnabled =
|
||||
values.paymentType === "due" ||
|
||||
|
|
@ -223,8 +225,6 @@ const SelectAmountScreen = () => {
|
|||
: "Select Amount";
|
||||
}
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
style={styles.container}
|
||||
|
|
@ -232,7 +232,10 @@ const SelectAmountScreen = () => {
|
|||
// Improved keyboard offset
|
||||
// keyboardVerticalOffset={Platform.OS === "ios" ? 88 : 0}
|
||||
>
|
||||
<Header title="Select Amount" showBackButton={true} />
|
||||
<Header
|
||||
title={t("payment.select-amount")}
|
||||
showBackButton={true}
|
||||
/>
|
||||
|
||||
<ScrollView
|
||||
style={styles.content}
|
||||
|
|
@ -372,7 +375,9 @@ const SelectAmountScreen = () => {
|
|||
disabled={!isButtonEnabled}
|
||||
>
|
||||
{getPaymentAmount() < payments.MIN_AMOUNT ? (
|
||||
<Text style={styles.payButtonText}>Select Amount</Text>
|
||||
<Text style={styles.payButtonText}>
|
||||
{t("payment.select-amount")}
|
||||
</Text>
|
||||
) : (
|
||||
<Text style={styles.payButtonText}>
|
||||
Pay ₹{getPaymentAmount().toFixed(2)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useTransition } from "react";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
|
|
@ -22,9 +22,11 @@ import { router } from "expo-router";
|
|||
import { useSnackbar } from "@/contexts/Snackbar";
|
||||
import Header from "@/components/common/Header";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Overlay } from "@/components/common/Overlay";
|
||||
|
||||
export default function EditName() {
|
||||
const { data } = useSelector((state: RootState) => state.user);
|
||||
const [isLoading, setIsLoading] = useState<boolean>();
|
||||
const originalName = data?.name || "";
|
||||
const dispatch = useDispatch();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
|
@ -34,23 +36,27 @@ export default function EditName() {
|
|||
.max(57, "Name cannot exceed 57 characters"),
|
||||
});
|
||||
const { showSnackbar } = useSnackbar();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const handleSave = async (values: { name: string }) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await api.put(`${BASE_URL}/api/v1/update-user-information`, {
|
||||
name: values.name,
|
||||
mobile: data?.mobile,
|
||||
});
|
||||
|
||||
dispatch(setUserData({ name: values.name }));
|
||||
showSnackbar("Name updated successfully", "success");
|
||||
showSnackbar(`${t("profile.name-changed")}`, "success");
|
||||
router.back();
|
||||
} catch (error) {
|
||||
showSnackbar(`${t("service.something-went-wrong")}`, "error");
|
||||
console.error("Error updating name:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header title={t("profile.edit-name")} showBackButton={true} />
|
||||
|
|
@ -124,6 +130,7 @@ export default function EditName() {
|
|||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</KeyboardAvoidingView>
|
||||
<Overlay isUploading={isLoading ?? false} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<svg width="29" height="28" viewBox="0 0 29 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_901_1089" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="4" y="4" width="21" height="20">
|
||||
<rect x="4.57031" y="4" width="20" height="20" fill="#D9D9D9"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_901_1089)">
|
||||
<path d="M16.6536 19C16.0703 19 15.5773 18.7986 15.1745 18.3958C14.7717 17.993 14.5703 17.5 14.5703 16.9167C14.5703 16.3333 14.7717 15.8403 15.1745 15.4375C15.5773 15.0347 16.0703 14.8333 16.6536 14.8333C17.237 14.8333 17.73 15.0347 18.1328 15.4375C18.5356 15.8403 18.737 16.3333 18.737 16.9167C18.737 17.5 18.5356 17.993 18.1328 18.3958C17.73 18.7986 17.237 19 16.6536 19ZM8.73698 22.3333C8.27865 22.3333 7.88628 22.1701 7.5599 21.8437C7.23351 21.5174 7.07031 21.125 7.07031 20.6667V8.99999C7.07031 8.54166 7.23351 8.1493 7.5599 7.82291C7.88628 7.49652 8.27865 7.33332 8.73698 7.33332H9.57031V6.49999C9.57031 6.26388 9.65017 6.06596 9.8099 5.90624C9.96962 5.74652 10.1675 5.66666 10.4036 5.66666C10.6398 5.66666 10.8377 5.74652 10.9974 5.90624C11.1571 6.06596 11.237 6.26388 11.237 6.49999V7.33332H17.9036V6.49999C17.9036 6.26388 17.9835 6.06596 18.1432 5.90624C18.303 5.74652 18.5009 5.66666 18.737 5.66666C18.9731 5.66666 19.171 5.74652 19.3307 5.90624C19.4905 6.06596 19.5703 6.26388 19.5703 6.49999V7.33332H20.4036C20.862 7.33332 21.2543 7.49652 21.5807 7.82291C21.9071 8.1493 22.0703 8.54166 22.0703 8.99999V20.6667C22.0703 21.125 21.9071 21.5174 21.5807 21.8437C21.2543 22.1701 20.862 22.3333 20.4036 22.3333H8.73698ZM8.73698 20.6667H20.4036V12.3333H8.73698V20.6667ZM8.73698 10.6667H20.4036V8.99999H8.73698V10.6667Z" fill="#565F70"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -4,6 +4,7 @@ import { StyleSheet, Text, TouchableOpacity } from "react-native";
|
|||
import { useEffect, useState } from "react";
|
||||
import { getLanguage, setLanguage } from "@/services/i18n";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSnackbar } from "@/contexts/Snackbar";
|
||||
|
||||
interface CustomerSupportProps {
|
||||
visible: boolean;
|
||||
|
|
@ -23,12 +24,15 @@ export default function LanguageModal({
|
|||
})();
|
||||
}, []);
|
||||
|
||||
const { showSnackbar } = useSnackbar();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleLanguagePress = (lang: "en" | "hi") => {
|
||||
setSelectedLang(lang);
|
||||
setLanguage(lang);
|
||||
onClose();
|
||||
showSnackbar(`${t("profile.lang-changed")}`, "success");
|
||||
};
|
||||
return (
|
||||
<BottomSheetModal
|
||||
|
|
@ -42,6 +46,7 @@ export default function LanguageModal({
|
|||
selectedLang === "en" && styles.selectedCard,
|
||||
]}
|
||||
onPress={() => handleLanguagePress("en")}
|
||||
disabled={selectedLang === "en"}
|
||||
>
|
||||
<Text style={styles.languageText}>English</Text>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -52,6 +57,7 @@ export default function LanguageModal({
|
|||
selectedLang === "hi" && styles.selectedCard,
|
||||
]}
|
||||
onPress={() => handleLanguagePress("hi")}
|
||||
disabled={selectedLang === "hi"}
|
||||
>
|
||||
<Text style={styles.languageText}>हिन्दी</Text>
|
||||
</TouchableOpacity>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Snackbar, Portal } from "react-native-paper";
|
||||
import { StyleSheet, Text } from "react-native";
|
||||
import { Snackbar, Portal, Checkbox } from "react-native-paper";
|
||||
import { StyleSheet, Text, View } from "react-native";
|
||||
import CheckBox from "@/assets/icons/check_circle.svg";
|
||||
import CrossIcon from "@/assets/icons/cancel.svg";
|
||||
|
||||
interface CustomSnackbarProps {
|
||||
message: string;
|
||||
bgColor: string;
|
||||
textColor: string;
|
||||
borderColor: string;
|
||||
icon: React.ReactNode;
|
||||
duration: number;
|
||||
visible: boolean;
|
||||
onDismiss: () => void;
|
||||
|
|
@ -15,6 +19,8 @@ const CustomSnackbar: React.FC<CustomSnackbarProps> = ({
|
|||
message,
|
||||
bgColor,
|
||||
textColor,
|
||||
borderColor,
|
||||
icon,
|
||||
duration,
|
||||
visible,
|
||||
onDismiss,
|
||||
|
|
@ -35,16 +41,29 @@ const CustomSnackbar: React.FC<CustomSnackbarProps> = ({
|
|||
onDismiss={onDismiss}
|
||||
style={[
|
||||
styles.snackbar,
|
||||
{ backgroundColor: bgColor, zIndex: 999, elevation: 999 },
|
||||
{
|
||||
backgroundColor: bgColor,
|
||||
borderColor,
|
||||
zIndex: 999,
|
||||
elevation: 999,
|
||||
},
|
||||
]}
|
||||
duration={Snackbar.DURATION_SHORT}
|
||||
>
|
||||
<Text style={{ color: textColor, ...styles.message }}>{message}</Text>
|
||||
<View style={styles.content}>
|
||||
{icon}
|
||||
<Text style={[styles.message, { color: textColor }]}>{message}</Text>
|
||||
</View>
|
||||
</Snackbar>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: 8,
|
||||
},
|
||||
message: {
|
||||
fontStyle: "normal",
|
||||
fontWeight: "bold",
|
||||
|
|
@ -59,6 +78,8 @@ const styles = StyleSheet.create({
|
|||
borderRadius: 5,
|
||||
marginBottom: 60,
|
||||
color: "#242C3B",
|
||||
borderWidth: 1,
|
||||
borderColor: "#B6ECDD",
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -57,9 +57,9 @@ const BatteryWarrantyCard: React.FC<Props> = ({
|
|||
})()}
|
||||
</Text>
|
||||
</View>
|
||||
<Pressable style={styles.iconButton}>
|
||||
<View style={styles.iconButton}>
|
||||
<ChevronRight />
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.progressContainer}>
|
||||
<View style={styles.progressBar}>
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ export default function IssueSelectorModal({
|
|||
style={[
|
||||
styles.clearText,
|
||||
!hasSelection && styles.clearTextDisabled,
|
||||
selectedValues.length > 0 && { color: "#006C4D" }, // 👈 Add this line
|
||||
]}
|
||||
>
|
||||
Clear
|
||||
|
|
@ -123,7 +124,7 @@ export default function IssueSelectorModal({
|
|||
onValueChange={() => toggleValue(option.value)}
|
||||
color={
|
||||
selectedValues.includes(option.value)
|
||||
? "#252A34"
|
||||
? "#009E71"
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export const useTabConfig = () => {
|
|||
export const MESSAGES = {
|
||||
AUTHENTICATION: {
|
||||
INVALID_TOKEN: "Invalid Token",
|
||||
VERIFICATION_FAILED: "Verification failed, try again later",
|
||||
VERIFICATION_FAILED: "OTP incorrect",
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -91,10 +91,10 @@ export const ALERT_STYLES = {
|
|||
};
|
||||
|
||||
export const SUPPORT = {
|
||||
WHATSAPP_NUMBER: "918685846459",
|
||||
WHATSAPP_NUMBER: "919717116943",
|
||||
WHATSAPP_PLACEHOLDER: "Hi, I need help regarding my vehicle.",
|
||||
PHONE: "+911234567890",
|
||||
EMAIL: "support@vecmocon.com",
|
||||
PHONE: "+919717116943",
|
||||
EMAIL: "baas@vecmocon.com",
|
||||
EMAIL_SUBJECT: "Support Request",
|
||||
EMAIL_BODY: "Hello,\n\nI need assistance with...",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import React, { createContext, useContext, useState, ReactNode } from "react";
|
||||
import CustomSnackbar from "../components/common/CustomSnackbar";
|
||||
import CheckIcon from "@/assets/icons/check_circle.svg";
|
||||
import CrossIcon from "@/assets/icons/cancel.svg";
|
||||
|
||||
interface SnackbarContextProps {
|
||||
showSnackbar: (message: string, type: "success" | "error") => void;
|
||||
showSnackbar: (message: string, type: "success" | "error" | "info") => void;
|
||||
}
|
||||
|
||||
const SnackbarContext = createContext<SnackbarContextProps | undefined>(
|
||||
|
|
@ -30,20 +32,44 @@ export const SnackbarProvider: React.FC<SnackbarProviderProps> = ({
|
|||
textColor: "",
|
||||
duration: 2,
|
||||
visible: false,
|
||||
icon: <></>,
|
||||
borderColor: "",
|
||||
});
|
||||
|
||||
const showSnackbar = (
|
||||
message: string,
|
||||
type: "success" | "error" | "info"
|
||||
) => {
|
||||
const bgColor =
|
||||
type === "success" ? "#DFF2E9" : type === "error" ? "#FDEDED" : "#E0F7FA";
|
||||
const textColor =
|
||||
type === "success" ? "#242C3B" : type === "error" ? "#D51D10" : "#00796B";
|
||||
let bgColor = "";
|
||||
let textColor = "";
|
||||
let borderColor = "";
|
||||
let icon = <></>;
|
||||
|
||||
console.log(type);
|
||||
|
||||
if (type === "success") {
|
||||
bgColor = "#DFF2E9";
|
||||
textColor = "#242C3B";
|
||||
borderColor = "#B6ECDD";
|
||||
icon = <CheckIcon width={20} height={20} fill="#242C3B" />;
|
||||
} else if (type === "error") {
|
||||
bgColor = "#FDEDED";
|
||||
textColor = "#D51D10";
|
||||
borderColor = "#F5C6CB";
|
||||
icon = <CrossIcon width={20} height={20} fill="#D51D10" />;
|
||||
} else if (type === "info") {
|
||||
bgColor = "#ffffff";
|
||||
textColor = "#055160"; // dark blue text
|
||||
borderColor = "#B6E0FE"; // optional subtle border
|
||||
// icon = <InfoIcon width={20} height={20} fill="#055160" />;
|
||||
}
|
||||
|
||||
setSnackbar({
|
||||
message,
|
||||
bgColor,
|
||||
textColor,
|
||||
borderColor,
|
||||
icon,
|
||||
duration: 2,
|
||||
visible: true,
|
||||
});
|
||||
|
|
@ -63,6 +89,8 @@ export const SnackbarProvider: React.FC<SnackbarProviderProps> = ({
|
|||
message={snackbar.message}
|
||||
bgColor={snackbar.bgColor}
|
||||
textColor={snackbar.textColor}
|
||||
borderColor={snackbar.borderColor}
|
||||
icon={snackbar.icon}
|
||||
duration={snackbar.duration}
|
||||
visible={snackbar.visible}
|
||||
onDismiss={hideSnackbar}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
"welcome": "Welcome to Driver Saathi",
|
||||
"enter-mobile-number": "Enter Mobile Number",
|
||||
"enter-registered-mobile-number": "Enter your registered mobile number",
|
||||
"for-any-queries-contact-us": "For any queries, contact us",
|
||||
"for-any-queries": "For any queries, ",
|
||||
"contact-us": "contact us",
|
||||
"number-not-registered": "Number not registered.",
|
||||
"enter-otp": "Please enter OTP sent to your mobile number",
|
||||
"verify-otp": "Verify OTP",
|
||||
|
|
@ -38,7 +39,8 @@
|
|||
"day": "day(s)",
|
||||
"alerts": "Alerts",
|
||||
"emi-alert": "14 days left to pay the EMI!",
|
||||
"km": "km"
|
||||
"km": "km",
|
||||
"days-left-to-pay-emi": "days left to pay the EMI!"
|
||||
},
|
||||
"profile": {
|
||||
"my-account": "My Account",
|
||||
|
|
@ -59,7 +61,9 @@
|
|||
"customer-support": "Customer Support",
|
||||
"whatsapp": "Whatsapp",
|
||||
"call-us": "Call Us",
|
||||
"email": "Email"
|
||||
"email": "Email",
|
||||
"lang-changed": "भाषा सफलतापूर्वक बदल दी गई",
|
||||
"fetching-location": "Fetching location..."
|
||||
},
|
||||
"payment": {
|
||||
"last-emi-details": "Last EMI Details",
|
||||
|
|
@ -85,10 +89,13 @@
|
|||
"monthly-emi": "Monthly EMI",
|
||||
"installments-paid": "Installments Paid",
|
||||
"emi-paid-till-now": "EMI Paid Till Now",
|
||||
"transaction-detail": "Transaction Detail",
|
||||
"transaction-details": "Transaction Details",
|
||||
"transaction-successful": "Transaction successful",
|
||||
"payment-mode": "Payment mode",
|
||||
"paid-to": "Paid to",
|
||||
"paid-to": "Paid To",
|
||||
"paid-by": "Paid By",
|
||||
"order-id": "Order ID",
|
||||
"transaction-id": "Transaction ID",
|
||||
"upi-transaction-id": "UPI Transaction ID",
|
||||
"all-emi-paid": "All EMI Paid",
|
||||
"contact-dealer": "For further queries, contact your dealer!",
|
||||
|
|
@ -119,12 +126,11 @@
|
|||
"supported-formats": "Supported formats include JPG, JPEG and PNG.",
|
||||
"comments": "Comments",
|
||||
"submit": "Submit",
|
||||
"select-issues-tba": "Select issues",
|
||||
"clear": "Clear",
|
||||
"issues-selected": "issue selected",
|
||||
"service-request-success": "Service request submitted successfully",
|
||||
"something-went-wrong": "Something went wrong!",
|
||||
"select-valid-time": "Select valid",
|
||||
"select-valid-time": "Select valid time",
|
||||
"words": "words"
|
||||
},
|
||||
"battery": {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
"welcome": "ड्राइवर साथी में आपका स्वागत है",
|
||||
"enter-mobile-number": "मोबाइल नंबर दर्ज करें",
|
||||
"enter-registered-mobile-number": "अपना पंजीकृत मोबाइल नंबर दर्ज करें",
|
||||
"for-any-queries-contact-us": "किसी भी प्रकार की सहायता के लिए, हमसे संपर्क करें",
|
||||
"for-any-queries": "किसी भी प्रकार की सहायता के लिए, ",
|
||||
"contact-us": " हमसे संपर्क करें",
|
||||
"number-not-registered": "नंबर पंजीकृत नहीं है।",
|
||||
"enter-otp": "कृपया अपने मोबाइल नंबर पर भेजा गया OTP दर्ज करें।",
|
||||
"verify-otp": "ओटीपी वेरिफाई करें",
|
||||
|
|
@ -38,7 +39,9 @@
|
|||
"day": "दिन",
|
||||
"alerts": "अलर्ट",
|
||||
"emi-alert": "EMI का भुगतान करने के लिए 14 दिन शेष!",
|
||||
"km": "कि.मी."
|
||||
"km": "कि.मी.",
|
||||
"days-left-to-pay-emi": "दिन बाकी हैं ईएमआई भरने के लिए!",
|
||||
"fetching-location": "स्थान प्राप्त किया जा रहा है..."
|
||||
},
|
||||
"profile": {
|
||||
"my-account": "मेरा खाता",
|
||||
|
|
@ -59,7 +62,8 @@
|
|||
"customer-support": "ग्राहक सहायता",
|
||||
"whatsapp": "व्हाट्सएप",
|
||||
"call-us": "हमें कॉल करें",
|
||||
"email": "ईमेल"
|
||||
"email": "ईमेल",
|
||||
"lang-changed": "Language changed successfully"
|
||||
},
|
||||
"payment": {
|
||||
"last-emi-details": "अंतिम EMI विवरण",
|
||||
|
|
@ -85,10 +89,13 @@
|
|||
"monthly-emi": "मासिक EMI",
|
||||
"installments-paid": "भुगतान की गई किश्तें",
|
||||
"emi-paid-till-now": "अभी तक भुगतान की गई EMI",
|
||||
"transaction-detail": "लेनदेन विवरण",
|
||||
"transaction-details": "लेनदेन विवरण",
|
||||
"transaction-successful": "लेनदेन सफल",
|
||||
"payment-mode": "भुगतान मोड",
|
||||
"paid-to": "भुगतान किया गया",
|
||||
"paid-to": "भुगतान प्राप्तकर्ता",
|
||||
"paid-by": "भुगतानकर्ता",
|
||||
"order-id": "आर्डर ID",
|
||||
"transaction-id": "लेनदेन ID",
|
||||
"upi-transaction-id": "यूपीआई ट्रांजैक्शन आईडी",
|
||||
"all-emi-paid": "सभी EMI का भुगतान किया गया",
|
||||
"contact-dealer": "अधिक जानकारी के लिए, अपने डीलर से संपर्क करें!",
|
||||
|
|
@ -96,7 +103,7 @@
|
|||
"emi-completed": "EMI पूर्ण",
|
||||
"plan-name": "18 महीने की योजना",
|
||||
"view-plan": "प्लान देखें",
|
||||
"advance-amount": "अतिरिक्त राशि",
|
||||
"advance-amount": "एडवांस राशि",
|
||||
"failed": "फेल हो गया",
|
||||
"select-amount": "राशि का चयन करें",
|
||||
"pay-amount-due": "बकाया राशि भुगतान करें",
|
||||
|
|
@ -119,7 +126,6 @@
|
|||
"supported-formats": "समर्थित प्रारूपों में JPG, JPEG और PNG शामिल हैं।",
|
||||
"comments": "टिप्पणियाँ",
|
||||
"submit": "सबमिट करें",
|
||||
"select-issues-tba": "समस्याओं का चयन करें",
|
||||
"clear": "साफ़ करें",
|
||||
"issues-selected": "समस्याएँ चुनी गई",
|
||||
"service-request-success": "सेवा अनुरोध सफलतापूर्वक सबमिट किया गया",
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ export const initSocket = async () => {
|
|||
//get latest telemetry as fallback option
|
||||
token = await fetchToken();
|
||||
controllingServer = await fetchControllingServer(token);
|
||||
store.dispatch(setTelemetryLoading());
|
||||
await fetchLatestTelemetry(token, controllingServer);
|
||||
connectSocket();
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -70,22 +70,32 @@ export const sendOTP = createAsyncThunk<SendOTPResponse, SendOTPParams>(
|
|||
return response.data;
|
||||
// if (!response.data.status) throw new Error(response.data.message);
|
||||
} catch (error: any) {
|
||||
const serverMessage = error.response?.data?.message;
|
||||
return rejectWithValue(serverMessage || "Something went wrong");
|
||||
let message = "Something went wrong. Please try again.";
|
||||
|
||||
if (axios.isAxiosError(error)) {
|
||||
// try to read backend message safely
|
||||
message = error.response?.data?.message || error.message || message;
|
||||
} else if (error instanceof Error) {
|
||||
message = error.message;
|
||||
}
|
||||
console.log(message, "message");
|
||||
return rejectWithValue(message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const verifyOTP = createAsyncThunk<VerifyOTPResponse, VerifyOTPParams>(
|
||||
"auth/verifyOTP",
|
||||
async (params, { rejectWithValue }) => {
|
||||
export const verifyOTP = createAsyncThunk<
|
||||
VerifyOTPResponse,
|
||||
VerifyOTPParams,
|
||||
{ rejectValue: string }
|
||||
>("auth/verifyOTP", async (params, { rejectWithValue }) => {
|
||||
try {
|
||||
console.log("params", params);
|
||||
const response = await axios.post<VerifyOTPResponse>(
|
||||
`${BASE_URL}/api/v1/verify-otp`,
|
||||
params
|
||||
);
|
||||
if (!response.data.success) throw new Error(response.data.message);
|
||||
if (!response.data.success) return rejectWithValue(response.data.message);
|
||||
|
||||
// Store tokens
|
||||
await AsyncStorage.setItem(
|
||||
|
|
@ -95,11 +105,17 @@ export const verifyOTP = createAsyncThunk<VerifyOTPResponse, VerifyOTPParams>(
|
|||
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.log(error.message);
|
||||
return rejectWithValue(MESSAGES.AUTHENTICATION.VERIFICATION_FAILED);
|
||||
let message = "Something went wrong. Please try again.";
|
||||
|
||||
if (axios.isAxiosError(error)) {
|
||||
message = error.response?.data?.message || error.message || message;
|
||||
} else if (error instanceof Error) {
|
||||
message = error.message;
|
||||
}
|
||||
console.log(message, "message");
|
||||
return rejectWithValue(message);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
export const logout = createAsyncThunk(
|
||||
"auth/logout",
|
||||
|
|
@ -173,7 +189,7 @@ const authSlice = createSlice({
|
|||
})
|
||||
.addCase(verifyOTP.rejected, (state, action) => {
|
||||
state.status = AUTH_STATUSES.FAILED;
|
||||
state.verifyOTPError = action.error.message || "Failed to verify OTP";
|
||||
state.verifyOTPError = action.payload || "Failed to verify OTP";
|
||||
})
|
||||
.addCase(logout.pending, (state) => {
|
||||
state.status = AUTH_STATUSES.LOADING;
|
||||
|
|
|
|||
Loading…
Reference in New Issue