merged todo list and feedback form working state
This commit is contained in:
@@ -16,6 +16,7 @@ import OtpInput from './src/screens/login/OtpInput';
|
||||
import TodoList from './src/screens/todoList/TodoList';
|
||||
import { RootState } from './src/store/store';
|
||||
import Profile from './src/screens/Profile';
|
||||
import interactionsHandler from './src/screens/caseDetails/interactionsHandler';
|
||||
|
||||
const Stack = createNativeStackNavigator();
|
||||
|
||||
@@ -28,7 +29,7 @@ const ProtectedRouter = () => {
|
||||
|
||||
// for setting user token in global.ts for api calling's
|
||||
setGlobalUserData(sessionDetails?.sessionToken);
|
||||
|
||||
const d = interactionsHandler()
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
if (!deviceId) {
|
||||
@@ -68,6 +69,7 @@ const ProtectedRouter = () => {
|
||||
component={Widget}
|
||||
options={{
|
||||
header: () => null,
|
||||
animation: 'slide_from_right'
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
Submodule RN-UI-LIB updated: ba5a756af9...a6ebb5280b
@@ -1,5 +1,5 @@
|
||||
import axiosInstance, {ApiKeys, getApiUrl} from '../components/utlis/apiHelper';
|
||||
import { navigateToScreen } from '../components/utlis/navigationUtlis';
|
||||
import {navigateToScreen} from '../components/utlis/navigationUtlis';
|
||||
import {
|
||||
resetTodoList,
|
||||
setCasesListData,
|
||||
@@ -52,3 +52,17 @@ export const postPinnedList =
|
||||
dispatch(setTodoListOffline(updatedCaseList));
|
||||
});
|
||||
};
|
||||
|
||||
export const syncCaseDetail = (data: any) => (dispatch: AppDispatch) => {
|
||||
const url = getApiUrl(ApiKeys.FEEDBACK);
|
||||
|
||||
console.log(data);
|
||||
axiosInstance
|
||||
.post(url, {
|
||||
id: data.id,
|
||||
...data,
|
||||
})
|
||||
.then(res => console.log(res.data))
|
||||
.catch(err => console.log(err, 'error'));
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ const IconLabel: React.FC<IconLabelProps> = props => {
|
||||
<View style={[styles.icon, iconStyle]}>
|
||||
{icon ? icon : <BulletIcon />}
|
||||
</View>
|
||||
<Text style={textStyle}>{text}</Text>
|
||||
<Text light style={textStyle}>{text}</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import React, {useEffect} from 'react';
|
||||
import {View} from 'react-native';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Control, Controller } from 'react-hook-form';
|
||||
import { useSelector } from 'react-redux';
|
||||
import RNDropDown from '../../../../RN-UI-LIB/src/components/dropdown/Dropdown';
|
||||
import RNOptions from '../../../../RN-UI-LIB/src/components/dropdown/Options';
|
||||
import {useState} from 'react';
|
||||
import {Control, Controller} from 'react-hook-form';
|
||||
import {useSelector} from 'react-redux';
|
||||
import RNCheckboxGroup from '../../../../RN-UI-LIB/src/components/chechbox/CheckboxGroup';
|
||||
import {ICheckboxOption} from '../../../../RN-UI-LIB/src/components/chechbox/types';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import { GenericStyles } from '../../../../RN-UI-LIB/src/styles';
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import { RootState } from '../../../store/store';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import {RootState} from '../../../store/store';
|
||||
import {AnswerType} from '../interface';
|
||||
import QuestionRenderingEngine from '../QuestionRenderingEngine';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import RNCheckboxGroup from '../../../../RN-UI-LIB/src/components/chechbox/CheckboxGroup';
|
||||
import { ICheckboxOption } from '../../../../RN-UI-LIB/src/components/chechbox/types';
|
||||
import { AnswerType } from '../interface';
|
||||
import {useAppSelector } from '../../../hooks';
|
||||
|
||||
interface ICheckBoxGroup {
|
||||
questionType: string;
|
||||
@@ -29,6 +27,7 @@ interface ICheckBoxGroup {
|
||||
|
||||
const CheckBoxGroup: React.FC<ICheckBoxGroup> = props => {
|
||||
const {questionId, widgetId, journeyId, caseId, sectionId, error} = props;
|
||||
const template = useAppSelector(state => state.case.templateData)
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
const options = template.options;
|
||||
@@ -38,9 +37,7 @@ const CheckBoxGroup: React.FC<ICheckBoxGroup> = props => {
|
||||
|
||||
const dataFromRedux = useSelector(
|
||||
(state: RootState) =>
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.[widgetId]?.[
|
||||
sectionId
|
||||
]?.[questionId],
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.widgetContext?.[widgetId]?.sectionContext?.[sectionId]?.questionContext?.[questionId]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -50,7 +47,6 @@ const CheckBoxGroup: React.FC<ICheckBoxGroup> = props => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dataFromRedux]);
|
||||
|
||||
|
||||
const computeNextQuestion = (optionId: keyof typeof options) => {
|
||||
if (options[optionId]?.associateQuestions.length < 1) {
|
||||
setAssociatedQuestions([]);
|
||||
@@ -59,38 +55,52 @@ const CheckBoxGroup: React.FC<ICheckBoxGroup> = props => {
|
||||
setAssociatedQuestions(options[optionId]?.associateQuestions);
|
||||
};
|
||||
|
||||
const optiosList = question.options.map(option =>({label: options[option].text, value: option}));
|
||||
const optiosList = question.options.map((option: any) => ({
|
||||
label: options[option].text,
|
||||
value: option,
|
||||
}));
|
||||
|
||||
const handleChange = (change : Array<ICheckboxOption> | null, onChange : (...event: any[]) => void) => {
|
||||
const values = change?.map(item=>item.value)
|
||||
const handleChange = (
|
||||
change: Array<ICheckboxOption> | null,
|
||||
onChange: (...event: any[]) => void,
|
||||
) => {
|
||||
const values = change?.map(item => item.value);
|
||||
onChange({
|
||||
answer: values,
|
||||
type: AnswerType.array
|
||||
})
|
||||
}
|
||||
type: AnswerType.array,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={GenericStyles.mt12}>
|
||||
{question.text ?<Text dark bold>
|
||||
{question.text}{' '}
|
||||
{question.type === 'mandatory' && (
|
||||
<Text style={GenericStyles.redText}>*</Text>
|
||||
)}
|
||||
</Text>: null}
|
||||
{question.text ? (
|
||||
<Text dark bold>
|
||||
{question.text}{' '}
|
||||
{question.type === 'mandatory' && (
|
||||
<Text style={GenericStyles.redText}>*</Text>
|
||||
)}
|
||||
</Text>
|
||||
) : null}
|
||||
<Controller
|
||||
control={props.control}
|
||||
rules={{
|
||||
required: question.type === 'mandatory',
|
||||
}}
|
||||
render={({field: {onChange, value}}) => {
|
||||
console.log(value)
|
||||
return(
|
||||
<RNCheckboxGroup onSelectionChange={(change => handleChange(change, onChange))} defaultValue={value?.answer} options={optiosList} />
|
||||
)
|
||||
console.log(value);
|
||||
return (
|
||||
<RNCheckboxGroup
|
||||
onSelectionChange={change =>
|
||||
handleChange(change, onChange)
|
||||
}
|
||||
defaultValue={value?.answer}
|
||||
options={optiosList}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
name={`${sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
<ErrorMessage show={error?.sectionContext?.[sectionId]?.questionContext?.[questionId]} />
|
||||
{associatedQuestions?.map((nextQuestion: string, index) => {
|
||||
if (
|
||||
template.questions[
|
||||
|
||||
@@ -8,11 +8,11 @@ import RNDropDown from '../../../../RN-UI-LIB/src/components/dropdown/Dropdown';
|
||||
import RNOptions from '../../../../RN-UI-LIB/src/components/dropdown/Options';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import {RootState} from '../../../store/store';
|
||||
import QuestionRenderingEngine from '../QuestionRenderingEngine';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import {AnswerType} from '../interface';
|
||||
import {AnswerType, Options} from '../interface';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
|
||||
interface IDropDown {
|
||||
questionType: string;
|
||||
@@ -27,6 +27,7 @@ interface IDropDown {
|
||||
|
||||
const DropDown: React.FC<IDropDown> = props => {
|
||||
const {questionId, widgetId, journeyId, caseId, sectionId, error} = props;
|
||||
const template = useAppSelector(state => state.case.templateData);
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
const options = template.options;
|
||||
@@ -36,9 +37,7 @@ const DropDown: React.FC<IDropDown> = props => {
|
||||
|
||||
const dataFromRedux = useSelector(
|
||||
(state: RootState) =>
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.[widgetId]?.[
|
||||
sectionId
|
||||
]?.[questionId],
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.widgetContext?.[widgetId]?.sectionContext?.[sectionId]?.questionContext?.[questionId]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -48,27 +47,6 @@ const DropDown: React.FC<IDropDown> = props => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dataFromRedux]);
|
||||
|
||||
// const dispatch = useDispatch();
|
||||
// const answer = useSelector(
|
||||
// (state: RootState) =>
|
||||
// state.counter.caseForm?.[caseId]?.[journeyId]?.[widgetId]?.[
|
||||
// sectionId
|
||||
// ]?.[questionId] || 'not_found',
|
||||
// );
|
||||
|
||||
// const registerValue = (id: string) => {
|
||||
// dispatch(
|
||||
// updateInteraction({
|
||||
// caseId,
|
||||
// journeyId,
|
||||
// widgetId,
|
||||
// questionId,
|
||||
// answer: id,
|
||||
// sectionId,
|
||||
// }),
|
||||
// );
|
||||
// };
|
||||
|
||||
const computeNextQuestion = (optionId: keyof typeof options) => {
|
||||
if (options[optionId]?.associateQuestions.length < 1) {
|
||||
setAssociatedQuestions([]);
|
||||
@@ -105,22 +83,21 @@ const DropDown: React.FC<IDropDown> = props => {
|
||||
bottomSheetHeight={question.options.length - 1 * 10}
|
||||
onValueChange={change => handleChange(change, onChange)}
|
||||
value={value?.answer}>
|
||||
{question.options.map(option => {
|
||||
{question.options.map((option: keyof typeof options) => {
|
||||
return (
|
||||
<RNOptions
|
||||
id={option}
|
||||
id={option as string}
|
||||
label={
|
||||
options[option as keyof typeof options]
|
||||
?.text
|
||||
options[option]?.text
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</RNDropDown>
|
||||
)}
|
||||
name={`${sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
<ErrorMessage show={error?.sectionContext?.[sectionId]?.questionContext?.[questionId]} />
|
||||
{associatedQuestions?.map((nextQuestion: string, index) => {
|
||||
if (
|
||||
template.questions[
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Control, Controller } from 'react-hook-form';
|
||||
import {
|
||||
Image,
|
||||
ImageBackground,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View,
|
||||
View
|
||||
} from 'react-native';
|
||||
import React, {useEffect} from 'react';
|
||||
import {Control, Controller} from 'react-hook-form';
|
||||
import CameraClickPicture from '../../../../RN-UI-LIB/src/components/camera_click_picture/CameraClickPicture';
|
||||
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import {useState} from 'react';
|
||||
import {useSelector} from 'react-redux';
|
||||
import {RootState} from '../../../store/store';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import DeleteIcon from '../../../../RN-UI-LIB/src/Icons/DeleteIcon';
|
||||
import {COLORS} from '../../../../RN-UI-LIB/src/styles/colors';
|
||||
import { useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import DeleteIcon from '../../../../RN-UI-LIB/src/Icons/DeleteIcon';
|
||||
import { GenericStyles } from '../../../../RN-UI-LIB/src/styles';
|
||||
import { COLORS } from '../../../../RN-UI-LIB/src/styles/colors';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
import { RootState } from '../../../store/store';
|
||||
import { AnswerType } from '../interface';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
|
||||
interface IImageUpload {
|
||||
questionType: string;
|
||||
@@ -34,13 +33,12 @@ interface IImageUpload {
|
||||
const ImageUpload: React.FC<IImageUpload> = props => {
|
||||
const {questionId, error, sectionId, caseId, journeyId, widgetId} = props;
|
||||
const [image, setImage] = useState('');
|
||||
const template = useAppSelector(state => state.case.templateData);
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
const dataFromRedux = useSelector(
|
||||
(state: RootState) =>
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.[widgetId]?.[
|
||||
sectionId
|
||||
]?.[questionId],
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.widgetContext?.[widgetId]?.sectionContext?.[sectionId]?.questionContext?.[questionId]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -84,7 +82,7 @@ const ImageUpload: React.FC<IImageUpload> = props => {
|
||||
onPictureClickSuccess={clickedImage => handleChange(clickedImage, onChange)}
|
||||
/>
|
||||
)}
|
||||
name={`${props.sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
) : (
|
||||
<View>
|
||||
@@ -97,7 +95,7 @@ const ImageUpload: React.FC<IImageUpload> = props => {
|
||||
</ImageBackground>
|
||||
</View>
|
||||
)}
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
<ErrorMessage show={error?.sectionContext?.[sectionId]?.questionContext?.[questionId]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,11 +9,11 @@ import RadioChip from '../../../../RN-UI-LIB/src/components/radio_button/RadioCh
|
||||
import RadioGroup from '../../../../RN-UI-LIB/src/components/radio_button/RadioGroup';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import {RootState} from '../../../store/store';
|
||||
import QuestionRenderingEngine from '../QuestionRenderingEngine';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import { AnswerType } from '../interface';
|
||||
import {AnswerType} from '../interface';
|
||||
import {useAppSelector} from '../../../hooks';
|
||||
|
||||
interface IRadioButton {
|
||||
questionType: string;
|
||||
@@ -28,8 +28,8 @@ interface IRadioButton {
|
||||
|
||||
const RadioButton: React.FC<IRadioButton> = props => {
|
||||
const {questionId, widgetId, journeyId, caseId, sectionId, error} = props;
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
const template = useAppSelector(state => state.case.templateData);
|
||||
const question = template.questions[questionId];
|
||||
const options = template.options;
|
||||
const [associatedQuestions, setAssociatedQuestions] = useState<
|
||||
Array<string>
|
||||
@@ -37,9 +37,9 @@ const RadioButton: React.FC<IRadioButton> = props => {
|
||||
|
||||
const dataFromRedux = useSelector(
|
||||
(state: RootState) =>
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.[widgetId]?.[
|
||||
sectionId
|
||||
]?.[questionId],
|
||||
state.case.caseForm?.[caseId]?.[journeyId]?.widgetContext?.[
|
||||
widgetId
|
||||
]?.sectionContext?.[sectionId]?.questionContext?.[questionId],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -49,27 +49,6 @@ const RadioButton: React.FC<IRadioButton> = props => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [dataFromRedux]);
|
||||
|
||||
// const dispatch = useDispatch();
|
||||
// const answer = useSelector(
|
||||
// (state: RootState) =>
|
||||
// state.counter.caseForm?.[caseId]?.[journeyId]?.[widgetId]?.[
|
||||
// sectionId
|
||||
// ]?.[questionId] || 'not_found',
|
||||
// );
|
||||
|
||||
// const registerValue = (id: string) => {
|
||||
// dispatch(
|
||||
// updateInteraction({
|
||||
// caseId,
|
||||
// journeyId,
|
||||
// widgetId,
|
||||
// questionId,
|
||||
// answer: id,
|
||||
// sectionId,
|
||||
// }),
|
||||
// );
|
||||
// };
|
||||
|
||||
const computeNextQuestion = (optionId: keyof typeof options) => {
|
||||
if (options[optionId]?.associateQuestions.length < 1) {
|
||||
setAssociatedQuestions([]);
|
||||
@@ -78,16 +57,16 @@ const RadioButton: React.FC<IRadioButton> = props => {
|
||||
setAssociatedQuestions(options[optionId]?.associateQuestions);
|
||||
};
|
||||
|
||||
|
||||
const handleChange = (change : string | null, onChange : (...event: any[]) => void) => {
|
||||
const handleChange = (
|
||||
change: string | null,
|
||||
onChange: (...event: any[]) => void,
|
||||
) => {
|
||||
computeNextQuestion(change as keyof typeof options);
|
||||
onChange({
|
||||
answer: change,
|
||||
type: AnswerType.option
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
type: AnswerType.option,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={GenericStyles.mt12}>
|
||||
@@ -110,32 +89,35 @@ const RadioButton: React.FC<IRadioButton> = props => {
|
||||
question.metadata.orientation || 'verticle'
|
||||
}>
|
||||
{question?.metadata.buttonType === 'button'
|
||||
? question.options.map(option => {
|
||||
return(
|
||||
<RNRadioButton
|
||||
id={option}
|
||||
value={
|
||||
options[
|
||||
option as keyof typeof options
|
||||
]?.text
|
||||
}
|
||||
/>
|
||||
)})
|
||||
: question.options.map(option => (
|
||||
? question.options.map((option: keyof typeof options) => {
|
||||
return (
|
||||
<RNRadioButton
|
||||
id={option as string}
|
||||
value={
|
||||
options[option]?.text
|
||||
}
|
||||
/>
|
||||
);
|
||||
})
|
||||
: question.options.map((option: keyof typeof options) => (
|
||||
<RadioChip
|
||||
id={option}
|
||||
id={option as string}
|
||||
value={
|
||||
options[
|
||||
option as keyof typeof options
|
||||
]?.text
|
||||
options[option]?.text
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
)}
|
||||
name={`${sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
<ErrorMessage
|
||||
show={
|
||||
error?.widgetContext?.[widgetId]?.sectionContext?.[
|
||||
sectionId
|
||||
]?.questionContext?.[questionId]
|
||||
}
|
||||
/>
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
{associatedQuestions?.map((nextQuestion: string, index) => {
|
||||
if (
|
||||
template.questions[
|
||||
@@ -148,7 +130,7 @@ const RadioButton: React.FC<IRadioButton> = props => {
|
||||
questionType={
|
||||
template.questions[
|
||||
nextQuestion as keyof typeof template.questions
|
||||
].input_type
|
||||
].inputType
|
||||
}
|
||||
questionId={nextQuestion}
|
||||
name={widgetId}
|
||||
|
||||
@@ -3,10 +3,10 @@ import React from 'react';
|
||||
import {Control, Controller} from 'react-hook-form';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import StarRating from '../../../../RN-UI-LIB/src/components/star_rating/StarRating';
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import { AnswerType } from '../interface';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
interface IRating {
|
||||
questionType: string;
|
||||
questionId: string;
|
||||
@@ -19,8 +19,8 @@ interface IRating {
|
||||
}
|
||||
|
||||
const Rating: React.FC<IRating> = props => {
|
||||
const {questionId, error, sectionId} = props;
|
||||
|
||||
const {questionId, error, sectionId, widgetId} = props;
|
||||
const template = useAppSelector(state => state.case.templateData);
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
if (!question) {
|
||||
@@ -55,9 +55,9 @@ const Rating: React.FC<IRating> = props => {
|
||||
maxRating={5}
|
||||
/>
|
||||
)}
|
||||
name={`${props.sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
<ErrorMessage show={error?.sectionContext?.[sectionId]?.questionContext?.[questionId]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,12 +2,12 @@ import {View} from 'react-native';
|
||||
import React from 'react';
|
||||
import {Control, Controller} from 'react-hook-form';
|
||||
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import RNTextArea from '../../../../RN-UI-LIB/src/components/TextArea';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import { AnswerType } from '../interface';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
|
||||
interface ITextArea {
|
||||
questionType: string;
|
||||
@@ -21,8 +21,8 @@ interface ITextArea {
|
||||
}
|
||||
|
||||
const TextArea: React.FC<ITextArea> = props => {
|
||||
const {questionId, error, sectionId} = props;
|
||||
|
||||
const {questionId, error, sectionId, widgetId} = props;
|
||||
const template = useAppSelector(state => state.case.templateData);
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
if (!question) {
|
||||
@@ -58,9 +58,9 @@ const TextArea: React.FC<ITextArea> = props => {
|
||||
title=""
|
||||
/>
|
||||
)}
|
||||
name={`${props.sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
<ErrorMessage show={error?.sectionContext?.[sectionId]?.questionContext?.[questionId]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,10 +4,10 @@ import RNTextInput from '../../../../RN-UI-LIB/src/components/TextInput';
|
||||
import {GenericStyles} from '../../../../RN-UI-LIB/src/styles';
|
||||
import {Control, Controller} from 'react-hook-form';
|
||||
|
||||
import template from '../../../data/RealTemplateData.json';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
import ErrorMessage from './ErrorMessage';
|
||||
import { AnswerType } from '../interface';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
|
||||
interface ITextInput {
|
||||
questionType: string;
|
||||
@@ -21,8 +21,8 @@ interface ITextInput {
|
||||
}
|
||||
|
||||
const TextInput: React.FC<ITextInput> = props => {
|
||||
const {questionId, error, sectionId} = props;
|
||||
|
||||
const {questionId, error, sectionId, widgetId} = props;
|
||||
const template = useAppSelector(state => state.case.templateData);
|
||||
const question =
|
||||
template.questions[questionId as keyof typeof template.questions];
|
||||
if (!question) {
|
||||
@@ -56,9 +56,9 @@ const TextInput: React.FC<ITextInput> = props => {
|
||||
containerStyle={[GenericStyles.mt12]}
|
||||
/>
|
||||
)}
|
||||
name={`${props.sectionId}.${questionId}`}
|
||||
name={`widgetContext.${widgetId}.sectionContext.${props.sectionId}.questionContext.${questionId}`}
|
||||
/>
|
||||
<ErrorMessage show={error?.[sectionId]?.[questionId]} />
|
||||
<ErrorMessage show={error?.widgetContext?.[widgetId]?.sectionContext?.[sectionId]?.questionContext?.[questionId]} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Pressable, ScrollView, StyleSheet, View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import React, {useState} from 'react';
|
||||
import {useForm} from 'react-hook-form';
|
||||
import {Pressable, ScrollView, StyleSheet, View} from 'react-native';
|
||||
import {SafeAreaView} from 'react-native-safe-area-context';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
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';
|
||||
import BackArrowIcon from '../../../RN-UI-LIB/src/Icons/BackArrowIcon';
|
||||
import CloseIcon from '../../../RN-UI-LIB/src/Icons/CloseIcon';
|
||||
import { GenericStyles, getShadowStyle } from '../../../RN-UI-LIB/src/styles';
|
||||
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import Realjson from '../../data/RealTemplateData.json';
|
||||
import { updateInteraction } from '../../reducer/caseReducre';
|
||||
import { RootState } from '../../store/store';
|
||||
import { goBack, navigateToScreen } from '../utlis/navigationUtlis';
|
||||
import {
|
||||
ConditionType,
|
||||
IDecision, ILeaf
|
||||
} from './interface';
|
||||
import {GenericStyles, getShadowStyle} from '../../../RN-UI-LIB/src/styles';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import {useAppSelector} from '../../hooks';
|
||||
import { updateCaseDetail } from '../../reducer/allCasesSlice';
|
||||
import {deleteInteraction, updateInteraction} from '../../reducer/caseReducre';
|
||||
import {RootState} from '../../store/store';
|
||||
import {goBack, navigateToScreen} from '../utlis/navigationUtlis';
|
||||
import {ConditionType, IDecision, ILeaf} from './interface';
|
||||
import RenderQuestion from './RenderQuestion';
|
||||
|
||||
interface IWidget {
|
||||
@@ -32,21 +31,25 @@ interface IWidget {
|
||||
const Widget: React.FC<IWidget> = props => {
|
||||
const {name, params} = props.route;
|
||||
const {caseId, journey} = params;
|
||||
const {sections, transitionRules, isLeaf} =
|
||||
Realjson.widget[name as keyof typeof Realjson.widget];
|
||||
const sectionMap = Realjson.sections;
|
||||
const templateData = useAppSelector(state => state.case.templateData);
|
||||
const caseData = useAppSelector(state => state.allCases.caseDetails[caseId]);
|
||||
const {sections, transitionRules, isLeaf} = templateData.widget[name];
|
||||
const sectionMap = templateData.sections;
|
||||
const {actions, conditions} = transitionRules;
|
||||
const [error, setError] = useState();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const dataToBeValidated = useSelector(
|
||||
(state: RootState) => state.case.caseForm?.[caseId]?.[journey]?.[name],
|
||||
const dataToBeValidated = useAppSelector(
|
||||
state => state.case.caseForm?.[caseId]?.[journey],
|
||||
);
|
||||
|
||||
console.log(dataToBeValidated);
|
||||
|
||||
const journeyData = useSelector(
|
||||
(state: RootState) => state.case.caseForm?.[caseId]?.[journey],
|
||||
);
|
||||
|
||||
console.log(journeyData);
|
||||
|
||||
const {control, handleSubmit} = useForm({
|
||||
defaultValues: dataToBeValidated,
|
||||
@@ -55,7 +58,11 @@ const Widget: React.FC<IWidget> = props => {
|
||||
const evaluateLeaf = (leaf: ILeaf, data: any): boolean => {
|
||||
switch (leaf.operator) {
|
||||
case 'MATCHES':
|
||||
return leaf.right === data[leaf.section][leaf.left]?.answer;
|
||||
return (
|
||||
leaf.right ===
|
||||
data?.widgetContext?.[name]?.sectionContext?.[leaf.section]
|
||||
?.questionContext?.[leaf.left]?.answer
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -66,7 +73,9 @@ const Widget: React.FC<IWidget> = props => {
|
||||
case 'MATCHES':
|
||||
return (
|
||||
leaf.right ===
|
||||
journeyData[leaf.widgetId][leaf.section][leaf.left]
|
||||
journeyData.widgetContext[leaf.widgetId]?.sectionContext?.[
|
||||
leaf.section
|
||||
]?.questionContext?.[leaf.left]
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
@@ -114,7 +123,7 @@ const Widget: React.FC<IWidget> = props => {
|
||||
};
|
||||
|
||||
const onSubmit = (data: any) => {
|
||||
console.log(data)
|
||||
console.log(data, 'submit');
|
||||
dispatch(
|
||||
updateInteraction({
|
||||
caseId,
|
||||
@@ -139,16 +148,31 @@ const Widget: React.FC<IWidget> = props => {
|
||||
answer: data,
|
||||
}),
|
||||
);
|
||||
const rules = Realjson.journey[journey].transitionRules.conditions;
|
||||
const screeenAction = Realjson.journey[journey].transitionRules.actions;
|
||||
let nextScreenName = '';
|
||||
const rules =
|
||||
templateData.journey[journey as keyof typeof templateData.journey]
|
||||
.transitionRules.conditions;
|
||||
const screeenAction =
|
||||
templateData.journey[journey as keyof typeof templateData.journey]
|
||||
.transitionRules.actions;
|
||||
let nextActions = '';
|
||||
if (rules.condition_type === 'LEAF_NODE') {
|
||||
nextScreenName = screeenAction[evaluateLeafJourney(rules)];
|
||||
nextActions = screeenAction[String(evaluateLeafJourney(rules as ILeaf))];
|
||||
} else {
|
||||
const answer = String(evaluateComposite(rules));
|
||||
nextScreenName = screeenAction[answer];
|
||||
const answer = String(evaluateComposite(rules as IDecision, data));
|
||||
nextActions = screeenAction[answer];
|
||||
}
|
||||
|
||||
console.log(nextActions);
|
||||
// dispatch some actions to redux store
|
||||
dispatch(updateCaseDetail({
|
||||
caseId,
|
||||
journeyId: journey,
|
||||
widgetId: name,
|
||||
answer: data,
|
||||
caseData: caseData,
|
||||
nextActions
|
||||
}))
|
||||
|
||||
navigateToScreen('Home', {
|
||||
journey: journey,
|
||||
caseId,
|
||||
@@ -185,7 +209,7 @@ const Widget: React.FC<IWidget> = props => {
|
||||
GenericStyles.p16,
|
||||
GenericStyles.whiteBackground,
|
||||
]}>
|
||||
{sections.map((section, index: number) => (
|
||||
{sections.map((section: any, index: number) => (
|
||||
<View
|
||||
key={section + index}
|
||||
style={[
|
||||
@@ -224,7 +248,17 @@ const Widget: React.FC<IWidget> = props => {
|
||||
variant={'secondary'}
|
||||
style={styles.fb45}
|
||||
title={'Back'}
|
||||
onPress={goBack}
|
||||
onPress={() => {
|
||||
dispatch(
|
||||
deleteInteraction({
|
||||
caseId,
|
||||
journeyId: journey,
|
||||
widgetId: name,
|
||||
}),
|
||||
);
|
||||
goBack();
|
||||
}}
|
||||
leftIcon={<BackArrowIcon size={10} />}
|
||||
/>
|
||||
<Button
|
||||
style={styles.fb45}
|
||||
|
||||
@@ -54,7 +54,13 @@ export interface ILeaf {
|
||||
|
||||
export enum AnswerType {
|
||||
text = 'text',
|
||||
option = 'option',
|
||||
number = 'number',
|
||||
array = 'array'
|
||||
option = 'text',
|
||||
number = 'text',
|
||||
array = 'option'
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
text: string;
|
||||
associatedQuestions: Array<string>;
|
||||
metadata: any;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ export enum ApiKeys {
|
||||
ALL_CASES,
|
||||
CASE_DETAIL,
|
||||
PINNED_CASES,
|
||||
LOGOUT
|
||||
LOGOUT,
|
||||
FEEDBACK
|
||||
}
|
||||
|
||||
const API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
|
||||
@@ -29,6 +30,7 @@ API_URLS[ApiKeys.ALL_CASES] = '/cases/all-cases';
|
||||
API_URLS[ApiKeys.CASE_DETAIL] = '/cases/get-cases';
|
||||
API_URLS[ApiKeys.PINNED_CASES] = '/cases/pin';
|
||||
API_URLS[ApiKeys.LOGOUT] = '/auth/logout';
|
||||
API_URLS[ApiKeys.FEEDBACK] = '/cases/feedback';
|
||||
|
||||
const MOCK_API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
|
||||
|
||||
|
||||
@@ -39,8 +39,14 @@
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"true": "verified",
|
||||
"false": "not verified"
|
||||
"true": {
|
||||
"status": "VERIFIED_SUCCESS",
|
||||
"nextJourney": ""
|
||||
},
|
||||
"false":{
|
||||
"status": "VERIFICATION_FAILED",
|
||||
"nextJourney": "PERMANENT_ADDRESS_VERIFICATION_TASK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"isLeaf": false
|
||||
|
||||
@@ -68,7 +68,11 @@ const allCasesSlice = createSlice({
|
||||
if (details?.length) {
|
||||
const initialValue = {...state.caseDetails};
|
||||
const detailsData = details.reduce((prev: any, item: any) => {
|
||||
prev[item.id] = item;
|
||||
prev[item.id] = {
|
||||
...item,
|
||||
isSynced: true,
|
||||
|
||||
};
|
||||
return prev;
|
||||
}, initialValue);
|
||||
state.caseDetails = detailsData;
|
||||
@@ -79,6 +83,58 @@ const allCasesSlice = createSlice({
|
||||
state.pinnedRankCount = maxPinnedRank;
|
||||
state.loading = false;
|
||||
},
|
||||
|
||||
updateCaseDetail: (state, action) => {
|
||||
const {caseId, journeyId, answer, caseData, nextActions} =
|
||||
action.payload;
|
||||
console.log(action.payload);
|
||||
const updatedValue = {...caseData};
|
||||
updatedValue.isSynced = false;
|
||||
if (!updatedValue.context) {
|
||||
updatedValue.context = {
|
||||
taskSequence: updatedValue.tasks.map(task => task.taskType),
|
||||
currentTask: nextActions.nextJourney,
|
||||
taskContext: {
|
||||
[journeyId]: [
|
||||
{
|
||||
taskStatus: nextActions.status,
|
||||
...answer,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (updatedValue.context.taskContext?.[journeyId]) {
|
||||
const journey = [
|
||||
...updatedValue.context.taskContext?.[journeyId],
|
||||
{
|
||||
taskStatus: nextActions.status,
|
||||
...answer,
|
||||
},
|
||||
];
|
||||
updatedValue.context = {
|
||||
currentTask: nextActions.nextJourney,
|
||||
taskContext: {
|
||||
[journeyId]: journey,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const taskContext = updatedValue.taskContext;
|
||||
(taskContext[journeyId] = [
|
||||
{
|
||||
taskStatus: nextActions.status,
|
||||
...answer,
|
||||
},
|
||||
]),
|
||||
(updatedValue.context = {
|
||||
currentTask: nextActions.nextJourney,
|
||||
taskContext,
|
||||
});
|
||||
}
|
||||
state.caseDetails[caseId] = updatedValue;
|
||||
},
|
||||
|
||||
setPinnedRank: (state, action) => {
|
||||
const caseId = action.payload.caseReferenceId;
|
||||
const isCasePresent = state.intermediateTodoListMap[caseId];
|
||||
@@ -157,7 +213,8 @@ export const {
|
||||
proceedToTodoList,
|
||||
deleteIntermediateTodoListItem,
|
||||
setSelectedTodoListMap,
|
||||
resetSelectedTodoList
|
||||
resetSelectedTodoList,
|
||||
updateCaseDetail,
|
||||
} = allCasesSlice.actions;
|
||||
|
||||
export default allCasesSlice.reducer;
|
||||
|
||||
@@ -7,26 +7,23 @@ interface ICaseReducer {
|
||||
caseForm: {
|
||||
[caseId: string]: {
|
||||
[journeyId: string]: {
|
||||
[sectionId: string]: {
|
||||
"widgetContext":{
|
||||
[widgetId: string]: {
|
||||
[questionId: string]: string;
|
||||
"sectionContext":{
|
||||
[sectionId: string]: {
|
||||
"questionContext":{
|
||||
[questionId: string]: string;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
toBeSynced: {
|
||||
[caseId: string]: {
|
||||
[journeyId: string]: {
|
||||
[sectionId: string]: {
|
||||
[widgetId: string]: {
|
||||
[questionId: string]: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
toBeSynced: any;
|
||||
allCases: Array<Data>;
|
||||
templateData: any;
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
@@ -148,7 +145,8 @@ const initialState = {
|
||||
GEOLOCATION: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
templateData: {}
|
||||
} as ICaseReducer;
|
||||
|
||||
export const caseSlice = createSlice({
|
||||
name: 'case',
|
||||
@@ -167,14 +165,24 @@ export const caseSlice = createSlice({
|
||||
data[caseId] = {};
|
||||
}
|
||||
if (!data[caseId][journeyId]) {
|
||||
// @ts-ignore
|
||||
data[caseId][journeyId] = {};
|
||||
}
|
||||
if (!data[caseId][journeyId][widgetId]) {
|
||||
data[caseId][journeyId][widgetId] = {};
|
||||
}
|
||||
data[caseId][journeyId][widgetId] = answer;
|
||||
|
||||
data[caseId][journeyId] = answer;
|
||||
state.caseForm = data;
|
||||
},
|
||||
deleteInteraction: (state, action) => {
|
||||
const {caseId, journeyId, widgetId, answer} = action.payload;
|
||||
console.log({caseId, journeyId, widgetId, answer})
|
||||
const data = state.caseForm;
|
||||
delete data[caseId][journeyId].widgetContext[widgetId];
|
||||
state.caseForm = data;
|
||||
},
|
||||
|
||||
updateTemplateData: (state, action) => {
|
||||
state.templateData = action.payload;
|
||||
},
|
||||
setAllCases: (state, action) => {
|
||||
state.allCases = action.payload;
|
||||
},
|
||||
@@ -185,7 +193,7 @@ export const caseSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const {increaseByOne, decreaseByOne, updateInteraction, setAllCases} =
|
||||
export const {increaseByOne, decreaseByOne, updateInteraction, setAllCases, deleteInteraction, updateTemplateData} =
|
||||
caseSlice.actions;
|
||||
|
||||
export default caseSlice.reducer;
|
||||
|
||||
@@ -18,6 +18,8 @@ import {
|
||||
import AllCases from './AllCases';
|
||||
import ComplatedCase from './ComplatedCase';
|
||||
import {CaseStatuses} from './interface';
|
||||
import RealJson from '../../data/RealTemplateData.json';
|
||||
import { updateTemplateData } from '../../reducer/caseReducre';
|
||||
|
||||
const LogoActions = () => {
|
||||
const {newlyPinnedCases, selectedTodoListCount} = useAppSelector(
|
||||
@@ -44,6 +46,8 @@ const LogoActions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const AllCasesMain = () => {
|
||||
const {casesList, newlyPinnedCases, selectedTodoListCount} = useAppSelector(
|
||||
state => state.allCases,
|
||||
@@ -75,6 +79,9 @@ const AllCasesMain = () => {
|
||||
const handleProfileIconPress = () => {
|
||||
navigateToScreen('Profile');
|
||||
};
|
||||
useEffect(() => {
|
||||
dispatch(updateTemplateData(RealJson));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={GenericStyles.fill}>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { SafeAreaView, StyleSheet, View } from 'react-native';
|
||||
import { Alert, SafeAreaView, StyleSheet, View } from 'react-native';
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import BackArrowIcon from '../../../RN-UI-LIB/src/Icons/BackArrowIcon';
|
||||
import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
|
||||
@@ -30,12 +30,23 @@ const CaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
<View style={GenericStyles.p16}>
|
||||
<UserDetailsSection caseDetail={detailObject} />
|
||||
<TaskStepper caseDetail={detailObject} />
|
||||
<Button
|
||||
{/* <Button
|
||||
style={{}}
|
||||
title="Trigger journey"
|
||||
variant="secondary"
|
||||
onPress={() => navigateToScreen('w1', {caseId: 'labkjisbldfyuk', journey: 'COMMUNICATION_ADDRESS_VERIFICATION_TASK'})}
|
||||
/>
|
||||
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>
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
@@ -1,66 +1,108 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import { useSelector } from 'react-redux';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import {
|
||||
Image, Modal,
|
||||
Pressable,
|
||||
SafeAreaView,
|
||||
StyleSheet,
|
||||
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 CalenderIcon from '../../assets/icons/CalenderIcon';
|
||||
import DocumentIcon from '../../assets/icons/DocumentIcon';
|
||||
import IconLabel from '../../common/IconLabel';
|
||||
import { RootState } from '../../store/store';
|
||||
import { CaseDetail, LoanAccountStatusUIMapping, LoanTypeUIMapping } from './interface';
|
||||
|
||||
interface IUserDetailsSection{
|
||||
caseDetail : any;
|
||||
interface IUserDetailsSection {
|
||||
caseDetail: CaseDetail;
|
||||
}
|
||||
|
||||
const UserDetailsSection: React.FC<IUserDetailsSection> = (props) => {
|
||||
const UserDetailsSection: React.FC<IUserDetailsSection> = props => {
|
||||
const {caseDetail} = props;
|
||||
const {customerInfo, loanDetails} = caseDetail;
|
||||
const disbursalDate = loanDetails.disbursalDate;
|
||||
const allocationDate = loanDetails.allocationDate;
|
||||
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);
|
||||
|
||||
const handleOpenClose = useCallback(() => {
|
||||
setOpenImage(prev => !prev);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={[GenericStyles.row, GenericStyles.pb16, styles.container]}>
|
||||
<View style={[styles.avatarContainer]}>
|
||||
<Avatar
|
||||
name={customerInfo.customerName}
|
||||
dataURI={customerInfo.imageURL}
|
||||
/>
|
||||
<Pressable onPress={handleOpenClose}>
|
||||
<Avatar
|
||||
size={60}
|
||||
name={customerInfo.customerName}
|
||||
dataURI={customerInfo.imageURL}
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
<View style={[styles.infoContainer]}>
|
||||
<Heading dark type="h4">
|
||||
{customerInfo.customerName}
|
||||
</Heading>
|
||||
<View style={[GenericStyles.row]}>
|
||||
<View style={[GenericStyles.row, GenericStyles.mb8]}>
|
||||
<IconLabel
|
||||
containerStyle={{flex: 0.5}}
|
||||
icon={<DocumentIcon />}
|
||||
text={loanDetails.loanType}
|
||||
text={LoanTypeUIMapping[loanDetails.loanType]}
|
||||
/>
|
||||
<IconLabel
|
||||
text={loanDetails.loanAccountStatus}
|
||||
containerStyle={{flex: 0.5}}
|
||||
containerStyle={GenericStyles.ml10}
|
||||
text={LoanAccountStatusUIMapping[loanDetails.loanAccountStatus]}
|
||||
/>
|
||||
</View>
|
||||
<View style={[GenericStyles.row]}>
|
||||
<View style={[GenericStyles.row, GenericStyles.mb8]}>
|
||||
<IconLabel
|
||||
icon={<CalenderIcon />}
|
||||
text={disbursalDate}
|
||||
containerStyle={{flex: 0.5}}
|
||||
/>
|
||||
<IconLabel
|
||||
text={`${loanDetails.tenureMonths} months`}
|
||||
containerStyle={{flex: 0.5}}
|
||||
text={`${loanDetails.tenureMonths} ${loanDetails.tenureMonths > 1 ? "Months" : "Month"}`}
|
||||
containerStyle={GenericStyles.ml10}
|
||||
/>
|
||||
</View>
|
||||
<View style={[GenericStyles.pt16]}>
|
||||
<Text style={[GenericStyles.fontSize15]}>
|
||||
<Text light style={[GenericStyles.fontSize15]}>
|
||||
Allocated on {allocationDate}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Modal animationType={'slide'} visible={openImage} onRequestClose={handleOpenClose}>
|
||||
<SafeAreaView
|
||||
style={[
|
||||
GenericStyles.fill,
|
||||
{backgroundColor: COLORS.BACKGROUND.HEADER},
|
||||
]}>
|
||||
<View style={GenericStyles.p16}>
|
||||
<Pressable onPress={handleOpenClose}>
|
||||
<CloseIcon />
|
||||
</Pressable>
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.fill,
|
||||
GenericStyles.alignCenter,
|
||||
GenericStyles.row
|
||||
]}>
|
||||
<Image
|
||||
style={[
|
||||
GenericStyles.fill,
|
||||
styles.imageStyle,
|
||||
]}
|
||||
source={{uri: customerInfo.imageURL}}
|
||||
resizeMode={'contain'}
|
||||
/>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</Modal>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -78,6 +120,12 @@ const styles = StyleSheet.create({
|
||||
infoContainer: {
|
||||
flex: 0.6,
|
||||
},
|
||||
imageStyle:{
|
||||
height: 300
|
||||
},
|
||||
backgroundColor:{
|
||||
backgroundColor: COLORS.BACKGROUND.HEADER
|
||||
}
|
||||
});
|
||||
|
||||
export default UserDetailsSection;
|
||||
|
||||
28
src/screens/caseDetails/interactionsHandler.tsx
Normal file
28
src/screens/caseDetails/interactionsHandler.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { StyleSheet, Text, View } from 'react-native'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useAppDispatch, useAppSelector } from '../../hooks'
|
||||
import { _map } from '../../../RN-UI-LIB/src/utlis/common';
|
||||
import { syncCaseDetail } from '../../action/dataActions';
|
||||
|
||||
const interactionsHandler = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const allCasesDetails = useAppSelector(state => state.allCases.caseDetails);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const notSyncedCases: Array<any> = [];
|
||||
_map(allCasesDetails, (el)=> {
|
||||
if(!allCasesDetails[el].isSynced){
|
||||
const caseId = allCasesDetails[el].id
|
||||
notSyncedCases.push({...allCasesDetails[el], caseId})
|
||||
}
|
||||
})
|
||||
console.log(notSyncedCases.length, "not synced")
|
||||
notSyncedCases.map((caseItem)=> dispatch(syncCaseDetail(caseItem)))
|
||||
}, [allCasesDetails])
|
||||
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default interactionsHandler
|
||||
121
src/screens/caseDetails/interface.ts
Normal file
121
src/screens/caseDetails/interface.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
export enum LoanType {
|
||||
PERSONAL_LOAN = "PERSONAL_LOAN",
|
||||
HOUSE_LOAN = "HOUSE_LOAN"
|
||||
}
|
||||
|
||||
export enum LoanAccountStatus {
|
||||
ACTIVE = "ACTIVE",
|
||||
CLOSE = "CLOSE"
|
||||
}
|
||||
|
||||
export enum LoanAccountStatusUIMapping {
|
||||
ACTIVE = "Active",
|
||||
CLOSE = "Close"
|
||||
}
|
||||
|
||||
export enum LoanTypeUIMapping {
|
||||
PERSONAL_LOAN = 'Personal loan',
|
||||
HOUSE_LOAN = 'House loan'
|
||||
}
|
||||
|
||||
export interface LoanDetails {
|
||||
loanAccountNumber: string;
|
||||
disbursalDate: string;
|
||||
disbursementAmount: number;
|
||||
firstDueDate: string;
|
||||
tenureMonths: number;
|
||||
loanType: LoanType;
|
||||
loanAccountStatus: LoanAccountStatus;
|
||||
productCode: string;
|
||||
}
|
||||
|
||||
export interface CustomerInfo {
|
||||
customerReferenceId: string;
|
||||
customerName: string;
|
||||
primaryPhoneNumber: string;
|
||||
imageURL: string;
|
||||
geoLocation: string;
|
||||
}
|
||||
|
||||
export interface Address {
|
||||
referenceId: string;
|
||||
houseNumber: string;
|
||||
lineOne: string;
|
||||
lineTwo: string;
|
||||
locality: string;
|
||||
street: string;
|
||||
city: string;
|
||||
state: string;
|
||||
pinCode: string;
|
||||
type: string;
|
||||
source: string;
|
||||
current: boolean;
|
||||
permanent: boolean;
|
||||
zipCode?: any;
|
||||
addressQualityStatus?: any;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
'@class': string;
|
||||
address: Address;
|
||||
geoLocation: string;
|
||||
primaryPhoneNumber: string;
|
||||
}
|
||||
|
||||
export interface Task {
|
||||
taskId: number;
|
||||
taskType: string;
|
||||
metadata: Metadata;
|
||||
}
|
||||
|
||||
export interface Q1 {
|
||||
optionId: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface QuestionContext {
|
||||
q1: Q1[];
|
||||
}
|
||||
|
||||
export interface S1 {
|
||||
questionContext: QuestionContext;
|
||||
}
|
||||
|
||||
export interface SectionContext {
|
||||
s1: S1;
|
||||
}
|
||||
|
||||
export interface W1 {
|
||||
sectionContext: SectionContext;
|
||||
}
|
||||
|
||||
export interface WidgetContext {
|
||||
w1: W1;
|
||||
}
|
||||
|
||||
export interface COMMUNICATIONADDRESSVERIFICATIONTASK {
|
||||
taskStatus: string;
|
||||
widgetContext: WidgetContext;
|
||||
}
|
||||
|
||||
export interface TaskContext {
|
||||
COMMUNICATION_ADDRESS_VERIFICATION_TASK: COMMUNICATIONADDRESSVERIFICATIONTASK[];
|
||||
}
|
||||
|
||||
export interface Context {
|
||||
taskSequence: string[];
|
||||
currentTask: string;
|
||||
taskContext: TaskContext;
|
||||
}
|
||||
|
||||
export interface CaseDetail {
|
||||
id: string;
|
||||
caseStatus: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
allocatedAt: number;
|
||||
loanDetails: LoanDetails;
|
||||
customerInfo: CustomerInfo;
|
||||
tasks: Task[];
|
||||
context: Context;
|
||||
}
|
||||
Reference in New Issue
Block a user