Basic job details.
This commit is contained in:
24
components/data-label/data-label.jsx
Normal file
24
components/data-label/data-label.jsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { DateTime } from "luxon";
|
||||
import React from "react";
|
||||
import { Text, View } from "react-native";
|
||||
|
||||
export default function DataLabelComponent({
|
||||
label,
|
||||
content,
|
||||
dateTime,
|
||||
...restProps
|
||||
}) {
|
||||
let theContent = content;
|
||||
|
||||
if (dateTime && content)
|
||||
theContent = DateTime.fromISO(content).toLocaleString(
|
||||
DateTime.DATETIME_SHORT
|
||||
);
|
||||
const { key, ...rest } = restProps;
|
||||
return (
|
||||
<View key={key} {...rest} style={{ margin: 4, ...restProps.style }}>
|
||||
<Text style={{ color: "slategray" }}>{label}</Text>
|
||||
<Text>{theContent}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
RefreshControl,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { Card, Headline, Subheading } from "react-native-paper";
|
||||
import DataLabelComponent from "../data-label/data-label.component";
|
||||
import StyleRepeater from "../style-repeater/style-repeater";
|
||||
import styles from "../styles";
|
||||
|
||||
export default function JobTombstone({ job, loading, refetch }) {
|
||||
const { t } = useTranslation();
|
||||
if (!job) {
|
||||
<Card>
|
||||
<Text>Job is not defined.</Text>
|
||||
</Card>;
|
||||
}
|
||||
const onRefresh = async () => {
|
||||
return refetch();
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
style={styles.cardBackground}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={loading} onRefresh={onRefresh} />
|
||||
}
|
||||
>
|
||||
<StyleRepeater childStyle={{ margin: 4 }}>
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.jobinfo")} />
|
||||
<Card.Content>
|
||||
<Headline>{job.status}</Headline>
|
||||
{job.inproduction && (
|
||||
<Subheading>{t("objects.jobs.labels.inproduction")}</Subheading>
|
||||
)}
|
||||
{job.inproduction &&
|
||||
job.production_vars &&
|
||||
!!job.production_vars.note && (
|
||||
<Subheading>{job.production_vars.note}</Subheading>
|
||||
)}
|
||||
</Card.Content>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.claiminformation")} />
|
||||
<Card.Content style={localStyles.twoColumnCard}>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.owner")}
|
||||
content={`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
||||
job.ownr_co_nm || ""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.vehicle")}
|
||||
content={
|
||||
<View>
|
||||
<Text>{`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${
|
||||
job.v_model_desc || ""
|
||||
}`}</Text>
|
||||
<Text>{job.v_vin}</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.ins_co_nm")}
|
||||
content={job.ins_co_nm}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.clm_no")}
|
||||
content={job.clm_no}
|
||||
/>
|
||||
</View>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.employeeassignments")} />
|
||||
<Card.Content>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_body")}
|
||||
content={`${
|
||||
(job.employee_body_rel && job.employee_body_rel.first_name) ||
|
||||
""
|
||||
} ${
|
||||
(job.employee_body_rel && job.employee_body_rel.last_name) || ""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_prep")}
|
||||
content={`${
|
||||
(job.employee_prep_rel && job.employee_prep_rel.first_name) ||
|
||||
""
|
||||
} ${
|
||||
(job.employee_prep_rel && job.employee_prep_rel.last_name) || ""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_refinish")}
|
||||
content={`${
|
||||
(job.employee_refinish_rel &&
|
||||
job.employee_refinish_rel.first_name) ||
|
||||
""
|
||||
} ${
|
||||
(job.employee_refinish_rel &&
|
||||
job.employee_refinish_rel.last_name) ||
|
||||
""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_csr")}
|
||||
content={`${
|
||||
(job.employee_csr_rel && job.employee_csr_rel.first_name) || ""
|
||||
} ${
|
||||
(job.employee_csr_rel && job.employee_csr_rel.last_name) || ""
|
||||
}`}
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.dates")} />
|
||||
<Card.Content style={localStyles.twoColumnCard}>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.scheduled_in")}
|
||||
content={job.scheduled_in}
|
||||
dateTime
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.actual_in")}
|
||||
content={job.actual_in}
|
||||
dateTime
|
||||
/>
|
||||
</View>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.scheduled_completion")}
|
||||
content={job.scheduled_completion}
|
||||
dateTime
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.scheduled_delivery")}
|
||||
content={job.scheduled_delivery}
|
||||
dateTime
|
||||
/>
|
||||
</View>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</StyleRepeater>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const localStyles = StyleSheet.create({
|
||||
twoColumnCard: { display: "flex", flexDirection: "row" },
|
||||
twoColumnCardColumn: { flex: 1 },
|
||||
status: {
|
||||
textAlign: "center",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
},
|
||||
inproduction: {
|
||||
textAlign: "center",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
},
|
||||
});
|
||||
72
components/job-lines/job-lines.jsx
Normal file
72
components/job-lines/job-lines.jsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { GET_JOB_BY_PK } from "@/graphql/jobs.queries";
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { useGlobalSearchParams } from "expo-router";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ScrollView, Text } from "react-native";
|
||||
import { ActivityIndicator, Card, DataTable } from "react-native-paper";
|
||||
|
||||
export default function JobLines(props) {
|
||||
const { jobId } = useGlobalSearchParams();
|
||||
|
||||
const { loading, error, data, refetch } = useQuery(GET_JOB_BY_PK, {
|
||||
variables: {
|
||||
id: jobId,
|
||||
},
|
||||
skip: !jobId,
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
const onRefresh = async () => {
|
||||
return refetch();
|
||||
};
|
||||
if (loading) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
if (!data?.jobs_by_pk) {
|
||||
return (
|
||||
<Card>
|
||||
<Text>Job is not defined.</Text>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
const job = data.jobs_by_pk;
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<DataTable>
|
||||
<DataTable.Header>
|
||||
<DataTable.Title> {t("jobdetail.labels.lines_desc")}</DataTable.Title>
|
||||
<DataTable.Title>
|
||||
{t("jobdetail.labels.lines_lbr_ty")}
|
||||
</DataTable.Title>
|
||||
<DataTable.Title numeric>
|
||||
{t("jobdetail.labels.lines_lb_hrs")}
|
||||
</DataTable.Title>
|
||||
<DataTable.Title>
|
||||
{t("jobdetail.labels.lines_part_type")}
|
||||
</DataTable.Title>
|
||||
<DataTable.Title numeric>
|
||||
{t("jobdetail.labels.lines_qty")}
|
||||
</DataTable.Title>
|
||||
</DataTable.Header>
|
||||
|
||||
{job.joblines.map((item) => (
|
||||
<DataTable.Row key={item.id}>
|
||||
<DataTable.Cell style={{ flex: 4 }}>
|
||||
{item.line_desc}
|
||||
</DataTable.Cell>
|
||||
<DataTable.Cell>
|
||||
{item.mod_lbr_ty && t(`jobdetail.lbr_types.${item.mod_lbr_ty}`)}
|
||||
</DataTable.Cell>
|
||||
<DataTable.Cell numeric>{item.mod_lb_hrs}</DataTable.Cell>
|
||||
<DataTable.Cell>
|
||||
{item.part_type && t(`jobdetail.part_types.${item.part_type}`)}
|
||||
</DataTable.Cell>
|
||||
<DataTable.Cell numeric>{item.part_qty}</DataTable.Cell>
|
||||
</DataTable.Row>
|
||||
))}
|
||||
</DataTable>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
186
components/job-tombstone/job-tombstone.jsx
Normal file
186
components/job-tombstone/job-tombstone.jsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import { GET_JOB_BY_PK } from "@/graphql/jobs.queries";
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
RefreshControl,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { ActivityIndicator, Card } from "react-native-paper";
|
||||
import DataLabelComponent from "../data-label/data-label";
|
||||
|
||||
export default function JobTombstone() {
|
||||
const { jobId } = useLocalSearchParams();
|
||||
const { loading, error, data, refetch } = useQuery(GET_JOB_BY_PK, {
|
||||
variables: {
|
||||
id: jobId,
|
||||
},
|
||||
skip: !jobId,
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
const onRefresh = async () => {
|
||||
return refetch();
|
||||
};
|
||||
if (loading) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
if (!data.jobs_by_pk) {
|
||||
return (
|
||||
<Card>
|
||||
<Text>Job is not defined.</Text>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
const job = data.jobs_by_pk;
|
||||
return (
|
||||
<ScrollView
|
||||
contentContainerStyle={{
|
||||
rowGap: 16,
|
||||
padding: 10,
|
||||
}}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={loading} onRefresh={onRefresh} />
|
||||
}
|
||||
>
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.jobinfo")} />
|
||||
<Card.Content>
|
||||
<Text>{job.status}</Text>
|
||||
{job.inproduction && (
|
||||
<Text>{t("objects.jobs.labels.inproduction")}</Text>
|
||||
)}
|
||||
{job.inproduction &&
|
||||
job.production_vars &&
|
||||
!!job.production_vars.note && (
|
||||
<Text>{job.production_vars.note}</Text>
|
||||
)}
|
||||
</Card.Content>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.claiminformation")} />
|
||||
<Card.Content style={localStyles.twoColumnCard}>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.owner")}
|
||||
content={`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
||||
job.ownr_co_nm || ""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.vehicle")}
|
||||
content={
|
||||
<View>
|
||||
<Text>{`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${
|
||||
job.v_model_desc || ""
|
||||
}`}</Text>
|
||||
<Text>{job.v_vin}</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.ins_co_nm")}
|
||||
content={job.ins_co_nm}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.clm_no")}
|
||||
content={job.clm_no}
|
||||
/>
|
||||
</View>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.employeeassignments")} />
|
||||
<Card.Content>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_body")}
|
||||
content={`${
|
||||
(job.employee_body_rel && job.employee_body_rel.first_name) || ""
|
||||
} ${
|
||||
(job.employee_body_rel && job.employee_body_rel.last_name) || ""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_prep")}
|
||||
content={`${
|
||||
(job.employee_prep_rel && job.employee_prep_rel.first_name) || ""
|
||||
} ${
|
||||
(job.employee_prep_rel && job.employee_prep_rel.last_name) || ""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_refinish")}
|
||||
content={`${
|
||||
(job.employee_refinish_rel &&
|
||||
job.employee_refinish_rel.first_name) ||
|
||||
""
|
||||
} ${
|
||||
(job.employee_refinish_rel &&
|
||||
job.employee_refinish_rel.last_name) ||
|
||||
""
|
||||
}`}
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.employee_csr")}
|
||||
content={`${
|
||||
(job.employee_csr_rel && job.employee_csr_rel.first_name) || ""
|
||||
} ${
|
||||
(job.employee_csr_rel && job.employee_csr_rel.last_name) || ""
|
||||
}`}
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
<Card>
|
||||
<Card.Title title={t("jobdetail.labels.dates")} />
|
||||
<Card.Content style={localStyles.twoColumnCard}>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.scheduled_in")}
|
||||
content={job.scheduled_in}
|
||||
dateTime
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.actual_in")}
|
||||
content={job.actual_in}
|
||||
dateTime
|
||||
/>
|
||||
</View>
|
||||
<View style={localStyles.twoColumnCardColumn}>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.scheduled_completion")}
|
||||
content={job.scheduled_completion}
|
||||
dateTime
|
||||
/>
|
||||
<DataLabelComponent
|
||||
label={t("objects.jobs.fields.scheduled_delivery")}
|
||||
content={job.scheduled_delivery}
|
||||
dateTime
|
||||
/>
|
||||
</View>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const localStyles = StyleSheet.create({
|
||||
twoColumnCard: { display: "flex", flexDirection: "row" },
|
||||
twoColumnCardColumn: { flex: 1 },
|
||||
status: {
|
||||
textAlign: "center",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
},
|
||||
inproduction: {
|
||||
textAlign: "center",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user