From 00626328c4d720bcdb6d4ac39d174ea345b277ec Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 8 Oct 2025 14:09:09 -0700 Subject: [PATCH] Add job tabs. --- app/jobs/[jobId]/_layout.tsx | 59 +++++++ app/jobs/[jobId]/documents.tsx | 10 ++ app/jobs/{[jobId].tsx => [jobId]/index.tsx} | 4 +- app/jobs/[jobId]/lines.tsx | 10 ++ app/jobs/[jobId]/notes.tsx | 10 ++ app/jobs/_layout.tsx | 1 + components/error/error-display.jsx | 9 + components/job-detail/job-detail.jsx | 173 ++++++++++++++++++++ 8 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 app/jobs/[jobId]/_layout.tsx create mode 100644 app/jobs/[jobId]/documents.tsx rename app/jobs/{[jobId].tsx => [jobId]/index.tsx} (75%) create mode 100644 app/jobs/[jobId]/lines.tsx create mode 100644 app/jobs/[jobId]/notes.tsx create mode 100644 components/error/error-display.jsx create mode 100644 components/job-detail/job-detail.jsx diff --git a/app/jobs/[jobId]/_layout.tsx b/app/jobs/[jobId]/_layout.tsx new file mode 100644 index 0000000..9fbbfff --- /dev/null +++ b/app/jobs/[jobId]/_layout.tsx @@ -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 ( + + ( + + ), + }} + /> + ( + + ), + }} + /> + ( + + ), + }} + /> + ( + + ), + }} + /> + + ); +} + +export default JobTabLayout; diff --git a/app/jobs/[jobId]/documents.tsx b/app/jobs/[jobId]/documents.tsx new file mode 100644 index 0000000..a00269b --- /dev/null +++ b/app/jobs/[jobId]/documents.tsx @@ -0,0 +1,10 @@ +import { Text, View } from "react-native"; + +function Documents() { + return ( + + Documents + + ); +} +export default Documents; diff --git a/app/jobs/[jobId].tsx b/app/jobs/[jobId]/index.tsx similarity index 75% rename from app/jobs/[jobId].tsx rename to app/jobs/[jobId]/index.tsx index ff52b6a..8cca6a1 100644 --- a/app/jobs/[jobId].tsx +++ b/app/jobs/[jobId]/index.tsx @@ -1,12 +1,14 @@ import { useLocalSearchParams } from "expo-router"; 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(); return ( Job Details for Job ID: {JSON.stringify(params)} + ); } diff --git a/app/jobs/[jobId]/lines.tsx b/app/jobs/[jobId]/lines.tsx new file mode 100644 index 0000000..2902eb3 --- /dev/null +++ b/app/jobs/[jobId]/lines.tsx @@ -0,0 +1,10 @@ +import { Text, View } from "react-native"; + +function JobLines() { + return ( + + Job Lines + + ); +} +export default JobLines; diff --git a/app/jobs/[jobId]/notes.tsx b/app/jobs/[jobId]/notes.tsx new file mode 100644 index 0000000..38b41c0 --- /dev/null +++ b/app/jobs/[jobId]/notes.tsx @@ -0,0 +1,10 @@ +import { Text, View } from "react-native"; + +function Notes() { + return ( + + Notes + + ); +} +export default Notes; diff --git a/app/jobs/_layout.tsx b/app/jobs/_layout.tsx index ed4fa48..78202d7 100644 --- a/app/jobs/_layout.tsx +++ b/app/jobs/_layout.tsx @@ -31,6 +31,7 @@ function JobsStack() { ({ + //headerShown: false, title: (route.params as any)?.title || "Job Details", })} /> diff --git a/components/error/error-display.jsx b/components/error/error-display.jsx new file mode 100644 index 0000000..df4b749 --- /dev/null +++ b/components/error/error-display.jsx @@ -0,0 +1,9 @@ +import { Text, View } from "react-native"; + +export default function ErrorDisplay({ errorMessage }) { + return ( + + {errorMessage} + + ); +} diff --git a/components/job-detail/job-detail.jsx b/components/job-detail/job-detail.jsx new file mode 100644 index 0000000..e556f49 --- /dev/null +++ b/components/job-detail/job-detail.jsx @@ -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) { + + Job is not defined. + ; + } + const onRefresh = async () => { + return refetch(); + }; + + return ( + + } + > + + + + + {job.status} + {job.inproduction && ( + {t("objects.jobs.labels.inproduction")} + )} + {job.inproduction && + job.production_vars && + !!job.production_vars.note && ( + {job.production_vars.note} + )} + + + + + + + + + + {`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${ + job.v_model_desc || "" + }`} + {job.v_vin} + + } + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +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", + }, +});