Release (#269)
* change apm url to portal url TP-25597 (#262)
* change apm url to portal url TP-25597
* fix config dev TP-25597
* enable sso TP-122 (#261)
* TP-24980 | Package version bump and submodule update
* enable sso TP-122
* TP-122 update rnUi
* fix crypto js failing issue TP-122
* error handling add TP-122
* change error text TP-122
* add disable button timer TP-122
* remove extra dispatch TP-122
* fix UI with design TP-122
* fix icon TP-122
* fix design nit picks and add google icon TP-122
* Revert "TP-25967 | Added Web Alias config + Updating NewAddressContainer with alias (#266)" (#267)
This reverts commit c9fefc0309.
* move code back to AuthRouter TP-122
* foreground service notification title and config update TP-122
* fix package json TP-122
* emiBreakupBottomSheet formatting revert TP-122
* remoce disable function TP-122
Co-authored-by: Aman Chaturvedi <aman.chaturvedi@navi.com>
Co-authored-by: Himanshu Kansal <himanshu.kansal@navi.com>
* TP-122 bump package
Co-authored-by: Aman Chaturvedi <aman.chaturvedi@navi.com>
Co-authored-by: Himanshu Kansal <himanshu.kansal@navi.com>
This commit is contained in:
committed by
GitHub Enterprise
parent
f510b2d63e
commit
3249e55014
Submodule RN-UI-LIB updated: 50f7e796a8...b162be37b2
@@ -131,8 +131,8 @@ def reactNativeArchitectures() {
|
||||
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
||||
}
|
||||
|
||||
def VERSION_CODE = 52
|
||||
def VERSION_NAME = "2.1.11"
|
||||
def VERSION_CODE = 53
|
||||
def VERSION_NAME = "2.1.12"
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
@@ -4,4 +4,4 @@ export const JANUS_SERVICE_URL = 'https://dev-longhorn-portal.np.navi-tech.in/ap
|
||||
export const ENV = 'dev';
|
||||
export const IS_SSO_ENABLED = false;
|
||||
export const APM_APP_NAME = 'cosmos-app';
|
||||
export const APM_BASE_URL = 'https://apm-server.np.navi-tech.in';
|
||||
export const APM_BASE_URL = 'https://dev-longhorn-portal.np.navi-tech.in/apm-events';
|
||||
|
||||
@@ -2,6 +2,6 @@ export const BASE_AV_APP_URL = 'https://longhorn.navi.com/field-app';
|
||||
export const SENTRY_DSN = 'https://5daa4832fade44b389b265de9b26c2fd@longhorn.navi.com/glitchtip-events/172';
|
||||
export const JANUS_SERVICE_URL = 'https://longhorn.navi.com/api/events/json';
|
||||
export const ENV = 'prod';
|
||||
export const IS_SSO_ENABLED = false;
|
||||
export const IS_SSO_ENABLED = true;
|
||||
export const APM_APP_NAME = 'cosmos-app';
|
||||
export const APM_BASE_URL = 'https://apm-server.prod.navi-tech.in';
|
||||
export const APM_BASE_URL = 'https://longhorn.navi.com/apm-events';
|
||||
|
||||
@@ -4,4 +4,4 @@ export const JANUS_SERVICE_URL = 'https://qa-longhorn-portal.np.navi-tech.in/api
|
||||
export const ENV = 'qa';
|
||||
export const IS_SSO_ENABLED = false;
|
||||
export const APM_APP_NAME = 'cosmos-app';
|
||||
export const APM_BASE_URL = 'https://apm-server.np.navi-tech.in';
|
||||
export const APM_BASE_URL = 'https://qa-longhorn-portal.np.navi-tech.in/apm-events';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "AV_APP",
|
||||
"version": "2.1.11",
|
||||
"version": "2.1.12",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android:dev": "yarn move:dev && react-native run-android",
|
||||
@@ -56,6 +56,7 @@
|
||||
"react-native-device-info": "10.3.0",
|
||||
"react-native-fast-image": "8.6.3",
|
||||
"react-native-geolocation-service": "5.3.1",
|
||||
"react-native-get-random-values": "^1.8.0",
|
||||
"react-native-image-picker": "4.10.2",
|
||||
"react-native-pager-view": "6.1.2",
|
||||
"react-native-permissions": "3.6.1",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ToastMessages } from './../screens/allCases/constants';
|
||||
import 'react-native-get-random-values';
|
||||
import crypto from 'crypto-js';
|
||||
import { IUser, setAuthData } from '../reducer/userSlice';
|
||||
import axiosInstance, { ApiKeys, API_STATUS_CODE, getApiUrl } from '../components/utlis/apiHelper';
|
||||
@@ -19,7 +21,6 @@ import { toast } from '../../RN-UI-LIB/src/components/toast';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { clearAllAsyncStorage, setAsyncStorageItem } from '../components/utlis/commonFunctions';
|
||||
import { logError } from '../components/utlis/errorUtils';
|
||||
import { getUniqueId } from 'react-native-device-info';
|
||||
import { Linking } from 'react-native';
|
||||
|
||||
export interface GenerateOTPPayload {
|
||||
@@ -78,7 +79,6 @@ export const signInGoogle = () => async (dispatch: Dispatch) => {
|
||||
await setAsyncStorageItem('codeVerifier', codeVerifier);
|
||||
const state = crypto.lib.WordArray.random(16).toString();
|
||||
const url = getApiUrl(ApiKeys.SIGN_IN_GOOGLE);
|
||||
dispatch(setFormLoading(true));
|
||||
const response = await axiosInstance.get(url, {
|
||||
params: {
|
||||
codeChallenge,
|
||||
@@ -87,15 +87,14 @@ export const signInGoogle = () => async (dispatch: Dispatch) => {
|
||||
headers: { donotHandleError: false },
|
||||
});
|
||||
if (response?.data?.signInUrl) {
|
||||
Linking.openURL(response.data.signInUrl);
|
||||
await Linking.openURL(response.data.signInUrl);
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error as Error);
|
||||
toast({
|
||||
text1: 'Error in google sign in',
|
||||
type: 'error',
|
||||
});
|
||||
} finally {
|
||||
dispatch(setFormLoading(false));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -108,16 +107,12 @@ export const verifyGoogleSignIn =
|
||||
return;
|
||||
}
|
||||
const parsedCodeVerify = JSON.parse(codeVerify);
|
||||
const response = await axiosInstance.post(
|
||||
url,
|
||||
{
|
||||
code,
|
||||
state,
|
||||
codeVerifier: parsedCodeVerify,
|
||||
deviceId: deviceId,
|
||||
},
|
||||
{ headers: { donotHandleError: true } }
|
||||
);
|
||||
const response = await axiosInstance.post(url, {
|
||||
code,
|
||||
state,
|
||||
codeVerifier: parsedCodeVerify,
|
||||
deviceId: deviceId,
|
||||
});
|
||||
if (response?.data?.sessionDetails) {
|
||||
const { sessionDetails, user } = response.data;
|
||||
dispatch(
|
||||
@@ -132,12 +127,17 @@ export const verifyGoogleSignIn =
|
||||
}
|
||||
} catch (error) {
|
||||
logError(error as Error);
|
||||
toast({
|
||||
text1: 'error in google sign in',
|
||||
type: 'error',
|
||||
});
|
||||
} finally {
|
||||
() => dispatch(setFormLoading(false));
|
||||
if (error?.response?.status === API_STATUS_CODE.NOT_FOUND) {
|
||||
toast({
|
||||
text1: ToastMessages.GENERIC_ERROR_TOAST,
|
||||
type: 'error',
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
text1: error?.response?.data?.message ?? ToastMessages.SSO_SERVER_SIGN_IN_ERROR,
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,11 @@ export const getNotifications =
|
||||
const startTime = yesterday.getTime();
|
||||
const url = getApiUrl(ApiKeys.NOTIFICATIONS, {}, { ...payload, startTime });
|
||||
return axiosInstance
|
||||
.get(url)
|
||||
.get(url, {
|
||||
headers: {
|
||||
showInSpecificComponents: ['Notifications'],
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
const notifications = response?.data?.notificationResponse?.notifications;
|
||||
const { totalElements, totalPages, totalUnreadElements } = response?.data;
|
||||
@@ -66,9 +70,19 @@ export const getNotifications =
|
||||
|
||||
export const notificationAction = (payload: INotificationAction[]) => (dispatch: AppDispatch) => {
|
||||
const url = getApiUrl(ApiKeys.NOTIFICATION_ACTION);
|
||||
return axiosInstance.post(url, payload).then(() => {
|
||||
dispatch(addActionToNotifications(payload));
|
||||
});
|
||||
return axiosInstance
|
||||
.post(
|
||||
url,
|
||||
{
|
||||
headers: {
|
||||
showInSpecificComponents: ['Notifications'],
|
||||
},
|
||||
},
|
||||
payload
|
||||
)
|
||||
.then(() => {
|
||||
dispatch(addActionToNotifications(payload));
|
||||
});
|
||||
};
|
||||
|
||||
export const notificationDelivered = (payload: { ids: string[] }) => (dispatch: AppDispatch) => {
|
||||
|
||||
43
src/assets/icons/GoogleIcon.tsx
Normal file
43
src/assets/icons/GoogleIcon.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import * as React from 'react';
|
||||
import Svg, { Path } from 'react-native-svg';
|
||||
|
||||
function GoogleIcon(props) {
|
||||
return (
|
||||
<Svg
|
||||
width={38}
|
||||
height={38}
|
||||
viewBox="0 0 38 38"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<Path d="M0 8a8 8 0 018-8h22a8 8 0 018 8v22a8 8 0 01-8 8H8a8 8 0 01-8-8V8z" fill="#fff" />
|
||||
<Path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M27.64 19.204c0-.638-.057-1.252-.164-1.84H19v3.48h4.844a4.14 4.14 0 01-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z"
|
||||
fill="#4285F4"
|
||||
/>
|
||||
<Path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19 28c2.43 0 4.467-.805 5.956-2.18l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711h-3.007v2.332A8.997 8.997 0 0019 28z"
|
||||
fill="#34A853"
|
||||
/>
|
||||
<Path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M13.964 20.71a5.41 5.41 0 01-.282-1.71c0-.592.102-1.17.282-1.71V14.96h-3.007A8.996 8.996 0 0010 19.001c0 1.452.348 2.827.957 4.042l3.007-2.332z"
|
||||
fill="#FBBC05"
|
||||
/>
|
||||
<Path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19 13.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C23.463 10.891 21.426 10 19 10a8.996 8.996 0 00-8.043 4.958l3.007 2.332c.708-2.127 2.692-3.71 5.036-3.71z"
|
||||
fill="#EA4335"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default GoogleIcon;
|
||||
@@ -4,4 +4,4 @@ export const JANUS_SERVICE_URL = 'https://qa-longhorn-portal.np.navi-tech.in/api
|
||||
export const ENV = 'qa';
|
||||
export const IS_SSO_ENABLED = false;
|
||||
export const APM_APP_NAME = 'cosmos-app';
|
||||
export const APM_BASE_URL = 'https://apm-server.np.navi-tech.in';
|
||||
export const APM_BASE_URL = 'https://qa-longhorn-portal.np.navi-tech.in/apm-events';
|
||||
|
||||
@@ -56,4 +56,6 @@ export const ToastMessages = {
|
||||
OFFLINE_MESSAGE: 'You seem to be offline',
|
||||
PAYMENT_LINK_NOT_GENERATED: 'Payment link could not be generated',
|
||||
PAYMENT_LINK_RETRY: 'Please retry after an hour for this number',
|
||||
GENERIC_ERROR_TOAST: 'Something went wrong',
|
||||
SSO_SERVER_SIGN_IN_ERROR: 'Error while signing in to cosmos',
|
||||
};
|
||||
|
||||
@@ -16,79 +16,74 @@ interface IEmiBreakupBottomSheet {
|
||||
emiItem: IEmiItem;
|
||||
listNumber: number;
|
||||
}
|
||||
const EmiBreakupBottomSheet: React.FC<IEmiBreakupBottomSheet> = props => {
|
||||
const EmiBreakupBottomSheet: React.FC<IEmiBreakupBottomSheet> = (props) => {
|
||||
const { openBottomSheet, setOpenBottomSheet, emiItem, listNumber } = props;
|
||||
return (
|
||||
<BottomSheet
|
||||
heightPercentage={40}
|
||||
visible={openBottomSheet}
|
||||
HeaderNode={() => (
|
||||
<View style={[...row, GenericStyles.p16]}>
|
||||
<Heading dark type="h4">
|
||||
EMI {listNumber} breakup
|
||||
</Heading>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
onPress={() => setOpenBottomSheet(prev => !prev)}>
|
||||
<CloseIcon color={COLORS.TEXT.LIGHT} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
setVisible={() => setOpenBottomSheet(prev => !prev)}>
|
||||
<View style={[GenericStyles.p16]}>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Principal</Text>
|
||||
<Text dark>{formatAmount(emiItem?.totalUnpaidPrincipal ?? 0)}</Text>
|
||||
</View>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Interest</Text>
|
||||
<Text dark bold>
|
||||
{formatAmount(emiItem?.totalUnpaidInterest ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
{
|
||||
emiItem?.totalUnpaidEmiPenaltyCharges ?
|
||||
(
|
||||
<>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Interest</Text>
|
||||
<Text dark bold>
|
||||
{formatAmount(emiItem?.totalUnpaidEmiPenaltyCharges ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
) :
|
||||
(
|
||||
<>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Other fees</Text>
|
||||
<Text dark bold>
|
||||
{formatAmount(emiItem?.totalUnpaidOtherFees ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
}
|
||||
<View style={styles.horizontalLine} />
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text dark bold>
|
||||
Total Overdue Amount
|
||||
</Text>
|
||||
<Text style={{ color: COLORS.TEXT.RED }}>
|
||||
{formatAmount(emiItem?.totalOverDueAmount ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
<BottomSheet
|
||||
heightPercentage={40}
|
||||
visible={openBottomSheet}
|
||||
HeaderNode={() => (
|
||||
<View style={[...row, GenericStyles.p16]}>
|
||||
<Heading dark type="h4">
|
||||
EMI {listNumber} breakup
|
||||
</Heading>
|
||||
<TouchableOpacity activeOpacity={0.7} onPress={() => setOpenBottomSheet((prev) => !prev)}>
|
||||
<CloseIcon color={COLORS.TEXT.LIGHT} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
setVisible={() => setOpenBottomSheet((prev) => !prev)}
|
||||
>
|
||||
<View style={[GenericStyles.p16]}>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Principal</Text>
|
||||
<Text dark>{formatAmount(emiItem?.totalUnpaidPrincipal ?? 0)}</Text>
|
||||
</View>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Interest</Text>
|
||||
<Text dark bold>
|
||||
{formatAmount(emiItem?.totalUnpaidInterest ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
{emiItem?.totalUnpaidEmiPenaltyCharges ? (
|
||||
<>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Interest</Text>
|
||||
<Text dark bold>
|
||||
{formatAmount(emiItem?.totalUnpaidEmiPenaltyCharges ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text light>Other fees</Text>
|
||||
<Text dark bold>
|
||||
{formatAmount(emiItem?.totalUnpaidOtherFees ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
<View style={styles.horizontalLine} />
|
||||
<View style={[...row, GenericStyles.pb16]}>
|
||||
<Text dark bold>
|
||||
Total Overdue Amount
|
||||
</Text>
|
||||
<Text style={{ color: COLORS.TEXT.RED }}>
|
||||
{formatAmount(emiItem?.totalOverDueAmount ?? 0)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
horizontalLine: {
|
||||
height: 1,
|
||||
backgroundColor: COLORS.BORDER.PRIMARY,
|
||||
width: '100%',
|
||||
marginBottom: 16,
|
||||
},
|
||||
horizontalLine: {
|
||||
height: 1,
|
||||
backgroundColor: COLORS.BORDER.PRIMARY,
|
||||
width: '100%',
|
||||
marginBottom: 16,
|
||||
},
|
||||
});
|
||||
export default EmiBreakupBottomSheet;
|
||||
|
||||
@@ -13,140 +13,122 @@ import Tag from '../../../RN-UI-LIB/src/components/Tag';
|
||||
import { formatAmount } from '../../../RN-UI-LIB/src/utlis/amount';
|
||||
|
||||
export interface IEmiItem {
|
||||
status: 'SCHEDULED' | 'PAID' | 'UNPAID' | 'CANCELLED';
|
||||
dueDate: string; //YYYY-MM-DD
|
||||
totalOverDueAmount: number;
|
||||
paidOnDate: string; //YYYY-MM-DD
|
||||
totalUnpaidPrincipal: number;
|
||||
totalUnpaidInterest: number;
|
||||
totalUnpaidPenalInterest: number;
|
||||
totalUnpaidLateFeeAmount: number;
|
||||
totalUnpaidBounceFeeAmount: number;
|
||||
totalUnpaidEmiPenaltyCharges: number;
|
||||
totalUnpaidOtherFees?: number;
|
||||
status: 'SCHEDULED' | 'PAID' | 'UNPAID' | 'CANCELLED';
|
||||
dueDate: string; //YYYY-MM-DD
|
||||
totalOverDueAmount: number;
|
||||
paidOnDate: string; //YYYY-MM-DD
|
||||
totalUnpaidPrincipal: number;
|
||||
totalUnpaidInterest: number;
|
||||
totalUnpaidPenalInterest: number;
|
||||
totalUnpaidLateFeeAmount: number;
|
||||
totalUnpaidBounceFeeAmount: number;
|
||||
totalUnpaidEmiPenaltyCharges: number;
|
||||
totalUnpaidOtherFees?: number;
|
||||
}
|
||||
interface IEmiScheduleItem {
|
||||
listNumber: number;
|
||||
emiItem: IEmiItem;
|
||||
selectedTab: EmiSelectedTab;
|
||||
listNumber: number;
|
||||
emiItem: IEmiItem;
|
||||
selectedTab: EmiSelectedTab;
|
||||
}
|
||||
|
||||
const EmiScheduleItem: React.FC<IEmiScheduleItem> = ({
|
||||
listNumber,
|
||||
emiItem,
|
||||
selectedTab,
|
||||
}) => {
|
||||
const [openBottomSheet, setOpenBottomSheet] = React.useState(false);
|
||||
const EmiScheduleItem: React.FC<IEmiScheduleItem> = ({ listNumber, emiItem, selectedTab }) => {
|
||||
const [openBottomSheet, setOpenBottomSheet] = React.useState(false);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.leftContainer}>
|
||||
<Text
|
||||
dark
|
||||
style={[GenericStyles.pl12, GenericStyles.fontSize12]}>
|
||||
{listNumber}
|
||||
</Text>
|
||||
<Text
|
||||
light
|
||||
style={[GenericStyles.pl12, GenericStyles.fontSize12]}>
|
||||
EMI
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[...row, GenericStyles.fill, GenericStyles.p12]}>
|
||||
<View>
|
||||
<Text
|
||||
style={
|
||||
emiItem.status === 'UNPAID'
|
||||
? {
|
||||
color: COLORS.TEXT.RED,
|
||||
}
|
||||
: null
|
||||
}>
|
||||
{formatAmount(emiItem?.totalOverDueAmount)}
|
||||
</Text>
|
||||
<Text light>
|
||||
{dateFormat(
|
||||
new Date(emiItem.dueDate),
|
||||
BUSINESS_DATE_FORMAT,
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
<View>
|
||||
{emiItem.status === 'UNPAID' ? (
|
||||
<>
|
||||
{selectedTab === EmiSelectedTab.ALL ? (
|
||||
<Tag variant="error" text="Unpaid" />
|
||||
) : (
|
||||
<Button
|
||||
title="Breakup"
|
||||
variant="primaryText"
|
||||
onPress={() => setOpenBottomSheet(true)}
|
||||
textStyle={{
|
||||
fontSize: 12,
|
||||
fontWeight: '500',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
{emiItem.status === 'PAID' ? (
|
||||
<>
|
||||
{selectedTab === EmiSelectedTab.ALL ? (
|
||||
<Tag variant="success" text="Paid" />
|
||||
) : (
|
||||
<Text light style={[GenericStyles.fontSize12]}>
|
||||
Paid on:{' '}
|
||||
<Text
|
||||
style={[
|
||||
GenericStyles.fontSize12,
|
||||
{
|
||||
color: COLORS.TEXT.GREEN,
|
||||
},
|
||||
]}>
|
||||
{dateFormat(
|
||||
new Date(emiItem.paidOnDate),
|
||||
BUSINESS_DATE_FORMAT,
|
||||
)}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
{emiItem.status === 'SCHEDULED' ? (
|
||||
<Tag variant="gray" text="Scheduled" />
|
||||
) : null}
|
||||
|
||||
{emiItem.status === 'CANCELLED' ? (
|
||||
<Tag variant="yellow" text="Cancelled" />
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
<EmiBreakupBottomSheet
|
||||
emiItem={emiItem}
|
||||
openBottomSheet={openBottomSheet}
|
||||
setOpenBottomSheet={setOpenBottomSheet}
|
||||
listNumber={listNumber}
|
||||
/>
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.leftContainer}>
|
||||
<Text dark style={[GenericStyles.pl12, GenericStyles.fontSize12]}>
|
||||
{listNumber}
|
||||
</Text>
|
||||
<Text light style={[GenericStyles.pl12, GenericStyles.fontSize12]}>
|
||||
EMI
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[...row, GenericStyles.fill, GenericStyles.p12]}>
|
||||
<View>
|
||||
<Text
|
||||
style={
|
||||
emiItem.status === 'UNPAID'
|
||||
? {
|
||||
color: COLORS.TEXT.RED,
|
||||
}
|
||||
: null
|
||||
}
|
||||
>
|
||||
{formatAmount(emiItem?.totalOverDueAmount)}
|
||||
</Text>
|
||||
<Text light>{dateFormat(new Date(emiItem.dueDate), BUSINESS_DATE_FORMAT)}</Text>
|
||||
</View>
|
||||
);
|
||||
<View>
|
||||
{emiItem.status === 'UNPAID' ? (
|
||||
<>
|
||||
{selectedTab === EmiSelectedTab.ALL ? (
|
||||
<Tag variant="error" text="Unpaid" />
|
||||
) : (
|
||||
<Button
|
||||
title="Breakup"
|
||||
variant="primaryText"
|
||||
onPress={() => setOpenBottomSheet(true)}
|
||||
textStyle={{
|
||||
fontSize: 12,
|
||||
fontWeight: '500',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
{emiItem.status === 'PAID' ? (
|
||||
<>
|
||||
{selectedTab === EmiSelectedTab.ALL ? (
|
||||
<Tag variant="success" text="Paid" />
|
||||
) : (
|
||||
<Text light style={[GenericStyles.fontSize12]}>
|
||||
Paid on:{' '}
|
||||
<Text
|
||||
style={[
|
||||
GenericStyles.fontSize12,
|
||||
{
|
||||
color: COLORS.TEXT.GREEN,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{dateFormat(new Date(emiItem.paidOnDate), BUSINESS_DATE_FORMAT)}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
{emiItem.status === 'SCHEDULED' ? <Tag variant="gray" text="Scheduled" /> : null}
|
||||
|
||||
{emiItem.status === 'CANCELLED' ? <Tag variant="yellow" text="Cancelled" /> : null}
|
||||
</View>
|
||||
</View>
|
||||
<EmiBreakupBottomSheet
|
||||
emiItem={emiItem}
|
||||
openBottomSheet={openBottomSheet}
|
||||
setOpenBottomSheet={setOpenBottomSheet}
|
||||
listNumber={listNumber}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
borderWidth: 1,
|
||||
borderColor: COLORS.BORDER.PRIMARY,
|
||||
borderRadius: 4,
|
||||
marginBottom: 12,
|
||||
height: 68,
|
||||
flexDirection: 'row',
|
||||
alignContent: 'center',
|
||||
},
|
||||
leftContainer: {
|
||||
alignContent: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: COLORS.BACKGROUND.SILVER,
|
||||
width: 43,
|
||||
},
|
||||
container: {
|
||||
borderWidth: 1,
|
||||
borderColor: COLORS.BORDER.PRIMARY,
|
||||
borderRadius: 4,
|
||||
marginBottom: 12,
|
||||
height: 68,
|
||||
flexDirection: 'row',
|
||||
alignContent: 'center',
|
||||
},
|
||||
leftContainer: {
|
||||
alignContent: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: COLORS.BACKGROUND.SILVER,
|
||||
width: 43,
|
||||
},
|
||||
});
|
||||
|
||||
export default EmiScheduleItem;
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
@@ -10,29 +11,39 @@ import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
|
||||
import NaviLogoIcon from '../../../RN-UI-LIB/src/Icons/NaviLogoIcon';
|
||||
import {
|
||||
generateOTP,
|
||||
GenerateOTPPayload,
|
||||
type GenerateOTPPayload,
|
||||
signInGoogle,
|
||||
} from '../../action/authActions';
|
||||
import { useAppDispatch } from '../../hooks';
|
||||
import { RootState } from '../../store/store';
|
||||
import { type RootState } from '../../store/store';
|
||||
import { addClickstreamEvent } from '../../services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from '../../common/Constants';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import Layout from '../layout/Layout';
|
||||
import { IS_SSO_ENABLED } from '../../constants/config';
|
||||
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import GoogleIcon from '../../assets/icons/GoogleIcon';
|
||||
|
||||
interface ILoginForm {
|
||||
phoneNumber: string;
|
||||
}
|
||||
|
||||
|
||||
const Login = () => {
|
||||
function Login() {
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
getValues,
|
||||
formState: { errors, isValid },
|
||||
formState: { isValid },
|
||||
} = useForm<ILoginForm>();
|
||||
const dispatch = useAppDispatch();
|
||||
const { phoneNumber, OTPError, isLoading, deviceId } = useSelector((state: RootState) => ({
|
||||
deviceId: state.user.deviceId,
|
||||
phoneNumber: state.loginInfo.phoneNumber,
|
||||
OTPError: state.loginInfo.OTPError,
|
||||
isLoading: state.loginInfo.isLoading,
|
||||
}));
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
isValid &&
|
||||
@@ -45,13 +56,8 @@ const Login = () => {
|
||||
|
||||
useEffect(() => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.AV_LOGIN_SCREEN_LOAD);
|
||||
|
||||
}, []);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { phoneNumber, OTPError, isLoading } = useSelector(
|
||||
(state: RootState) => state.loginInfo,
|
||||
);
|
||||
|
||||
const handleGenerateOTP = (data: GenerateOTPPayload) => {
|
||||
addClickstreamEvent(
|
||||
@@ -64,17 +70,18 @@ const Login = () => {
|
||||
dispatch(signInGoogle());
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<SafeAreaView
|
||||
style={[
|
||||
GenericStyles.p16,
|
||||
styles.container,
|
||||
GenericStyles.whiteBackground,
|
||||
GenericStyles.fill,
|
||||
// GenericStyles.justifyContentCenter,
|
||||
]}>
|
||||
<NaviLogoIcon style={[GenericStyles.mb12, styles.mt84]} />
|
||||
<Heading dark>Login to Cosmos</Heading>
|
||||
<Heading style={styles.headingStyles} bold dark>Login to COSMOS</Heading>
|
||||
<Text light style={[GenericStyles.mb24, GenericStyles.mt4]}>
|
||||
Use your registered mobile number
|
||||
</Text>
|
||||
@@ -98,42 +105,77 @@ const Login = () => {
|
||||
name="phoneNumber"
|
||||
rules={{ required: true, minLength: 10, maxLength: 10 }}
|
||||
/>
|
||||
|
||||
<Button
|
||||
title="Get OTP"
|
||||
onPress={handleSubmit(handleGenerateOTP)}
|
||||
style={[GenericStyles.w100, GenericStyles.mt24]}
|
||||
disabled={!isValid || isLoading}
|
||||
showLoader={isLoading}
|
||||
testID={'test_get_otp'}
|
||||
testID="test_get_otp"
|
||||
textStyle={
|
||||
GenericStyles.fontSize16
|
||||
}
|
||||
/>
|
||||
{IS_SSO_ENABLED ? <>
|
||||
<Text
|
||||
style={[
|
||||
GenericStyles.centerAlignedText,
|
||||
GenericStyles.mt24,
|
||||
<View style={[GenericStyles.centerAlignedRow,
|
||||
GenericStyles.mt24,]}>
|
||||
<View style={styles.horizontalLine} />
|
||||
|
||||
<Text
|
||||
style={[GenericStyles.mh12]}
|
||||
bold
|
||||
light>
|
||||
or
|
||||
</Text>
|
||||
|
||||
<View style={styles.horizontalLine} />
|
||||
</View>
|
||||
<Button
|
||||
title="Log in with Google"
|
||||
onPress={signInWithGoogle}
|
||||
style={[GenericStyles.w100, GenericStyles.mt24,
|
||||
]}
|
||||
variant='secondary'
|
||||
buttonStyle={styles.googleButton}
|
||||
showLoader={isLoading}
|
||||
testID="test_sso_login"
|
||||
textStyle={[{
|
||||
color: COLORS.TEXT.DARK,
|
||||
},
|
||||
GenericStyles.fontSize16
|
||||
]}
|
||||
bold
|
||||
dark>
|
||||
OR
|
||||
</Text>
|
||||
<Button
|
||||
title="SSO login for Navi Employees"
|
||||
onPress={signInWithGoogle}
|
||||
style={[GenericStyles.w100, GenericStyles.mt24]}
|
||||
showLoader={isLoading}
|
||||
testID={'test_sso_login'}
|
||||
/>
|
||||
leftIcon={
|
||||
<GoogleIcon />
|
||||
}
|
||||
/>
|
||||
</>
|
||||
: null }
|
||||
|
||||
</SafeAreaView>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
mt84: {
|
||||
marginTop: 84,
|
||||
},
|
||||
horizontalLine: {
|
||||
backgroundColor: COLORS.BORDER.PRIMARY,
|
||||
width: '38%',
|
||||
height: 0.5,
|
||||
},
|
||||
googleButton: {
|
||||
paddingBottom: 5,
|
||||
paddingTop: 5,
|
||||
},
|
||||
container: {
|
||||
padding: 32,
|
||||
},
|
||||
headingStyles: {
|
||||
fontWeight: '600'
|
||||
}
|
||||
});
|
||||
|
||||
export default Login;
|
||||
|
||||
@@ -22,12 +22,17 @@ class CosmosForegroundService {
|
||||
if (!ForegroundService.is_running()) {
|
||||
await ForegroundService.start({
|
||||
id: FOREGROUND_SERVICE_ID,
|
||||
title: 'Cosmos app',
|
||||
message: 'Cosmos Service is running',
|
||||
title: 'Tap to open Cosmos',
|
||||
message: '',
|
||||
icon: 'ic_launcher',
|
||||
color: '#000000',
|
||||
// @ts-ignore
|
||||
setOnlyAlertOnce: true,
|
||||
setOnlyAlertOnce: false,
|
||||
priority: 'low',
|
||||
visibility: 'hidden',
|
||||
importance: 'low',
|
||||
sound: null,
|
||||
vibrate: null,
|
||||
});
|
||||
}
|
||||
const { task, ...rest } = currentTask;
|
||||
|
||||
14
yarn.lock
14
yarn.lock
@@ -4183,6 +4183,11 @@ fake-xml-http-request@^2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.1.2.tgz#f1786720cae50bbb46273035a0173414f3e85e74"
|
||||
integrity sha512-HaFMBi7r+oEC9iJNpc3bvcW7Z7iLmM26hPDmlb0mFwyANSsOQAtJxbdWsXITKOzZUyMYK0zYCv3h5yDj9TsiXg==
|
||||
|
||||
fast-base64-decode@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418"
|
||||
integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
@@ -5994,7 +5999,7 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
lint-staged@^13.2.1:
|
||||
lint-staged@13.2.1:
|
||||
version "13.2.1"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.1.tgz#9d30a14e3e42897ef417bc98556fb757f75cae87"
|
||||
integrity sha512-8gfzinVXoPfga5Dz/ZOn8I2GOhf81Wvs+KwbEXQn/oWZAvCVS2PivrXfVbFJc93zD16uC0neS47RXHIjXKYZQw==
|
||||
@@ -7605,6 +7610,13 @@ react-native-geolocation-service@5.3.1:
|
||||
resolved "https://registry.yarnpkg.com/react-native-geolocation-service/-/react-native-geolocation-service-5.3.1.tgz#4ce1017789da6fdfcf7576eb6f59435622af4289"
|
||||
integrity sha512-LTXPtPNmrdhx+yeWG47sAaCgQc3nG1z+HLLHlhK/5YfOgfLcAb9HAkhREPjQKPZOUx8pKZMIpdGFUGfJYtimXQ==
|
||||
|
||||
react-native-get-random-values@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.8.0.tgz#1cb4bd4bd3966a356e59697b8f372999fe97cb16"
|
||||
integrity sha512-H/zghhun0T+UIJLmig3+ZuBCvF66rdbiWUfRSNS6kv5oDSpa1ZiVyvRWtuPesQpT8dXj+Bv7WJRQOUP+5TB1sA==
|
||||
dependencies:
|
||||
fast-base64-decode "^1.0.0"
|
||||
|
||||
react-native-gradle-plugin@^0.70.3:
|
||||
version "0.70.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8"
|
||||
|
||||
Reference in New Issue
Block a user