Merge pull request #16 from medici/case-details-fixes
Case details and call sheet fixes
This commit is contained in:
@@ -1,18 +1,14 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Alert,
|
||||
RefreshControl,
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import BackArrowIcon from '../../../RN-UI-LIB/src/Icons/BackArrowIcon';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {goBack, navigateToScreen} from '../../components/utlis/navigationUtlis';
|
||||
import {useAppDispatch, useAppSelector} from '../../hooks';
|
||||
import {useAppSelector} from '../../hooks';
|
||||
import CaseDetailsHeader from './CaseDetailsHeader';
|
||||
import TaskStepper from './journeyStepper/TaskStepper';
|
||||
import UserDetailsSection from './UserDetailsSection';
|
||||
|
||||
@@ -36,7 +32,7 @@ const CaseDetails: React.FC<ICaseDetails> = props => {
|
||||
} = props;
|
||||
|
||||
const [refreshing, setRefreshing] = React.useState(false);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const detailObject = useAppSelector(
|
||||
state => state.allCases.caseDetails[caseId],
|
||||
);
|
||||
@@ -56,35 +52,10 @@ const CaseDetails: React.FC<ICaseDetails> = props => {
|
||||
onRefresh={onRefresh}
|
||||
/>
|
||||
}>
|
||||
<View
|
||||
style={[
|
||||
styles.navigationContainer,
|
||||
GenericStyles.row,
|
||||
GenericStyles.alignCenter,
|
||||
GenericStyles.p16,
|
||||
]}>
|
||||
<BackArrowIcon onPress={goBack} />
|
||||
</View>
|
||||
<CaseDetailsHeader />
|
||||
<View style={GenericStyles.p16}>
|
||||
<UserDetailsSection caseDetail={detailObject} />
|
||||
<TaskStepper caseDetail={detailObject} />
|
||||
{/* <Button
|
||||
style={{}}
|
||||
title="Trigger journey"
|
||||
variant="secondary"
|
||||
onPress={() => Alert.alert("Confirm" , 'Are you sure you want to logout?', [
|
||||
{
|
||||
text: 'Cancle',
|
||||
onPress: (value?: string) => console.log(value),
|
||||
style: 'default'
|
||||
},
|
||||
{
|
||||
text: 'Logout',
|
||||
onPress: (value?: string) => console.log(value),
|
||||
style: 'cancel'
|
||||
},
|
||||
])}
|
||||
/> */}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
|
||||
42
src/screens/caseDetails/CaseDetailsHeader.tsx
Normal file
42
src/screens/caseDetails/CaseDetailsHeader.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import {Pressable, StyleSheet, View} from 'react-native';
|
||||
import React from 'react';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import {navigateToScreen} from '../../components/utlis/navigationUtlis';
|
||||
import ArrowBackSmallIcon from '../../../RN-UI-LIB/src/Icons/ArrowBackSmallIcon';
|
||||
|
||||
const CaseDetailsHeader = () => {
|
||||
const handleBackIconPress = () => {
|
||||
navigateToScreen('Home');
|
||||
};
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.row,
|
||||
GenericStyles.alignCenter,
|
||||
styles.header,
|
||||
]}>
|
||||
<Pressable onPress={handleBackIconPress}>
|
||||
<ArrowBackSmallIcon />
|
||||
</Pressable>
|
||||
<Heading type="h5" style={styles.headerLabel}>
|
||||
Customer details
|
||||
</Heading>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default CaseDetailsHeader;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
header: {
|
||||
backgroundColor: COLORS.BACKGROUND.HEADER,
|
||||
height: 56,
|
||||
paddingLeft: 26,
|
||||
},
|
||||
headerLabel: {
|
||||
color: COLORS.BACKGROUND.PRIMARY,
|
||||
marginLeft: 16,
|
||||
},
|
||||
});
|
||||
@@ -1,22 +1,27 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import React, {useCallback, useState} from 'react';
|
||||
import {
|
||||
Image, Modal,
|
||||
Image,
|
||||
Modal,
|
||||
Pressable,
|
||||
SafeAreaView,
|
||||
StyleSheet,
|
||||
View
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Avatar from '../../../RN-UI-LIB/src/components/Avatar';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import CloseIcon from '../../../RN-UI-LIB/src/Icons/CloseIcon';
|
||||
import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
|
||||
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import { dateFormat } from '../../../RN-UI-LIB/src/utlis/dates';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import {dateFormat} from '../../../RN-UI-LIB/src/utlis/dates';
|
||||
import CalenderIcon from '../../assets/icons/CalenderIcon';
|
||||
import DocumentIcon from '../../assets/icons/DocumentIcon';
|
||||
import IconLabel from '../../common/IconLabel';
|
||||
import { CaseDetail, LoanAccountStatusUIMapping, LoanTypeUIMapping } from './interface';
|
||||
import {
|
||||
CaseDetail,
|
||||
LoanAccountStatusUIMapping,
|
||||
LoanTypeUIMapping,
|
||||
} from './interface';
|
||||
|
||||
interface IUserDetailsSection {
|
||||
caseDetail: CaseDetail;
|
||||
@@ -25,8 +30,14 @@ interface IUserDetailsSection {
|
||||
const UserDetailsSection: React.FC<IUserDetailsSection> = props => {
|
||||
const {caseDetail} = props;
|
||||
const {customerInfo, loanDetails} = caseDetail;
|
||||
const disbursalDate = dateFormat(new Date(loanDetails.disbursalDate), "DD MMM, YYYY");
|
||||
const allocationDate = dateFormat(new Date(caseDetail.allocatedAt), "DD MMM, YYYY");
|
||||
const disbursalDate = dateFormat(
|
||||
new Date(loanDetails.disbursalDate),
|
||||
'DD MMM, YYYY',
|
||||
);
|
||||
const allocationDate = dateFormat(
|
||||
new Date(caseDetail.allocatedAt),
|
||||
'DD MMM, YYYY',
|
||||
);
|
||||
|
||||
const [openImage, setOpenImage] = useState<boolean>(false);
|
||||
|
||||
@@ -36,36 +47,37 @@ const UserDetailsSection: React.FC<IUserDetailsSection> = props => {
|
||||
|
||||
return (
|
||||
<View style={[GenericStyles.row, GenericStyles.pb16, styles.container]}>
|
||||
<View style={[styles.avatarContainer]}>
|
||||
<Pressable onPress={handleOpenClose}>
|
||||
<Avatar
|
||||
size={60}
|
||||
name={customerInfo.customerName}
|
||||
dataURI={customerInfo.imageURL}
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
<Pressable onPress={handleOpenClose}>
|
||||
<Avatar
|
||||
size={64}
|
||||
name={customerInfo.customerName}
|
||||
dataURI={customerInfo.imageURL}
|
||||
/>
|
||||
</Pressable>
|
||||
<View style={[styles.infoContainer]}>
|
||||
<Heading dark type="h4">
|
||||
<Heading dark type="h3">
|
||||
{customerInfo.customerName}
|
||||
</Heading>
|
||||
<View style={[GenericStyles.row, GenericStyles.mb8]}>
|
||||
<View style={[GenericStyles.row, GenericStyles.mb8, GenericStyles.mt4]}>
|
||||
<IconLabel
|
||||
icon={<DocumentIcon />}
|
||||
text={LoanTypeUIMapping[loanDetails.loanType]}
|
||||
/>
|
||||
<IconLabel
|
||||
containerStyle={GenericStyles.ml10}
|
||||
text={LoanAccountStatusUIMapping[loanDetails.loanAccountStatus]}
|
||||
text={
|
||||
LoanAccountStatusUIMapping[
|
||||
loanDetails.loanAccountStatus
|
||||
]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View style={[GenericStyles.row, GenericStyles.mb8]}>
|
||||
<IconLabel icon={<CalenderIcon />} text={disbursalDate} />
|
||||
<IconLabel
|
||||
icon={<CalenderIcon />}
|
||||
text={disbursalDate}
|
||||
/>
|
||||
<IconLabel
|
||||
text={`${loanDetails.tenureMonths} ${loanDetails.tenureMonths > 1 ? "Months" : "Month"}`}
|
||||
text={`${loanDetails.tenureMonths} ${
|
||||
loanDetails.tenureMonths > 1 ? 'Months' : 'Month'
|
||||
}`}
|
||||
containerStyle={GenericStyles.ml10}
|
||||
/>
|
||||
</View>
|
||||
@@ -75,7 +87,10 @@ const UserDetailsSection: React.FC<IUserDetailsSection> = props => {
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Modal animationType={'slide'} visible={openImage} onRequestClose={handleOpenClose}>
|
||||
<Modal
|
||||
animationType={'slide'}
|
||||
visible={openImage}
|
||||
onRequestClose={handleOpenClose}>
|
||||
<SafeAreaView
|
||||
style={[
|
||||
GenericStyles.fill,
|
||||
@@ -90,13 +105,10 @@ const UserDetailsSection: React.FC<IUserDetailsSection> = props => {
|
||||
style={[
|
||||
GenericStyles.fill,
|
||||
GenericStyles.alignCenter,
|
||||
GenericStyles.row
|
||||
GenericStyles.row,
|
||||
]}>
|
||||
<Image
|
||||
style={[
|
||||
GenericStyles.fill,
|
||||
styles.imageStyle,
|
||||
]}
|
||||
style={[GenericStyles.fill, styles.imageStyle]}
|
||||
source={{uri: customerInfo.imageURL}}
|
||||
resizeMode={'contain'}
|
||||
/>
|
||||
@@ -108,24 +120,19 @@ const UserDetailsSection: React.FC<IUserDetailsSection> = props => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
avatarContainer: {
|
||||
height: 60,
|
||||
width: 60,
|
||||
flex: 0.2,
|
||||
},
|
||||
container: {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: COLORS.BORDER.PRIMARY,
|
||||
},
|
||||
infoContainer: {
|
||||
flex: 0.6,
|
||||
marginLeft: 16,
|
||||
},
|
||||
imageStyle:{
|
||||
height: 300
|
||||
imageStyle: {
|
||||
height: 300,
|
||||
},
|
||||
backgroundColor: {
|
||||
backgroundColor: COLORS.BACKGROUND.HEADER,
|
||||
},
|
||||
backgroundColor:{
|
||||
backgroundColor: COLORS.BACKGROUND.HEADER
|
||||
}
|
||||
});
|
||||
|
||||
export default UserDetailsSection;
|
||||
|
||||
@@ -47,7 +47,7 @@ const PhoneNumberSelectionBottomSheet: React.FC<
|
||||
styles.bottomSheetHeader,
|
||||
]}>
|
||||
<Heading dark type="h5">
|
||||
Customer's Number
|
||||
Customer's numbers
|
||||
</Heading>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
@@ -82,6 +82,7 @@ const PhoneNumberSelectionBottomSheet: React.FC<
|
||||
setShowPhoneNumberBottomSheet(prev => !prev);
|
||||
setShowCallingBottomSheet(prev => !prev);
|
||||
}}
|
||||
disabled={!selectedPhoneNumber}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {Linking, View} from 'react-native';
|
||||
import {Linking, StyleSheet, View} from 'react-native';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import Button from '../../../../RN-UI-LIB/src/components/Button';
|
||||
import React from 'react';
|
||||
import MapPinIcon from '../../../../RN-UI-LIB/src/Icons/MapPinIcon';
|
||||
|
||||
const TaskContent = ({
|
||||
address,
|
||||
@@ -24,16 +25,27 @@ const TaskContent = ({
|
||||
<View style={[GenericStyles.row]}>
|
||||
{geolocationUrl && (
|
||||
<Button
|
||||
style={{marginRight: 10}}
|
||||
style={styles.geolocationBtn}
|
||||
variant="secondary"
|
||||
onPress={openGeolocation}
|
||||
title="Open in maps"
|
||||
title="Open map"
|
||||
leftIcon={<MapPinIcon />}
|
||||
/>
|
||||
)}
|
||||
<Button title="Add Feedback" />
|
||||
<Button title="Add feedback" style={styles.feedbackBtn} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
geolocationBtn: {
|
||||
width: 124,
|
||||
marginRight: 10,
|
||||
},
|
||||
feedbackBtn: {
|
||||
width: 150,
|
||||
},
|
||||
});
|
||||
|
||||
export default TaskContent;
|
||||
|
||||
@@ -10,6 +10,7 @@ import PhoneNumberSelectionBottomSheet from './PhoneNumberSelectionBottomSheet';
|
||||
import TaskContent from './TaskContent';
|
||||
import StepperHeader, {STEPPER_STATE} from './StepperHeader';
|
||||
import { navigateToScreen } from '../../../components/utlis/navigationUtlis';
|
||||
import Heading from '../../../../RN-UI-LIB/src/components/Heading';
|
||||
|
||||
interface IStepperContent {
|
||||
content?: React.ReactNode;
|
||||
@@ -35,16 +36,26 @@ const TaskStepper: React.FC<ITaskStepper> = porps => {
|
||||
React.useState(false);
|
||||
const [showCallingBottomSheet, setShowCallingBottomSheet] =
|
||||
React.useState(false);
|
||||
const {tasks, context, mobileNumbers} = useSelector((state: RootState) => ({
|
||||
const {tasks, context, mobileNumbers = []} = useSelector((state: RootState) => ({
|
||||
mobileNumbers: state.case.customerInfo.mobileNumbers,
|
||||
tasks: state.case.tasks,
|
||||
context: state.case.context,
|
||||
}));
|
||||
const [selectedPhoneNumber, setSelectedPhoneNumber] = React.useState('');
|
||||
|
||||
const handleCustomerCall = () => {
|
||||
if(mobileNumbers?.length > 0) {
|
||||
setShowPhoneNumberBottomSheet(true)
|
||||
return;
|
||||
}
|
||||
setSelectedPhoneNumber(mobileNumbers[0]);
|
||||
setShowCallingBottomSheet(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<View style={[GenericStyles.p16]}>
|
||||
<Heading type='h3' style={styles.header} dark bold>Addresses</Heading>
|
||||
{tasks.map((task, index) => {
|
||||
const verdict =
|
||||
// @ts-ignore
|
||||
@@ -107,9 +118,9 @@ const TaskStepper: React.FC<ITaskStepper> = porps => {
|
||||
<View style={[GenericStyles.row, styles.journeyContainer]}>
|
||||
<Button
|
||||
style={[styles.callCustomerButton]}
|
||||
title="Call Customer"
|
||||
title="Call customer"
|
||||
variant="secondary"
|
||||
onPress={() => setShowPhoneNumberBottomSheet(true)}
|
||||
onPress={handleCustomerCall}
|
||||
/>
|
||||
</View>
|
||||
<PhoneNumberSelectionBottomSheet
|
||||
@@ -130,9 +141,13 @@ const TaskStepper: React.FC<ITaskStepper> = porps => {
|
||||
};
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
header: {
|
||||
marginBottom: 18
|
||||
},
|
||||
journeyContainer: {
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: COLORS.BORDER.PRIMARY,
|
||||
borderStyle: 'dashed'
|
||||
},
|
||||
stepperCurrent: {
|
||||
height: PixelRatio.roundToNearestPixel(32),
|
||||
@@ -184,13 +199,10 @@ export const styles = StyleSheet.create({
|
||||
paddingLeft: 28.5,
|
||||
},
|
||||
bottomSheetHeader: {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: COLORS.BORDER.PRIMARY,
|
||||
paddingBottom: 20,
|
||||
},
|
||||
phoneNumberSelectionSection: {
|
||||
paddingBottom: 30,
|
||||
// height: 170,
|
||||
},
|
||||
bottomSheetButton: {
|
||||
position: 'absolute',
|
||||
|
||||
Reference in New Issue
Block a user