diff --git a/app/assets/images/cleaner_phone.js b/app/assets/images/cleaner_phone.js new file mode 100644 index 000000000..02c15fe30 --- /dev/null +++ b/app/assets/images/cleaner_phone.js @@ -0,0 +1,26 @@ +import * as React from 'react'; +import Svg, { G, Path, Defs, ClipPath } from 'react-native-svg'; + +function CleanerPhone(props) { + return ( + + + + + + + + + + + + ); +} + +export default CleanerPhone; diff --git a/app/assets/images/exclamation_icon.js b/app/assets/images/exclamation_icon.js new file mode 100644 index 000000000..346f7ea33 --- /dev/null +++ b/app/assets/images/exclamation_icon.js @@ -0,0 +1,22 @@ +import * as React from 'react'; +import Svg, { Path } from 'react-native-svg'; + +function Exclamation(props) { + return ( + + + + ); +} + +export default Exclamation; diff --git a/app/assets/images/sync_failed.js b/app/assets/images/sync_failed.js new file mode 100644 index 000000000..67ad3f841 --- /dev/null +++ b/app/assets/images/sync_failed.js @@ -0,0 +1,30 @@ +import * as React from 'react'; +import Svg, { G, Path, Defs, ClipPath } from 'react-native-svg'; + +function SyncFail(props) { + return ( + + + + + + + + + + + ); +} + +export default SyncFail; diff --git a/app/assets/images/sync_success.js b/app/assets/images/sync_success.js new file mode 100644 index 000000000..94fa7befc --- /dev/null +++ b/app/assets/images/sync_success.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import Svg, { Path } from 'react-native-svg'; + +function SyncSuccess(props) { + return ( + + + + ); +} + +export default SyncSuccess; diff --git a/app/assets/index.js b/app/assets/index.js index 2fd029684..5207526ee 100644 --- a/app/assets/index.js +++ b/app/assets/index.js @@ -53,8 +53,16 @@ import SpeciesLeaf from './images/drawerIcons/speciesLeaf'; import ProjectDoc from './images/drawerIcons/projectDoc'; import PieAdditionalData from './images/drawerIcons/pieAdditionalData'; import OfflineMapIcon from './images/drawerIcons/offlineMapIcon'; +import CleanerPhone from './images/cleaner_phone'; +import Exclamation from './images/exclamation_icon'; +import SyncSuccess from './images/sync_success'; +import SyncFail from './images/sync_failed'; export { + SyncFail, + SyncSuccess, + Exclamation, + CleanerPhone, ProjectDoc, OfflineMapIcon, PieAdditionalData, diff --git a/app/components/MainScreen/BottomBar.tsx b/app/components/MainScreen/BottomBar.tsx index 9b92dd732..0dabd58ad 100644 --- a/app/components/MainScreen/BottomBar.tsx +++ b/app/components/MainScreen/BottomBar.tsx @@ -88,19 +88,19 @@ const AddOptions = ({ onReqClose, navigation }: any) => { svgIcon: , title: 'Monitoring Plot', coming_soon: true, - onPress: () => navigation.navigate('Intervention'), + onPress: () => navigation.navigate('Interventions'), }, { svgIcon: , title: 'Project Site', coming_soon: true, - onPress: () => navigation.navigate('Intervention'), + onPress: () => navigation.navigate('Interventions'), }, { svgIcon: , title: 'Intervention', coming_soon: true, - onPress: () => navigation.navigate('Intervention'), + onPress: () => navigation.navigate('Interventions'), }, { svgIcon: , diff --git a/app/components/Navigator/BottomTab.tsx b/app/components/Navigator/BottomTab.tsx index 06b6547da..22ab40545 100644 --- a/app/components/Navigator/BottomTab.tsx +++ b/app/components/Navigator/BottomTab.tsx @@ -5,6 +5,7 @@ import MainScreen from '../MainScreen'; import { ComingSoon } from '../Common'; import BottomBar from '../MainScreen/BottomBar'; import NavDrawer from './Drawer'; +import Interventions from '../../screens/Interventions/Interventions'; const screenOptions = { headerShown: false }; @@ -15,7 +16,7 @@ const BottomTab = () => { return ( - + ); diff --git a/app/components/Navigator/MainNavigator.tsx b/app/components/Navigator/MainNavigator.tsx index bef4ad49d..fca573f7e 100644 --- a/app/components/Navigator/MainNavigator.tsx +++ b/app/components/Navigator/MainNavigator.tsx @@ -48,6 +48,7 @@ import ProjectConfig from '../../screens/ManageProjectsFlow/ProjectConfig'; import AdditionalDataSettings from '../AdditionalData/AdditionalDataSettings'; import RemeasurementForm from '../../screens/RemeasurementFlow/RemeasurementForm'; import RemeasurementReview from '../../screens/RemeasurementFlow/RemeasurementReview'; +import Interventions from '../../screens/Interventions/Interventions'; const Stack = createStackNavigator(); const screenOptions = { headerShown: false }; @@ -86,6 +87,7 @@ export default function MainNavigator() { + diff --git a/app/screens/Interventions/Interventions.tsx b/app/screens/Interventions/Interventions.tsx new file mode 100644 index 000000000..cb942be2d --- /dev/null +++ b/app/screens/Interventions/Interventions.tsx @@ -0,0 +1,339 @@ +import React, { useState } from 'react'; +import FontAwesome from 'react-native-vector-icons/FontAwesome'; +import { StyleSheet, Text, TouchableOpacity, View, SafeAreaView, FlatList } from 'react-native'; + +import { Colors, Typography } from '../../styles'; +import { CleanerPhone, Exclamation, MultipleTreeIcon, SyncFail, SyncSuccess } from '../../assets'; + +const FILTER_TYPES = ['All', 'Incomplete', 'Synced', 'Unsynced']; +const INTERVENTION_DATA = [ + { + title: '1 Apple Tree', + type: ['On Site', 'Point'], + createdAt: 'Feb 18, 2020', + synced: false, + complete: false, + }, + { + title: '24 Tree', + type: ['On Site', 'Point'], + createdAt: 'Feb 18, 2020', + synced: true, + complete: true, + }, + { + title: '136 m', + type: ['Fire Break', 'On Site', 'Point'], + createdAt: 'Feb 18, 2020', + synced: false, + complete: false, + }, + { + title: '8 m2', + type: ['Invasive Grass Removal', 'On Site', 'Point'], + createdAt: 'Feb 18, 2020', + synced: true, + complete: true, + }, + { + title: '12 m2', + type: ['Invasive Grass Removal', 'On Site', 'Point'], + createdAt: 'Feb 18, 2020', + synced: false, + complete: true, + }, +]; + +function getColor(key: string) { + switch (key) { + case 'Point': + return { color: '#F2994A', backgroundColor: '#F2994A20' }; + case 'On Site': + case 'Invasive Grass Removal': + return { color: Colors.PRIMARY, backgroundColor: Colors.PRIMARY + '20' }; + case 'Fire Break': + return { color: '#EB5757', backgroundColor: '#EB575720' }; + default: + break; + } +} + +const Interventions = () => { + const [interventionsList, setInterventionsList] = useState>(INTERVENTION_DATA); + const [selectedFilter, setSelectedFilter] = useState(FILTER_TYPES[0]); + + const handleEdit = () => {}; + const _handleSelectFilter = (item: string) => () => { + setSelectedFilter(item); + if (item === 'All') { + setInterventionsList(INTERVENTION_DATA); + } else if (item === 'Incomplete') { + setInterventionsList(INTERVENTION_DATA.filter(el => !el.complete)); + } else if (item === 'Synced') { + setInterventionsList(INTERVENTION_DATA.filter(el => el.synced)); + } else { + setInterventionsList(INTERVENTION_DATA.filter(el => !el.synced && el.complete)); + } + }; + const filteredLength = (key: string) => { + if (key === 'All') { + return INTERVENTION_DATA.length; + } else if (key === 'Incomplete') { + return INTERVENTION_DATA.filter(el => !el.complete).length; + } else if (key === 'Synced') { + return INTERVENTION_DATA.filter(el => el.synced).length; + } else { + return ( + INTERVENTION_DATA.filter(el => !el.synced).length - + INTERVENTION_DATA.filter(el => !el.complete).length + ); + } + }; + + const renderFilters = ({ item }) => ( + + + {item === 'All' ? `${item} ${filteredLength(item)}` : `${filteredLength(item)} ${item}`} + + + ); + + const renderIntervention = ({ item }) => ( + + + {item.complete ? : } + + {item.title} + + {item.type.map(type => ( + + {type} + + ))} + + {!item.complete && {item.createdAt}} + + + {!item.complete ? ( + + + + + + + + + ) : ( + <> + + {item.createdAt} + + + {item.synced ? : } + + + )} + + ); + + return ( + + + Interventions + + + Free up space + + + `FILTER_TYPES${index}`} + /> + `INTERVENTION_DATA${index}`} + /> + + ); +}; + +export default Interventions; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + header: { + padding: 16, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + freeSpaceBtn: { + borderWidth: 1, + borderRadius: 4, + paddingVertical: 2, + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 4, + borderColor: Colors.PRIMARY + '10', + backgroundColor: Colors.PRIMARY + '20', + }, + freeSpaceTxt: { + fontFamily: Typography.FONT_FAMILY_SEMI_BOLD, + fontSize: Typography.FONT_SIZE_10, + color: Colors.TEXT_COLOR, + }, + headerTitle: { + fontFamily: Typography.FONT_FAMILY_EXTRA_BOLD, + fontSize: Typography.FONT_SIZE_22, + color: Colors.TEXT_COLOR, + }, + filterItemCon: { + height: 28, + marginRight: 5, + borderRadius: 120, + backgroundColor: Colors.WHITE, + }, + filterLabel: { + paddingVertical: 6, + paddingHorizontal: 12, + color: Colors.TEXT_COLOR, + fontSize: Typography.FONT_SIZE_14, + marginTop: -2, + }, + filterList: { + marginTop: 16, + maxHeight: 30, + paddingHorizontal: 16, + }, + flatListCon: { + alignItems: 'center', + paddingRight: 25, + }, + interventionList: { + marginTop: 16, + paddingHorizontal: 16, + }, + avatar: { + width: 42, + height: 42, + borderRadius: 8, + backgroundColor: '#8282821A', + justifyContent: 'center', + alignItems: 'center', + }, + itemCon: { + padding: 8, + borderRadius: 8, + marginBottom: 12, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + backgroundColor: Colors.WHITE, + }, + itemInfoCon: { + flexDirection: 'row', + }, + itemInfo: { + marginLeft: 13, + }, + itemTitle: { + fontSize: Typography.FONT_SIZE_14, + fontFamily: Typography.FONT_FAMILY_BOLD, + }, + typeCon: { + flexDirection: 'row', + }, + itemWrap: { + borderRadius: 4, + marginRight: 4, + marginVertical: 6, + }, + type: { + paddingVertical: 3, + paddingHorizontal: 10, + fontSize: Typography.FONT_SIZE_8, + fontWeight: Typography.FONT_WEIGHT_BOLD, + }, + itemDate: { + fontSize: Typography.FONT_SIZE_10, + fontFamily: Typography.FONT_FAMILY_SEMI_BOLD, + color: Colors.DARK_TEXT_COLOR, + }, + btns: { + flexDirection: 'row', + marginRight: 15, + height: '85%', + }, + editBtn: { + width: 28, + height: 28, + borderRadius: 4, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: Colors.PRIMARY + '20', + }, + trashBtn: { + width: 28, + height: 28, + marginLeft: 12, + borderRadius: 4, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: Colors.PLANET_CRIMSON + '20', + }, + syncContainer: { + top: 0, + right: 0, + width: 32, + height: 26, + alignItems: 'center', + position: 'absolute', + borderTopRightRadius: 8, + justifyContent: 'center', + borderBottomLeftRadius: 8, + }, + boxShadow: { + // shadow + shadowColor: '#000000', + shadowOffset: { + width: 0, + height: 8, + }, + shadowOpacity: 0.05, + shadowRadius: 4.62, + elevation: 5, + }, +});