todo list changes
This commit is contained in:
@@ -1,24 +1,52 @@
|
||||
import {Dispatch} from 'redux';
|
||||
import axiosInstance, {ApiKeys, getApiUrl} from '../components/utlis/apiHelper';
|
||||
import {setCasesListData} from '../reducer/allCasesSlice';
|
||||
import {
|
||||
resetTodoList,
|
||||
setCasesListData,
|
||||
setLoading,
|
||||
setTodoListOffline,
|
||||
} from '../reducer/allCasesSlice';
|
||||
import {ICaseItem} from '../screens/allCases/interface';
|
||||
import {AppDispatch} from '../store/store';
|
||||
|
||||
export const getAllCases = () => (dispatch: Dispatch) => {
|
||||
export const getAllCases = () => (dispatch: AppDispatch) => {
|
||||
const url = getApiUrl(ApiKeys.ALL_CASES);
|
||||
axiosInstance.get(url).then(async response => {
|
||||
const caseDetails = await getAllCaseDetails(response.data)
|
||||
dispatch(setCasesListData({allCases : response.data, details: caseDetails }));
|
||||
dispatch(setLoading(true));
|
||||
axiosInstance.get(url).then(response => {
|
||||
dispatch(getAllCaseDetails(response.data));
|
||||
});
|
||||
};
|
||||
|
||||
export const getAllCaseDetails = async (data: Array<ICaseItem>) => {
|
||||
const caseList = data.map(caseItem => caseItem.caseReferenceId);
|
||||
const url = getApiUrl(ApiKeys.CASE_DETAIL);
|
||||
try {
|
||||
const result = await axiosInstance.get(url, {params: {caseIds: caseList.join(',')}})
|
||||
console.log(result)
|
||||
return await result.data;
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
export const getAllCaseDetails =
|
||||
(data: Array<ICaseItem>) => (dispatch: AppDispatch) => {
|
||||
const caseList = data.map(caseItem => caseItem.caseReferenceId);
|
||||
const url = getApiUrl(ApiKeys.CASE_DETAIL);
|
||||
axiosInstance
|
||||
.get(url, {
|
||||
params: {caseIds: caseList.join(',')},
|
||||
})
|
||||
.then(response => {
|
||||
dispatch(
|
||||
setCasesListData({allCases: data, details: response.data}),
|
||||
);
|
||||
dispatch(resetTodoList());
|
||||
})
|
||||
.catch(err => console.log(err));
|
||||
};
|
||||
|
||||
export const postPinnedList =
|
||||
(pinnedCases: ICaseItem[], updatedCaseList: ICaseItem[]) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch(setLoading(true));
|
||||
const payload = pinnedCases
|
||||
.map(caseItem => caseItem.caseReferenceId)
|
||||
.join('&pins=');
|
||||
const url = getApiUrl(ApiKeys.PINNED_CASES);
|
||||
axiosInstance
|
||||
.post(url + `?pins=${payload}`)
|
||||
.then(response => {
|
||||
dispatch(getAllCases());
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(setTodoListOffline(updatedCaseList));
|
||||
});
|
||||
};
|
||||
|
||||
49
src/components/floatingInfoText/index.tsx
Normal file
49
src/components/floatingInfoText/index.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import {View, StyleSheet} from 'react-native';
|
||||
import React from 'react';
|
||||
import {GenericStyles, getShadowStyle} from '../../../RN-UI-LIB/src/styles';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import InfoIcon from '../../../RN-UI-LIB/src/Icons/InfoIcon';
|
||||
|
||||
interface IFloatingInfoText {
|
||||
top?: number;
|
||||
bottom?: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
const FloatingInfoText: React.FC<IFloatingInfoText> = ({message, top, bottom}) => {
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
GenericStyles.centerAlignedRow,
|
||||
{top, bottom},
|
||||
]}>
|
||||
<View style={[styles.textContainer, getShadowStyle(2), GenericStyles.centerAlignedRow]}>
|
||||
<InfoIcon color={COLORS.BASE.BLUE} />
|
||||
<Text small style={styles.text}>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
},
|
||||
textContainer: {
|
||||
paddingHorizontal: 30,
|
||||
paddingVertical: 3,
|
||||
borderRadius: 4,
|
||||
backgroundColor: COLORS.BACKGROUND.BLUE,
|
||||
},
|
||||
text: {
|
||||
color: COLORS.BASE.BLUE,
|
||||
marginLeft: 10
|
||||
},
|
||||
});
|
||||
|
||||
export default FloatingInfoText;
|
||||
@@ -17,7 +17,8 @@ export enum ApiKeys {
|
||||
GENERATE_OTP,
|
||||
VERIFY_OTP,
|
||||
ALL_CASES,
|
||||
CASE_DETAIL
|
||||
CASE_DETAIL,
|
||||
PINNED_CASES
|
||||
}
|
||||
|
||||
const API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
|
||||
@@ -25,6 +26,7 @@ API_URLS[ApiKeys.GENERATE_OTP] = '/auth/otp/generate';
|
||||
API_URLS[ApiKeys.VERIFY_OTP] = '/auth/otp/verify';
|
||||
API_URLS[ApiKeys.ALL_CASES] = '/cases/all-cases';
|
||||
API_URLS[ApiKeys.CASE_DETAIL] = '/cases/get-cases';
|
||||
API_URLS[ApiKeys.PINNED_CASES] = '/cases/pin';
|
||||
|
||||
const MOCK_API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
|
||||
|
||||
@@ -74,7 +76,6 @@ const errorsToRetry = [];
|
||||
const axiosInstance = axios.create();
|
||||
|
||||
axiosInstance.interceptors.request.use(request => {
|
||||
console.log(request)
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
request.retry = request?.retry < 4 ? request.retry : 3;
|
||||
|
||||
@@ -5,6 +5,9 @@ export const navigationRef: RefObject<any> = React.createRef();
|
||||
|
||||
// if screen already exists then navigate to it otherwise push screen
|
||||
export const navigateToScreen = (name: string, params: object = {}) => {
|
||||
if(navigationRef.current?.getCurrentRoute()?.name === name) {
|
||||
return;
|
||||
}
|
||||
navigationRef.current?.navigate(name, params);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ import {_map} from '../../RN-UI-LIB/src/utlis/common';
|
||||
import {Search} from '../../RN-UI-LIB/src/utlis/search';
|
||||
import {createSlice} from '@reduxjs/toolkit';
|
||||
import {navigateToScreen} from '../components/utlis/navigationUtlis';
|
||||
import {
|
||||
ICaseItem,
|
||||
} from '../screens/allCases/interface';
|
||||
import {ICaseItem} from '../screens/allCases/interface';
|
||||
|
||||
export type ICasesMap = {[key: string]: ICaseItem};
|
||||
|
||||
@@ -14,6 +12,8 @@ interface IAllCasesSlice {
|
||||
casesListMap: ICasesMap;
|
||||
intermediateTodoList: ICaseItem[];
|
||||
intermediateTodoListMap: ICasesMap;
|
||||
selectedTodoListMap: ICasesMap;
|
||||
selectedTodoListCount: number;
|
||||
initialPinnedRankCount: number;
|
||||
pinnedRankCount: number;
|
||||
loading: boolean;
|
||||
@@ -29,6 +29,8 @@ const initialState: IAllCasesSlice = {
|
||||
casesListMap: {},
|
||||
intermediateTodoList: [],
|
||||
intermediateTodoListMap: {},
|
||||
selectedTodoListCount: 0,
|
||||
selectedTodoListMap: {},
|
||||
initialPinnedRankCount: 0,
|
||||
pinnedRankCount: 0,
|
||||
loading: false,
|
||||
@@ -42,13 +44,13 @@ const getPinnedListDetails = (casesList: ICaseItem[]) => {
|
||||
let maxPinnedRank = 0;
|
||||
const pinnedList: ICaseItem[] = [];
|
||||
casesList.forEach(caseItem => {
|
||||
const {pinnedRank} = caseItem;
|
||||
if (!pinnedRank) {
|
||||
const {pinRank} = caseItem;
|
||||
if (pinRank === null || pinRank === undefined) {
|
||||
return;
|
||||
}
|
||||
pinnedList.push(caseItem);
|
||||
if (pinnedRank > maxPinnedRank) {
|
||||
maxPinnedRank = pinnedRank;
|
||||
if (pinRank > maxPinnedRank) {
|
||||
maxPinnedRank = pinRank;
|
||||
}
|
||||
});
|
||||
return {pinnedList, maxPinnedRank};
|
||||
@@ -58,6 +60,9 @@ const allCasesSlice = createSlice({
|
||||
name: 'cases',
|
||||
initialState,
|
||||
reducers: {
|
||||
setLoading: (state, action) => {
|
||||
state.loading = action.payload;
|
||||
},
|
||||
setCasesListData: (state, action) => {
|
||||
const {allCases, details} = action.payload;
|
||||
if (details?.length) {
|
||||
@@ -72,6 +77,8 @@ const allCasesSlice = createSlice({
|
||||
const {pinnedList, maxPinnedRank} = getPinnedListDetails(allCases);
|
||||
state.pinnedList = pinnedList;
|
||||
state.pinnedRankCount = maxPinnedRank;
|
||||
state.loading = false;
|
||||
navigateToScreen('Home')
|
||||
},
|
||||
setPinnedRank: (state, action) => {
|
||||
const caseId = action.payload.caseReferenceId;
|
||||
@@ -83,14 +90,14 @@ const allCasesSlice = createSlice({
|
||||
state.pinnedRankCount++;
|
||||
state.newlyPinnedCases++;
|
||||
const selectedCase = {...action.payload};
|
||||
selectedCase.pinnedRank = state.pinnedRankCount;
|
||||
selectedCase.pinRank = state.pinnedRankCount;
|
||||
state.intermediateTodoListMap[caseId] = selectedCase;
|
||||
}
|
||||
},
|
||||
proceedToTodoList: state => {
|
||||
state.intermediateTodoList = Object.values(
|
||||
state.intermediateTodoListMap,
|
||||
).sort((caseA, caseB) => caseA.pinnedRank - caseB.pinnedRank);
|
||||
).sort((caseA, caseB) => caseA.pinRank - caseB.pinRank);
|
||||
navigateToScreen('TodoList');
|
||||
},
|
||||
deleteIntermediateTodoListItem: (state, action) => {
|
||||
@@ -116,34 +123,42 @@ const allCasesSlice = createSlice({
|
||||
state.newlyPinnedCases = 0;
|
||||
state.pinnedRankCount = state.initialPinnedRankCount;
|
||||
},
|
||||
setTodoList: state => {
|
||||
state.newlyPinnedCases = 0;
|
||||
const list = state.casesList.map(caseItem => {
|
||||
const pinnedItem =
|
||||
state.intermediateTodoListMap[caseItem.caseReferenceId];
|
||||
return {
|
||||
...caseItem,
|
||||
pinnedRank: pinnedItem
|
||||
? pinnedItem.pinnedRank
|
||||
: caseItem.pinnedRank,
|
||||
};
|
||||
});
|
||||
state.casesList = list;
|
||||
setTodoListOffline: (state, action) => {
|
||||
state.casesList = action.payload;
|
||||
state.intermediateTodoListMap = {};
|
||||
state.newlyPinnedCases = 0;
|
||||
navigateToScreen('Home');
|
||||
},
|
||||
setSelectedTodoListMap: (state, action) => {
|
||||
const caseId = action.payload.caseReferenceId;
|
||||
const isCasePresent = state.selectedTodoListMap[caseId];
|
||||
if (isCasePresent) {
|
||||
delete state.selectedTodoListMap[caseId];
|
||||
state.selectedTodoListCount--;
|
||||
} else {
|
||||
state.selectedTodoListCount++;
|
||||
const selectedCase = {...action.payload};
|
||||
state.selectedTodoListMap[caseId] = selectedCase;
|
||||
}
|
||||
},
|
||||
resetSelectedTodoList: (state) => {
|
||||
state.selectedTodoListCount = 0;
|
||||
state.selectedTodoListMap = {};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
setLoading,
|
||||
setCasesListData,
|
||||
setPinnedRank,
|
||||
setTodoList,
|
||||
setTodoListOffline,
|
||||
resetTodoList,
|
||||
filterData,
|
||||
proceedToTodoList,
|
||||
deleteIntermediateTodoListItem
|
||||
deleteIntermediateTodoListItem,
|
||||
setSelectedTodoListMap,
|
||||
resetSelectedTodoList
|
||||
} = allCasesSlice.actions;
|
||||
|
||||
export default allCasesSlice.reducer;
|
||||
|
||||
@@ -1,27 +1,24 @@
|
||||
import React, {useEffect, useMemo, useState} from 'react';
|
||||
import {StyleSheet, View, VirtualizedList} from 'react-native';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
import {useSelector} from 'react-redux';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import {navigateToScreen} from '../../components/utlis/navigationUtlis';
|
||||
import {proceedToTodoList, resetTodoList} from '../../reducer/allCasesSlice';
|
||||
import {RootState} from '../../store/store';
|
||||
import {CaseStatuses, ICaseItem, CaseTypes} from './interface';
|
||||
import {COMPLETED_STATUSES, ListHeaderItems} from './contants';
|
||||
import CaseItem from './CaseItem';
|
||||
import CasesActionButtons from './CasesActionButtons';
|
||||
import FloatingInfoText from '../../components/floatingInfoText';
|
||||
|
||||
export const Separator = () => <View style={styles.separator} />;
|
||||
|
||||
export const getItem = (item: Array<ICaseItem>, index: number) => item[index];
|
||||
|
||||
const AllCases = () => {
|
||||
const {casesList, newlyPinnedCases} = useSelector(
|
||||
const {casesList, newlyPinnedCases, selectedTodoListCount} = useSelector(
|
||||
(state: RootState) => state.allCases,
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const pendingCases = useMemo(
|
||||
() =>
|
||||
@@ -54,10 +51,13 @@ const AllCases = () => {
|
||||
|
||||
//extracting data for todo list and other cases
|
||||
filteredList.forEach(caseItem => {
|
||||
if (caseItem.pinnedRank) {
|
||||
pinnedList.push({...caseItem, type: CaseTypes.TODO});
|
||||
} else {
|
||||
if (
|
||||
caseItem.pinRank === null ||
|
||||
caseItem.pinRank === undefined
|
||||
) {
|
||||
otherList.push({...caseItem, type: CaseTypes.CASE});
|
||||
} else {
|
||||
pinnedList.push({...caseItem, type: CaseTypes.TODO});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -73,11 +73,6 @@ const AllCases = () => {
|
||||
compiledList.push(...otherList);
|
||||
}
|
||||
|
||||
pinnedList.sort(
|
||||
(caseItemA, caseItemB) =>
|
||||
caseItemA.pinnedRank - caseItemB.pinnedRank,
|
||||
);
|
||||
|
||||
let completedPinnedCasesCount = 0;
|
||||
pinnedList.forEach(todo => {
|
||||
if (todo.caseStatus === CaseStatuses.CLOSED) {
|
||||
@@ -95,14 +90,6 @@ const AllCases = () => {
|
||||
};
|
||||
}, [filteredList]);
|
||||
|
||||
const handleTodoProceedClick = () => {
|
||||
dispatch(proceedToTodoList());
|
||||
};
|
||||
|
||||
const handleCancelTodoList = () => {
|
||||
dispatch(resetTodoList());
|
||||
};
|
||||
|
||||
const handleSearchChange = (query: string) => {
|
||||
const filterList = pendingCases.filter(caseItem => caseItem);
|
||||
};
|
||||
@@ -132,27 +119,14 @@ const AllCases = () => {
|
||||
) : (
|
||||
<Text>Nothing to show</Text>
|
||||
)}
|
||||
{newlyPinnedCases ? (
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.row,
|
||||
GenericStyles.justifyContentSpaceBetween,
|
||||
GenericStyles.p16,
|
||||
styles.actionBtns,
|
||||
]}>
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
style={styles.fb45}
|
||||
title={'Cancel'}
|
||||
onPress={handleCancelTodoList}
|
||||
/>
|
||||
<Button
|
||||
style={styles.fb45}
|
||||
title={'Proceed'}
|
||||
onPress={handleTodoProceedClick}
|
||||
/>
|
||||
</View>
|
||||
) : null}
|
||||
{newlyPinnedCases || selectedTodoListCount ? (
|
||||
<CasesActionButtons />
|
||||
) : (
|
||||
<FloatingInfoText
|
||||
bottom={24}
|
||||
message="Press on customer image to select cases"
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -167,9 +141,6 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: COLORS.BACKGROUND.PRIMARY,
|
||||
borderTopWidth: 1,
|
||||
},
|
||||
fb45: {
|
||||
flexBasis: '45%',
|
||||
},
|
||||
});
|
||||
|
||||
export default AllCases;
|
||||
|
||||
101
src/screens/allCases/CasesActionButtons.tsx
Normal file
101
src/screens/allCases/CasesActionButtons.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import {StyleSheet, View} from 'react-native';
|
||||
import React from 'react';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import {useSelector} from 'react-redux';
|
||||
import {proceedToTodoList, resetSelectedTodoList, resetTodoList} from '../../reducer/allCasesSlice';
|
||||
import {RootState} from '../../store/store';
|
||||
import {CaseTypes, ICaseItem} from './interface';
|
||||
import {useAppDispatch} from '../../hooks';
|
||||
import {postPinnedList} from '../../action/dataActions';
|
||||
|
||||
export const CasesActionButtons = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
newlyPinnedCases,
|
||||
selectedTodoListCount,
|
||||
selectedTodoListMap,
|
||||
casesList,
|
||||
} = useSelector((state: RootState) => state.allCases);
|
||||
const handleTodoProceedClick = () => {
|
||||
dispatch(proceedToTodoList());
|
||||
};
|
||||
|
||||
const handleCancelTodoList = () => {
|
||||
dispatch(resetTodoList());
|
||||
};
|
||||
|
||||
const handleRemovePinnedList = () => {
|
||||
const updatedPinnedList: ICaseItem[] = [];
|
||||
const updatedCaseList: ICaseItem[] = casesList.map(caseItem => {
|
||||
const {caseReferenceId, pinRank} = caseItem;
|
||||
if (selectedTodoListMap[caseReferenceId]) {
|
||||
caseItem.pinRank = null;
|
||||
caseItem.type = CaseTypes.CASE;
|
||||
} else if (pinRank !== null && pinRank !== undefined) {
|
||||
updatedPinnedList.push(caseItem);
|
||||
}
|
||||
return caseItem;
|
||||
});
|
||||
dispatch(resetSelectedTodoList());
|
||||
dispatch(postPinnedList(updatedPinnedList, updatedCaseList));
|
||||
};
|
||||
|
||||
if (!newlyPinnedCases && !selectedTodoListCount) {
|
||||
return null;
|
||||
}
|
||||
const renderActions = () => {
|
||||
if (newlyPinnedCases) {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
style={styles.fb45}
|
||||
title={'Cancel'}
|
||||
onPress={handleCancelTodoList}
|
||||
/>
|
||||
<Button
|
||||
style={styles.fb45}
|
||||
title={'Proceed'}
|
||||
onPress={handleTodoProceedClick}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (selectedTodoListCount) {
|
||||
return (
|
||||
<Button
|
||||
style={GenericStyles.fill}
|
||||
title={'Remove from list'}
|
||||
onPress={handleRemovePinnedList}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.row,
|
||||
GenericStyles.justifyContentSpaceBetween,
|
||||
GenericStyles.p16,
|
||||
styles.actionBtns,
|
||||
]}>
|
||||
{renderActions()}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
actionBtns: {
|
||||
borderTopColor: COLORS.BORDER.PRIMARY,
|
||||
backgroundColor: COLORS.BACKGROUND.PRIMARY,
|
||||
borderTopWidth: 1,
|
||||
},
|
||||
fb45: {
|
||||
flexBasis: '45%',
|
||||
},
|
||||
});
|
||||
|
||||
export default CasesActionButtons;
|
||||
@@ -1,43 +1,62 @@
|
||||
import {Pressable, StyleSheet, View} from 'react-native';
|
||||
import React from 'react';
|
||||
import {CaseStatuses, ICaseItem, TaskTitleUIMapping, CaseTypes} from './interface';
|
||||
import {
|
||||
CaseStatuses,
|
||||
ICaseItem,
|
||||
TaskTitleUIMapping,
|
||||
CaseTypes,
|
||||
} from './interface';
|
||||
import Avatar from '../../../RN-UI-LIB/src/components/Avatar';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
import {setPinnedRank} from '../../reducer/allCasesSlice';
|
||||
import {
|
||||
setPinnedRank,
|
||||
setSelectedTodoListMap,
|
||||
} from '../../reducer/allCasesSlice';
|
||||
import {RootState} from '../../store/store';
|
||||
import RoundCheckIcon from '../../icons/RoundCheckIcon';
|
||||
import {navigateToScreen} from '../../components/utlis/navigationUtlis';
|
||||
|
||||
interface IListItem {
|
||||
caseData: ICaseItem;
|
||||
// True if it's from the inside todo screen
|
||||
isTodoItem?: boolean;
|
||||
compleatedList?: boolean;
|
||||
}
|
||||
|
||||
const ListItem: React.FC<IListItem> = props => {
|
||||
const {caseData, compleatedList, isTodoItem} = props;
|
||||
const {type, caseReferenceId: caseId, customerInfo} = caseData;
|
||||
const {type, caseReferenceId: caseId} = caseData;
|
||||
const dispatch = useDispatch();
|
||||
|
||||
if (!compleatedList && caseData.caseStatus === CaseStatuses.CLOSED) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {intermediateTodoListMap} = useSelector(
|
||||
(state: RootState) => state.allCases,
|
||||
);
|
||||
const {
|
||||
intermediateTodoListMap,
|
||||
selectedTodoListMap,
|
||||
newlyPinnedCases,
|
||||
selectedTodoListCount,
|
||||
} = useSelector((state: RootState) => state.allCases);
|
||||
|
||||
const handleAvatarClick = () => {
|
||||
if (isTodoItem || caseData.caseStatus === CaseStatuses.CLOSED) {
|
||||
return;
|
||||
}
|
||||
if (type === CaseTypes.CASE && selectedTodoListCount > 0) {
|
||||
return;
|
||||
}
|
||||
if (type === CaseTypes.TODO && newlyPinnedCases > 0) {
|
||||
return;
|
||||
}
|
||||
if (type === CaseTypes.CASE) {
|
||||
dispatch(setPinnedRank(caseData));
|
||||
return;
|
||||
} else if (type === CaseTypes.TODO) {
|
||||
dispatch(setSelectedTodoListMap(caseData));
|
||||
// select todo item
|
||||
}
|
||||
};
|
||||
@@ -46,7 +65,9 @@ const ListItem: React.FC<IListItem> = props => {
|
||||
navigateToScreen('caseDetail', {caseId});
|
||||
};
|
||||
|
||||
const caseSelected = !isTodoItem && intermediateTodoListMap?.[caseId];
|
||||
const caseSelected =
|
||||
!isTodoItem &&
|
||||
(intermediateTodoListMap?.[caseId] || selectedTodoListMap?.[caseId]);
|
||||
|
||||
const address = caseData.currentTask.metadata?.address;
|
||||
const poneNumber = caseData.currentTask.metadata?.primaryPhoneNumber;
|
||||
@@ -73,7 +94,9 @@ const ListItem: React.FC<IListItem> = props => {
|
||||
GenericStyles.ph16,
|
||||
styles.pv12,
|
||||
GenericStyles.row,
|
||||
GenericStyles.whiteBackground,
|
||||
caseSelected
|
||||
? GenericStyles.silverBackground
|
||||
: GenericStyles.whiteBackground,
|
||||
]}>
|
||||
<Pressable
|
||||
style={[styles.avatarContainer, styles.alignSelf]}
|
||||
@@ -93,9 +116,7 @@ const ListItem: React.FC<IListItem> = props => {
|
||||
</Heading>
|
||||
<Text dark ellipsizeMode="tail" numberOfLines={2}>
|
||||
{TaskTitleUIMapping[caseData.currentTask.title]}:{' '}
|
||||
<Text>
|
||||
{displayAddress}
|
||||
</Text>
|
||||
<Text>{displayAddress}</Text>
|
||||
</Text>
|
||||
{/* TODO write color coding logic with tag component */}
|
||||
{/* {caseData.caseVerdict !== caseVerdict.NEW && (
|
||||
|
||||
@@ -2,18 +2,52 @@ import React, {useEffect} from 'react';
|
||||
import {StyleSheet, View} from 'react-native';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import Tabs from '../../../RN-UI-LIB/src/components/tabs/Tabs';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import BackArrowSmallIcon from '../../../RN-UI-LIB/src/Icons/ArrowBackSmallIcon';
|
||||
import NaviLogoIcon from '../../../RN-UI-LIB/src/Icons/NaviLogoIcon';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import {getAllCases} from '../../action/dataActions';
|
||||
import {useAppDispatch, useAppSelector} from '../../hooks';
|
||||
import {
|
||||
resetSelectedTodoList,
|
||||
resetTodoList,
|
||||
} from '../../reducer/allCasesSlice';
|
||||
import AllCases from './AllCases';
|
||||
import ComplatedCase from './ComplatedCase';
|
||||
import {CaseStatuses} from './interface';
|
||||
|
||||
const LogoActions = () => {
|
||||
const {newlyPinnedCases, selectedTodoListCount} = useAppSelector(
|
||||
state => state.allCases,
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
if (!newlyPinnedCases && !selectedTodoListCount) {
|
||||
return <NaviLogoIcon />;
|
||||
}
|
||||
const handleBackPressIfTodoSelected = () => {
|
||||
dispatch(newlyPinnedCases ? resetTodoList() : resetSelectedTodoList());
|
||||
};
|
||||
const count = newlyPinnedCases || selectedTodoListCount;
|
||||
return (
|
||||
<View style={GenericStyles.centerAlignedRow}>
|
||||
<BackArrowSmallIcon onPress={handleBackPressIfTodoSelected} />
|
||||
<Text
|
||||
style={[styles.text, styles.selectedText]}
|
||||
bold
|
||||
light>
|
||||
{count} selected
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const AllCasesMain = () => {
|
||||
const data = useAppSelector(state => state.allCases.casesList);
|
||||
const completed = data.filter(
|
||||
const {casesList, newlyPinnedCases, selectedTodoListCount} = useAppSelector(
|
||||
state => state.allCases,
|
||||
);
|
||||
const completed = casesList.filter(
|
||||
caseData =>
|
||||
caseData.caseStatus === CaseStatuses.CLOSED ||
|
||||
caseData.caseStatus === CaseStatuses.EXPIRED ||
|
||||
@@ -23,7 +57,7 @@ const AllCasesMain = () => {
|
||||
const tabItems = [
|
||||
{
|
||||
key: 'first',
|
||||
title: `Pending (${data.length - completed.length})`,
|
||||
title: `Pending (${casesList.length - completed.length})`,
|
||||
content: AllCases,
|
||||
},
|
||||
{
|
||||
@@ -46,10 +80,12 @@ const AllCasesMain = () => {
|
||||
GenericStyles.row,
|
||||
GenericStyles.justifyContentSpaceBetween,
|
||||
]}>
|
||||
<NaviLogoIcon />
|
||||
<Heading type={'h5'} style={styles.text} bold light>
|
||||
My allocations
|
||||
</Heading>
|
||||
<LogoActions />
|
||||
{!newlyPinnedCases && !selectedTodoListCount && (
|
||||
<Heading type={'h5'} style={styles.text} bold light>
|
||||
My allocations
|
||||
</Heading>
|
||||
)}
|
||||
<View style={styles.iconSkeliton} />
|
||||
</View>
|
||||
<Tabs
|
||||
@@ -74,6 +110,10 @@ const styles = StyleSheet.create({
|
||||
height: 64,
|
||||
backgroundColor: COLORS.BACKGROUND.HEADER,
|
||||
},
|
||||
selectedText: {
|
||||
marginLeft: 18,
|
||||
fontSize: 16
|
||||
},
|
||||
});
|
||||
|
||||
export default AllCasesMain;
|
||||
|
||||
@@ -78,7 +78,7 @@ export const caseVerdictAndColor = {
|
||||
|
||||
export interface ICaseItem {
|
||||
type?: CaseTypes; // this is for maintaing frontend
|
||||
pinnedRank: number;
|
||||
pinRank: number | null;
|
||||
updatedAt: any;
|
||||
allocatedAt: any;
|
||||
caseReferenceId: string;
|
||||
|
||||
@@ -20,8 +20,7 @@ interface ICaseDetails {
|
||||
const CaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
const {route : { params : {caseId}}} = props;
|
||||
|
||||
const detailObject = useAppSelector(state => state.allCases.caseDetails[caseId])
|
||||
console.log(detailObject);
|
||||
const detailObject = useAppSelector(state => state.allCases.caseDetails[caseId]);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={[GenericStyles.fill, GenericStyles.whiteBackground]}>
|
||||
|
||||
@@ -20,22 +20,40 @@ import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import {
|
||||
deleteIntermediateTodoListItem,
|
||||
resetTodoList,
|
||||
setPinnedRank,
|
||||
setTodoList,
|
||||
} from '../../reducer/allCasesSlice';
|
||||
import {navigateToScreen} from '../../components/utlis/navigationUtlis';
|
||||
import SwipeableContainer from '../../components/SwipeableContainer';
|
||||
import {postPinnedList} from '../../action/dataActions';
|
||||
import {useAppDispatch} from '../../hooks';
|
||||
|
||||
const TodoList = () => {
|
||||
const {
|
||||
pinnedList = [],
|
||||
intermediateTodoList = [],
|
||||
casesList,
|
||||
intermediateTodoListMap,
|
||||
loading,
|
||||
} = useSelector((state: RootState) => state.allCases);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleCreateTodoList = () => {
|
||||
dispatch(setTodoList());
|
||||
const updatedPinnedList: ICaseItem[] = [];
|
||||
const updatedCaseList = casesList.map(caseItem => {
|
||||
const pinnedItem =
|
||||
intermediateTodoListMap[caseItem.caseReferenceId];
|
||||
if (caseItem.pinRank !== null && caseItem.pinRank !== undefined) {
|
||||
updatedPinnedList.push(caseItem);
|
||||
}
|
||||
if (pinnedItem) {
|
||||
updatedPinnedList.push(pinnedItem);
|
||||
}
|
||||
return pinnedItem ? pinnedItem : caseItem;
|
||||
});
|
||||
const sortedPinnedList: ICaseItem[] = updatedPinnedList.sort(
|
||||
(caseA, caseB) => caseA.pinRank - caseB.pinRank,
|
||||
);
|
||||
dispatch(postPinnedList(sortedPinnedList, updatedCaseList));
|
||||
};
|
||||
|
||||
const handleCancelTodoList = () => {
|
||||
@@ -98,6 +116,7 @@ const TodoList = () => {
|
||||
}
|
||||
onPress={handleCreateTodoList}
|
||||
style={GenericStyles.w100}
|
||||
showLoader={loading}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user