diff --git a/src/field/FieldList.tsx b/src/field/FieldList.tsx
new file mode 100644
index 0000000..6243ce3
--- /dev/null
+++ b/src/field/FieldList.tsx
@@ -0,0 +1,153 @@
+import {
+ Box,
+ Button,
+ Paper,
+ Tab,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Tabs
+} from "@mui/material";
+import React, { useCallback, useEffect, useState } from "react";
+import { useMobile, useSnackbar } from "hooks";
+import { useGlobalState, useFieldAPI } from "providers";
+//import HarvestTable from "harvestPlan/HarvestTable";
+import { Field } from "models";
+import GrainDescriber from "grain/GrainDescriber";
+import { pond } from "protobuf-ts/pond";
+import HarvestSettings from "harvestPlan/HarvestSettings";
+
+interface TabPanelProps {
+ children?: React.ReactNode;
+ index: any;
+ value: any;
+}
+
+function TabPanelMine(props: TabPanelProps) {
+ const { children, value, index, ...other } = props;
+
+ return (
+
+ {value === index && {children}}
+
+ );
+}
+
+export default function FieldList() {
+ const [{ as }] = useGlobalState();
+ const isMobile = useMobile();
+ const fieldAPI = useFieldAPI();
+ const { openSnack } = useSnackbar();
+ const [fields, setFields] = useState([]);
+ const [value, setValue] = React.useState(0);
+ const [openHarvestSettings, setOpenHarvestSettings] = useState(false);
+ const [fieldForPlan, setFieldForPlan] = useState(Field.create());
+
+ const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
+ setValue(newValue);
+ };
+
+ const loadFields = useCallback(() => {
+ fieldAPI
+ .listFields(500, 0, "asc", "fieldName", undefined, as)
+ .then(resp => {
+ setFields(resp.data.fields.map(f => Field.any(f)));
+ // resp.data.fields.forEach(f => {
+ // if (f.settings) {
+ // fieldAPI.updateField(f.settings.key, f.settings);
+ // }
+ // });
+ })
+ .catch(err => {
+ openSnack("Failed to load Field Mapping");
+ });
+ }, [fieldAPI, as, openSnack]);
+
+ useEffect(() => {
+ loadFields();
+ }, [loadFields]);
+
+ const calcTotalAcres = () => {
+ let totalAcres = 0;
+ fields.forEach(field => {
+ totalAcres += field.acres();
+ });
+ totalAcres = Math.round(totalAcres);
+ return totalAcres;
+ };
+
+ const listFieldsInfo = fields.map((field, index) => (
+
+ {field.fieldName()}
+ {field.landLoc()}
+
+ {field.crop() === pond.Grain.GRAIN_CUSTOM
+ ? field.customType()
+ : GrainDescriber(field.crop()).name}
+
+ {field.calculateAcres()}
+
+ {field.permissions.includes(pond.Permission.PERMISSION_WRITE) && (
+
+ )}
+
+
+ ));
+
+ return (
+
+
+
+ {/* {!isMobile && }
+ {!isMobile && } */}
+
+
+
+
+
+
+ Field Name
+ Land Location
+ Main Crop Type
+ Acres ({calcTotalAcres()} Total)
+ Create New Plan
+
+
+ {listFieldsInfo}
+
+
+
+ {/* need to re-factor the harvest table file before restoring these functions */}
+ {/*
+
+
+
+
+ */}
+ setOpenHarvestSettings(false)}
+ field={fieldForPlan}
+ />
+
+ );
+}
\ No newline at end of file
diff --git a/src/navigation/Router.tsx b/src/navigation/Router.tsx
index 377fd7c..a576a50 100644
--- a/src/navigation/Router.tsx
+++ b/src/navigation/Router.tsx
@@ -21,6 +21,7 @@ import Ventilation from "pages/VentEditor";
// import Transactions from "pages/Transactions";
// import BinCableEstimator from "pages/BinCableEstimator";
import { useGlobalState } from "providers";
+// import Fields from "pages/Fields";
//import Site from "pages/Site";
const DeviceHistory = lazy(() => import("pages/DeviceHistory"));
@@ -49,6 +50,7 @@ const Tasks = lazy(() => import("pages/Tasks"));
const Transactions = lazy(() => import("pages/Transactions"));
const BinCableEstimator = lazy(() => import("pages/BinCableEstimator"));
const APIDocs = lazy(() => import("pages/APIDocs"));
+const Fields = lazy(()=> import("pages/Fields"));
interface Props {
toggleTheme: () => void;
@@ -326,6 +328,7 @@ export default function Router(props: Props) {
{user.hasFeature("developer") &&
} />
}
+ } />
{/* Map pages */}
} />
diff --git a/src/navigation/SideNavigator.tsx b/src/navigation/SideNavigator.tsx
index 36c5be5..007b345 100644
--- a/src/navigation/SideNavigator.tsx
+++ b/src/navigation/SideNavigator.tsx
@@ -41,6 +41,7 @@ import { getThemeType } from "theme";
import ObjectHeaterIcon from "products/Construction/ObjectHeaterIcon";
import TasksIcon from "products/Construction/TasksIcon";
import CableIcon from "products/Bindapt/CableIcon";
+import FieldListIcon from "products/AgIcons/FieldList";
const drawerWidth = 230;
@@ -243,6 +244,20 @@ export default function SideNavigator(props: Props) {
)}
+ {(isAg || user.hasFeature("admin")) && (
+
+ goTo("/fields")}
+ classes={getClasses("/fields")}
+ >
+
+
+
+ {open && }
+
+
+ )}
{(isMiPCA || user.hasFeature("admin")) && (
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/pbHelpers/HarvestPlan.ts b/src/pbHelpers/HarvestPlan.ts
new file mode 100644
index 0000000..70e2979
--- /dev/null
+++ b/src/pbHelpers/HarvestPlan.ts
@@ -0,0 +1,43 @@
+import { pond } from "protobuf-ts/pond";
+import { capitalize } from "utils/strings";
+import { or } from "utils";
+import GrainDescriber from "grain/GrainDescriber";
+
+//TODO handle new keys for pre/post seed
+const keyTranslator = new Map([
+ ["createDate", "Create Date"],
+ ["actualYield", "Actual Yield"],
+ ["cropType", "Crop Type"],
+ ["field", "Field"],
+ ["grainType", "grain"],
+ ["yieldTarget", "Yield Target"],
+ ["bushelPrice", "Price per Bushel"],
+ ["preSeedMaterials", "Pre-seed Material Cost (acre)"],
+ ["preSeedEquipment", "Pre-seed Equipment Cost (acre)"]
+]);
+
+// Keys will be stringified by default if not found in the keyTranslator
+export function TranslateKey(key: keyof pond.HarvestPlanSettings): string {
+ let translatedKey = keyTranslator.get(key);
+ return translatedKey ? translatedKey : capitalize(key.toString());
+}
+
+const valueTranslator = new Map<
+ keyof pond.HarvestPlanSettings,
+ (device: pond.HarvestPlanSettings) => string
+>([
+ ["createDate", device => new Date(device.createDate).toString()],
+ ["cropType", device => GrainDescriber(device.cropType).name]
+]);
+
+// Values will be stringified by default if its key is not found in the valueTranslator
+export function TranslateValue(
+ key: keyof pond.HarvestPlanSettings,
+ device: pond.HarvestPlanSettings
+) {
+ let translatorFunc = valueTranslator.get(key);
+ let value: any = or(device[key], "");
+ let d: string;
+ d = or(value.toString(), "");
+ return translatorFunc ? translatorFunc(device) : device[key] ? capitalize(d) : "";
+}