Files
imexmobile/components/labor-allocations-table/labor-allocations-table.component.jsx
2023-07-25 14:10:27 -04:00

191 lines
6.8 KiB
JavaScript

import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { FlatList, StyleSheet, Text, View } from "react-native";
import _ from "lodash";
import { ActivityIndicator, Card, DataTable, Divider } from "react-native-paper";
import { GET_LINE_TICKET_BY_PK } from "../../graphql/jobs.queries";
import ErrorDisplay from "../error-display/error-display.component";
import { useQuery } from "@apollo/client";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { selectCurrentEmployee } from "../../redux/employee/employee.selectors";
import { CalculateAllocationsTotals } from "../../util/labor-allocations-table.utility";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
technician: selectCurrentEmployee,
});
export function LaborAllocationsTable({ jobId, bodyshop, technician,costCenterDiff,selectedCostCenter, style, shouldRefresh}) {
const { t } = useTranslation();
const onRefresh = async () => { return refetch(); };
const { loading, error, data, refetch } = useQuery(GET_LINE_TICKET_BY_PK, {
variables: { id: jobId },
skip: !!!jobId,
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
});
if (error) return <ErrorDisplay errorMessage={error.message} />;
const [totals, setTotals] = useState([]);
useEffect(() => {
if (!!data?.joblines && !!data?.timetickets && !!bodyshop){
let temptotals = CalculateAllocationsTotals(
bodyshop,
data?.joblines,
data?.timetickets,
data?.adjustments
);
if(!!selectedCostCenter){
let tempCostCenterDiff = Math.round(
temptotals.find(
(total) =>
total["cost_center"] === selectedCostCenter.label
)?.difference * 10
) / 10;
costCenterDiff.current= tempCostCenterDiff;
}
setTotals(
temptotals
);
}
if (!jobId) setTotals([]);
}, [data?.joblines, data?.timetickets, bodyshop, data?.adjustments, jobId, selectedCostCenter]);
useEffect(() => {
!!shouldRefresh && shouldRefresh ? onRefresh() : null
},[shouldRefresh]);
const summary =
totals &&
totals.reduce(
(acc, val) => {
acc.hrs_total += val.total;
acc.hrs_claimed += val.claimed;
acc.adjustments += val.adjustments;
acc.difference += val.difference;
return acc;
},
{ hrs_total: 0, hrs_claimed: 0, adjustments: 0, difference: 0 }
);
if (loading) return <ActivityIndicator color="dodgerblue" size="large" />;
return (
<View style={style}>
{typeof data !== "undefined" ? (
<Card style={{ flex: 1 }}>
<Card.Title title={t("laborallocations.labels.laborallocations")} />
<Card.Content>
<View style={localStyles.headerArea}>
<Text style={localStyles.headertext}>{t("laborallocations.labels.costcenter")}</Text>
<Text style={localStyles.headertext}>{t("laborallocations.labels.hourstotal")}</Text>
<Text style={localStyles.headertext}>{t("laborallocations.labels.hoursclaimed")}</Text>
{/* <Text numberOfLines={2} style={{ flex: 1, flexWrap:'wrap' }}>Hours Claimed</Text> */}
<Text style={localStyles.headertextAdjusts}>{t("laborallocations.labels.adjustments")}</Text>
<Text style={localStyles.headertext}>{t("laborallocations.labels.difference")}</Text>
</View>
<Divider orientation="vertical" />
<DataTable>
<FlatList
data={totals}
keyExtractor={(item) => item.cost_center}
ItemSeparatorComponent={<Divider orientation="vertical" />}
renderItem={(object) => (
<DataTable.Row style={{ flex: 1, justifyContent:"space-evenly" }}>
<View style={{ flex: 1, alignItems: "flex-start" }}>
<Text>
{object.item.cost_center} {" ("}
{object.item.mod_lbr_ty}
{")"}
</Text>
</View>
<View style={{ flex: 1, alignItems: "center" }}>
<Text>
{object.item.total && object.item.total.toFixed(1)}
</Text>
</View>
<View style={{ flex: 1, alignItems: "center" }}>
<Text>
{object.item.claimed && object.item.claimed.toFixed(1)}
</Text>
</View>
<View style={{ flex: 1, alignItems: "center" }}>
<Text>
{object.item.adjustments &&
object.item.adjustments.toFixed(1)}
</Text>
</View>
<View style={{ flex: 1, alignItems: "center" }}>
<Text
style={{
color: object.item.difference >= 0 ? "green" : "red",
}}
>
{_.round(object.item.difference, 1)}
</Text>
</View>
</DataTable.Row>
)}
/>
{summary && (
<View style={localStyles.headerArea}>
<Text style={localStyles.footertext}>{t("laborallocations.labels.totals")}</Text>
<Text style={localStyles.footertext}>
{summary.hrs_total.toFixed(1)}
</Text>
<Text style={localStyles.footertext}>
{summary.hrs_claimed.toFixed(1)}
</Text>
<Text style={localStyles.footertext}>
{summary.adjustments.toFixed(1)}
</Text>
<Text style={localStyles.footertext}>
{summary.difference.toFixed(1)}
</Text>
</View>
)}
</DataTable>
</Card.Content>
</Card>
) : null}
{/* use "totals" for the rows in the table */}
{/* use "summary" for the totals at the bottom */}
</View>
);
}
const localStyles = StyleSheet.create({
headerArea: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
margin: 1,
},
footertext: {
flex: 1,
textAlign: "center",
textAlignVertical: "center",
margin: 1,
paddingBottom: 8,
},
headertext: {
flex: 1,
textAlign: "center",
textAlignVertical: "center",
margin: 1,
paddingBottom: 8,
},
headertextAdjusts: {
flex: 1,
textAlign: "center",
textAlignVertical: "center",
margin: 1,
paddingBottom: 8,
},
});
export default connect(mapStateToProps, null)(LaborAllocationsTable);