Kunal changed merged
This commit is contained in:
Submodule RN-UI-LIB updated: a6ebb5280b...e5ab5d07c9
16
src/assets/icons/FilterIcon.tsx
Normal file
16
src/assets/icons/FilterIcon.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as React from "react";
|
||||
import Svg, { Path } from "react-native-svg";
|
||||
const FilterIcon = () => (
|
||||
<Svg
|
||||
width={16}
|
||||
height={18}
|
||||
viewBox="0 0 16 18"
|
||||
fill="none"
|
||||
>
|
||||
<Path
|
||||
d="M15.8456 0.780302C15.7312 0.54479 15.5585 0.347411 15.3463 0.209792C15.1341 0.0721637 14.8906 -0.000412239 14.6423 1.76134e-06H1.35695C1.10879 -0.000250239 0.865321 0.0723077 0.653091 0.209774C0.440852 0.34724 0.267994 0.544331 0.153345 0.779573C0.0386958 1.01482 -0.0133408 1.27919 0.00291016 1.54387C0.0191527 1.80855 0.10306 2.06339 0.245487 2.2806L0.265695 2.3112L5.89461 10.2042V17.1C5.89453 17.2629 5.93596 17.4228 6.01426 17.5626C6.09257 17.7024 6.20498 17.8169 6.33937 17.8937C6.47375 17.9706 6.62515 18.007 6.77747 17.9991C6.92971 17.9912 7.07714 17.9393 7.20395 17.8488L9.73 16.0488C9.84527 15.9666 9.93975 15.8552 10.0052 15.7246C10.0705 15.5939 10.1047 15.4481 10.1047 15.3V10.2033L15.7538 2.2833C15.8968 2.06596 15.981 1.81071 15.9971 1.54558C16.0133 1.28045 15.9608 1.01567 15.8456 0.780302Z"
|
||||
fill="#969696"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
export default FilterIcon;
|
||||
20
src/common/Constants.ts
Normal file
20
src/common/Constants.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export enum CONDITIONAL_OPERATORS {
|
||||
EQUALS = 'EQUALS',
|
||||
LESS_THAN_EQUAL_TO = 'LESS_THAN_EQUAL_TO',
|
||||
}
|
||||
|
||||
export enum FILTER_TYPES {
|
||||
DATE = 'DATE',
|
||||
STRING = 'STRING',
|
||||
SEARCH = 'SEARCH',
|
||||
}
|
||||
|
||||
export enum SELECTION_TYPES {
|
||||
SINGLE = 'SINGLE',
|
||||
MULTIPLE = 'MULTIPLE',
|
||||
}
|
||||
|
||||
export interface Option {
|
||||
label: string;
|
||||
value: any;
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
import React, {useEffect, useMemo} from 'react';
|
||||
import {PixelRatio, StyleSheet, TouchableOpacity, View} from 'react-native';
|
||||
import {GenericStyles} from '../../../../../RN-UI-LIB/src/styles';
|
||||
import Heading from '../../../../../RN-UI-LIB/src/components/Heading';
|
||||
import Text from '../../../../../RN-UI-LIB/src/components/Text';
|
||||
import {COLORS} from '../../../../../RN-UI-LIB/src/styles/colors';
|
||||
import {useSelector} from 'react-redux';
|
||||
import {RootState} from '../../../../store/store';
|
||||
import TextInput from '../../../../../RN-UI-LIB/src/components/TextInput';
|
||||
import CheckboxGroup from '../../../../../RN-UI-LIB/src/components/chechbox/CheckboxGroup';
|
||||
import {useAppDispatch} from '../../../../hooks';
|
||||
import {
|
||||
CONDITIONAL_OPERATORS,
|
||||
FILTER_TYPES,
|
||||
SELECTION_TYPES,
|
||||
} from '../../../../common/Constants';
|
||||
import {getObjectValueFromKeys} from '../../../utlis/parsers';
|
||||
import {IFilter} from '../../../../screens/allCases/interface';
|
||||
import {
|
||||
clearSelectedFilters,
|
||||
setSelectedFilters,
|
||||
} from '../../../../reducer/allCasesSlice';
|
||||
import RadioGroup from '../../../../../RN-UI-LIB/src/components/radio_button/RadioGroup';
|
||||
import RadioButton from '../../../../../RN-UI-LIB/src/components/radio_button/RadioButton';
|
||||
import {Search} from '../../../../../RN-UI-LIB/src/utlis/search';
|
||||
|
||||
interface FilterContainerProps {
|
||||
closeFilterModal: () => void;
|
||||
}
|
||||
|
||||
class Data {}
|
||||
|
||||
export const evaluateFilterForCases = (
|
||||
caseRecord: Data,
|
||||
filters: Record<string, IFilter>,
|
||||
selectedFilters: Record<string, any>,
|
||||
) => {
|
||||
let evaluatedResult = true;
|
||||
Object.keys(selectedFilters).forEach(key => {
|
||||
switch (filters[key].filterType) {
|
||||
case FILTER_TYPES.DATE:
|
||||
switch (filters[key].operator) {
|
||||
case CONDITIONAL_OPERATORS.EQUALS:
|
||||
if (selectedFilters[key]) {
|
||||
evaluatedResult =
|
||||
evaluatedResult &&
|
||||
selectedFilters[key][
|
||||
(getObjectValueFromKeys(
|
||||
caseRecord,
|
||||
filters[key].fieldToCompare.split('.'),
|
||||
) -
|
||||
new Date().getTime()) /
|
||||
1000
|
||||
];
|
||||
}
|
||||
break;
|
||||
case CONDITIONAL_OPERATORS.LESS_THAN_EQUAL_TO:
|
||||
if (selectedFilters[key]) {
|
||||
evaluatedResult =
|
||||
evaluatedResult &&
|
||||
getObjectValueFromKeys(
|
||||
caseRecord,
|
||||
filters[key].fieldToCompare.split('.'),
|
||||
) <=
|
||||
new Date().getTime() -
|
||||
selectedFilters[key] * 1000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case FILTER_TYPES.STRING:
|
||||
switch (filters[key].operator) {
|
||||
case CONDITIONAL_OPERATORS.EQUALS:
|
||||
if (selectedFilters[key]) {
|
||||
evaluatedResult =
|
||||
evaluatedResult &&
|
||||
selectedFilters[key][
|
||||
getObjectValueFromKeys(
|
||||
caseRecord,
|
||||
filters[key].fieldToCompare.split('.'),
|
||||
)
|
||||
];
|
||||
// selectedFilters[key].some(
|
||||
// filter => {
|
||||
// console.log('filter.value .....' , filter.value);
|
||||
// console.log('field value' , getObjectValueFromKeys(
|
||||
// caseRecord,
|
||||
// filters[key].fieldToCompare.split(
|
||||
// '.',
|
||||
// )));
|
||||
// return filter.value ===
|
||||
// getObjectValueFromKeys(
|
||||
// caseRecord,
|
||||
// filters[key].fieldToCompare.split(
|
||||
// '.',
|
||||
// ),
|
||||
// )
|
||||
// },
|
||||
// );
|
||||
}
|
||||
break;
|
||||
case CONDITIONAL_OPERATORS.LESS_THAN_EQUAL_TO:
|
||||
if (selectedFilters[key]) {
|
||||
evaluatedResult =
|
||||
evaluatedResult &&
|
||||
selectedFilters[key] <=
|
||||
getObjectValueFromKeys(
|
||||
caseRecord,
|
||||
filters[key].fieldToCompare.split('.'),
|
||||
);
|
||||
// selectedFilters[key].some(
|
||||
// filter =>
|
||||
// filter.value <=
|
||||
// getObjectValueFromKeys(
|
||||
// caseRecord,
|
||||
// filters[key].fieldToCompare.split('.'),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
return evaluatedResult;
|
||||
};
|
||||
|
||||
const FiltersContainer: React.FC<FilterContainerProps> = props => {
|
||||
const {closeFilterModal} = props;
|
||||
const {filters, selectedFilters, casesList, filterList} = useSelector(
|
||||
(state: RootState) => ({
|
||||
filters: state.allCases.filters,
|
||||
selectedFilters: state.allCases.selectedFilters,
|
||||
casesList: state.allCases.casesList,
|
||||
filterList: state.allCases.filterList,
|
||||
}),
|
||||
);
|
||||
const [selectedFiltersMap, setSelectedFiltersMap] = React.useState<
|
||||
Record<string, any>
|
||||
>(selectedFilters);
|
||||
const filterKeys = Object.keys(filters);
|
||||
const [selectedFilterKey, setSelectedFilterKey] = React.useState<string>(filterKeys[0] || '');
|
||||
const [filterSearchString, setFilterSearchString] =
|
||||
React.useState<string>('');
|
||||
const dispatch = useAppDispatch();
|
||||
const handleFilterSelection = (filterValues: any) => {
|
||||
console.log('handleFilterSelection', filterValues);
|
||||
console.log(filterValues);
|
||||
selectedFilterKey &&
|
||||
setSelectedFiltersMap({[selectedFilterKey]: filterValues});
|
||||
};
|
||||
const disableApplyButton = useMemo(
|
||||
() => Object.keys(selectedFiltersMap).length === 0,
|
||||
[selectedFiltersMap],
|
||||
);
|
||||
|
||||
const applyFilter = () => {
|
||||
// dispatch(
|
||||
// setFilterList(
|
||||
// casesList.filter(record =>
|
||||
// evaluateFilterForCases(
|
||||
// record,
|
||||
// Object.keys(selectedFilters),
|
||||
// filters,
|
||||
// selectedFilters,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
dispatch(setSelectedFilters(selectedFiltersMap));
|
||||
closeFilterModal();
|
||||
};
|
||||
|
||||
const onClearAll = () => {
|
||||
setSelectedFiltersMap({});
|
||||
Object.keys(selectedFilters).length > 0 && dispatch(clearSelectedFilters());
|
||||
};
|
||||
|
||||
const Options = React.useMemo(() => {
|
||||
if (selectedFilterKey) {
|
||||
const options =
|
||||
filterSearchString.length > 0
|
||||
? Search(
|
||||
filterSearchString,
|
||||
filters[selectedFilterKey].options || [],
|
||||
{keys: ['label']},
|
||||
).map(option => option.obj)
|
||||
: filters[selectedFilterKey].options;
|
||||
console.log('options..........', options);
|
||||
switch (filters[selectedFilterKey].selectionType) {
|
||||
case SELECTION_TYPES.MULTIPLE:
|
||||
// const options = filters[selectedFilterKey].options?.filter(
|
||||
// option =>
|
||||
// option.label
|
||||
// .toLowerCase()
|
||||
// .indexOf(filterSearchString) > -1,
|
||||
// );
|
||||
// const selectedFilterValues = selectedFilters[
|
||||
// selectedFilterKey
|
||||
// ]?.map((x: any) => x.value);
|
||||
// console.log("selectedFilters", selectedFilterValues)
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.filterSelector,
|
||||
GenericStyles.row,
|
||||
GenericStyles.alignCenter,
|
||||
]}>
|
||||
<CheckboxGroup
|
||||
onSelectionChange={handleFilterSelection}
|
||||
options={options || []}
|
||||
defaultValue={
|
||||
selectedFiltersMap[selectedFilterKey]
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
case SELECTION_TYPES.SINGLE:
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.filterSelector,
|
||||
GenericStyles.row,
|
||||
GenericStyles.alignCenter,
|
||||
]}>
|
||||
<RadioGroup
|
||||
orientation="verticle"
|
||||
value={selectedFiltersMap[selectedFilterKey]}
|
||||
onValueChange={handleFilterSelection}>
|
||||
{options?.map(option => (
|
||||
<RadioButton
|
||||
value={option.label}
|
||||
id={option.value}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
return <></>;
|
||||
}, [selectedFilterKey, selectedFiltersMap, filterSearchString]);
|
||||
|
||||
return (
|
||||
<View style={[GenericStyles.fill, {flex: 1}]}>
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.row,
|
||||
GenericStyles.spaceBetween,
|
||||
GenericStyles.p16,
|
||||
styles.borderBottom,
|
||||
]}>
|
||||
<Heading dark type="h5">
|
||||
Filters
|
||||
</Heading>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
onPress={closeFilterModal}>
|
||||
<Text dark bold style={[styles.blueText]}>
|
||||
Close
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={[GenericStyles.row, {alignItems: 'stretch', flex: 1}]}>
|
||||
<View
|
||||
style={[
|
||||
styles.p8,
|
||||
styles.filterColumn,
|
||||
styles.borderRight1,
|
||||
]}>
|
||||
{filterKeys.map(
|
||||
key =>
|
||||
(
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.filterSelector,
|
||||
GenericStyles.row,
|
||||
GenericStyles.alignCenter,
|
||||
GenericStyles.spaceBetween,
|
||||
styles.mv8,
|
||||
key === selectedFilterKey &&
|
||||
styles.selectedFilterKey,
|
||||
]}
|
||||
activeOpacity={0.7}
|
||||
onPress={() => {
|
||||
setSelectedFilterKey(key);
|
||||
setFilterSearchString('');
|
||||
}}>
|
||||
<Text
|
||||
style={[
|
||||
key === selectedFilterKey &&
|
||||
styles.blueText,
|
||||
]}
|
||||
dark>
|
||||
{filters[key].displayText}
|
||||
</Text>
|
||||
{selectedFiltersMap[key] && (
|
||||
<View
|
||||
style={[
|
||||
key === selectedFilterKey
|
||||
? styles.filterCountSelected
|
||||
: styles.filterCount,
|
||||
]}>
|
||||
<Text
|
||||
style={[
|
||||
key === selectedFilterKey &&
|
||||
GenericStyles.whiteText,
|
||||
]}
|
||||
bold
|
||||
dark
|
||||
small>
|
||||
{typeof selectedFiltersMap[key] ===
|
||||
'object'
|
||||
? Object.keys(
|
||||
selectedFiltersMap[key],
|
||||
).length
|
||||
: 1}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
),
|
||||
)}
|
||||
</View>
|
||||
<View style={[styles.p8, styles.filterColumn]}>
|
||||
{selectedFilterKey && (
|
||||
<>
|
||||
<View style={[GenericStyles.pt16, styles.ph7]}>
|
||||
<TextInput
|
||||
placeholder="Search..."
|
||||
defaultValue={filterSearchString}
|
||||
onChangeText={value =>
|
||||
setFilterSearchString(value)
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
{Options}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
<View style={[GenericStyles.row]}>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
onPress={onClearAll}
|
||||
style={[
|
||||
styles.bottomCTA,
|
||||
{flex: 1, alignItems: 'center'},
|
||||
styles.clearAllButton,
|
||||
]}>
|
||||
<Heading dark type="h5">
|
||||
Clear all
|
||||
</Heading>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
onPress={applyFilter}
|
||||
disabled={disableApplyButton}
|
||||
style={[
|
||||
styles.applyButton,
|
||||
styles.bottomCTA,
|
||||
{flex: 1, alignItems: 'center'},
|
||||
]}>
|
||||
<Heading dark type="h5" style={[GenericStyles.whiteText]}>
|
||||
Apply
|
||||
</Heading>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
blueText: {
|
||||
color: COLORS.TEXT.BLUE,
|
||||
},
|
||||
borderBottom: {
|
||||
borderColor: COLORS.BORDER.PRIMARY,
|
||||
borderWidth: 1,
|
||||
},
|
||||
mv8: {
|
||||
marginVertical: 4,
|
||||
},
|
||||
p8: {
|
||||
padding: 8,
|
||||
},
|
||||
filterColumn: {
|
||||
flex: 1,
|
||||
alignItems: 'stretch',
|
||||
},
|
||||
filterSelector: {
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 8,
|
||||
},
|
||||
selectedFilterKey: {
|
||||
backgroundColor: COLORS.BACKGROUND.BLUE,
|
||||
borderRadius: 6,
|
||||
},
|
||||
borderRight1: {
|
||||
borderRightWidth: 1,
|
||||
borderRightColor: COLORS.BORDER.PRIMARY,
|
||||
},
|
||||
bottomCTA: {
|
||||
paddingVertical: 12,
|
||||
},
|
||||
applyButton: {
|
||||
backgroundColor: COLORS.TEXT.BLUE,
|
||||
},
|
||||
clearAllButton: {
|
||||
borderTopColor: COLORS.BORDER.PRIMARY,
|
||||
borderRightColor: COLORS.BORDER.PRIMARY,
|
||||
borderRightWidth: 1,
|
||||
borderTopWidth: 1,
|
||||
},
|
||||
ph7: {
|
||||
paddingHorizontal: 7,
|
||||
},
|
||||
filterCount: {
|
||||
backgroundColor: COLORS.BACKGROUND.SILVER,
|
||||
borderColor: COLORS.BORDER.PRIMARY,
|
||||
borderWidth: 1,
|
||||
height: PixelRatio.roundToNearestPixel(25),
|
||||
width: PixelRatio.roundToNearestPixel(25),
|
||||
borderRadius: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
filterCountSelected: {
|
||||
backgroundColor: COLORS.TEXT.BLUE,
|
||||
height: PixelRatio.roundToNearestPixel(25),
|
||||
width: PixelRatio.roundToNearestPixel(25),
|
||||
borderRadius: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default FiltersContainer;
|
||||
11
src/components/utlis/parsers.ts
Normal file
11
src/components/utlis/parsers.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export const getObjectValueFromKeys: (obj: Record<string, any> , keysArray: Array<string>) => any = (obj , keysArray) => {
|
||||
|
||||
if (keysArray.length && obj[keysArray[0]]){
|
||||
return getObjectValueFromKeys(obj[keysArray[0]], keysArray.slice(1));
|
||||
}else if (obj){
|
||||
console.log(obj);
|
||||
return obj
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
export const BASE_AV_APP_URL = 'https://dev-longhorn-server.np.navi-tech.in/av';
|
||||
export const BASE_AV_APP_URL = 'https://dev-longhorn-server.np.navi-tech.in/av/';
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
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, IFilter,
|
||||
} from '../screens/allCases/interface';
|
||||
import {CONDITIONAL_OPERATORS, FILTER_TYPES, SELECTION_TYPES} from "../common/Constants";
|
||||
|
||||
export type ICasesMap = {[key: string]: ICaseItem};
|
||||
|
||||
@@ -21,6 +23,9 @@ interface IAllCasesSlice {
|
||||
newlyPinnedCases: number;
|
||||
completedCases: number;
|
||||
caseDetails: any;
|
||||
filters: Record<string, IFilter>;
|
||||
searchQuery: string;
|
||||
selectedFilters: Record<string, any>
|
||||
}
|
||||
|
||||
const initialState: IAllCasesSlice = {
|
||||
@@ -38,6 +43,89 @@ const initialState: IAllCasesSlice = {
|
||||
newlyPinnedCases: 0,
|
||||
completedCases: 0,
|
||||
caseDetails: {},
|
||||
filters: {
|
||||
pincodes: {
|
||||
filterType: FILTER_TYPES.STRING,
|
||||
selectionType: SELECTION_TYPES.MULTIPLE,
|
||||
displayText: 'Pincode',
|
||||
fieldToCompare: 'currentTask.metadata.address.pinCode',
|
||||
operator: CONDITIONAL_OPERATORS.EQUALS,
|
||||
options: [
|
||||
{
|
||||
label: "500000",
|
||||
value: "500000"
|
||||
},
|
||||
{
|
||||
label: "560036",
|
||||
value: "560036"
|
||||
},
|
||||
{
|
||||
label: "560037",
|
||||
value: "560037"
|
||||
}
|
||||
]
|
||||
},
|
||||
caseStatus: {
|
||||
filterType: FILTER_TYPES.STRING,
|
||||
selectionType: SELECTION_TYPES.MULTIPLE,
|
||||
displayText: 'Feedback',
|
||||
fieldToCompare: 'caseStatus',
|
||||
operator: CONDITIONAL_OPERATORS.EQUALS,
|
||||
options: [
|
||||
{
|
||||
label: "New",
|
||||
value: "NEW"
|
||||
},
|
||||
{
|
||||
label: "Unassigned",
|
||||
value: "UNASSIGNED"
|
||||
},
|
||||
{
|
||||
label: "Assigned",
|
||||
value: "ASSIGNED"
|
||||
},
|
||||
{
|
||||
label: "In Progress",
|
||||
value: "IN_PROGRESS"
|
||||
},
|
||||
{
|
||||
label: "Closed",
|
||||
value: "CLOSED"
|
||||
},
|
||||
{
|
||||
label: "Force closed",
|
||||
value: "FORCE_CLOSED"
|
||||
},
|
||||
{
|
||||
label: "Expired",
|
||||
value: "EXPIRED"
|
||||
}
|
||||
]
|
||||
},
|
||||
allocatedAt: {
|
||||
filterType: FILTER_TYPES.DATE,
|
||||
selectionType: SELECTION_TYPES.SINGLE,
|
||||
displayText: 'Allocation Date',
|
||||
fieldToCompare: 'allocatedAt',
|
||||
operator: CONDITIONAL_OPERATORS.LESS_THAN_EQUAL_TO,
|
||||
options: [
|
||||
{
|
||||
label: "Last 2 days",
|
||||
value: 172800
|
||||
},
|
||||
{
|
||||
label: "Last 5 days",
|
||||
value: 432000
|
||||
},
|
||||
{
|
||||
label: "Last 10 days",
|
||||
value: 864000
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
searchQuery: '',
|
||||
selectedFilters: {}
|
||||
};
|
||||
|
||||
const getPinnedListDetails = (casesList: ICaseItem[]) => {
|
||||
@@ -71,7 +159,7 @@ const allCasesSlice = createSlice({
|
||||
prev[item.id] = {
|
||||
...item,
|
||||
isSynced: true,
|
||||
|
||||
|
||||
};
|
||||
return prev;
|
||||
}, initialValue);
|
||||
@@ -214,7 +302,22 @@ const allCasesSlice = createSlice({
|
||||
console.log("is side data notfound")
|
||||
state.caseDetails[id].isSynced = false;
|
||||
}
|
||||
|
||||
},
|
||||
setFilters: (state , action) => {
|
||||
state.filters = {...state.filters , ...action.payload}
|
||||
},
|
||||
setSelectedFilters: (state , action) => {
|
||||
state.selectedFilters = {...state.selectedFilters , ...action.payload}
|
||||
},
|
||||
clearSelectedFilters: (state) => {
|
||||
state.selectedFilters = {};
|
||||
},
|
||||
setFilterList: (state, action) => {
|
||||
console.log('filterList.....', action.payload);
|
||||
state.filterList = action.payload;
|
||||
},
|
||||
setSearchQuery: (state, action) => {
|
||||
state.searchQuery = action.payload;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -228,10 +331,15 @@ export const {
|
||||
filterData,
|
||||
proceedToTodoList,
|
||||
deleteIntermediateTodoListItem,
|
||||
setSelectedFilters,
|
||||
setFilterList,
|
||||
clearSelectedFilters,
|
||||
setFilters,
|
||||
setSelectedTodoListMap,
|
||||
resetSelectedTodoList,
|
||||
updateCaseDetail,
|
||||
updateSingleCase
|
||||
updateSingleCase,
|
||||
setSearchQuery,
|
||||
} = allCasesSlice.actions;
|
||||
|
||||
export default allCasesSlice.reducer;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import React, {useEffect, useMemo, useState} from 'react';
|
||||
import {StyleSheet, View, VirtualizedList} from 'react-native';
|
||||
import {useSelector} from 'react-redux';
|
||||
import {
|
||||
Modal,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
VirtualizedList,
|
||||
} from 'react-native';
|
||||
import {useDispatch, 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';
|
||||
@@ -8,49 +14,61 @@ import {RootState} from '../../store/store';
|
||||
import {CaseStatuses, ICaseItem, CaseTypes} from './interface';
|
||||
import {COMPLETED_STATUSES, ListHeaderItems} from './contants';
|
||||
import CaseItem from './CaseItem';
|
||||
import {Search} from '../../../RN-UI-LIB/src/utlis/search';
|
||||
import CasesActionButtons from './CasesActionButtons';
|
||||
import FloatingInfoText from '../../components/floatingInfoText';
|
||||
import {setSearchQuery} from '../../reducer/allCasesSlice';
|
||||
import FiltersContainer, {
|
||||
evaluateFilterForCases,
|
||||
} from '../../components/screens/allCases/allCasesFilters/FiltersContainer';
|
||||
import TextInput from '../../../RN-UI-LIB/src/components/TextInput';
|
||||
import SearchIcon from '../../../RN-UI-LIB/src/Icons/SearchIcon';
|
||||
import FilterIcon from '../../assets/icons/FilterIcon';
|
||||
|
||||
export const Separator = () => <View style={styles.separator} />;
|
||||
|
||||
export const getItem = (item: Array<ICaseItem>, index: number) => item[index];
|
||||
|
||||
const AllCases = () => {
|
||||
const {casesList, newlyPinnedCases, selectedTodoListCount} = useSelector(
|
||||
(state: RootState) => state.allCases,
|
||||
);
|
||||
const {
|
||||
casesList,
|
||||
newlyPinnedCases,
|
||||
selectedTodoListCount,
|
||||
selectedFilters,
|
||||
filters,
|
||||
searchQuery,
|
||||
} = useSelector((state: RootState) => state.allCases);
|
||||
const dispatch = useDispatch();
|
||||
const [pendingCases , setPendingCases] = useState([]);
|
||||
|
||||
const pendingCases = useMemo(
|
||||
() =>
|
||||
casesList.filter(caseItem => {
|
||||
if (!COMPLETED_STATUSES.includes(caseItem.caseStatus)) {
|
||||
return caseItem;
|
||||
}
|
||||
}),
|
||||
[casesList],
|
||||
);
|
||||
|
||||
const [filteredList, setFilteredList] =
|
||||
useState<Array<ICaseItem>>(pendingCases);
|
||||
|
||||
useEffect(() => {
|
||||
setFilteredList(pendingCases);
|
||||
}, [pendingCases]);
|
||||
useEffect(()=>{
|
||||
const filteredList = casesList.filter(caseItem => {
|
||||
return !COMPLETED_STATUSES.includes(caseItem.caseStatus) &&
|
||||
evaluateFilterForCases(
|
||||
caseItem,
|
||||
filters,
|
||||
selectedFilters,
|
||||
);
|
||||
});
|
||||
console.log('inside useEffect');
|
||||
// @ts-ignore
|
||||
setPendingCases(searchQuery.length > 0 ? Search(searchQuery , filteredList || [] , { keys: ['customerInfo.name']}).map(filteredListItem => filteredListItem.obj) : filteredList);
|
||||
},[casesList , filters , selectedFilters , searchQuery])
|
||||
|
||||
const {compiledList, completedPinnedCasesCount, pendingPinnedCasesCount} =
|
||||
useMemo(() => {
|
||||
const pinnedList: Array<ICaseItem> = [];
|
||||
const otherList: Array<ICaseItem> = [];
|
||||
const compiledList: Array<ICaseItem> = [];
|
||||
if (!filteredList.length) {
|
||||
if (!pendingCases.length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Filter input
|
||||
compiledList.push(ListHeaderItems.FILTER as ICaseItem);
|
||||
// compiledList.push(ListHeaderItems.FILTER as ICaseItem);
|
||||
|
||||
//extracting data for todo list and other cases
|
||||
filteredList.forEach(caseItem => {
|
||||
pendingCases.forEach(caseItem => {
|
||||
if (
|
||||
caseItem.pinRank === null ||
|
||||
caseItem.pinRank === undefined
|
||||
@@ -88,34 +106,75 @@ const AllCases = () => {
|
||||
completedPinnedCasesCount,
|
||||
pendingPinnedCasesCount,
|
||||
};
|
||||
}, [filteredList]);
|
||||
}, [pendingCases]);
|
||||
|
||||
const handleSearchChange = (query: string) => {
|
||||
const filterList = pendingCases.filter(caseItem => caseItem);
|
||||
// const filterList = query.length > 0 ? Search(query , filteredList || [] , { keys: ['customerInfo.name']}).map(filteredListItem => filteredListItem.obj) : filteredList;
|
||||
// setFilteredList(filterList);
|
||||
dispatch(setSearchQuery(query));
|
||||
};
|
||||
const [showFilterModal, setShowFilterModal] =
|
||||
React.useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<View style={GenericStyles.fill}>
|
||||
<>
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.ph16,
|
||||
styles.pv12,
|
||||
GenericStyles.whiteBackground,
|
||||
GenericStyles.centerAlignedRow,
|
||||
]}>
|
||||
<TextInput
|
||||
style={[{flexBasis: '75%'}]}
|
||||
LeftComponent={<SearchIcon />}
|
||||
onChangeText={handleSearchChange}
|
||||
placeholder="Search by name, address"
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={[styles.filterButton]}
|
||||
activeOpacity={0.7}
|
||||
onPress={() => setShowFilterModal(prev => !prev)}>
|
||||
<FilterIcon />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Modal
|
||||
animationType="slide"
|
||||
animated
|
||||
onRequestClose={() => setShowFilterModal(prev => !prev)}
|
||||
visible={showFilterModal}>
|
||||
<FiltersContainer
|
||||
closeFilterModal={() =>
|
||||
setShowFilterModal(prev => !prev)
|
||||
}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
{compiledList ? (
|
||||
<VirtualizedList
|
||||
data={compiledList}
|
||||
stickyHeaderIndices={[0]}
|
||||
initialNumToRender={4}
|
||||
renderItem={row => (
|
||||
<CaseItem
|
||||
data={row}
|
||||
completedPinnedCasesCount={
|
||||
completedPinnedCasesCount
|
||||
}
|
||||
pendingPinnedCasesCount={pendingPinnedCasesCount}
|
||||
handleSearchChange={handleSearchChange}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.caseReferenceId}
|
||||
getItemCount={item => item.length}
|
||||
getItem={getItem}
|
||||
ItemSeparatorComponent={<Separator />}
|
||||
/>
|
||||
<>
|
||||
<VirtualizedList
|
||||
data={compiledList}
|
||||
stickyHeaderIndices={[0]}
|
||||
initialNumToRender={4}
|
||||
renderItem={row => (
|
||||
<CaseItem
|
||||
data={row}
|
||||
completedPinnedCasesCount={
|
||||
completedPinnedCasesCount
|
||||
}
|
||||
pendingPinnedCasesCount={
|
||||
pendingPinnedCasesCount
|
||||
}
|
||||
handleSearchChange={handleSearchChange}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.caseReferenceId}
|
||||
getItemCount={item => item.length}
|
||||
getItem={getItem}
|
||||
ItemSeparatorComponent={<Separator />}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Text>Nothing to show</Text>
|
||||
)}
|
||||
@@ -141,6 +200,19 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: COLORS.BACKGROUND.PRIMARY,
|
||||
borderTopWidth: 1,
|
||||
},
|
||||
pv12: {
|
||||
paddingVertical: 12,
|
||||
},
|
||||
filterButton: {
|
||||
flexBasis: '20%',
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: COLORS.BORDER.PRIMARY,
|
||||
borderRadius: 10,
|
||||
height: 52,
|
||||
justifyContent: 'center',
|
||||
marginLeft: 4,
|
||||
},
|
||||
});
|
||||
|
||||
export default AllCases;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import React from 'react';
|
||||
import {ListRenderItemInfo, StyleSheet, View} from 'react-native';
|
||||
import {
|
||||
ListRenderItemInfo,
|
||||
Modal,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import SearchIcon from '../../../RN-UI-LIB/src/Icons/SearchIcon';
|
||||
import {GenericStyles} from '../../../RN-UI-LIB/src/styles';
|
||||
import TextInput from '../../../RN-UI-LIB/src/components/TextInput';
|
||||
@@ -8,6 +14,9 @@ import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import ListItem from './ListItem';
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import Button from '../../../RN-UI-LIB/src/components/Button';
|
||||
import FilterIcon from '../../assets/icons/FilterIcon';
|
||||
import FiltersContainer from '../../components/screens/allCases/allCasesFilters/FiltersContainer';
|
||||
|
||||
interface ICaseItemProps {
|
||||
data: ListRenderItemInfo<ICaseItem>;
|
||||
@@ -23,23 +32,46 @@ const CaseItem: React.FC<ICaseItemProps> = ({
|
||||
handleSearchChange,
|
||||
}) => {
|
||||
const {FILTER, CASES_HEADER, TODO_HEADER} = CaseTypes;
|
||||
const [showFilterModal, setShowFilterModal] =
|
||||
React.useState<boolean>(false);
|
||||
|
||||
switch (caseData.type) {
|
||||
case FILTER:
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
GenericStyles.ph16,
|
||||
styles.pv12,
|
||||
GenericStyles.whiteBackground,
|
||||
]}>
|
||||
<TextInput
|
||||
LeftComponent={<SearchIcon />}
|
||||
onChangeText={handleSearchChange}
|
||||
placeholder="Search by name, address"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
// case FILTER:
|
||||
// return (
|
||||
// <>
|
||||
// <View
|
||||
// style={[
|
||||
// GenericStyles.ph16,
|
||||
// styles.pv12,
|
||||
// GenericStyles.whiteBackground,
|
||||
// GenericStyles.centerAlignedRow,
|
||||
// ]}>
|
||||
// <TextInput
|
||||
// style={[{flexBasis: '75%'}]}
|
||||
// LeftComponent={<SearchIcon />}
|
||||
// onChangeText={handleSearchChange}
|
||||
// placeholder="Search by name, address"
|
||||
// />
|
||||
// <TouchableOpacity
|
||||
// style={[styles.filterButton]}
|
||||
// activeOpacity={0.7}
|
||||
// onPress={() => setShowFilterModal(prev => !prev)}>
|
||||
// <FilterIcon />
|
||||
// </TouchableOpacity>
|
||||
// </View>
|
||||
// <Modal
|
||||
// animationType="slide"
|
||||
// animated
|
||||
// onRequestClose={() => setShowFilterModal(prev => !prev)}
|
||||
// visible={showFilterModal}>
|
||||
// <FiltersContainer
|
||||
// closeFilterModal={() =>
|
||||
// setShowFilterModal(prev => !prev)
|
||||
// }
|
||||
// />
|
||||
// </Modal>
|
||||
// </>
|
||||
// );
|
||||
case CASES_HEADER:
|
||||
return (
|
||||
<View
|
||||
@@ -97,6 +129,16 @@ const styles = StyleSheet.create({
|
||||
pv12: {
|
||||
paddingVertical: 12,
|
||||
},
|
||||
filterButton: {
|
||||
flexBasis: '20%',
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: COLORS.BORDER.PRIMARY,
|
||||
borderRadius: 10,
|
||||
height: 52,
|
||||
justifyContent: 'center',
|
||||
marginLeft: 4,
|
||||
},
|
||||
});
|
||||
|
||||
export default CaseItem;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {COLORS} from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import {CONDITIONAL_OPERATORS, FILTER_TYPES, Option, SELECTION_TYPES} from "../../common/Constants";
|
||||
|
||||
export enum CaseTypes {
|
||||
TODO_HEADER,
|
||||
@@ -147,3 +148,12 @@ export enum ClassType {
|
||||
'.GeoLocationEntityMetadata',
|
||||
'.CallingEntityMetadata'
|
||||
}
|
||||
|
||||
export interface IFilter {
|
||||
filterType: FILTER_TYPES,
|
||||
displayText: string,
|
||||
selectionType: SELECTION_TYPES,
|
||||
fieldToCompare: string,
|
||||
operator: CONDITIONAL_OPERATORS,
|
||||
options?: Option[],
|
||||
}
|
||||
|
||||
@@ -75,15 +75,14 @@ const PhoneNumberSelectionBottomSheet: React.FC<
|
||||
</>
|
||||
</View>
|
||||
<View style={GenericStyles.p16}>
|
||||
<Button
|
||||
style={{width: '100%'}}
|
||||
title="Proceed"
|
||||
onPress={() => {
|
||||
setShowPhoneNumberBottomSheet(prev => !prev);
|
||||
setShowCallingBottomSheet(prev => !prev);
|
||||
}}
|
||||
disabled={!selectedPhoneNumber}
|
||||
/>
|
||||
<Button
|
||||
style={{width: '100%'}}
|
||||
title="Proceed"
|
||||
onPress={() => {
|
||||
setShowPhoneNumberBottomSheet(prev => !prev);
|
||||
setShowCallingBottomSheet(prev => !prev);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
|
||||
@@ -28,8 +28,8 @@ const persistConfig = {
|
||||
key: 'root',
|
||||
version: 1,
|
||||
storage: AsyncStorage,
|
||||
whitelist: ['case', 'common', 'allCases', 'user'],
|
||||
blackList:['case'],
|
||||
whitelist: ['case', 'allCases', 'common', 'user'],
|
||||
blackList: ['case'],
|
||||
};
|
||||
|
||||
const persistedReducer = persistReducer(persistConfig, rootReducer);
|
||||
@@ -47,4 +47,4 @@ export const persistor = persistStore(store);
|
||||
export default store;
|
||||
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
|
||||
Reference in New Issue
Block a user