Add job tabs.

This commit is contained in:
Patrick Fic
2025-10-08 14:09:09 -07:00
parent 820da94a9f
commit 00626328c4
8 changed files with 275 additions and 1 deletions

View File

@@ -0,0 +1,59 @@
import FontAwesome from "@expo/vector-icons/FontAwesome";
import { Tabs } from "expo-router";
import { useTranslation } from "react-i18next";
function JobTabLayout() {
const { t } = useTranslation();
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: "blue",
tabBarPosition: "top",
headerShown: false,
tabBarStyle: {
marginTop: -50,
},
}}
>
<Tabs.Screen
name="index"
options={{
title: t("jobdetail.labels.job"),
tabBarIcon: ({ color }) => (
<FontAwesome size={28} name="home" color={color} />
),
}}
/>
<Tabs.Screen
name="lines"
options={{
title: t("jobdetail.labels.lines"),
tabBarIcon: ({ color }) => (
<FontAwesome size={28} name="cog" color={color} />
),
}}
/>
<Tabs.Screen
name="documents"
options={{
title: t("jobdetail.labels.documents"),
tabBarIcon: ({ color }) => (
<FontAwesome size={28} name="cog" color={color} />
),
}}
/>
<Tabs.Screen
name="notes"
options={{
title: t("jobdetail.labels.notes"),
tabBarIcon: ({ color }) => (
<FontAwesome size={28} name="cog" color={color} />
),
}}
/>
</Tabs>
);
}
export default JobTabLayout;

View File

@@ -0,0 +1,10 @@
import { Text, View } from "react-native";
function Documents() {
return (
<View>
<Text>Documents</Text>
</View>
);
}
export default Documents;

View File

@@ -1,12 +1,14 @@
import { useLocalSearchParams } from "expo-router"; import { useLocalSearchParams } from "expo-router";
import { StyleSheet, Text, View } from "react-native"; import { StyleSheet, Text, View } from "react-native";
import JobDetail from "../../../components/job-detail/job-detail";
export default function JobDetail() { export default function JobDetailScreen() {
const params = useLocalSearchParams(); const params = useLocalSearchParams();
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text>Job Details for Job ID: {JSON.stringify(params)}</Text> <Text>Job Details for Job ID: {JSON.stringify(params)}</Text>
<JobDetail />
</View> </View>
); );
} }

View File

@@ -0,0 +1,10 @@
import { Text, View } from "react-native";
function JobLines() {
return (
<View>
<Text>Job Lines</Text>
</View>
);
}
export default JobLines;

View File

@@ -0,0 +1,10 @@
import { Text, View } from "react-native";
function Notes() {
return (
<View>
<Text>Notes</Text>
</View>
);
}
export default Notes;

View File

@@ -31,6 +31,7 @@ function JobsStack() {
<Stack.Screen <Stack.Screen
name="[jobId]" name="[jobId]"
options={({ route }) => ({ options={({ route }) => ({
//headerShown: false,
title: (route.params as any)?.title || "Job Details", title: (route.params as any)?.title || "Job Details",
})} })}
/> />

View File

@@ -0,0 +1,9 @@
import { Text, View } from "react-native";
export default function ErrorDisplay({ errorMessage }) {
return (
<View style={{ backgroundColor: "red" }}>
<Text>{errorMessage}</Text>
</View>
);
}

View File

@@ -0,0 +1,173 @@
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",
},
});