Add logo and service logic

rename-package
vinay kumar 2025-09-15 19:10:30 +05:30
parent 1488116909
commit 04fd60d6bc
52 changed files with 562 additions and 294 deletions

41
.gitignore vendored
View File

@ -41,3 +41,44 @@ android/.idea/
android/local.properties android/local.properties
android/app/build/ android/app/build/
android/build/ android/build/
# @generated expo-cli sync-8d4afeec25ea8a192358fae2f8e2fc766bdce4ec
# The following patterns were generated by expo-cli
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
# dependencies
node_modules/
# Expo
.expo/
dist/
web-build/
expo-env.d.ts
# Native
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
# Metro
.metro-health-check*
# debug
npm-debug.*
yarn-debug.*
yarn-error.*
# macOS
.DS_Store
*.pem
# local env files
.env*.local
# typescript
*.tsbuildinfo
# @end expo-cli

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"java.configuration.updateBuildConfiguration": "interactive",
"java.compile.nullAnalysis.mode": "automatic"
}

View File

@ -87,12 +87,12 @@ android {
buildToolsVersion rootProject.ext.buildToolsVersion buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion compileSdk rootProject.ext.compileSdkVersion
namespace 'com.vinayjangra01.BatteryAsAService' namespace "com.vecmocon.driversaathi"
defaultConfig { defaultConfig {
applicationId 'com.vinayjangra01.BatteryAsAService' applicationId 'com.vecmocon.driversaathi'
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1 versionCode 5
versionName "1.0.0" versionName "1.0.0"
} }
signingConfigs { signingConfigs {

View File

@ -1,4 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.vecmocon.driversaathi" xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/>
@ -12,13 +12,15 @@
<data android:scheme="https"/> <data android:scheme="https"/>
</intent> </intent>
</queries> </queries>
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true"> <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true" android:requestLegacyExternalStorage="true">
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/> <meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
<meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="53.0.0"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/> <meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/> <meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
<meta-data <meta-data
android:name="com.google.android.geo.API_KEY" android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCJ4IkKM0ybTOwvdylLVx9BxL2ZV1PEvRk"/> android:value="AIzaSyCJ4IkKM0ybTOwvdylLVx9BxL2ZV1PEvRk"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://exp.host/@vecmocon/BatteryAsAService"/>
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait"> <activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
@ -29,6 +31,7 @@
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="batteryasaservice"/> <data android:scheme="batteryasaservice"/>
<data android:scheme="com.vecmocon.driversaathi"/>
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>

View File

@ -1,4 +1,4 @@
package com.vinayjangra01.BatteryAsAService package com.vecmocon.driversaathi
import expo.modules.splashscreen.SplashScreenManager import expo.modules.splashscreen.SplashScreenManager
import android.os.Build import android.os.Build

View File

@ -1,4 +1,4 @@
package com.vinayjangra01.BatteryAsAService package com.vecmocon.driversaathi
import android.app.Application import android.app.Application
import android.content.res.Configuration import android.content.res.Configuration

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/iconBackground"/> <background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
</adaptive-icon> </adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 B

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,6 +1,6 @@
<resources> <resources>
<string name="app_name">Driver Saathi</string> <string name="app_name">Driver Saathi</string>
<string name="expo_system_ui_user_interface_style" translatable="false">light</string>
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string> <string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string> <string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
<string name="expo_system_ui_user_interface_style" translatable="false">light</string>
</resources> </resources>

View File

@ -1,8 +1,8 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.EdgeToEdge"> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="android:statusBarColor">#252A34</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
</style> </style>
<style name="Theme.App.SplashScreen" parent="Theme.SplashScreen"> <style name="Theme.App.SplashScreen" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/splashscreen_background</item> <item name="windowSplashScreenBackground">@color/splashscreen_background</item>

View File

@ -55,5 +55,4 @@ EX_DEV_CLIENT_NETWORK_INSPECTOR=true
# Use legacy packaging to compress native libraries in the resulting APK. # Use legacy packaging to compress native libraries in the resulting APK.
expo.useLegacyPackaging=false expo.useLegacyPackaging=false
# Whether the app is configured to use edge-to-edge via the app config or `react-native-edge-to-edge` plugin expo.jsEngine=jsc
expo.edgeToEdgeEnabled=true

View File

@ -1,6 +1,6 @@
{ {
"expo": { "expo": {
"name": "BatteryAsAService", "name": "Driver Saathi",
"slug": "BatteryAsAService", "slug": "BatteryAsAService",
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "portrait",
@ -22,7 +22,8 @@
"backgroundColor": "#ffffff" "backgroundColor": "#ffffff"
}, },
"edgeToEdgeEnabled": true, "edgeToEdgeEnabled": true,
"package": "com.vinayjangra01.BatteryAsAService" "package": "com.vecmocon.driversaathi",
"versionCode": 5
}, },
"web": { "web": {
"bundler": "metro", "bundler": "metro",

View File

@ -9,6 +9,7 @@ import NetInfo from "@react-native-community/netinfo";
import { getPaymentSummary, getUserDetails } from "@/store/userSlice"; import { getPaymentSummary, getUserDetails } from "@/store/userSlice";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { logout } from "@/store/authSlice"; import { logout } from "@/store/authSlice";
import { getLanguage, setLanguage } from "@/services/i18n";
export default function TabLayout() { export default function TabLayout() {
const { isLoggedIn } = useSelector((state: RootState) => state.auth); const { isLoggedIn } = useSelector((state: RootState) => state.auth);
@ -34,10 +35,16 @@ export default function TabLayout() {
useEffect(() => { useEffect(() => {
const fetchAndInit = async () => { const fetchAndInit = async () => {
try { try {
const lang = await getLanguage();
setLanguage(lang || "en");
const result = await dispatch(getUserDetails()).unwrap(); const result = await dispatch(getUserDetails()).unwrap();
await dispatch(getPaymentSummary()); await dispatch(getPaymentSummary());
console.log("User details fetched", result);
if (result?.batteries?.[0]?.device_id) {
initSocket(); initSocket();
} else {
console.warn("Skipping initSocket, no device_id yet");
}
} catch (error) { } catch (error) {
console.error("Failed to fetch user details", error); console.error("Failed to fetch user details", error);
showSnackbar("Failed to fetch user details", "error"); showSnackbar("Failed to fetch user details", "error");

View File

@ -35,9 +35,7 @@ import {
getPaymentSummary, getPaymentSummary,
getUserDetails, getUserDetails,
} from "@/store/userSlice"; } from "@/store/userSlice";
import api from "@/services/axiosClient";
import { setDueAmount } from "@/store/paymentSlice"; import { setDueAmount } from "@/store/paymentSlice";
import { EmiResponse } from "./payments";
import { Image } from "expo-image"; import { Image } from "expo-image";
import EMINotification from "@/components/Payments/EmiNotification"; import EMINotification from "@/components/Payments/EmiNotification";
@ -45,15 +43,20 @@ export default function HomeScreen() {
const { t } = useTranslation(); const { t } = useTranslation();
const navigation = useNavigation(); const navigation = useNavigation();
const [isSupportModalVisible, setIsSupportModalVisible] = useState(false); const [isSupportModalVisible, setIsSupportModalVisible] = useState(false);
const { SoC, SoH, chargingState, lat, lon, loading, error, totalDistance } = const { SoC, SoH, chargingState, lat, lon, loading, totalDistance } =
useSelector((state: RootState) => state.telemetry); useSelector((state: RootState) => state.telemetry);
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
const spinValue = useState(new Animated.Value(0))[0]; const spinValue = useState(new Animated.Value(0))[0];
const { data, paymentSummary } = useSelector( const {
(state: RootState) => state.user data,
); paymentSummary,
loading: userLoading,
} = useSelector((state: RootState) => state.user);
const isRefreshing = refreshing || userLoading;
const [prevPosition, setPrevPosition] = useState<{ const [prevPosition, setPrevPosition] = useState<{
lat: number; lat: number;
lon: number; lon: number;
@ -122,18 +125,26 @@ export default function HomeScreen() {
}, },
headerTitle: () => ( headerTitle: () => (
<View style={styles.headerTitleContainer}> <View style={styles.headerTitleContainer}>
<View style={styles.logoContainer}>
<Image
source={require("../../assets/images/lio_logo.png")}
style={styles.logo}
/>
</View>
<View>
<Text style={styles.title}>{model}</Text> <Text style={styles.title}>{model}</Text>
<Text style={styles.subtitle}>{chasisNumber}</Text> <Text style={styles.subtitle}>{chasisNumber}</Text>
</View> </View>
</View>
), ),
headerRight: () => ( headerRight: () => (
<View style={styles.rightContainer}> <View style={styles.rightContainer}>
<Pressable onPress={handleManualRefresh} disabled={refreshing}> <Pressable onPress={handleManualRefresh} disabled={isRefreshing}>
<Animated.View style={{ transform: [{ rotate: spin }] }}> <Animated.View style={{ transform: [{ rotate: spin }] }}>
<RefreshIcon <RefreshIcon
width={50} width={50}
height={50} height={50}
opacity={refreshing ? 0.5 : 1} opacity={isRefreshing ? 0.5 : 1}
/> />
</Animated.View> </Animated.View>
</Pressable> </Pressable>
@ -159,7 +170,7 @@ export default function HomeScreen() {
</View> </View>
), ),
}); });
}, [navigation, data, model, chasisNumber, refreshing]); }, [navigation, data, model, chasisNumber, isRefreshing]);
const openInGoogleMaps = () => { const openInGoogleMaps = () => {
const url = `https://www.google.com/maps/search/?api=1&query=${lat},${lon}`; const url = `https://www.google.com/maps/search/?api=1&query=${lat},${lon}`;
@ -225,7 +236,8 @@ export default function HomeScreen() {
<View style={{ flex: 1, backgroundColor: "#F3F5F8" }}> <View style={{ flex: 1, backgroundColor: "#F3F5F8" }}>
<StatusBar style="dark" /> <StatusBar style="dark" />
<ScrollView contentContainerStyle={styles.container} style={{ flex: 1 }}> <ScrollView contentContainerStyle={styles.container} style={{ flex: 1 }}>
{daysLeftToPayEmi && daysLeftToPayEmiText && daysLeftToPayEmi > 0 && ( {daysLeftToPayEmi != undefined &&
Boolean(daysLeftToPayEmi && daysLeftToPayEmi > 0) && (
<ServiceReminderCard <ServiceReminderCard
type={ type={
daysLeftToPayEmi >= payments.EMI_WARNING_DAYS_THRESHOLD daysLeftToPayEmi >= payments.EMI_WARNING_DAYS_THRESHOLD
@ -238,7 +250,11 @@ export default function HomeScreen() {
/> />
)} )}
{regularServiceDueInDaysText && ( {regularServiceDueInDaysText &&
Boolean(
regularServiceDueInDaysText &&
regularServiceDueInDaysText.trim() !== ""
) && (
<ServiceReminderCard <ServiceReminderCard
type="info" type="info"
message={regularServiceDueInDaysText} message={regularServiceDueInDaysText}
@ -429,6 +445,22 @@ const mapStyle = [
]; ];
const styles = StyleSheet.create({ const styles = StyleSheet.create({
logo: {
width: "100%",
height: "100%",
resizeMode: "contain",
},
logoContainer: {
padding: 8,
borderRadius: 44 / 2, // make it perfectly round
borderWidth: 2,
borderColor: "#E5E9F0",
width: 44,
height: 44,
alignItems: "center",
justifyContent: "center",
overflow: "hidden", // ensures image doesn't overflow
},
errorText: { errorText: {
color: "#565F70", color: "#565F70",
fontWeight: "400", fontWeight: "400",
@ -480,8 +512,9 @@ const styles = StyleSheet.create({
backgroundColor: "#F3F5F8", backgroundColor: "#F3F5F8",
}, },
headerTitleContainer: { headerTitleContainer: {
flexDirection: "column", flexDirection: "row",
backgroundColor: "#F3F5F8", backgroundColor: "#F3F5F8",
gap: 8,
}, },
title: { title: {
fontSize: 14, fontSize: 14,

View File

@ -10,6 +10,7 @@ import {
ScrollView, ScrollView,
KeyboardAvoidingView, KeyboardAvoidingView,
Platform, Platform,
ActivityIndicator,
} from "react-native"; } from "react-native";
import { Dropdown } from "react-native-element-dropdown"; import { Dropdown } from "react-native-element-dropdown";
import { DateTimePickerAndroid } from "@react-native-community/datetimepicker"; import { DateTimePickerAndroid } from "@react-native-community/datetimepicker";
@ -30,15 +31,24 @@ import CalendarIcon from "@/assets/icons/calendar.svg";
interface FormValues { interface FormValues {
serviceType: string | null; serviceType: string | null;
issues: string[]; issues: number[];
comments: string | null; comments: string | null;
date: Date | null; date: Date | null;
photos: string[]; photos: string[];
} }
interface Issue {
id: number;
name: string;
}
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
serviceType: Yup.string().required("Service Type is required"), serviceType: Yup.string().required("Service Type is required"),
issues: Yup.array().min(1, "At least one issue is required"), issues: Yup.array().when("serviceType", {
is: (val: string) => val !== "Regular",
then: (schema) => schema.min(1, "At least one issue is required"),
otherwise: (schema) => schema.notRequired(),
}),
date: Yup.date().required("Date and Time is required"), date: Yup.date().required("Date and Time is required"),
photos: Yup.array().min(1, "At least one photo is required"), photos: Yup.array().min(1, "At least one photo is required"),
comments: Yup.string(), comments: Yup.string(),
@ -47,12 +57,34 @@ const validationSchema = Yup.object().shape({
export default function ServiceFormScreen(): JSX.Element { export default function ServiceFormScreen(): JSX.Element {
const [isFocus, setIsFocus] = useState<boolean>(false); const [isFocus, setIsFocus] = useState<boolean>(false);
const [isIssueSelectorVisible, setIssueSelectorVisible] = useState(false); const [isIssueSelectorVisible, setIssueSelectorVisible] = useState(false);
const [issues, setIssues] = useState<Issue[]>([]);
const [isLoadingIssues, setIsLoadingIssues] = useState(false);
const { showSnackbar } = useSnackbar(); const { showSnackbar } = useSnackbar();
function toggleIssueSelector() { function toggleIssueSelector() {
setIssueSelectorVisible(!isIssueSelectorVisible); setIssueSelectorVisible(!isIssueSelectorVisible);
} }
const fetchIssues = async () => {
try {
setIsLoadingIssues(true);
const response = await api.get(`${BASE_URL}/api/v1/service-issue-list`);
if (response.data.success) {
setIssues(response.data.data);
} else {
throw new Error(response.data?.message || "Failed to fetch issues");
}
} catch (error: any) {
console.error("Error fetching issues:", error);
showSnackbar(`${t("service.something-went-wrong")}`, "error");
setIssues([]);
} finally {
setIsLoadingIssues(false);
}
};
const initialValues: FormValues = { const initialValues: FormValues = {
serviceType: null, serviceType: null,
issues: [], issues: [],
@ -126,6 +158,32 @@ export default function ServiceFormScreen(): JSX.Element {
const { t } = useTranslation(); const { t } = useTranslation();
const handleServiceTypeChange = async (
item: { label: string; value: string },
setFieldValue: (field: string, value: any) => void,
setFieldTouched: (field: string, touched: boolean) => void
) => {
setFieldValue("serviceType", item.value);
if (item.value === "Regular") {
setFieldValue("issues", []);
setFieldTouched("issues", false);
setIssues([]);
} else if (item.value === "On-demand") {
await fetchIssues();
setFieldValue("issues", []);
setFieldTouched("issues", false);
}
setIsFocus(false);
};
const getSelectedIssuesText = (selectedIssueIds: number[]) => {
if (selectedIssueIds.length === 0) return `${t("service.select-issue")}`;
if (selectedIssueIds.length === 1) return "1 issue selected";
return `${selectedIssueIds.length} issues selected`;
};
return ( return (
<KeyboardAvoidingView <KeyboardAvoidingView
style={styles.container} style={styles.container}
@ -196,6 +254,7 @@ export default function ServiceFormScreen(): JSX.Element {
errors, errors,
touched, touched,
isSubmitting, isSubmitting,
setFieldTouched,
}) => ( }) => (
<View style={styles.formContainer}> <View style={styles.formContainer}>
<View style={styles.inputContainer}> <View style={styles.inputContainer}>
@ -223,10 +282,13 @@ export default function ServiceFormScreen(): JSX.Element {
value={values.serviceType} value={values.serviceType}
onFocus={() => setIsFocus(true)} onFocus={() => setIsFocus(true)}
onBlur={() => setIsFocus(false)} onBlur={() => setIsFocus(false)}
onChange={(item) => { onChange={(item) =>
setFieldValue("serviceType", item.value); handleServiceTypeChange(
setIsFocus(false); item,
}} setFieldValue,
setFieldTouched
)
}
renderLeftIcon={() => ( renderLeftIcon={() => (
<View style={{ marginRight: 10 }}> <View style={{ marginRight: 10 }}>
{/* Add your icon component here if needed */} {/* Add your icon component here if needed */}
@ -242,13 +304,22 @@ export default function ServiceFormScreen(): JSX.Element {
{t("service.issue")} <Text style={styles.required}>*</Text> {t("service.issue")} <Text style={styles.required}>*</Text>
</Text> </Text>
<TouchableOpacity <TouchableOpacity
style={styles.inputBox} style={[styles.inputBox]}
onPress={toggleIssueSelector} onPress={toggleIssueSelector}
disabled={values.serviceType === "Regular" || isLoadingIssues}
> >
<Text style={styles.issueText}> <Text
{values.issues.length > 0 style={[
? values.issues.length + " issues selected" styles.issueText,
: `${t("service.select-issue")}`} values.serviceType === "Regular" &&
styles.issueTextDisabled,
]}
>
{isLoadingIssues ? (
<ActivityIndicator />
) : (
getSelectedIssuesText(values.issues)
)}
</Text> </Text>
<ChevronRight /> <ChevronRight />
</TouchableOpacity> </TouchableOpacity>
@ -341,6 +412,7 @@ export default function ServiceFormScreen(): JSX.Element {
setFieldValue("issues", selectedIssues); setFieldValue("issues", selectedIssues);
}} }}
initialSelectedValues={values.issues} initialSelectedValues={values.issues}
issues={issues}
/> />
{isSubmitting && <Overlay isUploading={isSubmitting} />} {isSubmitting && <Overlay isUploading={isSubmitting} />}
</View> </View>
@ -352,6 +424,9 @@ export default function ServiceFormScreen(): JSX.Element {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
issueTextDisabled: {
color: "#949CAC",
},
container: { container: {
flex: 1, flex: 1,
}, },

View File

@ -109,24 +109,14 @@ export default function WelcomeScreen() {
<Text style={styles.error}>{sendOTPError}</Text> <Text style={styles.error}>{sendOTPError}</Text>
)} )}
</View> </View>
</View>
<View style={styles.bottomSection}>
<View style={styles.contactContainer}>
<View style={{ flexDirection: "row" }}>
<Text>{t("onboarding.for-any-queries")}</Text>
<TouchableOpacity onPress={makePhoneCall}>
<Text style={styles.link}>
{t("onboarding.contact-us")}
</Text>
</TouchableOpacity>
</View>
</View>
{/* ✅ Send OTP button placed just below input box */}
<TouchableOpacity <TouchableOpacity
onPress={handleSubmit as unknown as () => void} onPress={handleSubmit as unknown as () => void}
style={{ style={{
...styles.button, ...styles.button,
marginTop: 16,
marginBottom: 16,
backgroundColor: backgroundColor:
values.phone.length === 10 && values.phone.length === 10 &&
!errors.phone && !errors.phone &&
@ -144,6 +134,17 @@ export default function WelcomeScreen() {
{t("onboarding.send-otp")} {t("onboarding.send-otp")}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
<View style={styles.contactContainer}>
<View style={{ flexDirection: "row" }}>
<Text>{t("onboarding.for-any-queries")}</Text>
<TouchableOpacity onPress={makePhoneCall}>
<Text style={styles.link}>
{t("onboarding.contact-us")}
</Text>
</TouchableOpacity>
</View>
</View>
</View> </View>
</View> </View>
)} )}

View File

@ -106,8 +106,7 @@ const styles = StyleSheet.create({
color: "#2f465e", color: "#2f465e",
}, },
selectButton: { selectButton: {
marginTop: "auto", marginTop: 16,
marginBottom: 16,
padding: 16, padding: 16,
borderRadius: 4, borderRadius: 4,
alignItems: "center", alignItems: "center",

View File

@ -147,8 +147,8 @@ export default function ProfileScreen() {
</View> </View>
<View style={styles.card}> <View style={styles.card}>
{menuItem(`${t("profile.about-app")}`)} {/* {menuItem(`${t("profile.about-app")}`)}
<View style={styles.divider} /> <View style={styles.divider} /> */}
{menuItem(`${t("profile.logout")}`, handleLogout)} {menuItem(`${t("profile.logout")}`, handleLogout)}
</View> </View>
</ScrollView> </ScrollView>

BIN
assets/images/lio_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -12,11 +12,17 @@ import Checkbox from "expo-checkbox";
import { issueConfig } from "@/constants/config"; import { issueConfig } from "@/constants/config";
import CloseIcon from "@/assets/icons/close.svg"; import CloseIcon from "@/assets/icons/close.svg";
interface Issue {
id: number;
name: string;
}
interface IssueSelectorModalProps { interface IssueSelectorModalProps {
visible: boolean; visible: boolean;
onClose: () => void; onClose: () => void;
onSelect: (selectedValues: string[]) => void; onSelect: (selectedValues: number[]) => void;
initialSelectedValues?: string[]; // Previously saved selections initialSelectedValues?: number[]; // Previously saved selections
issues: Issue[];
} }
export default function IssueSelectorModal({ export default function IssueSelectorModal({
@ -24,26 +30,22 @@ export default function IssueSelectorModal({
onClose, onClose,
onSelect, onSelect,
initialSelectedValues = [], initialSelectedValues = [],
issues = [],
}: IssueSelectorModalProps) { }: IssueSelectorModalProps) {
const [selectedValues, setSelectedValues] = useState<string[]>( const [selectedValues, setSelectedValues] = useState<number[]>(
initialSelectedValues initialSelectedValues
); );
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const toggleValue = (value: string) => { const toggleValue = (id: number) => {
setSelectedValues((prev) => setSelectedValues((prev) =>
prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value] prev.includes(id) ? prev.filter((v) => v !== id) : [...prev, id]
); );
}; };
const filteredConfig = issueConfig const filteredIssues = issues.filter((issue) =>
.map((group) => ({ issue.name.toLowerCase().includes(search.toLowerCase())
...group, );
options: group.options.filter((option) =>
option.label.toLowerCase().includes(search.toLowerCase())
),
}))
.filter((group) => group.options.length > 0);
const clearSelection = () => setSelectedValues([]); const clearSelection = () => setSelectedValues([]);
@ -95,13 +97,13 @@ export default function IssueSelectorModal({
<View style={styles.counterBar}> <View style={styles.counterBar}>
<Text <Text
style={styles.counterText} style={styles.counterText}
>{`${selectedValues.length}/23 Selected`}</Text> >{`${selectedValues.length}/${issues.length} Selected`}</Text>
<TouchableOpacity onPress={clearSelection} disabled={!hasSelection}> <TouchableOpacity onPress={clearSelection} disabled={!hasSelection}>
<Text <Text
style={[ style={[
styles.clearText, styles.clearText,
!hasSelection && styles.clearTextDisabled, !hasSelection && styles.clearTextDisabled,
selectedValues.length > 0 && { color: "#006C4D" }, // 👈 Add this line selectedValues.length > 0 && { color: "#006C4D" },
]} ]}
> >
Clear Clear
@ -110,29 +112,34 @@ export default function IssueSelectorModal({
</View> </View>
<ScrollView style={styles.scrollArea}> <ScrollView style={styles.scrollArea}>
{filteredConfig.map((group) => ( {filteredIssues.length > 0 ? (
<View key={group.category}> filteredIssues.map((issue) => (
<Text style={styles.category}>{group.category}</Text>
{group.options.map((option) => (
<TouchableOpacity <TouchableOpacity
key={option.value} key={issue.id}
style={styles.itemRow} style={styles.itemRow}
onPress={() => toggleValue(option.value)} onPress={() => toggleValue(issue.id)}
> >
<Checkbox <Checkbox
value={selectedValues.includes(option.value)} value={selectedValues.includes(issue.id)}
onValueChange={() => toggleValue(option.value)} onValueChange={() => toggleValue(issue.id)}
color={ color={
selectedValues.includes(option.value) selectedValues.includes(issue.id) ? "#009E71" : undefined
? "#009E71"
: undefined
} }
/> />
<Text style={styles.itemLabel}>{option.label}</Text> <Text style={styles.itemLabel}>{issue.name}</Text>
</TouchableOpacity> </TouchableOpacity>
))} ))
) : issues.length === 0 ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>No issues available</Text>
</View> </View>
))} ) : (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>
No issues found for "{search}"
</Text>
</View>
)}
</ScrollView> </ScrollView>
<View style={styles.buttonsContainer}> <View style={styles.buttonsContainer}>
@ -163,6 +170,16 @@ export default function IssueSelectorModal({
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
emptyContainer: {
padding: 20,
alignItems: "center",
justifyContent: "center",
},
emptyText: {
fontSize: 16,
color: "#717B8F",
textAlign: "center",
},
buttonsContainer: { buttonsContainer: {
flexDirection: "row", flexDirection: "row",
justifyContent: "space-between", justifyContent: "space-between",

View File

@ -181,7 +181,7 @@ export const issueConfig = [
]; ];
export const payments = { export const payments = {
MIN_AMOUNT: 1, MIN_AMOUNT: 200,
LINK_EXPIRED: "Payment link expired", LINK_EXPIRED: "Payment link expired",
SOCKET_CONNECTION_TIMEOUT_IN_SECS: 5, SOCKET_CONNECTION_TIMEOUT_IN_SECS: 5,
REGISTER_TRANSACTION_EMIT_EVENT_NAME: "register-transaction", REGISTER_TRANSACTION_EMIT_EVENT_NAME: "register-transaction",

View File

@ -9,7 +9,10 @@
}, },
"production": { "production": {
"autoIncrement": true, "autoIncrement": true,
"distribution": "internal" "distribution": "store"
} }
},
"cli": {
"appVersionSource": "local"
} }
} }

8
index.js Normal file
View File

@ -0,0 +1,8 @@
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);

385
package-lock.json generated
View File

@ -37,7 +37,7 @@
"react": "19.0.0", "react": "19.0.0",
"react-dom": "19.0.0", "react-dom": "19.0.0",
"react-i18next": "^15.5.3", "react-i18next": "^15.5.3",
"react-native": "0.79.4", "react-native": "0.79.6",
"react-native-element-dropdown": "^2.12.4", "react-native-element-dropdown": "^2.12.4",
"react-native-maps": "1.24.2", "react-native-maps": "1.24.2",
"react-native-otp-entry": "^1.8.5", "react-native-otp-entry": "^1.8.5",
@ -143,15 +143,15 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.27.5", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
"integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.27.5", "@babel/parser": "^7.28.3",
"@babel/types": "^7.27.3", "@babel/types": "^7.28.2",
"@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.25", "@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2" "jsesc": "^3.0.2"
}, },
"engines": { "engines": {
@ -240,6 +240,15 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
} }
}, },
"node_modules/@babel/helper-globals": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-member-expression-to-functions": { "node_modules/@babel/helper-member-expression-to-functions": {
"version": "7.27.1", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz",
@ -492,12 +501,12 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.27.5", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
"integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.27.3" "@babel/types": "^7.28.2"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@ -1509,27 +1518,27 @@
}, },
"node_modules/@babel/traverse--for-generate-function-map": { "node_modules/@babel/traverse--for-generate-function-map": {
"name": "@babel/traverse", "name": "@babel/traverse",
"version": "7.27.4", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
"integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.27.3", "@babel/generator": "^7.28.3",
"@babel/parser": "^7.27.4", "@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.3",
"@babel/template": "^7.27.2", "@babel/template": "^7.27.2",
"@babel/types": "^7.27.3", "@babel/types": "^7.28.2",
"debug": "^4.3.1", "debug": "^4.3.1"
"globals": "^11.1.0"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.27.6", "version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.27.1", "@babel/helper-string-parser": "^7.27.1",
@ -2636,17 +2645,13 @@
} }
}, },
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8", "version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24" "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
} }
}, },
"node_modules/@jridgewell/resolve-uri": { "node_modules/@jridgewell/resolve-uri": {
@ -2658,15 +2663,6 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": { "node_modules/@jridgewell/source-map": {
"version": "0.3.6", "version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
@ -2684,9 +2680,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25", "version": "0.3.30",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/resolve-uri": "^3.1.0",
@ -3401,9 +3397,9 @@
} }
}, },
"node_modules/@react-native/assets-registry": { "node_modules/@react-native/assets-registry": {
"version": "0.79.4", "version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.4.tgz", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.6.tgz",
"integrity": "sha512-7PjHNRtYlc36B7P1PHme8ZV0ZJ/xsA/LvMoXe6EX++t7tSPJ8iYCMBryZhcdnztgce73b94Hfx6TTGbLF+xtUg==", "integrity": "sha512-UVSP1224PWg0X+mRlZNftV5xQwZGfawhivuW8fGgxNK9MS/U84xZ+16lkqcPh1ank6MOt239lIWHQ1S33CHgqA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@ -3544,12 +3540,12 @@
} }
}, },
"node_modules/@react-native/community-cli-plugin": { "node_modules/@react-native/community-cli-plugin": {
"version": "0.79.4", "version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.4.tgz", "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.6.tgz",
"integrity": "sha512-lx1RXEJwU9Tcs2B2uiDZBa6yghU6m6STvwYqHbJlFZyNN1k3JRa9j0/CDu+0fCFacIn7rEfZpb4UWi5YhsHpQg==", "integrity": "sha512-ZHVst9vByGsegeaddkD2YbZ6NvYb4n3pD9H7Pit94u+NlByq2uBJghoOjT6EKqg+UVl8tLRdi88cU2pDPwdHqA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@react-native/dev-middleware": "0.79.4", "@react-native/dev-middleware": "0.79.6",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"debug": "^2.2.0", "debug": "^2.2.0",
"invariant": "^2.2.4", "invariant": "^2.2.4",
@ -3570,6 +3566,37 @@
} }
} }
}, },
"node_modules/@react-native/community-cli-plugin/node_modules/@react-native/debugger-frontend": {
"version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.79.6.tgz",
"integrity": "sha512-lIK/KkaH7ueM22bLO0YNaQwZbT/oeqhaghOvmZacaNVbJR1Cdh/XAqjT8FgCS+7PUnbxA8B55NYNKGZG3O2pYw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=18"
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/@react-native/dev-middleware": {
"version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.79.6.tgz",
"integrity": "sha512-BK3GZBa9c7XSNR27EDRtxrgyyA3/mf1j3/y+mPk7Ac0Myu85YNrXnC9g3mL5Ytwo0g58TKrAIgs1fF2Q5Mn6mQ==",
"license": "MIT",
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.79.6",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
"debug": "^2.2.0",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1",
"open": "^7.0.3",
"serve-static": "^1.16.2",
"ws": "^6.2.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@react-native/community-cli-plugin/node_modules/debug": { "node_modules/@react-native/community-cli-plugin/node_modules/debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -3597,6 +3624,15 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@react-native/community-cli-plugin/node_modules/ws": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
"integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
"license": "MIT",
"dependencies": {
"async-limiter": "~1.0.0"
}
},
"node_modules/@react-native/debugger-frontend": { "node_modules/@react-native/debugger-frontend": {
"version": "0.79.4", "version": "0.79.4",
"resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.79.4.tgz", "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.79.4.tgz",
@ -3653,18 +3689,18 @@
} }
}, },
"node_modules/@react-native/gradle-plugin": { "node_modules/@react-native/gradle-plugin": {
"version": "0.79.4", "version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.79.4.tgz", "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.79.6.tgz",
"integrity": "sha512-Gv5ryy23k7Sib2xVgqw65GTryg9YTij6URcMul5cI7LRcW0Aa1/FPb26l388P4oeNGNdDoAkkS+CuCWNunRuWg==", "integrity": "sha512-C5odetI6py3CSELeZEVz+i00M+OJuFZXYnjVD4JyvpLn462GesHRh+Se8mSkU5QSaz9cnpMnyFLJAx05dokWbA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@react-native/js-polyfills": { "node_modules/@react-native/js-polyfills": {
"version": "0.79.4", "version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.79.4.tgz", "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.79.6.tgz",
"integrity": "sha512-VyKPo/l9zP4+oXpQHrJq4vNOtxF7F5IMdQmceNzTnRpybRvGGgO/9jYu9mdmdKRO2KpQEc5dB4W2rYhVKdGNKg==", "integrity": "sha512-6wOaBh1namYj9JlCNgX2ILeGUIwc6OP6MWe3Y5jge7Xz9fVpRqWQk88Q5Y9VrAtTMTcxoX3CvhrfRr3tGtSfQw==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@ -10237,9 +10273,9 @@
} }
}, },
"node_modules/metro": { "node_modules/metro": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro/-/metro-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro/-/metro-0.82.5.tgz",
"integrity": "sha512-/gFmw3ux9CPG5WUmygY35hpyno28zi/7OUn6+OFfbweA8l0B+PPqXXLr0/T6cf5nclCcH0d22o+02fICaShVxw==", "integrity": "sha512-8oAXxL7do8QckID/WZEKaIFuQJFUTLzfVcC48ghkHhNK2RGuQq8Xvf4AVd+TUA0SZtX0q8TGNXZ/eba1ckeGCg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.24.7", "@babel/code-frame": "^7.24.7",
@ -10257,24 +10293,24 @@
"error-stack-parser": "^2.0.6", "error-stack-parser": "^2.0.6",
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"graceful-fs": "^4.2.4", "graceful-fs": "^4.2.4",
"hermes-parser": "0.28.1", "hermes-parser": "0.29.1",
"image-size": "^1.0.2", "image-size": "^1.0.2",
"invariant": "^2.2.4", "invariant": "^2.2.4",
"jest-worker": "^29.7.0", "jest-worker": "^29.7.0",
"jsc-safe-url": "^0.2.2", "jsc-safe-url": "^0.2.2",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
"metro-babel-transformer": "0.82.4", "metro-babel-transformer": "0.82.5",
"metro-cache": "0.82.4", "metro-cache": "0.82.5",
"metro-cache-key": "0.82.4", "metro-cache-key": "0.82.5",
"metro-config": "0.82.4", "metro-config": "0.82.5",
"metro-core": "0.82.4", "metro-core": "0.82.5",
"metro-file-map": "0.82.4", "metro-file-map": "0.82.5",
"metro-resolver": "0.82.4", "metro-resolver": "0.82.5",
"metro-runtime": "0.82.4", "metro-runtime": "0.82.5",
"metro-source-map": "0.82.4", "metro-source-map": "0.82.5",
"metro-symbolicate": "0.82.4", "metro-symbolicate": "0.82.5",
"metro-transform-plugins": "0.82.4", "metro-transform-plugins": "0.82.5",
"metro-transform-worker": "0.82.4", "metro-transform-worker": "0.82.5",
"mime-types": "^2.1.27", "mime-types": "^2.1.27",
"nullthrows": "^1.1.1", "nullthrows": "^1.1.1",
"serialize-error": "^2.1.0", "serialize-error": "^2.1.0",
@ -10291,14 +10327,14 @@
} }
}, },
"node_modules/metro-babel-transformer": { "node_modules/metro-babel-transformer": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.82.5.tgz",
"integrity": "sha512-4juJahGRb1gmNbQq48lNinB6WFNfb6m0BQqi/RQibEltNiqTCxew/dBspI2EWA4xVCd3mQWGfw0TML4KurQZnQ==", "integrity": "sha512-W/scFDnwJXSccJYnOFdGiYr9srhbHPdxX9TvvACOFsIXdLilh3XuxQl/wXW6jEJfgIb0jTvoTlwwrqvuwymr6Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.25.2", "@babel/core": "^7.25.2",
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"hermes-parser": "0.28.1", "hermes-parser": "0.29.1",
"nullthrows": "^1.1.1" "nullthrows": "^1.1.1"
}, },
"engines": { "engines": {
@ -10306,39 +10342,39 @@
} }
}, },
"node_modules/metro-babel-transformer/node_modules/hermes-estree": { "node_modules/metro-babel-transformer/node_modules/hermes-estree": {
"version": "0.28.1", "version": "0.29.1",
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.28.1.tgz", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
"integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==", "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/metro-babel-transformer/node_modules/hermes-parser": { "node_modules/metro-babel-transformer/node_modules/hermes-parser": {
"version": "0.28.1", "version": "0.29.1",
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.28.1.tgz", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
"integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==", "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"hermes-estree": "0.28.1" "hermes-estree": "0.29.1"
} }
}, },
"node_modules/metro-cache": { "node_modules/metro-cache": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.82.5.tgz",
"integrity": "sha512-vX0ylSMGtORKiZ4G8uP6fgfPdDiCWvLZUGZ5zIblSGylOX6JYhvExl0Zg4UA9pix/SSQu5Pnp9vdODMFsNIxhw==", "integrity": "sha512-AwHV9607xZpedu1NQcjUkua8v7HfOTKfftl6Vc9OGr/jbpiJX6Gpy8E/V9jo/U9UuVYX2PqSUcVNZmu+LTm71Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"exponential-backoff": "^3.1.1", "exponential-backoff": "^3.1.1",
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"https-proxy-agent": "^7.0.5", "https-proxy-agent": "^7.0.5",
"metro-core": "0.82.4" "metro-core": "0.82.5"
}, },
"engines": { "engines": {
"node": ">=18.18" "node": ">=18.18"
} }
}, },
"node_modules/metro-cache-key": { "node_modules/metro-cache-key": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.82.5.tgz",
"integrity": "sha512-2JCTqcpF+f2OghOpe/+x+JywfzDkrHdAqinPFWmK2ezNAU/qX0jBFaTETogPibFivxZJil37w9Yp6syX8rFUng==", "integrity": "sha512-qpVmPbDJuRLrT4kcGlUouyqLGssJnbTllVtvIgXfR7ZuzMKf0mGS+8WzcqzNK8+kCyakombQWR0uDd8qhWGJcA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flow-enums-runtime": "^0.0.6" "flow-enums-runtime": "^0.0.6"
@ -10348,9 +10384,9 @@
} }
}, },
"node_modules/metro-cache/node_modules/agent-base": { "node_modules/metro-cache/node_modules/agent-base": {
"version": "7.1.3", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 14" "node": ">= 14"
@ -10370,42 +10406,42 @@
} }
}, },
"node_modules/metro-config": { "node_modules/metro-config": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.82.5.tgz",
"integrity": "sha512-Ki3Wumr3hKHGDS7RrHsygmmRNc/PCJrvkLn0+BWWxmbOmOcMMJDSmSI+WRlT8jd5VPZFxIi4wg+sAt5yBXAK0g==", "integrity": "sha512-/r83VqE55l0WsBf8IhNmc/3z71y2zIPe5kRSuqA5tY/SL/ULzlHUJEMd1szztd0G45JozLwjvrhAzhDPJ/Qo/g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"connect": "^3.6.5", "connect": "^3.6.5",
"cosmiconfig": "^5.0.5", "cosmiconfig": "^5.0.5",
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"jest-validate": "^29.7.0", "jest-validate": "^29.7.0",
"metro": "0.82.4", "metro": "0.82.5",
"metro-cache": "0.82.4", "metro-cache": "0.82.5",
"metro-core": "0.82.4", "metro-core": "0.82.5",
"metro-runtime": "0.82.4" "metro-runtime": "0.82.5"
}, },
"engines": { "engines": {
"node": ">=18.18" "node": ">=18.18"
} }
}, },
"node_modules/metro-core": { "node_modules/metro-core": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.82.5.tgz",
"integrity": "sha512-Xo4ozbxPg2vfgJGCgXZ8sVhC2M0lhTqD+tsKO2q9aelq/dCjnnSb26xZKcQO80CQOQUL7e3QWB7pLFGPjZm31A==", "integrity": "sha512-OJL18VbSw2RgtBm1f2P3J5kb892LCVJqMvslXxuxjAPex8OH7Eb8RBfgEo7VZSjgb/LOf4jhC4UFk5l5tAOHHA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
"metro-resolver": "0.82.4" "metro-resolver": "0.82.5"
}, },
"engines": { "engines": {
"node": ">=18.18" "node": ">=18.18"
} }
}, },
"node_modules/metro-file-map": { "node_modules/metro-file-map": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.82.5.tgz",
"integrity": "sha512-eO7HD1O3aeNsbEe6NBZvx1lLJUrxgyATjnDmb7bm4eyF6yWOQot9XVtxTDLNifECuvsZ4jzRiTInrbmIHkTdGA==", "integrity": "sha512-vpMDxkGIB+MTN8Af5hvSAanc6zXQipsAUO+XUx3PCQieKUfLwdoa8qaZ1WAQYRpaU+CJ8vhBcxtzzo3d9IsCIQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"debug": "^4.4.0", "debug": "^4.4.0",
@ -10423,9 +10459,9 @@
} }
}, },
"node_modules/metro-minify-terser": { "node_modules/metro-minify-terser": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.82.5.tgz",
"integrity": "sha512-W79Mi6BUwWVaM8Mc5XepcqkG+TSsCyyo//dmTsgYfJcsmReQorRFodil3bbJInETvjzdnS1mCsUo9pllNjT1Hg==", "integrity": "sha512-v6Nx7A4We6PqPu/ta1oGTqJ4Usz0P7c+3XNeBxW9kp8zayS3lHUKR0sY0wsCHInxZlNAEICx791x+uXytFUuwg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
@ -10436,9 +10472,9 @@
} }
}, },
"node_modules/metro-resolver": { "node_modules/metro-resolver": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.82.5.tgz",
"integrity": "sha512-uWoHzOBGQTPT5PjippB8rRT3iI9CTgFA9tRiLMzrseA5o7YAlgvfTdY9vFk2qyk3lW3aQfFKWkmqENryPRpu+Q==", "integrity": "sha512-kFowLnWACt3bEsuVsaRNgwplT8U7kETnaFHaZePlARz4Fg8tZtmRDUmjaD68CGAwc0rwdwNCkWizLYpnyVcs2g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flow-enums-runtime": "^0.0.6" "flow-enums-runtime": "^0.0.6"
@ -10448,9 +10484,9 @@
} }
}, },
"node_modules/metro-runtime": { "node_modules/metro-runtime": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.82.5.tgz",
"integrity": "sha512-vVyFO7H+eLXRV2E7YAUYA7aMGBECGagqxmFvC2hmErS7oq90BbPVENfAHbUWq1vWH+MRiivoRxdxlN8gBoF/dw==", "integrity": "sha512-rQZDoCUf7k4Broyw3Ixxlq5ieIPiR1ULONdpcYpbJQ6yQ5GGEyYjtkztGD+OhHlw81LCR2SUAoPvtTus2WDK5g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.25.0", "@babel/runtime": "^7.25.0",
@ -10461,9 +10497,9 @@
} }
}, },
"node_modules/metro-source-map": { "node_modules/metro-source-map": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.82.5.tgz",
"integrity": "sha512-9jzDQJ0FPas1FuQFtwmBHsez2BfhFNufMowbOMeG3ZaFvzeziE8A0aJwILDS3U+V5039ssCQFiQeqDgENWvquA==", "integrity": "sha512-wH+awTOQJVkbhn2SKyaw+0cd+RVSCZ3sHVgyqJFQXIee/yLs3dZqKjjeKKhhVeudgjXo7aE/vSu/zVfcQEcUfw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/traverse": "^7.25.3", "@babel/traverse": "^7.25.3",
@ -10471,9 +10507,9 @@
"@babel/types": "^7.25.2", "@babel/types": "^7.25.2",
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"invariant": "^2.2.4", "invariant": "^2.2.4",
"metro-symbolicate": "0.82.4", "metro-symbolicate": "0.82.5",
"nullthrows": "^1.1.1", "nullthrows": "^1.1.1",
"ob1": "0.82.4", "ob1": "0.82.5",
"source-map": "^0.5.6", "source-map": "^0.5.6",
"vlq": "^1.0.0" "vlq": "^1.0.0"
}, },
@ -10491,14 +10527,14 @@
} }
}, },
"node_modules/metro-symbolicate": { "node_modules/metro-symbolicate": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.82.5.tgz",
"integrity": "sha512-LwEwAtdsx7z8rYjxjpLWxuFa2U0J6TS6ljlQM4WAATKa4uzV8unmnRuN2iNBWTmRqgNR77mzmI2vhwD4QSCo+w==", "integrity": "sha512-1u+07gzrvYDJ/oNXuOG1EXSvXZka/0JSW1q2EYBWerVKMOhvv9JzDGyzmuV7hHbF2Hg3T3S2uiM36sLz1qKsiw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"invariant": "^2.2.4", "invariant": "^2.2.4",
"metro-source-map": "0.82.4", "metro-source-map": "0.82.5",
"nullthrows": "^1.1.1", "nullthrows": "^1.1.1",
"source-map": "^0.5.6", "source-map": "^0.5.6",
"vlq": "^1.0.0" "vlq": "^1.0.0"
@ -10520,9 +10556,9 @@
} }
}, },
"node_modules/metro-transform-plugins": { "node_modules/metro-transform-plugins": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.82.5.tgz",
"integrity": "sha512-NoWQRPHupVpnDgYguiEcm7YwDhnqW02iWWQjO2O8NsNP09rEMSq99nPjARWfukN7+KDh6YjLvTIN20mj3dk9kw==", "integrity": "sha512-57Bqf3rgq9nPqLrT2d9kf/2WVieTFqsQ6qWHpEng5naIUtc/Iiw9+0bfLLWSAw0GH40iJ4yMjFcFJDtNSYynMA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.25.2", "@babel/core": "^7.25.2",
@ -10537,9 +10573,9 @@
} }
}, },
"node_modules/metro-transform-worker": { "node_modules/metro-transform-worker": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.82.4.tgz", "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.82.5.tgz",
"integrity": "sha512-kPI7Ad/tdAnI9PY4T+2H0cdgGeSWWdiPRKuytI806UcN4VhFL6OmYa19/4abYVYF+Cd2jo57CDuwbaxRfmXDhw==", "integrity": "sha512-mx0grhAX7xe+XUQH6qoHHlWedI8fhSpDGsfga7CpkO9Lk9W+aPitNtJWNGrW8PfjKEWbT9Uz9O50dkI8bJqigw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.25.2", "@babel/core": "^7.25.2",
@ -10547,13 +10583,13 @@
"@babel/parser": "^7.25.3", "@babel/parser": "^7.25.3",
"@babel/types": "^7.25.2", "@babel/types": "^7.25.2",
"flow-enums-runtime": "^0.0.6", "flow-enums-runtime": "^0.0.6",
"metro": "0.82.4", "metro": "0.82.5",
"metro-babel-transformer": "0.82.4", "metro-babel-transformer": "0.82.5",
"metro-cache": "0.82.4", "metro-cache": "0.82.5",
"metro-cache-key": "0.82.4", "metro-cache-key": "0.82.5",
"metro-minify-terser": "0.82.4", "metro-minify-terser": "0.82.5",
"metro-source-map": "0.82.4", "metro-source-map": "0.82.5",
"metro-transform-plugins": "0.82.4", "metro-transform-plugins": "0.82.5",
"nullthrows": "^1.1.1" "nullthrows": "^1.1.1"
}, },
"engines": { "engines": {
@ -10567,18 +10603,18 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/metro/node_modules/hermes-estree": { "node_modules/metro/node_modules/hermes-estree": {
"version": "0.28.1", "version": "0.29.1",
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.28.1.tgz", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
"integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==", "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/metro/node_modules/hermes-parser": { "node_modules/metro/node_modules/hermes-parser": {
"version": "0.28.1", "version": "0.29.1",
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.28.1.tgz", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
"integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==", "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"hermes-estree": "0.28.1" "hermes-estree": "0.29.1"
} }
}, },
"node_modules/metro/node_modules/source-map": { "node_modules/metro/node_modules/source-map": {
@ -10981,9 +11017,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/ob1": { "node_modules/ob1": {
"version": "0.82.4", "version": "0.82.5",
"resolved": "https://registry.npmjs.org/ob1/-/ob1-0.82.4.tgz", "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.82.5.tgz",
"integrity": "sha512-n9S8e4l5TvkrequEAMDidl4yXesruWTNTzVkeaHSGywoTOIwTzZzKw7Z670H3eaXDZui5MJXjWGNzYowVZIxCA==", "integrity": "sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flow-enums-runtime": "^0.0.6" "flow-enums-runtime": "^0.0.6"
@ -11907,19 +11943,19 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/react-native": { "node_modules/react-native": {
"version": "0.79.4", "version": "0.79.6",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.79.4.tgz", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.79.6.tgz",
"integrity": "sha512-CfxYMuszvnO/33Q5rB//7cU1u9P8rSOvzhE2053Phdb8+6bof9NLayCllU2nmPrm8n9o6RU1Fz5H0yquLQ0DAw==", "integrity": "sha512-kvIWSmf4QPfY41HC25TR285N7Fv0Pyn3DAEK8qRL9dA35usSaxsJkHfw+VqnonqJjXOaoKCEanwudRAJ60TBGA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jest/create-cache-key-function": "^29.7.0", "@jest/create-cache-key-function": "^29.7.0",
"@react-native/assets-registry": "0.79.4", "@react-native/assets-registry": "0.79.6",
"@react-native/codegen": "0.79.4", "@react-native/codegen": "0.79.6",
"@react-native/community-cli-plugin": "0.79.4", "@react-native/community-cli-plugin": "0.79.6",
"@react-native/gradle-plugin": "0.79.4", "@react-native/gradle-plugin": "0.79.6",
"@react-native/js-polyfills": "0.79.4", "@react-native/js-polyfills": "0.79.6",
"@react-native/normalize-colors": "0.79.4", "@react-native/normalize-colors": "0.79.6",
"@react-native/virtualized-lists": "0.79.4", "@react-native/virtualized-lists": "0.79.6",
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"anser": "^1.4.9", "anser": "^1.4.9",
"ansi-regex": "^5.0.0", "ansi-regex": "^5.0.0",
@ -12207,10 +12243,37 @@
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/react-native/node_modules/@react-native/codegen": {
"version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.79.6.tgz",
"integrity": "sha512-iRBX8Lgbqypwnfba7s6opeUwVyaR23mowh9ILw7EcT2oLz3RqMmjJdrbVpWhGSMGq2qkPfqAH7bhO8C7O+xfjQ==",
"license": "MIT",
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/parser": "^7.25.3",
"glob": "^7.1.1",
"hermes-parser": "0.25.1",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1",
"yargs": "^17.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@babel/core": "*"
}
},
"node_modules/react-native/node_modules/@react-native/normalize-colors": {
"version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.6.tgz",
"integrity": "sha512-0v2/ruY7eeKun4BeKu+GcfO+SHBdl0LJn4ZFzTzjHdWES0Cn+ONqKljYaIv8p9MV2Hx/kcdEvbY4lWI34jC/mQ==",
"license": "MIT"
},
"node_modules/react-native/node_modules/@react-native/virtualized-lists": { "node_modules/react-native/node_modules/@react-native/virtualized-lists": {
"version": "0.79.4", "version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.79.4.tgz", "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.79.6.tgz",
"integrity": "sha512-0Mdcox6e5PTonuM1WIo3ks7MBAa3IDzj0pKnE5xAwSgQ0DJW2P5dYf+KjWmpkE+Yb0w41ZbtXPhKq+U2JJ6C/Q==", "integrity": "sha512-khA/Hrbb+rB68YUHrLubfLgMOD9up0glJhw25UE3Kntj32YDyuO0Tqc81ryNTcCekFKJ8XrAaEjcfPg81zBGPw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"invariant": "^2.2.4", "invariant": "^2.2.4",

View File

@ -3,7 +3,7 @@
"main": "expo-router/entry", "main": "expo-router/entry",
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"start": "expo start", "start": "expo start --dev-client",
"android": "expo run:android", "android": "expo run:android",
"ios": "expo run:ios", "ios": "expo run:ios",
"web": "expo start --web", "web": "expo start --web",
@ -42,7 +42,7 @@
"react": "19.0.0", "react": "19.0.0",
"react-dom": "19.0.0", "react-dom": "19.0.0",
"react-i18next": "^15.5.3", "react-i18next": "^15.5.3",
"react-native": "0.79.4", "react-native": "0.79.6",
"react-native-element-dropdown": "^2.12.4", "react-native-element-dropdown": "^2.12.4",
"react-native-maps": "1.24.2", "react-native-maps": "1.24.2",
"react-native-otp-entry": "^1.8.5", "react-native-otp-entry": "^1.8.5",

View File

@ -40,7 +40,8 @@
"alerts": "Alerts", "alerts": "Alerts",
"emi-alert": "14 days left to pay the EMI!", "emi-alert": "14 days left to pay the EMI!",
"km": "km", "km": "km",
"days-left-to-pay-emi": "days left to pay the EMI!" "days-left-to-pay-emi": "days left to pay the EMI!",
"fetching-location": "Fetching location..."
}, },
"profile": { "profile": {
"my-account": "My Account", "my-account": "My Account",
@ -62,8 +63,7 @@
"whatsapp": "Whatsapp", "whatsapp": "Whatsapp",
"call-us": "Call Us", "call-us": "Call Us",
"email": "Email", "email": "Email",
"lang-changed": "भाषा सफलतापूर्वक बदल दी गई", "lang-changed": "भाषा सफलतापूर्वक बदल दी गई"
"fetching-location": "Fetching location..."
}, },
"payment": { "payment": {
"last-emi-details": "Last EMI Details", "last-emi-details": "Last EMI Details",

View File

@ -36,8 +36,11 @@ const fetchToken = async (): Promise<string> => {
} }
}; };
const fetchControllingServer = async (token: string): Promise<string> => { const fetchControllingServer = async (
const hardwareDeviceId = store.getState().user.data?.batteries[0]?.device_id; token: string,
hardwareDeviceId: string
): Promise<string> => {
// const hardwareDeviceId = store.getState().user.data?.batteries[0]?.device_id;
console.log("Hardware Device ID:", store.getState().user.data); console.log("Hardware Device ID:", store.getState().user.data);
// const hardwareDeviceId = "VEC16000866082076280974"; // const hardwareDeviceId = "VEC16000866082076280974";
@ -103,11 +106,19 @@ export const connectSocket = () => {
export const initSocket = async () => { export const initSocket = async () => {
try { try {
const hardwareDeviceId =
store.getState().user.data?.batteries?.[0]?.device_id;
if (!hardwareDeviceId) {
console.warn("initSocket skipped: hardwareDeviceId not ready");
return; // just exit gracefully
}
console.log(hardwareDeviceId, "hardware deviced");
//get latest telemetry as fallback option //get latest telemetry as fallback option
token = await fetchToken(); token = await fetchToken();
controllingServer = await fetchControllingServer(token); controllingServer = await fetchControllingServer(token, hardwareDeviceId);
store.dispatch(setTelemetryLoading()); store.dispatch(setTelemetryLoading());
await fetchLatestTelemetry(token, controllingServer); await fetchLatestTelemetry(token, controllingServer, hardwareDeviceId);
connectSocket(); connectSocket();
} catch (err) { } catch (err) {
console.log(err, ""); console.log(err, "");
@ -171,11 +182,12 @@ const handleSocketData = (data: any) => {
const fetchLatestTelemetry = async ( const fetchLatestTelemetry = async (
token: string, token: string,
controllingServer: string controllingServer: string,
hardwareDeviceId: string
) => { ) => {
try { try {
const hardwareDeviceId = // const hardwareDeviceId =
store.getState().user.data?.batteries[0]?.device_id; // store.getState().user.data?.batteries[0]?.device_id;
if (!hardwareDeviceId || !token || !controllingServer) if (!hardwareDeviceId || !token || !controllingServer)
throw new Error("Missing hardwareDeviceId"); throw new Error("Missing hardwareDeviceId");

View File

@ -1,6 +1,7 @@
{ {
"extends": "expo/tsconfig.base", "extends": "expo/tsconfig.base",
"compilerOptions": { "compilerOptions": {
"jsx": "react-jsx",
"strict": true, "strict": true,
"paths": { "paths": {
"@/*": ["./*"] "@/*": ["./*"]