diff --git a/app/screens/FindMachine.js b/app/screens/FindMachine.js
index d4d2ca55..50710a85 100644
--- a/app/screens/FindMachine.js
+++ b/app/screens/FindMachine.js
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useContext, useEffect, useState } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import {
@@ -10,7 +10,9 @@ import {
StyleSheet,
TextInput,
View,
+ TouchableOpacity,
} from "react-native";
+import { useNavigation, useRoute } from "@react-navigation/native";
import { ThemeContext } from "../theme-context";
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
@@ -30,8 +32,9 @@ import {
WarningButton,
} from "../components";
import Checkbox from "expo-checkbox";
-
import { alphaSortNameObj } from "../utils/utilityFunctions";
+import { FontAwesome6 } from "@expo/vector-icons";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
let deviceWidth = Dimensions.get("window").width;
@@ -46,89 +49,83 @@ const getDisplayText = (machine, theme) => (
);
-class MultiSelectRow extends React.PureComponent {
- static contextType = ThemeContext;
-
- _onPress = () => {
- this.props.onPressItem(this.props.machine);
- };
-
- render() {
- const { index, machine, selected } = this.props;
- const theme = this.context.theme;
- const backgroundColor = index % 2 === 0 ? theme.base1 : theme.base2;
-
- return (
- [
- {
- display: "flex",
- flexDirection: "row",
- alignItems: "center",
- padding: 8,
- justifyContent: "space-between",
- },
- pressed
- ? { backgroundColor: theme.base4, opacity: 0.8 }
- : { backgroundColor, opacity: 1 },
- ]}
- >
-
- {getDisplayText(machine, theme)}
-
- {selected ? (
-
- ) : null}
-
- );
- }
-}
-
-MultiSelectRow.propTypes = {
- onPressItem: PropTypes.func,
- machine: PropTypes.object,
- selected: PropTypes.bool,
- index: PropTypes.number,
+const MultiSelectRow = ({ index, machine, selected, onPressItem }) => {
+ const { theme } = useContext(ThemeContext);
+ const backgroundColor = index % 2 === 0 ? theme.base1 : theme.base2;
+
+ const _onPress = () => onPressItem(machine);
+
+ return (
+ [
+ {
+ display: "flex",
+ flexDirection: "row",
+ alignItems: "center",
+ padding: 8,
+ justifyContent: "space-between",
+ },
+ pressed
+ ? { backgroundColor: theme.base4, opacity: 0.8 }
+ : { backgroundColor, opacity: 1 },
+ ]}
+ >
+
+ {getDisplayText(machine, theme)}
+
+ {selected ? (
+
+ ) : null}
+
+ );
};
-class FindMachine extends React.PureComponent {
- constructor(props) {
- super(props);
- const sortedMachines = alphaSortNameObj(props.machines.machines);
-
- this.state = {
- machines: sortedMachines,
- allMachines: sortedMachines,
- query: "",
- showModal: false,
- machine: {},
- condition: "",
- machineList: props.location.machineList,
- machinesInView: false,
- ic_enabled: undefined,
- };
- }
-
- componentDidMount() {
- this.props.navigation.setOptions({
- title: this.props.route.params?.machineFilter
+function FindMachine(props) {
+ const {
+ location,
+ machines,
+ mapLocations,
+ addMachineToLocation,
+ setMachineFilter,
+ } = props;
+
+ const navigation = useNavigation();
+ const route = useRoute();
+ const { theme } = useContext(ThemeContext);
+ const insets = useSafeAreaInsets();
+
+ const sortedMachines = alphaSortNameObj(machines.machines);
+ const [list, setList] = useState(sortedMachines);
+ const [allMachines] = useState(sortedMachines);
+ const [query, setQuery] = useState("");
+ const [showModal, setShowModal] = useState(false);
+ const [machine, setMachine] = useState({});
+ const [condition, setCondition] = useState("");
+ const [machineList, setMachineList] = useState(location.machineList || []);
+ const [machinesInView, setMachinesInView] = useState(false);
+ const [ic_enabled, setIcEnabled] = useState(undefined);
+ const [refresh, setRefresh] = useState(false);
+
+ useEffect(() => {
+ setMachineList(location.machineList || []);
+ }, [location.machineList]);
+
+ useEffect(() => {
+ navigation.setOptions({
+ title: route.params?.machineFilter
? "Select Machine to Filter"
- : `Select Machine${this.props.route.params?.multiSelect ? "s" : ""}`,
+ : `Select Machine${route.params?.multiSelect ? "s" : ""}`,
headerRight: () =>
- this.props.route.params?.showDone ? (
- this.props.navigation.goBack(null)}>
+ route.params?.showDone ? (
+ navigation.goBack(null)}>
{({ pressed }) => (
-
+
) : null,
});
- }
-
- componentDidUpdate() {
- this.props.navigation.setOptions({
- headerRight: () =>
- this.props.route.params?.showDone ? (
- this.props.navigation.goBack(null)}>
- {({ pressed }) => (
-
-
-
- )}
-
- ) : null,
- });
- }
-
- static contextType = ThemeContext;
-
- handleSearch = (query, machinesInView) => {
- const formattedQuery = query.toLowerCase();
-
- if (machinesInView) {
- const machinesInView = this.props.mapLocations.reduce((machines, loc) => {
- loc.machine_ids &&
- loc.machine_ids.map((machineId) => {
- if (machines.indexOf(machineId) === -1) machines.push(machineId);
- });
-
- return machines;
+ }, [
+ navigation,
+ route.params?.machineFilter,
+ route.params?.multiSelect,
+ route.params?.showDone,
+ ]);
+
+ useEffect(() => {
+ navigation.setParams?.({ showDone: (machineList?.length || 0) > 0 });
+ }, [machineList, navigation]);
+
+ const toArray = (maybeArrayOrObject) =>
+ Array.isArray(maybeArrayOrObject)
+ ? maybeArrayOrObject
+ : Object.values(maybeArrayOrObject || {});
+
+ const handleSearch = (q, wantInView) => {
+ const formatted = q.toLowerCase();
+
+ if (wantInView) {
+ const idsInView = toArray(mapLocations).reduce((ids, loc) => {
+ (loc?.machine_ids || []).forEach((id) => {
+ if (!ids.includes(id)) ids.push(id);
+ });
+ return ids;
}, []);
- const curMachines = this.state.allMachines.filter(
- (mach) => machinesInView.indexOf(mach.id) > -1,
- );
- const machines = curMachines.filter((m) =>
- m.name.toLowerCase().includes(formattedQuery),
+ const cur = allMachines.filter((m) => idsInView.includes(m.id));
+ const filtered = cur.filter((m) =>
+ m.name.toLowerCase().includes(formatted),
);
- this.setState({ query, machines });
+ setQuery(q);
+ setList(filtered);
} else {
- const machines = this.state.allMachines.filter((m) =>
- m.name.toLowerCase().includes(formattedQuery),
+ const filtered = allMachines.filter((m) =>
+ m.name.toLowerCase().includes(formatted),
);
- this.setState({ query, machines });
+ setQuery(q);
+ setList(filtered);
}
};
- handleClear = () => {
- this.setState({ query: "" });
+ const handleClear = () => {
+ setQuery("");
+ setList(allMachines);
};
- toggleViewMachinesInMapArea = (idx) => {
- if (idx === 0 && !!this.state.machinesInView) {
- this.handleSearch(this.state.query, false);
- this.setState({ machinesInView: false });
- } else if (idx === 1 && !!!this.state.machinesInView) {
- this.handleSearch(this.state.query, true);
- this.setState({ machinesInView: true });
+ const toggleViewMachinesInMapArea = (idx) => {
+ if (idx === 0 && machinesInView) {
+ handleSearch(query, false);
+ setMachinesInView(false);
+ } else if (idx === 1 && !machinesInView) {
+ handleSearch(query, true);
+ setMachinesInView(true);
}
};
- setSelected = (machine) => {
- if (this.props.route.params?.machineFilter) {
- this.props.setMachineFilter(machine);
- this.props.navigation.goBack();
+ const setSelected = (m) => {
+ if (route.params?.machineFilter) {
+ setMachineFilter(m);
+ navigation.goBack();
} else {
- this.setState({
- showModal: true,
- machine,
- });
+ setShowModal(true);
+ setMachine(m);
}
};
- addMachine = () => {
- this.props.addMachineToLocation(
- this.state.machine,
- this.state.condition,
- this.state.ic_enabled,
- );
- this.setState({ showModal: false });
- this.props.navigation.goBack();
+ const addMachineAndClose = () => {
+ addMachineToLocation(machine, condition, ic_enabled);
+ setShowModal(false);
+ navigation.goBack();
};
- cancelAddMachine = () => {
- this.setState({
- showModal: false,
- machine: {},
- condition: "",
- });
+ const returnToMachineSelection = () => {
+ setShowModal(false);
+ setMachine({});
+ setCondition("");
+ };
+
+ const returnToLocationDetails = () => {
+ setShowModal(false);
+ setMachine({});
+ setCondition("");
+ navigation.goBack();
+ };
+
+ const onPressMultiSelect = (m) => {
+ const selected = machineList.find((x) => x.id === m.id);
+ if (selected) {
+ removeMachineFromList(m);
+ } else {
+ addMachineToList(m);
+ }
+ setRefresh((r) => !r);
};
- renderRow = ({ item, index }) => {
- const theme = this.context.theme;
+ const keyExtractor = (m) => `${m.id}`;
+
+ const onIcEnabledPressed = (val) => {
+ if (ic_enabled === val) setIcEnabled(undefined);
+ else setIcEnabled(val);
+ };
+
+ const multiSelect = !!route.params?.multiSelect;
+ const isFiltering = !!route.params?.machineFilter;
+ const selectedIdx = machinesInView ? 1 : 0;
+ const s = getStyles(theme);
+ const keyboardDismissProp =
+ Platform.OS === "ios"
+ ? { keyboardDismissMode: "on-drag" }
+ : { onScrollBeginDrag: Keyboard.dismiss };
+
+ const { opdb_img, opdb_img_height, opdb_img_width } = machine;
+ const opdb_resized = (opdb_img_width || 0) - (deviceWidth - 48);
+ const opdb_img_height_calc =
+ (deviceWidth - 48) * ((opdb_img_height || 0) / (opdb_img_width || 1));
+ const opdbImgHeight =
+ opdb_resized > 0 ? opdb_img_height_calc : opdb_img_height;
+ const opdbImgWidth = opdb_resized > 0 ? deviceWidth - 48 : opdb_img_width;
+
+ const renderRow = ({ item, index }) => {
const backgroundColor = index % 2 === 0 ? theme.base1 : theme.base2;
return (
- this.setSelected(item)}>
+ setSelected(item)}>
{({ pressed }) => (
(
+ const renderMultiSelectRow = ({ item, index }) => (
m.id === item.id)}
+ onPressItem={onPressMultiSelect}
+ selected={!!(location.machineList || []).find((m) => m.id === item.id)}
index={index}
/>
);
- onPressMultiSelect = (machine) => {
- const selected = !!this.props.location.machineList.find(
- (m) => m.id === machine.id,
- );
-
- if (selected) {
- this.props.removeMachineFromList(machine);
- this.setState({
- refresh: !this.state.refresh,
- });
- } else {
- this.props.addMachineToList(machine);
- this.setState({
- refresh: !this.state.refresh,
- });
- }
- };
-
- keyExtractor = (machine) => `${machine.id}`;
-
- onIcEnabledPressed = (ic_enabled) => {
- const prevState = this.state.ic_enabled;
- // uncheck if pressing the currently checked box
- if (
- (!!prevState && !!ic_enabled) ||
- (prevState === false && ic_enabled === false)
- ) {
- return this.setState({ ic_enabled: undefined });
- }
-
- this.setState({ ic_enabled });
- };
-
- UNSAFE_componentWillReceiveProps(props) {
- if (
- this.props.location.machineList.length === 0 &&
- props.location.machineList.length > 0
- )
- this.props.navigation.setParams({ showDone: true });
-
- if (
- this.props.location.machineList.length > 0 &&
- props.location.machineList.length === 0
- )
- this.props.navigation.setParams({ showDone: false });
- }
-
- render() {
- const { machineList = [] } = this.props.location;
- const multiSelect =
- (this.props.route.params && this.props.route.params["multiSelect"]) ||
- false;
- const isFiltering = this.props.route.params?.machineFilter;
- const selectedIdx = this.state.machinesInView ? 1 : 0;
- const theme = this.context.theme;
- const s = getStyles(theme);
- const keyboardDismissProp =
- Platform.OS === "ios"
- ? { keyboardDismissMode: "on-drag" }
- : { onScrollBeginDrag: Keyboard.dismiss };
- const { opdb_img, opdb_img_height, opdb_img_width } = this.state.machine;
- const opdb_resized = opdb_img_width - (deviceWidth - 48);
- const opdb_img_height_calc =
- (deviceWidth - 48) * (opdb_img_height / opdb_img_width);
- const opdbImgHeight =
- opdb_resized > 0 ? opdb_img_height_calc : opdb_img_height;
- const opdbImgWidth = opdb_resized > 0 ? deviceWidth - 48 : opdb_img_width;
-
- return (
- <>
- {}}
- transparent={false}
- statusBarTranslucent={true}
- navigationBarTranslucent={true}
- >
-
-
-
+ return (
+ <>
+ {}}
+ transparent={false}
+ statusBarTranslucent
+ navigationBarTranslucent
+ >
+
+
+
+
+ returnToMachineSelection()}
+ style={s.backButton}
+ activeOpacity={0.5}
+ >
+
+
- Add{" "}
-
- {this.state.machine.name}
- {" "}
- to{" "}
-
- {this.props.location.location.name}
-
+ Add {machine.name} to{" "}
+ {location.name}
- {!!opdb_img && (
-
- )}
- this.setState({ condition })}
- textAlignVertical="top"
- underlineColorAndroid="transparent"
+
+
+ {!!opdb_img && (
+
- {this.state.machine.ic_eligible && (
-
-
- Does machine have Stern Insider Connected enabled?
-
-
- this.onIcEnabledPressed(true)}
- color={theme.purple}
- style={s.checkStyle}
- />
-
- Yes
-
- this.onIcEnabledPressed(false)}
- color={theme.purple}
- style={s.checkStyle}
- />
- No
-
+ )}
+
+
+
+ {machine.ic_eligible && (
+
+
+ Does machine have Stern Insider Connected enabled?
+
+
+ onIcEnabledPressed(true)}
+ color={theme.purple}
+ style={s.checkStyle}
+ />
+ Yes
+ onIcEnabledPressed(false)}
+ color={theme.purple}
+ style={s.checkStyle}
+ />
+ No
- )}
-
-
-
-
-
-
-
-
-
-
- this.handleSearch(query, this.state.machinesInView)
- }
- value={this.state.query}
- style={s.inputStyle}
- autoCorrect={false}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ handleSearch(q, machinesInView)}
+ value={query}
+ style={s.inputStyle}
+ autoCorrect={false}
+ />
+
+ {query.length > 0 && (
+
+
-
- {this.state.query.length > 0 && (
-
-
-
+
+ )}
+
+
+ {isFiltering ? (
+
+
+
+ ) : null}
+
+ {multiSelect ? (
+
+ {machineList.length === 0 ? (
+ 0 machines selected
+ ) : (
+
+
+ {`${machineList.length} machine${machineList.length > 1 ? "s" : ""} selected`}
+
+
)}
- {isFiltering ? (
-
-
-
- ) : null}
- {multiSelect ? (
-
- {machineList.length === 0 ? (
- 0 machines selected
- ) : (
-
- {`${
- machineList.length
- } machine${machineList.length > 1 ? "s" : ""} selected`}
-
- )}
-
- ) : null}
-
- >
- );
- }
+ ) : null}
+
+
+ >
+ );
}
const getStyles = (theme) =>
@@ -530,13 +488,24 @@ const getStyles = (theme) =>
fontSize: 18,
fontFamily: "Nunito-Regular",
},
-
+ headerContainer: {
+ flexDirection: "row",
+ alignItems: "center",
+ position: "relative",
+ justifyContent: "center",
+ },
+ backButton: {
+ position: "absolute",
+ left: 0,
+ top: 0,
+ bottom: 0,
+ justifyContent: "center",
+ },
textInput: {
backgroundColor: theme.white,
borderColor: theme.theme == "dark" ? theme.base4 : theme.indigo4,
borderWidth: 1,
marginHorizontal: 30,
- marginTop: 5,
marginBottom: 10,
borderRadius: 10,
fontFamily: "Nunito-Regular",
@@ -546,7 +515,7 @@ const getStyles = (theme) =>
verticalAlign: {
flexDirection: "column",
justifyContent: "top",
- marginTop: 80,
+ marginTop: 60,
marginBottom: 40,
},
multiSelect: {
@@ -605,7 +574,7 @@ const getStyles = (theme) =>
modalTitle: {
textAlign: "center",
marginHorizontal: 40,
- marginBottom: 15,
+ marginVertical: 20,
fontSize: 18,
fontFamily: "Nunito-Regular",
},
@@ -648,6 +617,7 @@ const mapStateToProps = ({ location, machines, locations }) => ({
machines,
mapLocations: locations.mapLocations || {},
});
+
const mapDispatchToProps = (dispatch) => ({
addMachineToLocation: (machine, condition, ic_enabled) =>
dispatch(addMachineToLocation(machine, condition, ic_enabled)),
@@ -655,4 +625,5 @@ const mapDispatchToProps = (dispatch) => ({
removeMachineFromList: (machine) => dispatch(removeMachineFromList(machine)),
setMachineFilter: (machine) => dispatch(setMachineFilter(machine)),
});
+
export default connect(mapStateToProps, mapDispatchToProps)(FindMachine);