From a207d5dff76ffef8b6b91556d78ff4969b16b1a2 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 27 Oct 2025 15:01:02 -0700 Subject: [PATCH] Delete unused code, remove logs, add dnd package. --- app.config.js | 4 +- app/_layout.tsx | 4 + .../camera-controls.component.jsx | 103 ----- .../camera-select-job.component.jsx | 184 -------- .../error-display/error-display.component.jsx | 10 - .../flat-list-item-separator.component.jsx | 15 - .../job-documents-local.component.jsx | 112 ----- .../job-documents/job-documents.component.jsx | 175 ------- .../job-lines/job-lines.component.jsx | 72 --- .../job-list-item/job-list-item.component.jsx | 90 ---- .../job-list/job-list.component.jsx | 94 ---- .../job-notes-item.component.jsx | 46 -- .../job-notes/job-notes.component.jsx | 37 -- .../job-space-available.component.jsx | 44 -- .../job-tombstone/job-tombstone.component.jsx | 172 ------- .../loading-display.component.jsx | 12 - .../media-cache-overlay.component.jsx | 27 -- .../screen-camera/screen-camera.jsx | 157 ------- .../screen-job-detail.component.jsx | 101 ----- .../screen-job-list.component.jsx | 6 - .../screen-main/screen-main.component.jsx | 197 -------- .../screen-media-browser.component.jsx | 162 ------- .../screen-media-cache.component.jsx | 140 ------ ...creen-messaging-conversation.component.jsx | 10 - .../screen-messaging-list.component.jsx | 10 - .../screen-production/screen-production.jsx | 90 ---- .../screen-settings.component.jsx | 34 -- .../screen-sign-in.component.jsx | 113 ----- .../screen-splash/screen-splash.component.jsx | 46 -- .../sign-in-error-alert.component.jsx | 53 --- .../style-repeater/style-repeater.jsx | 13 - components-old/styles.js | 12 - .../upload-delete-switch.component.jsx | 52 --- .../upload-progress-local.component.jsx | 218 --------- .../upload-progress.component.jsx | 426 ------------------ components/global-search/global-search.jsx | 2 - components/job-documents/job-documents.jsx | 5 - components/settings/settings.jsx | 10 +- constants/theme.ts | 53 --- env.js | 2 - graphql/client.js | 36 +- package-lock.json | 21 +- package.json | 3 +- redux/photos/photos.sagas.js | 6 +- 44 files changed, 42 insertions(+), 3137 deletions(-) delete mode 100644 components-old/camera-controls/camera-controls.component.jsx delete mode 100644 components-old/camera-select-job/camera-select-job.component.jsx delete mode 100644 components-old/error-display/error-display.component.jsx delete mode 100644 components-old/flat-list-item-separator/flat-list-item-separator.component.jsx delete mode 100644 components-old/job-documents/job-documents-local.component.jsx delete mode 100644 components-old/job-documents/job-documents.component.jsx delete mode 100644 components-old/job-lines/job-lines.component.jsx delete mode 100644 components-old/job-list-item/job-list-item.component.jsx delete mode 100644 components-old/job-list/job-list.component.jsx delete mode 100644 components-old/job-notes-item/job-notes-item.component.jsx delete mode 100644 components-old/job-notes/job-notes.component.jsx delete mode 100644 components-old/job-space-available/job-space-available.component.jsx delete mode 100644 components-old/job-tombstone/job-tombstone.component.jsx delete mode 100644 components-old/loading-display/loading-display.component.jsx delete mode 100644 components-old/media-cache-overlay/media-cache-overlay.component.jsx delete mode 100644 components-old/screen-camera/screen-camera.jsx delete mode 100644 components-old/screen-job-detail/screen-job-detail.component.jsx delete mode 100644 components-old/screen-job-list/screen-job-list.component.jsx delete mode 100644 components-old/screen-main/screen-main.component.jsx delete mode 100644 components-old/screen-media-browser/screen-media-browser.component.jsx delete mode 100644 components-old/screen-media-cache/screen-media-cache.component.jsx delete mode 100644 components-old/screen-messaging-conversation/screen-messaging-conversation.component.jsx delete mode 100644 components-old/screen-messaging-list/screen-messaging-list.component.jsx delete mode 100644 components-old/screen-production/screen-production.jsx delete mode 100644 components-old/screen-settings/screen-settings.component.jsx delete mode 100644 components-old/screen-sign-in/screen-sign-in.component.jsx delete mode 100644 components-old/screen-splash/screen-splash.component.jsx delete mode 100644 components-old/sign-in-error-alert/sign-in-error-alert.component.jsx delete mode 100644 components-old/style-repeater/style-repeater.jsx delete mode 100644 components-old/styles.js delete mode 100644 components-old/upload-delete-switch/upload-delete-switch.component.jsx delete mode 100644 components-old/upload-progress-local/upload-progress-local.component.jsx delete mode 100644 components-old/upload-progress/upload-progress.component.jsx delete mode 100644 constants/theme.ts diff --git a/app.config.js b/app.config.js index 43a6812..01ba285 100644 --- a/app.config.js +++ b/app.config.js @@ -15,7 +15,7 @@ export default ({ config }) => { projectId: IS_ROME ? "df105e21-a07f-4425-af10-2200a7704a48" : "ffe01f3a-d507-4698-82cd-da1f1cad450b" } }, - icon: IS_ROME ? "./assets/RomeIcon.png" : "./assets/logo192noa.png", + icon: IS_ROME ? "./assets/RomeIcon.png" : "./assets/ImEXlogo192noa.png", ios: { ...config.ios, bundleIdentifier: IS_ROME ? "com.rome.mobile" : "com.imex.imexmobile" @@ -55,7 +55,5 @@ export default ({ config }) => { } }) - - console.log("New Expo Config:", JSON.stringify(newConfig, null, 2)); return newConfig; }; \ No newline at end of file diff --git a/app/_layout.tsx b/app/_layout.tsx index 121fd00..414e42c 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,6 +1,7 @@ import { checkUserSession } from "@/redux/user/user.actions"; import { selectBodyshop, selectCurrentUser } from "@/redux/user/user.selectors"; import { ApolloProvider } from "@apollo/client"; +import { loadDevMessages, loadErrorMessages } from "@apollo/client/dev"; import MaterialIcons from "@expo/vector-icons/MaterialIcons"; import { DarkTheme, @@ -28,6 +29,9 @@ import { persistor, store } from "../redux/store"; import "../translations/i18n"; import { registerForPushNotificationsAsync } from "../util/notificationHandler"; +loadDevMessages(); +loadErrorMessages(); + function AuthenticatedLayout() { const { t } = useTranslation(); const paperTheme = usePaperTheme(); diff --git a/components-old/camera-controls/camera-controls.component.jsx b/components-old/camera-controls/camera-controls.component.jsx deleted file mode 100644 index e015c58..0000000 --- a/components-old/camera-controls/camera-controls.component.jsx +++ /dev/null @@ -1,103 +0,0 @@ -// // src/toolbar.component.js file -// import { Ionicons } from "@expo/vector-icons"; -// import { Camera } from "expo-camera"; -// import React from "react"; -// import { -// StyleSheet, -// TouchableOpacity, -// TouchableWithoutFeedback, -// View, -// } from "react-native"; - -// const styles = StyleSheet.create({ -// alignCenter: { -// flex: 1, -// alignItems: "center", -// justifyContent: "center", -// }, -// bottomToolbar: { -// marginTop: "auto", -// height: 100, -// display: "flex", -// justifyContent: "space-evenly", -// alignItems: "center", -// flexDirection: "row", -// }, -// captureBtn: { -// width: 60, -// height: 60, -// borderWidth: 2, -// borderRadius: 60, -// borderColor: "#FFFFFF", -// }, -// captureBtnActive: { -// width: 80, -// height: 80, -// }, -// captureBtnInternal: { -// width: 76, -// height: 76, -// borderWidth: 2, -// borderRadius: 76, -// backgroundColor: "red", -// borderColor: "transparent", -// }, -// }); - -// const { FlashMode: CameraFlashModes, Type: CameraTypes } = Camera.Constants; - -// export default function CameraControls({ -// capturing = false, -// cameraType = CameraTypes.back, -// flashMode = CameraFlashModes.off, -// setFlashMode, -// setCameraType, -// onCaptureIn, -// onCaptureOut, -// onLongCapture, -// onShortCapture, -// }) { -// return ( -// -// -// setFlashMode( -// flashMode === CameraFlashModes.on -// ? CameraFlashModes.off -// : CameraFlashModes.on -// ) -// } -// > -// -// - -// -// -// {capturing && } -// -// - -// -// setCameraType( -// cameraType === CameraTypes.back -// ? CameraTypes.front -// : CameraTypes.back -// ) -// } -// > -// -// -// -// ); -// } diff --git a/components-old/camera-select-job/camera-select-job.component.jsx b/components-old/camera-select-job/camera-select-job.component.jsx deleted file mode 100644 index fccbd55..0000000 --- a/components-old/camera-select-job/camera-select-job.component.jsx +++ /dev/null @@ -1,184 +0,0 @@ -import { useQuery } from "@apollo/client"; -import { Ionicons } from "@expo/vector-icons"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { FlatList, RefreshControl, View } from "react-native"; -import { Button, List, Modal, Portal, Searchbar } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries"; -import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions"; -import { - selectCurrentCameraJob, - selectCurrentCameraJobId, -} from "../../redux/app/app.selectors"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import ErrorDisplay from "../error-display/error-display.component"; -import LoadingDisplay from "../loading-display/loading-display.component"; - -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, - cameraJobId: selectCurrentCameraJobId, - cameraJob: selectCurrentCameraJob, -}); - -const mapDispatchToProps = (dispatch) => ({ - setCameraJobId: (id) => dispatch(setCameraJobId(id)), - setCameraJob: (job) => dispatch(setCameraJob(job)), -}); - -export function CameraSelectJob({ - bodyshop, - cameraJobId, - setCameraJobId, - cameraJob, - setCameraJob, -}) { - const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { - variables: { - statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], - }, - skip: !bodyshop, - }); - const { t } = useTranslation(); - const [visible, setVisible] = React.useState(false); - const [searchQuery, setSearchQuery] = React.useState(""); - if (loading) return ; - if (error) return ; - - const showModal = () => setVisible(true); - const hideModal = () => setVisible(false); - - const onRefresh = async () => { - return refetch(); - }; - - const onChangeSearch = (query) => setSearchQuery(query); - - const jobs = data - ? searchQuery === "" - ? data.jobs - : data.jobs.filter( - (j) => - (j.ro_number || "") - .toString() - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.ownr_co_nm || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.ownr_fn || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.ownr_ln || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.plate_no || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.v_model_desc || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.v_make_desc || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) - ) - : []; - - return ( - <> - - - - - - - - } - data={[{ id: "temp", ro_number: "Temporary Storage" }, ...jobs]} - keyExtractor={(item) => item.id} - renderItem={(object) => ( - { - setCameraJobId(object.item.id); - setCameraJob(object.item); - hideModal(); - setSearchQuery(""); - }} - left={() => { - if (object.item.id !== cameraJobId) return null; - return ( - - ); - }} - titleStyle={{ - ...(object.item.id === cameraJobId - ? { color: "dodgerblue" } - : {}), - }} - title={`${ - object.item.ro_number ? `${object.item.ro_number} ` : `` - }${object.item.ownr_fn || ""} ${object.item.ownr_ln || ""} ${ - object.item.ownr_co_nm || "" - } ${ - object.item.v_model_yr ? `- ${object.item.v_model_yr}` : "" - } ${ - object.item.v_make_desc ? `- ${object.item.v_make_desc}` : "" - } ${ - object.item.v_model_desc - ? `- ${object.item.v_model_desc}` - : "" - }`} - key={object.item.id} - /> - )} - /> - - - - - ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(CameraSelectJob); diff --git a/components-old/error-display/error-display.component.jsx b/components-old/error-display/error-display.component.jsx deleted file mode 100644 index 84f41b6..0000000 --- a/components-old/error-display/error-display.component.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import { View, Text } from "react-native"; - -export default function ErrorDisplay({ errorMessage }) { - return ( - - {errorMessage} - - ); -} diff --git a/components-old/flat-list-item-separator/flat-list-item-separator.component.jsx b/components-old/flat-list-item-separator/flat-list-item-separator.component.jsx deleted file mode 100644 index 511a779..0000000 --- a/components-old/flat-list-item-separator/flat-list-item-separator.component.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import { View, Text } from "react-native"; - -export default function FlatListItemSeparator() { - return ( - - ); -} diff --git a/components-old/job-documents/job-documents-local.component.jsx b/components-old/job-documents/job-documents-local.component.jsx deleted file mode 100644 index 181d31b..0000000 --- a/components-old/job-documents/job-documents-local.component.jsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { - FlatList, - Image, - RefreshControl, - Text, - TouchableOpacity, - View, -} from "react-native"; -import MediaCacheOverlay from "../media-cache-overlay/media-cache-overlay.component"; -import * as Sentry from "@sentry/react-native"; -import Toast from "react-native-toast-message"; - -import cleanAxios from "../../util/CleanAxios"; - -export default function JobDocumentsLocalComponent({ bodyshop, job }) { - const [previewVisible, setPreviewVisible] = useState(false); - const [images, setImages] = useState([]); - const [imgIndex, setImgIndex] = useState(0); - useEffect(() => { - if (job.id) { - getPhotos({ bodyshop, jobid: job.id, setImages }); - } - }, [job.id, bodyshop]); - - const onRefresh = async () => { - return getPhotos({ bodyshop, jobid: job.id, setImages }); - }; - - return ( - - - } - data={images} - numColumns={4} - style={{ flex: 1 }} - keyExtractor={(item) => item.id} - renderItem={(object) => ( - { - setImgIndex(object.index); - setPreviewVisible(true); - }} - > - - - )} - /> - - {images?.filter((d) => d.type?.mime?.startsWith("image")).length} - - - - - ); -} - -async function getPhotos({ bodyshop, jobid, setImages }) { - let localmediaserverhttp = bodyshop.localmediaserverhttp.trim(); - if (localmediaserverhttp.endsWith("/")) { - localmediaserverhttp = localmediaserverhttp.slice(0, -1); - } - - try { - const imagesFetch = await cleanAxios.post( - `${localmediaserverhttp}/jobs/list`, - { - jobid, - }, - { headers: { ims_token: bodyshop.localmediatoken } } - ); - - const normalizedImages = imagesFetch.data - .filter((d) => d.type?.mime?.startsWith("image")) - .map((d, idx) => { - return { - ...d, - // src: `${localmediaserverhttp}/${d.src}`, - - uri: `${localmediaserverhttp}${d.src}`, - thumbUrl: `${localmediaserverhttp}${d.thumbnail}`, - id: idx, - }; - }); - - setImages(normalizedImages); - } catch (error) { - Sentry.captureException(error); - Toast.show({ - type: "error", - text1: `Error fetching photos.`, - - text2: JSON.stringify(error), - }); - } -} diff --git a/components-old/job-documents/job-documents.component.jsx b/components-old/job-documents/job-documents.component.jsx deleted file mode 100644 index 899d05d..0000000 --- a/components-old/job-documents/job-documents.component.jsx +++ /dev/null @@ -1,175 +0,0 @@ -import axios from "axios"; -import React, { useEffect, useState } from "react"; -import { - FlatList, - Image, - RefreshControl, - Text, - TouchableOpacity, - View, -} from "react-native"; -import env from "../../env"; -import { DetermineFileType } from "../../util/document-upload.utility"; -import MediaCacheOverlay from "../media-cache-overlay/media-cache-overlay.component"; - -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -//import { splitClient } from "../screen-main/screen-main.component"; - -const mapStateToProps = createStructuredSelector({ - //currentUser: selectCurrentUser - bodyshop: selectBodyshop, -}); -const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) -}); -export default connect( - mapStateToProps, - mapDispatchToProps -)(JobDocumentsComponent); - -export function JobDocumentsComponent({ bodyshop, job, loading, refetch }) { - const [previewVisible, setPreviewVisible] = useState(false); - const [fullphotos, setFullPhotos] = useState([]); - const [imgIndex, setImgIndex] = useState(0); - - const useImgproxy = splitClient?.getTreatment("Imgproxy"); - - const onRefresh = async () => { - return refetch(); - }; - - useEffect(() => { - async function getPhotos() { - if (useImgproxy) { - const result = await axios.post( - `${env.API_URL}/media/imgproxy/thumbnails`, - { - jobid: job.id, - } - ); - - setFullPhotos( - result.data.map((doc, idx) => { - return { - id: idx, - videoUrl: - DetermineFileType(doc.type) === "video" && - doc.originalUrlViaProxyPath, - source: - DetermineFileType(doc.type) === "video" - ? { uri: doc.thumbnailUrl } - : { uri: doc.originalUrl }, - url: - DetermineFileType(doc.type) === "video" - ? doc.thumbnailUrl - : doc.originalUrl, - uri: - DetermineFileType(doc.type) === "video" - ? doc.originalUrlViaProxyPath - : doc.originalUrl, - thumbUrl: doc.thumbnailUrl, - }; - }) - ); - } else { - setFullPhotos( - job.documents.map((doc, idx) => { - return { - id: idx, - videoUrl: - DetermineFileType(doc.type) === "video" && GenerateSrcUrl(doc), - source: - DetermineFileType(doc.type) === "video" - ? { uri: GenerateThumbUrl(doc) } - : { uri: GenerateSrcUrl(doc) }, - url: - DetermineFileType(doc.type) === "video" - ? GenerateThumbUrl(doc) - : GenerateSrcUrl(doc), - uri: - DetermineFileType(doc.type) === "video" - ? GenerateThumbUrl(doc) - : GenerateSrcUrl(doc), - thumbUrl: GenerateThumbUrl(doc), - }; - }) - ); - } - } - - getPhotos(); - }, [job.documents]); - - return ( - - - } - data={fullphotos} - numColumns={4} - style={{ flex: 1 }} - keyExtractor={(item) => item.id} - renderItem={(object) => ( - { - setImgIndex(object.index); - setPreviewVisible(true); - }} - > - - - )} - /> - - - {fullphotos.length} - - - - - ); -} - -export const GenerateSrcUrl = (value) => { - let extension = value.extension; - if (extension && extension.toLowerCase().includes("heic")) extension = "jpg"; - - return `${env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType( - value.type - )}/upload/${value.key}${extension ? `.${extension}` : ""}`; -}; - -export const GenerateThumbUrl = (value) => { - let extension = value.extension; - if (extension && extension.includes("heic")) extension = "jpg"; - else if ( - DetermineFileType(value.type) !== "image" || - (value.type && value.type.includes("application")) - ) - extension = "jpg"; - - return `${env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType( - value.type - )}/upload/${env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS}/${value.key}${ - extension ? `.${extension}` : "" - }`; -}; diff --git a/components-old/job-lines/job-lines.component.jsx b/components-old/job-lines/job-lines.component.jsx deleted file mode 100644 index 05240b4..0000000 --- a/components-old/job-lines/job-lines.component.jsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { FlatList, RefreshControl, StyleSheet, Text, View } from "react-native"; -import { Card, DataTable } from "react-native-paper"; - -export default function JobLines({ job, loading, refetch }) { - const { t } = useTranslation(); - - if (!job) { - - Job is not defined. - ; - } - const onRefresh = async () => { - return refetch(); - }; - - return ( - - - - - {t("jobdetail.labels.lines_desc")} - - - {t("jobdetail.labels.lines_lbr_ty")} - - - {t("jobdetail.labels.lines_lb_hrs")} - - - {t("jobdetail.labels.lines_part_type")} - - - {t("jobdetail.labels.lines_qty")} - - - - - - } - keyExtractor={(item) => item.id} - renderItem={(object) => ( - - - {object.item.line_desc} - - - {object.item.mod_lbr_ty && - t(`jobdetail.lbr_types.${object.item.mod_lbr_ty}`)} - - - {object.item.mod_lb_hrs} - - - {object.item.part_type && - t(`jobdetail.part_types.${object.item.part_type}`)} - - - {object.item.part_qty} - - - )} - /> - - ); -} - -const localStyles = StyleSheet.create({}); diff --git a/components-old/job-list-item/job-list-item.component.jsx b/components-old/job-list-item/job-list-item.component.jsx deleted file mode 100644 index 5d7a516..0000000 --- a/components-old/job-list-item/job-list-item.component.jsx +++ /dev/null @@ -1,90 +0,0 @@ -import { Ionicons } from "@expo/vector-icons"; -import { useNavigation } from "@react-navigation/native"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { Button, List, Title } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { logImEXEvent } from "../../firebase/firebase.analytics"; -import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions"; - -const mapStateToProps = createStructuredSelector({}); -const mapDispatchToProps = (dispatch) => ({ - setCameraJobId: (id) => dispatch(setCameraJobId(id)), - setCameraJob: (job) => dispatch(setCameraJob(job)), -}); - -export function JobListItem({ setCameraJob, setCameraJobId, item }) { - const { t } = useTranslation(); - const navigation = useNavigation(); - // const _swipeableRow = useRef(null); - - // const RenderRightAction = (progress, dragX) => { - // const scale = dragX.interpolate({ - // inputRange: [-100, 0], - // outputRange: [0.7, 0], - // }); - - // return ( - // { - // logImEXEvent("imexmobile_setcamerajobid_swipe"); - // setCameraJobId(item.id); - // setCameraJob(item); - // navigation.navigate("MediaBrowserTab"); - // _swipeableRow.current.close(); - // }} - // > - // - // - // - // - // ); - // }; - - const onPress = () => { - logImEXEvent("imexmobile_view_job_detail"); - navigation.push("JobDetail", { - jobId: item.id, - title: item.ro_number || t("general.labels.na"), - job: item, - }); - }; - - return ( - {item.ro_number || t("general.labels.na")}} - description={`${item.ownr_fn || ""} ${item.ownr_ln || ""} ${ - item.ownr_co_nm || "" - } - ${item.v_model_yr || ""} ${item.v_make_desc || ""} ${ - item.v_model_desc || "" - }`} - right={({ style }) => ( - - )} - /> - ); -} - -export default connect(mapStateToProps, mapDispatchToProps)(JobListItem); diff --git a/components-old/job-list/job-list.component.jsx b/components-old/job-list/job-list.component.jsx deleted file mode 100644 index 56db494..0000000 --- a/components-old/job-list/job-list.component.jsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useQuery } from "@apollo/client"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { FlatList, RefreshControl, Text, View } from "react-native"; -import { Button, Searchbar, Title } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import ErrorDisplay from "../error-display/error-display.component"; -import JobListItem from "../job-list-item/job-list-item.component"; -import LoadingDisplay from "../loading-display/loading-display.component"; - -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, -}); - -export function JobListComponent({ bodyshop }) { - const { t } = useTranslation(); - const [searchQuery, setSearchQuery] = React.useState(""); - const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { - variables: { - statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], - }, - skip: !bodyshop, - notifyOnNetworkStatusChange: true, - }); - - const onRefresh = async () => { - return refetch(); - }; - const onChangeSearch = (query) => setSearchQuery(query); - - if (loading) return ; - if (error) return ; - if (data && data.jobs && data.jobs.length === 0) - return ( - - - <Text>{t("joblist.labels.nojobs")}</Text> - - - - ); - - const jobs = data - ? searchQuery === "" - ? data.jobs - : data.jobs.filter( - (j) => - (j.ro_number || "") - .toString() - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.ownr_co_nm || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.ownr_fn || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.ownr_ln || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.v_model_desc || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) || - (j.v_make_desc || "") - .toLowerCase() - .includes(searchQuery.toLowerCase()) - ) - : []; - - return ( - - - - } - style={{ flex: 1 }} - data={jobs} - renderItem={(object) => } - /> - - ); -} - -export default connect(mapStateToProps, null)(JobListComponent); diff --git a/components-old/job-notes-item/job-notes-item.component.jsx b/components-old/job-notes-item/job-notes-item.component.jsx deleted file mode 100644 index 78b1914..0000000 --- a/components-old/job-notes-item/job-notes-item.component.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { AntDesign } from "@expo/vector-icons"; -import { DateTime } from "luxon"; -import React from "react"; -import { Text, View } from "react-native"; -import { Card } from "react-native-paper"; -export default function NoteListItem({ item }) { - return ( - - - - {item.text} - - {item.private && ( - - )} - {item.critical && ( - - )} - {item.created_by} - - {DateTime.fromISO(item.created_at).toLocaleString( - DateTime.DATETIME_SHORT - )} - - - - - - ); -} diff --git a/components-old/job-notes/job-notes.component.jsx b/components-old/job-notes/job-notes.component.jsx deleted file mode 100644 index 01b9695..0000000 --- a/components-old/job-notes/job-notes.component.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { FlatList, RefreshControl, Text } from "react-native"; -import { Card } from "react-native-paper"; -import JobNotesItem from "../job-notes-item/job-notes-item.component"; -export default function JobNotes({ job, loading, refetch }) { - const { t } = useTranslation(); - if (!job) { - - Job is not defined. - ; - } - - const onRefresh = async () => { - return refetch(); - }; - - if (job.notes.length === 0) - return ( - - - {t("jobdetail.labels.nojobnotes")} - - - ); - - return ( - - } - style={{ flex: 1 }} - data={job.notes} - renderItem={(object) => } - /> - ); -} diff --git a/components-old/job-space-available/job-space-available.component.jsx b/components-old/job-space-available/job-space-available.component.jsx deleted file mode 100644 index c3d7d76..0000000 --- a/components-old/job-space-available/job-space-available.component.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useQuery } from "@apollo/client"; -import React from "react"; -import { ProgressBar } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { GET_DOC_SIZE_TOTALS } from "../../graphql/documents.queries"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import { View, Text } from "react-native"; -import { useTranslation } from "react-i18next"; -import { formatBytes } from "../../util/document-upload.utility"; -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, -}); -const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) -}); -export default connect(mapStateToProps, mapDispatchToProps)(JobSpaceAvailable); - -export function JobSpaceAvailable({ bodyshop, style, jobid }) { - const { t } = useTranslation(); - const { data } = useQuery(GET_DOC_SIZE_TOTALS, { - variables: { jobId: jobid }, - skip: !jobid || jobid === "temp", - }); - - if (!jobid || !data) return <>; - - const progress = - data.documents_aggregate.aggregate.sum.size / - ((bodyshop && bodyshop.jobsizelimit) || 1); - - return ( - - - {t("mediabrowser.labels.storageused", { - used: formatBytes(data.documents_aggregate.aggregate.sum.size), - total: formatBytes((bodyshop && bodyshop.jobsizelimit) || 1), - percent: Math.round(progress * 100), - })} - - - - ); -} diff --git a/components-old/job-tombstone/job-tombstone.component.jsx b/components-old/job-tombstone/job-tombstone.component.jsx deleted file mode 100644 index 30f0c37..0000000 --- a/components-old/job-tombstone/job-tombstone.component.jsx +++ /dev/null @@ -1,172 +0,0 @@ -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 "../../components/data-label/data-label"; -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", - }, -}); diff --git a/components-old/loading-display/loading-display.component.jsx b/components-old/loading-display/loading-display.component.jsx deleted file mode 100644 index 16a92b0..0000000 --- a/components-old/loading-display/loading-display.component.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import { View } from "react-native"; -import { BarIndicator } from "react-native-indicators"; - -export default function LoadingDisplay({ count = 5 }) { - //TODO: This is throwing an error per expo, but it appears to be happening inside the component itself. - return ( - - - - ); -} diff --git a/components-old/media-cache-overlay/media-cache-overlay.component.jsx b/components-old/media-cache-overlay/media-cache-overlay.component.jsx deleted file mode 100644 index 99fb6fa..0000000 --- a/components-old/media-cache-overlay/media-cache-overlay.component.jsx +++ /dev/null @@ -1,27 +0,0 @@ -import { SafeAreaView } from "react-native"; -import React from "react"; - -import ImageView from "react-native-image-viewing"; - -export default function MediaCacheOverlay({ - photos, - previewVisible, - setPreviewVisible, - imgIndex, - setImgIndex, -}) { - //const videoRef = React.useRef(null); - - return ( - - setPreviewVisible(false)} - visible={previewVisible} - images={photos} - imageIndex={imgIndex} - // onImageIndexChange={(...props) => { - // // console.log(props); - // }} - /> - - ); diff --git a/components-old/screen-camera/screen-camera.jsx b/components-old/screen-camera/screen-camera.jsx deleted file mode 100644 index b32b40f..0000000 --- a/components-old/screen-camera/screen-camera.jsx +++ /dev/null @@ -1,157 +0,0 @@ -// import { useFocusEffect } from "@react-navigation/native"; -// import { Camera } from "expo-camera"; -// import * as FileSystem from "expo-file-system"; -// import React, { useEffect, useRef, useState } from "react"; -// import { Text, View } from "react-native"; -// import { connect } from "react-redux"; -// import { createStructuredSelector } from "reselect"; -// import { -// selectCurrentCameraJob, -// selectCurrentCameraJobId, -// } from "../../redux/app/app.selectors"; -// import { addPhoto } from "../../redux/photos/photos.actions"; -// import CameraControls from "../camera-controls/camera-controls.component"; -// import CameraSelectJob from "../camera-select-job/camera-select-job.component"; - -// const mapStateToProps = createStructuredSelector({ -// cameraJobId: selectCurrentCameraJobId, -// cameraJob: selectCurrentCameraJob, -// }); -// const mapDispatchToProps = (dispatch) => ({ -// addPhoto: (photo) => dispatch(addPhoto(photo)), -// }); - -// export function ScreenCamera({ cameraJobId, addPhoto }) { -// const [hasPermission, setHasPermission] = useState(null); -// const [state, setState] = useState({ -// flashMode: Camera.Constants.FlashMode.off, -// capturing: null, -// cameraType: Camera.Constants.Type.back, -// tabHasFocus: null, -// }); -// const cameraRef = useRef(null); - -// useFocusEffect( -// React.useCallback(() => { -// // Do something when the screen is focused -// setState({ ...state, tabHasFocus: true }); -// return () => { -// // Do something when the screen is unfocused -// // Useful for cleanup functions -// setState({ ...state, tabHasFocus: false }); -// }; -// }, []) -// ); - -// useEffect(() => { -// (async () => { -// const { status } = await Camera.requestPermissionsAsync(); -// setHasPermission(status === "granted"); -// })(); -// }, []); - -// const setFlashMode = (flashMode) => setState({ ...state, flashMode }); -// const setCameraType = (cameraType) => setState({ ...state, cameraType }); -// const handleCaptureIn = () => setState({ ...state, capturing: true }); - -// const handleCaptureOut = () => { -// if (state.capturing) cameraRef.current.stopRecording(); -// }; - -// const handleShortCapture = async () => { -// if (cameraRef.current) { -// const options = { -// quality: 0.8, -// //base64: true, -// skipProcessing: true, -// }; - -// let photo = await cameraRef.current.takePictureAsync(options); -// const filename = photo.uri.substring(photo.uri.lastIndexOf("/") + 1); -// const newUri = FileSystem.documentDirectory + "photos/" + filename; - -// await FileSystem.moveAsync({ -// from: photo.uri, -// to: newUri, -// }); -// setState({ ...state, capturing: false }); -// addPhoto({ -// ...photo, -// id: filename, -// uri: newUri, -// jobId: cameraJobId, -// video: false, -// }); -// } -// }; - -// const handleLongCapture = async () => { -// console.log("Taking a video!"); -// if (cameraRef.current) { -// let video = await cameraRef.current.recordAsync(); - -// const filename = video.uri.substring(video.uri.lastIndexOf("/") + 1); -// const newUri = FileSystem.documentDirectory + "photos/" + filename; - -// await FileSystem.moveAsync({ -// from: video.uri, -// to: newUri, -// }); -// setState({ ...state, capturing: false }); -// console.log("Adding Photo", { -// ...video, -// id: filename, -// uri: newUri, -// jobId: cameraJobId, -// video: true, -// }); -// addPhoto({ -// ...video, -// id: filename, -// uri: newUri, -// jobId: cameraJobId, -// video: true, -// }); -// } -// }; - -// if (hasPermission === null || !state.tabHasFocus) { -// return ; -// } - -// if (hasPermission === false) { -// return No access to camera. Please ensure that you allow it.; -// } - -// const { flashMode, cameraType, capturing } = state; - -// return ( -// -// -// - -// -// -// -// ); -// } -// export default connect(mapStateToProps, mapDispatchToProps)(ScreenCamera); diff --git a/components-old/screen-job-detail/screen-job-detail.component.jsx b/components-old/screen-job-detail/screen-job-detail.component.jsx deleted file mode 100644 index 0bde256..0000000 --- a/components-old/screen-job-detail/screen-job-detail.component.jsx +++ /dev/null @@ -1,101 +0,0 @@ -import { useQuery } from "@apollo/client"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { useWindowDimensions } from "react-native"; -import { SceneMap, TabView, TabBar } from "react-native-tab-view"; -import { GET_JOB_BY_PK } from "../../graphql/jobs.queries"; -import ErrorDisplay from "../error-display/error-display.component"; -import JobDocuments from "../job-documents/job-documents.component"; -import JobLines from "../job-lines/job-lines.component"; -import JobNotes from "../job-notes/job-notes.component"; -import JobTombstone from "../job-tombstone/job-tombstone.component"; -import LoadingDisplay from "../loading-display/loading-display.component"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import JobDocumentsLocalComponent from "../job-documents/job-documents-local.component"; -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, -}); -const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) -}); -export default connect(mapStateToProps, mapDispatchToProps)(ScreenJobDetail); - -export function ScreenJobDetail({ bodyshop, route }) { - const { - params: { jobId }, - } = route; - const { t } = useTranslation(); - const layout = useWindowDimensions(); - const { loading, error, data, refetch } = useQuery(GET_JOB_BY_PK, { - variables: { - id: jobId, - }, - skip: !jobId, - }); - - const renderTabBar = (props) => ( - - ); - - const renderScene = SceneMap({ - job: () => - JobTombstone({ - job: data.jobs_by_pk, - loading: loading, - refetch: refetch, - }), - lines: () => - JobLines({ - job: data.jobs_by_pk, - loading: loading, - refetch: refetch, - }), - - documents: () => { - return bodyshop.uselocalmediaserver ? ( - - ) : ( - - ); - }, - - notes: () => - JobNotes({ - job: data.jobs_by_pk, - loading: loading, - refetch: refetch, - }), - }); - - const [index, setIndex] = React.useState(0); - const [routes] = React.useState([ - { key: "job", title: t("jobdetail.labels.job") }, - { key: "lines", title: t("jobdetail.labels.lines") }, - { key: "documents", title: t("jobdetail.labels.documents") }, - { key: "notes", title: t("jobdetail.labels.notes") }, - ]); - - if (loading) return ; - if (error) return ; - - return ( - - ); -} diff --git a/components-old/screen-job-list/screen-job-list.component.jsx b/components-old/screen-job-list/screen-job-list.component.jsx deleted file mode 100644 index ca2fd90..0000000 --- a/components-old/screen-job-list/screen-job-list.component.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from "react"; -import JobListComponent from "../job-list/job-list.component.jsx"; - -export default function ScreenJobList({ navigation }) { - return ; -} diff --git a/components-old/screen-main/screen-main.component.jsx b/components-old/screen-main/screen-main.component.jsx deleted file mode 100644 index eea93f8..0000000 --- a/components-old/screen-main/screen-main.component.jsx +++ /dev/null @@ -1,197 +0,0 @@ -import { Ionicons } from "@expo/vector-icons"; -import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; -import { NavigationContainer } from "@react-navigation/native"; -import { createNativeStackNavigator } from "@react-navigation/native-stack"; -import i18n from "i18next"; -import moment from "moment"; -import { useEffect } from "react"; -import { Button } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { logImEXEvent } from "../../firebase/firebase.analytics"; -import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions"; -import { - checkUserSession, - emailSignInStart, - signOutStart, -} from "../../redux/user/user.actions"; -import { - selectBodyshop, - selectCurrentUser, -} from "../../redux/user/user.selectors"; -import ScreenJobDetail from "../screen-job-detail/screen-job-detail.component"; -import ScreenJobList from "../screen-job-list/screen-job-list.component"; -import ScreenMediaBrowser from "../screen-media-browser/screen-media-browser.component"; -import ScreenSettingsComponent from "../screen-settings/screen-settings.component"; -import ScreenSignIn from "../screen-sign-in/screen-sign-in.component"; -import ScreenSplash from "../screen-splash/screen-splash.component"; - -const ActiveJobStack = createNativeStackNavigator(); -const MoreStack = createNativeStackNavigator(); -const BottomTabs = createBottomTabNavigator(); -const MediaBrowserStack = createNativeStackNavigator(); - -const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, - currentUser: selectCurrentUser, -}); - -const mapDispatchToProps = (dispatch) => ({ - checkUserSession: () => dispatch(checkUserSession()), - emailSignInStart: (email, password) => - dispatch(emailSignInStart({ email, password })), - signOutStart: () => dispatch(signOutStart()), - setCameraJobId: (id) => dispatch(setCameraJobId(id)), - setCameraJob: (job) => dispatch(setCameraJob(job)), -}); - -const JobsTabNavigator = connect( - mapStateToProps, - mapDispatchToProps -)(({ setCameraJobId, setCameraJob }) => ( - - ({ - title: i18n.t("joblist.labels.activejobs"), - })} - component={ScreenJobList} - /> - ({ - title: - (route.params && route.params.title) || - i18n.t("joblist.labels.detail"), - // eslint-disable-next-line react/display-name - headerRight: () => ( - - ), - })} - /> - -)); - -const MediaBrowserStackNavigator = () => ( - - - -); - -const MoreStackNavigator = () => ( - - - -); - -const BottomTabsNavigator = () => ( - ({ - // eslint-disable-next-line react/display-name - tabBarIcon: ({ color, size }) => { - let iconName; - if (route.name === "JobTab") { - iconName = "list"; - } else if (route.name === "MoreTab") { - iconName = "settings"; - } else if (route.name === "MediaBrowserTab") { - iconName = "camera"; - } else { - //iconName = "customerservice"; - } - - return ; - }, - })} - > - - - - -); - -export function ScreenMainComponent({ - checkUserSession, - currentUser, - bodyshop, -}) { - useEffect(() => { - checkUserSession(); - }, [checkUserSession]); - - // useEffect(() => { - // // LogRocket.init("idt6oy/imex-mobile", { - // // updateId: Updates.isEmbeddedLaunch ? null : Updates.updateId, - // // expoChannel: Updates.channel, - // // }); - // }, []); - - return ( - - {currentUser.authorized === null ? ( - - ) : currentUser.authorized ? ( - bodyshop ? ( - HasAccess(bodyshop) ? ( - - ) : ( - - ) - ) : ( - - ) - ) : ( - - )} - - ); -} -export default connect( - mapStateToProps, - mapDispatchToProps -)(ScreenMainComponent); - -function HasAccess({ features }) { - if (features.mobile === undefined || features.mobile === true) return true; - if (features.mobile === false) return false; - const d = moment(moment(features.mobile)); - if (d.isValid()) return d.isAfter(moment()); -} diff --git a/components-old/screen-media-browser/screen-media-browser.component.jsx b/components-old/screen-media-browser/screen-media-browser.component.jsx deleted file mode 100644 index 4692774..0000000 --- a/components-old/screen-media-browser/screen-media-browser.component.jsx +++ /dev/null @@ -1,162 +0,0 @@ -import Constants from "expo-constants"; -import * as ImagePicker from "expo-image-picker"; -import { useCallback, useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { StyleSheet, Text, View } from "react-native"; -import { Button } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { toggleDeleteAfterUpload } from "../../redux/app/app.actions"; -import { - selectCurrentCameraJobId, - selectDeleteAfterUpload, -} from "../../redux/app/app.selectors"; -import { selectBodyshop } from "../../redux/user/user.selectors"; -import CameraSelectJob from "../camera-select-job/camera-select-job.component"; -import JobSpaceAvailable from "../job-space-available/job-space-available.component"; -import UploadDeleteSwitch from "../upload-delete-switch/upload-delete-switch.component"; -import UploadProgressLocal from "../upload-progress-local/upload-progress-local.component"; -import UploadProgress from "../upload-progress/upload-progress.component"; - -const mapStateToProps = createStructuredSelector({ - selectedCameraJobId: selectCurrentCameraJobId, - bodyshop: selectBodyshop, - deleteAfterUpload: selectDeleteAfterUpload, -}); - -const mapDispatchToProps = (dispatch) => ({ - toggleDeleteAfterUpload: () => dispatch(toggleDeleteAfterUpload()), -}); - -export function ImageBrowserScreen({ - bodyshop, - selectedCameraJobId, - //toggleDeleteAfterUpload, - // deleteAfterUpload, -}) { - const { t } = useTranslation(); - const [uploads, setUploads] = useState(null); - const [density, setDensity] = useState(3); - const [tick, setTick] = useState(0); - - const forceRerender = useCallback(() => { - setTick((tick) => tick + 1); - }, []); - - useEffect(() => { - (async () => { - if (Constants.platform.ios) { - const cameraRollStatus = - await ImagePicker.requestMediaLibraryPermissionsAsync(); - const cameraStatus = await ImagePicker.requestCameraPermissionsAsync(); - if ( - cameraRollStatus.status !== "granted" || - cameraStatus.status !== "granted" - ) { - alert( - "Photo and Camera permissions have not been granted. Please open the settings app and allow these permissions to upload photos." - ); - } - } - })(); - }, []); - - const pickImage = async () => { - let result = await ImagePicker.launchImageLibraryAsync({ - mediaTypes: ["images", "videos"], - aspect: [4, 3], - quality: 1, - allowsMultipleSelection: true, - }); - setUploads(result.assets); - }; - - return ( - - - {bodyshop.uselocalmediaserver ? ( - - {t("mediabrowser.labels.localserver", { - url: bodyshop.localmediaserverhttp, - })} - - ) : ( - - )} - - - {!selectedCameraJobId && ( - - {t("mediabrowser.labels.selectjobassetselector")} - - )} - - {bodyshop.uselocalmediaserver ? ( - - ) : ( - - )} - - ); -} - -const styles = StyleSheet.create({ - flex: { - flex: 1, - }, - container: { - display: "flex", - // position: "relative", - }, - buttonStyle: { - //backgroundColor: "tomato", - }, - textStyle: { - color: "dodgerblue", - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(ImageBrowserScreen); - -// // Utility to get asset ID from URI if missing -// async function getAssetIdFromUri(uri, filename = null, maxPages = 10) { -// let after = null; -// let found = null; -// let pageCount = 0; - -// while (!found && pageCount < maxPages) { -// const page = await MediaLibrary.getAssetsAsync({ -// first: 100, -// mediaType: [MediaLibrary.MediaType.photo, MediaLibrary.MediaType.video], -// after, -// }); - -// // Try to match by URI -// found = page.assets.find((asset) => asset.uri === uri); - -// // Fallback: try to match by filename if not found and filename is available -// if (!found && filename) { -// found = page.assets.find((asset) => asset.filename === filename); -// } - -// after = page.endCursor; -// pageCount++; -// if (!after) break; -// } - -// return found ? found.id : null; -// } diff --git a/components-old/screen-media-cache/screen-media-cache.component.jsx b/components-old/screen-media-cache/screen-media-cache.component.jsx deleted file mode 100644 index b4f5f17..0000000 --- a/components-old/screen-media-cache/screen-media-cache.component.jsx +++ /dev/null @@ -1,140 +0,0 @@ -import _ from "lodash"; -import React, { useState } from "react"; -import { useTranslation } from "react-i18next"; -import { - ActivityIndicator, - FlatList, - Image, - SafeAreaView, - StyleSheet, - Text, - TouchableOpacity, - View, -} from "react-native"; -import { Button } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { - removeAllPhotos, - uploadAllPhotos, -} from "../../redux/photos/photos.actions"; -import { - selectPhotos, - selectUploadInProgress, -} from "../../redux/photos/photos.selectors"; -import MediaCacheOverlay from "../media-cache-overlay/media-cache-overlay.component"; - -const mapStateToProps = createStructuredSelector({ - photos: selectPhotos, - uploadInProgress: selectUploadInProgress, -}); -const mapDispatchToProps = (dispatch) => ({ - removeAllPhotos: () => dispatch(removeAllPhotos()), - uploadAllphotos: () => dispatch(uploadAllPhotos()), -}); - -export function ScreenMediaCache({ - photos, - removeAllPhotos, - uploadAllphotos, - uploadInProgress, -}) { - const { t } = useTranslation(); - const [previewVisible, setPreviewVisible] = useState(false); - const [imgIndex, setImgIndex] = useState(0); - - const groupedPhotos = _.groupBy(photos, "jobId"); - - const RenderJobPictures = ({ jobId, jobPhotos }) => ( - - {jobId} - item.id} - numColumns={4} - renderItem={(object) => - object.item.video ? ( - Video - ) : ( - { - setImgIndex(object.index); - setPreviewVisible(true); - }} - > - - - ) - } - /> - - ); - - return ( - - - - - - item} - renderItem={(object) => ( - - )} - /> - - {`${photos.length} Photos`} - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - actions: { - display: "flex", - flexDirection: "row", - justifyContent: "space-evenly", - }, - listContentContainer: { - //flex: 1, - justifyContent: "flex-start", - //flexDirection: "row", - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(ScreenMediaCache); - -// item.id} -// renderItem={(object) => {object.item}} -// />; diff --git a/components-old/screen-messaging-conversation/screen-messaging-conversation.component.jsx b/components-old/screen-messaging-conversation/screen-messaging-conversation.component.jsx deleted file mode 100644 index c881b5d..0000000 --- a/components-old/screen-messaging-conversation/screen-messaging-conversation.component.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import { View, Text } from "react-native"; - -export default function ScreenMessagingConversation({ navigation }) { - return ( - - - - ); -} diff --git a/components-old/screen-messaging-list/screen-messaging-list.component.jsx b/components-old/screen-messaging-list/screen-messaging-list.component.jsx deleted file mode 100644 index 069ff23..0000000 --- a/components-old/screen-messaging-list/screen-messaging-list.component.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import { View, Text } from "react-native"; - -export default function ScreenMessagingList() { - return ( - - A list of conversations. - - ); -} diff --git a/components-old/screen-production/screen-production.jsx b/components-old/screen-production/screen-production.jsx deleted file mode 100644 index e546389..0000000 --- a/components-old/screen-production/screen-production.jsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { useState } from "react"; -import { Text, View, StyleSheet, TouchableOpacity } from "react-native"; -import DraggableFlatList, { - ScaleDecorator, - NestableScrollContainer, - NestableDraggableFlatList, -} from "react-native-draggable-flatlist"; - -const NUM_ITEMS = 10; -function getColor(i) { - const multiplier = 255 / (NUM_ITEMS - 1); - const colorVal = i * multiplier; - return `rgb(${colorVal}, ${Math.abs(128 - colorVal)}, ${255 - colorVal})`; -} - -const initialData = [...Array(NUM_ITEMS)].map((d, index) => { - const backgroundColor = getColor(index); - return { - key: `item-${index}`, - label: String(index) + "", - height: 100, - width: 60 + Math.random() * 40, - backgroundColor, - }; -}); - -const initialData2 = [...Array(NUM_ITEMS)].map((d, index) => { - const backgroundColor = getColor(index); - return { - key: `item-${index}`, - label: String(index) + "", - height: 100, - width: 60 + Math.random() * 40, - backgroundColor, - }; -}); - -export default function App() { - const [data, setData] = useState(initialData); - const [data2, setData2] = useState(initialData2); - - const renderItem = ({ item, drag, isActive }) => { - return ( - - - {item.label} - - - ); - }; - - return ( - - setData(data)} - keyExtractor={(item) => item.key} - renderItem={renderItem} - /> - setData2(data)} - keyExtractor={(item) => item.key} - renderItem={renderItem} - /> - - ); -} - -const styles = StyleSheet.create({ - rowItem: { - height: 100, - width: 100, - alignItems: "center", - justifyContent: "center", - }, - text: { - color: "white", - fontSize: 24, - fontWeight: "bold", - textAlign: "center", - }, -}); diff --git a/components-old/screen-settings/screen-settings.component.jsx b/components-old/screen-settings/screen-settings.component.jsx deleted file mode 100644 index 5dc0c84..0000000 --- a/components-old/screen-settings/screen-settings.component.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import Constants from "expo-constants"; -import React from "react"; -import { useTranslation } from "react-i18next"; -import { View, Text } from "react-native"; -import { Title, Button } from "react-native-paper"; -import { purgeStoredState } from "redux-persist"; -import SignOutButton from "../sign-out-button/sign-out-button.component"; -import * as Updates from "expo-updates"; -import * as Application from "expo-application"; - -export default function ScreenSettingsComponent() { - const { t } = useTranslation(); - return ( - - - {t("settings.labels.version", { - number: `${Constants.expoConfig.version}(${Application.nativeBuildVersion} - ${Constants.expoConfig.extra.expover})`, - })} - - - Release Channel {Updates.channel} - - {/* - - )} - - - - {t("settings.labels.version", { - number: Constants.expoConfig.version, - })} - - - ); -} - -const localStyles = StyleSheet.create({ - content: { - display: "flex", - flex: 1, - }, - logo: { width: 100, height: 100 }, - input: { - margin: 12, - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(SignIn); diff --git a/components-old/screen-splash/screen-splash.component.jsx b/components-old/screen-splash/screen-splash.component.jsx deleted file mode 100644 index 0f138d0..0000000 --- a/components-old/screen-splash/screen-splash.component.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { ActivityIndicator, Image, StyleSheet, View } from "react-native"; -import { Title, Subheading, Divider } from "react-native-paper"; -import Logo from "../../assets/logo192.png"; -import SignOutButton from "../sign-out-button/sign-out-button.component"; - -export default function ScreenSplash({ noAccess }) { - const { t } = useTranslation(); - return ( - - - - {t("app.title")} - - - {noAccess ? ( - - - {t("app.nomobileaccess")} - - - - - ) : ( - - )} - - ); -} -const localStyles = StyleSheet.create({ - container: { - display: "flex", - flex: 1, - flexDirection: "column", - alignContent: "center", - justifyContent: "center", - }, - logoContainer: { - display: "flex", - flexDirection: "column", - margin: 10, - alignItems: "center", - }, - logo: { width: 175, height: 175, margin: 20 }, -}); diff --git a/components-old/sign-in-error-alert/sign-in-error-alert.component.jsx b/components-old/sign-in-error-alert/sign-in-error-alert.component.jsx deleted file mode 100644 index ba3fce8..0000000 --- a/components-old/sign-in-error-alert/sign-in-error-alert.component.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Title } from "react-native-paper"; -import React, { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { StyleSheet, View } from "react-native"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectSignInError } from "../../redux/user/user.selectors"; - -const mapStateToProps = createStructuredSelector({ - signInError: selectSignInError, -}); - -export function SignInErrorAlertComponent({ signInError }) { - const [errorText, setErrorText] = useState(""); - const { t } = useTranslation(); - - useEffect(() => { - let text; - if (signInError && signInError.code) - switch (signInError.code) { - case "auth/user-not-found": - text = t("signin.errors.usernotfound"); - break; - case "auth/invalid-email": - text = t("signin.errors.emailformat"); - break; - case "auth/wrong-password": - text = t("signin.errors.wrongpassword"); - break; - default: - text = signInError.code + " " + signInError.message; - break; - } - - setErrorText(text); - }, [signInError, setErrorText]); - return ( - - {errorText ? {errorText} : null} - - ); -} - -export default connect(mapStateToProps, null)(SignInErrorAlertComponent); - -const localStyles = StyleSheet.create({ - alert: { - color: "red", - textAlign: "center", - margin: 15, - padding: 15, - }, -}); diff --git a/components-old/style-repeater/style-repeater.jsx b/components-old/style-repeater/style-repeater.jsx deleted file mode 100644 index 0f18ee0..0000000 --- a/components-old/style-repeater/style-repeater.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from "react"; - -export default function StyleRepeater({ childStyle, children }) { - return ( - <> - {React.Children.map(children, (child) => - React.cloneElement(child, { - style: [child.props.style, childStyle], - }) - )} - - ); -} diff --git a/components-old/styles.js b/components-old/styles.js deleted file mode 100644 index 3ca0bee..0000000 --- a/components-old/styles.js +++ /dev/null @@ -1,12 +0,0 @@ -import { StyleSheet } from "react-native"; - -const cardBackgroundColor = "gainsboro"; - -export default StyleSheet.create({ - cardBackground: { - padding: 5, - backgroundColor: cardBackgroundColor, - display: "flex", - flex: 1, - }, -}); diff --git a/components-old/upload-delete-switch/upload-delete-switch.component.jsx b/components-old/upload-delete-switch/upload-delete-switch.component.jsx deleted file mode 100644 index eb89d22..0000000 --- a/components-old/upload-delete-switch/upload-delete-switch.component.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { StyleSheet, Text, View } from "react-native"; -import { Switch } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { toggleDeleteAfterUpload } from "../../redux/app/app.actions"; -import { selectDeleteAfterUpload } from "../../redux/app/app.selectors"; - -const mapStateToProps = createStructuredSelector({ - deleteAfterUpload: selectDeleteAfterUpload, -}); - -const mapDispatchToProps = (dispatch) => ({ - toggleDeleteAfterUpload: () => dispatch(toggleDeleteAfterUpload()), -}); - -export function UploadDeleteSwitch({ - deleteAfterUpload, - toggleDeleteAfterUpload, -}) { - - const { t } = useTranslation(); - return ( - - - {t("mediabrowser.labels.deleteafterupload")} - - { - toggleDeleteAfterUpload(); - }} - value={deleteAfterUpload} - /> - - ); -} -const styles = StyleSheet.create({ - container: { - display: "flex", - flexDirection: "row", - alignItems: "center", - margin: 10, - }, - - text: { - flex: 1, - }, -}); -export default connect(mapStateToProps, mapDispatchToProps)(UploadDeleteSwitch); diff --git a/components-old/upload-progress-local/upload-progress-local.component.jsx b/components-old/upload-progress-local/upload-progress-local.component.jsx deleted file mode 100644 index f8a959c..0000000 --- a/components-old/upload-progress-local/upload-progress-local.component.jsx +++ /dev/null @@ -1,218 +0,0 @@ -import * as MediaLibrary from "expo-media-library"; -import React, { useEffect, useState } from "react"; - -import { - ActivityIndicator, - Alert, - Modal, - Platform, - StyleSheet, - Text, - View, -} from "react-native"; -import { ProgressBar } from "react-native-paper"; -import Toast from "react-native-toast-message"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { logImEXEvent } from "../../firebase/firebase.analytics"; -import { - selectCurrentCameraJobId, - selectDeleteAfterUpload, -} from "../../redux/app/app.selectors"; -import * as Sentry from "@sentry/react-native"; - -import { formatBytes } from "../../util/document-upload.utility"; -import { handleLocalUpload } from "../../util/local-document-upload.utility"; - -const mapStateToProps = createStructuredSelector({ - selectedCameraJobId: selectCurrentCameraJobId, - deleteAfterUpload: selectDeleteAfterUpload, -}); - -export default connect(mapStateToProps, null)(UploadProgress); - -export function UploadProgress({ - selectedCameraJobId, - deleteAfterUpload, - uploads, - setUploads, - forceRerender, -}) { - const [progress, setProgress] = useState({ - loading: false, - uploadInProgress: false, - speed: 0, - }); - - useEffect(() => { - //Set the state of uploads to do. - if (uploads) { - beginUploads(uploads); - setUploads(null); - } - }, [uploads]); - - async function handleOnSuccess({ duration, data }) { - //If it's not in production, show a toast with the time. - Toast.show({ - type: "success", - text1: ` Upload completed in ${duration}.`, - // - // text2: duration, - }); - if (deleteAfterUpload) { - try { - if (Platform.OS === "android") { - //Create a new asset with the first file to delete. - // console.log('Trying new delete.'); - await MediaLibrary.getPermissionsAsync(false); - - const album = await MediaLibrary.createAlbumAsync( - "ImEX Mobile Deleted", - data.pop(), - false - ); - //Move the rest. - if (data.length > 0) { - const moveResult = await MediaLibrary.addAssetsToAlbumAsync( - data, - album, - false - ); - } - const deleteResult = await MediaLibrary.deleteAlbumsAsync(album); - - //Delete the album. - - //This defaults to delete all assets in the album. - } else { - await MediaLibrary.deleteAssetsAsync(data.map((f) => f.id)); - } - } catch (error) { - console.log("Unable to delete picture.", error); - Sentry.captureException(error); - } - } - - logImEXEvent("imexmobile_successful_upload"); - forceRerender(); - setProgress({ ...progress, speed: 0, percent: 1, uploadInProgress: false }); - } - - function handleOnProgress({ percent, loaded }) { - setProgress((progress) => ({ - ...progress, - speed: loaded - progress.loaded, - loaded: loaded, - percent, - })); - } - - function handleOnError({ assetid, error }) { - logImEXEvent("imexmobile_upload_documents_error"); - Toast.show({ - type: "error", - text1: "Unable to upload documents.", - text2: error, - autoHide: false, - }); - setProgress({ - speed: 0, - percent: 1, - uploadInProgress: false, - }); - } - - const beginUploads = async (data) => { - //Validate to make sure the totals for the file sizes do not exceed the total on the job. - setProgress({ - percent: 0, - loaded: 0, - uploadInProgress: true, - start: new Date(), - average: 0, - }); - - await handleLocalUpload({ - files: data, - onError: ({ assetid, error }) => handleOnError({ assetid, error }), - onProgress: ({ percent, loaded }) => - handleOnProgress({ percent, loaded }), - onSuccess: ({ duration }) => handleOnSuccess({ duration, data }), - context: { - jobid: - selectedCameraJobId !== "temp" ? selectedCameraJobId : "temporary", - }, - }); - }; - - return ( - { - Alert.alert("Cancel?", "Do you want to abort the upload?", [ - { - text: "Yes", - onPress: () => { - setUploads(null); - setProgress(null); - }, - }, - { text: "No" }, - ]); - }} - > - - - - - {`${formatBytes( - progress.speed - )}/sec`} - {`Avg. ${formatBytes( - progress.loaded / ((new Date() - progress.start) / 1000) - )}/sec`} - {`Total Uploaded ${formatBytes(progress.loaded)}`} - {`Duration ${( - (new Date() - progress.start) / - 1000 - ).toFixed(1)} sec`} - - - - ); -} -const styles = StyleSheet.create({ - modalContainer: { - display: "flex", - flex: 1, - justifyContent: "center", - }, - modal: { - // flex: 1, - display: "flex", - marginLeft: 20, - marginRight: 20, - backgroundColor: "white", - borderRadius: 20, - padding: 18, - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.25, - shadowRadius: 4, - elevation: 5, - }, -}); diff --git a/components-old/upload-progress/upload-progress.component.jsx b/components-old/upload-progress/upload-progress.component.jsx deleted file mode 100644 index d0388ae..0000000 --- a/components-old/upload-progress/upload-progress.component.jsx +++ /dev/null @@ -1,426 +0,0 @@ -import { useApolloClient } from "@apollo/client"; -import { File } from "expo-file-system"; -import * as MediaLibrary from "expo-media-library"; -import React, { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { - ActivityIndicator, - Alert, - Modal, - Platform, - StyleSheet, - Text, - View, -} from "react-native"; -import { Divider, ProgressBar } from "react-native-paper"; -import Toast from "react-native-toast-message"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import * as Sentry from "@sentry/react-native"; -import { logImEXEvent } from "../../firebase/firebase.analytics"; -import { GET_DOC_SIZE_TOTALS } from "../../graphql/documents.queries"; -import { - selectCurrentCameraJobId, - selectDeleteAfterUpload, -} from "../../redux/app/app.selectors"; -import { - selectBodyshop, - selectCurrentUser, -} from "../../redux/user/user.selectors"; -import { formatBytes, handleUpload } from "../../util/document-upload.utility"; - -const mapStateToProps = createStructuredSelector({ - currentUser: selectCurrentUser, - bodyshop: selectBodyshop, - selectedCameraJobId: selectCurrentCameraJobId, - deleteAfterUpload: selectDeleteAfterUpload, -}); - -export default connect(mapStateToProps, null)(UploadProgress); - -export function UploadProgress({ - currentUser, - bodyshop, - selectedCameraJobId, - deleteAfterUpload, - uploads, - setUploads, - forceRerender, -}) { - const [progress, setProgress] = useState({ - uploadInProgress: false, - totalToUpload: 0, - totalUploaded: 0, - startTime: null, - totalFiles: 0, - totalFilesCompleted: 0, - currentFile: null, - files: {}, //uri is the key, value is progress - }); - - let filesToDelete = []; - const client = useApolloClient(); - - const { t } = useTranslation(); - - useEffect(() => { - if (uploads) { - onDone(uploads); - setUploads(null); - } - }, [uploads]); - - function handleOnSuccess(asset) { - //NEEDS REDO. - filesToDelete.push(asset); - setProgress((progress) => ({ - ...progress, - // totalUploaded: progress.totalToUpload + asset.size, - totalFilesCompleted: progress.totalFilesCompleted + 1, - files: { - ...progress.files, - [asset.uri]: { - ...progress.files[asset.uri], - uploadEnd: new Date(), - }, - }, - })); - } - - function handleOnProgress({ uri, filename }, percent, loaded) { - //NEED REDO - setProgress((progress) => { - return { - ...progress, - totalUploaded: - progress.totalUploaded + - (loaded - (progress.files[uri]?.loaded || 0)), - files: { - ...progress.files, - [uri]: { - ...progress.files[uri], - percent, - filename, - speed: loaded - (progress.files[uri]?.loaded || 0), - loaded: loaded, - uploadStart: progress.files[uri]?.uploadStart || new Date(), - }, - }, - }; - }); - } - function handleOnError(error) { - logImEXEvent("imexmobile_upload_documents_error", { error }); - Toast.show({ - type: "error", - text1: "Unable to upload document.", - text2: error, - autoHide: false, - }); - } - - const onDone = async (selectedFiles) => { - setProgress((progress) => { - return { - ...progress, - uploadInProgress: true, - statusText: "Preparing upload...", - }; - }); - try { - //Validate to make sure the totals for the file sizes do not exceed the total on the job. - const data = []; - const totalOfUploads = await selectedFiles.reduce(async (acc, val) => { - //Get the size of the file based on URI. - if (acc.fileSize) { - return acc + acc.fileSize; - } else { - const info = new File(val.uri).size; - data.push({ ...info, ...val }); //Add in the size. - val.albumId && MediaLibrary.migrateAlbumIfNeededAsync(val.albumId); - return (await acc) + info.size; - } - }, 0); - - if (selectedCameraJobId !== "temp") { - const queryData = await client.query({ - query: GET_DOC_SIZE_TOTALS, - fetchPolicy: "network-only", - variables: { - jobId: selectedCameraJobId, - }, - }); - - if ( - bodyshop.jobsizelimit - - queryData.data.documents_aggregate.aggregate.sum.size <= - totalOfUploads - ) { - //No more room... abandon ship. - setProgress((progress) => ({ - ...progress, - speed: 0, - action: null, - statusText: null, - uploadInProgress: false, - })); - Alert.alert( - t("mediabrowser.labels.storageexceeded_title"), - t("mediabrowser.labels.storageexceeded") - ); - return; - } - //We made it this far. We have enough space, so let's start uploading. - setProgress((progress) => ({ - ...progress, - totalToUpload: totalOfUploads, - totalUploaded: 0, - totalFilesCompleted: 0, - startTime: new Date(), - totalFiles: data.length, - currentFile: null, - statusText: null, - files: {}, //uri is the key, value is progress - })); - } - - for (var i = 0; i < data.length + 4; i = i + 4) { - //Reset the files. - setProgress((progress) => ({ ...progress, files: {} })); - let proms = []; - if (data[i]) { - proms.push(CreateUploadProm(data[i])); - } - if (data[i + 1]) { - proms.push(CreateUploadProm(data[i + 1])); - } - if (data[i + 2]) { - proms.push(CreateUploadProm(data[i + 2])); - } - if (data[i + 3]) { - proms.push(CreateUploadProm(data[i + 3])); - } - - await Promise.all(proms); - } - } catch (error) { - console.log("Error during upload.", error, error.stack); - Sentry.captureException(error); - setProgress((progress) => ({ - ...progress, - speed: 0, - action: null, - statusText: null, - uploadInProgress: false, - })); - Alert.alert( - t("mediabrowser.labels.uploaderror_title"), - t("mediabrowser.labels.uploaderror") - ); - return; - } - - //Everything is uploaded, delete the succesful ones. - if (deleteAfterUpload) { - try { - if (Platform.OS === "android") { - //Create a new asset with the first file to delete. - // console.log('Trying new delete.'); - await MediaLibrary.getPermissionsAsync(false); - - const album = await MediaLibrary.createAlbumAsync( - "ImEX Mobile Deleted", - filesToDelete.pop(), - false - ); - //Move the rest. - if (filesToDelete.length > 0) { - const moveResult = await MediaLibrary.addAssetsToAlbumAsync( - filesToDelete, - album, - false - ); - } - const deleteResult = await MediaLibrary.deleteAlbumsAsync(album); - - //Delete the album. - - //This defaults to delete all assets in the album. - } else { - await MediaLibrary.deleteAssetsAsync(filesToDelete.map((f) => f.id)); - } - } catch (error) { - console.log("Unable to delete picture.", error); - Sentry.captureException(error); - } - } - filesToDelete = []; - Toast.show({ - type: "success", - text1: ` Upload completed.`, - // - // text2: duration, - }); - //Reset state. - - setProgress({ - uploadInProgress: false, - totalToUpload: 0, - totalUploaded: 0, - totalFilesCompleted: 0, - startTime: null, - totalFiles: 0, - currentFile: null, - files: {}, - }); - - forceRerender(); - }; - - const CreateUploadProm = async (p) => { - return handleUpload( - { - mediaId: p.id, - onError: handleOnError, - onProgress: ({ percent, loaded }) => - handleOnProgress(p, percent, loaded), - onSuccess: () => handleOnSuccess(p), - }, - { - bodyshop: bodyshop, - jobId: selectedCameraJobId !== "temp" ? selectedCameraJobId : null, - uploaded_by: currentUser.email, - photo: p, - } - ); - }; - - return ( - { - Alert.alert("Cancel?", "Do you want to abort the upload?", [ - { - text: "Yes", - onPress: () => { - setUploads(null); - setProgress({ - uploadInProgress: false, - totalToUpload: 0, - totalUploaded: 0, - totalFilesCompleted: 0, - startTime: null, - totalFiles: 0, - currentFile: null, - files: {}, - }); - }, - }, - { text: "No" }, - ]); - }} - > - - - {Object.keys(progress.files).map((key) => ( - - - {progress.files[key].filename} - - - - - {`${formatBytes( - progress.files[key].loaded / - (((progress.files[key].uploadEnd || new Date()) - - progress.files[key].uploadStart) / - 1000) - )}/sec`} - {progress.files[key].percent === 1 && ( - <> - - Processing... - - )} - - - - ))} - - {progress.statusText ? ( - <> - - {progress.statusText} - - - ) : ( - <> - {`${progress.totalFilesCompleted} of ${progress.totalFiles} uploaded.`} - {`${formatBytes(progress.totalUploaded)} of ${formatBytes( - progress.totalToUpload - )} uploaded.`} - - )} - - - - - ); -} -const styles = StyleSheet.create({ - modalContainer: { - display: "flex", - flex: 1, - justifyContent: "center", - }, - modal: { - //flex: 1, - display: "flex", - marginLeft: 20, - marginRight: 20, - backgroundColor: "white", - borderRadius: 20, - padding: 18, - shadowColor: "#000", - shadowOffset: { - width: 0, - height: 2, - }, - shadowOpacity: 0.25, - shadowRadius: 4, - elevation: 5, - }, - centeredView: { - justifyContent: "center", - alignItems: "center", - marginTop: 22, - }, - progressItem: { - display: "flex", - flexDirection: "row", - alignItems: "center", - marginBottom: 12, - marginLeft: 12, - marginRight: 12, - }, - progressText: { - flex: 1, - }, - progressBarContainer: { - flex: 3, - marginLeft: 12, - marginRight: 12, - }, -}); diff --git a/components/global-search/global-search.jsx b/components/global-search/global-search.jsx index 192bee3..645d520 100644 --- a/components/global-search/global-search.jsx +++ b/components/global-search/global-search.jsx @@ -47,8 +47,6 @@ export default function GlobalSearch() { if (!q) return; setLoading(true); setError(null); - // TODO: Integrate real search endpoint - console.log(`[GlobalSearch] (debounced placeholder) searching for: "${q}"`); try { const searchData = await axios.post(`${env.API_URL}/search`, { search: q, diff --git a/components/job-documents/job-documents.jsx b/components/job-documents/job-documents.jsx index ced9544..2ef7558 100644 --- a/components/job-documents/job-documents.jsx +++ b/components/job-documents/job-documents.jsx @@ -105,11 +105,6 @@ export function JobDocumentsComponent({ bodyshop }) { setFullPhotos(normalizedImages); } } catch (error) { - console.log( - "Error fetching photos:", - error.message, - JSON.stringify(error, null, 2) - ); setError(error.message || "Unknown error fetching photos."); } setLoading(false); diff --git a/components/settings/settings.jsx b/components/settings/settings.jsx index c37553c..0c0d3ce 100644 --- a/components/settings/settings.jsx +++ b/components/settings/settings.jsx @@ -144,7 +144,11 @@ function Tab({ bodyshop, currentUser, signOutStart }) { "Error", `Unable to register for notifications: ${error.message}` ); - console.log("Notification registration error:", error); + console.log( + "Notification registration error:", + error, + error.stack + ); } }} > @@ -161,7 +165,9 @@ function Tab({ bodyshop, currentUser, signOutStart }) { }`} - {`${t("settings.labels.signedinuser")} ${currentUser?.email || "Unknown"}`} + {`${t("settings.labels.signedinuser")} ${ + currentUser?.email || "Unknown" + }`} diff --git a/constants/theme.ts b/constants/theme.ts deleted file mode 100644 index f06facd..0000000 --- a/constants/theme.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Below are the colors that are used in the app. The colors are defined in the light and dark mode. - * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc. - */ - -import { Platform } from 'react-native'; - -const tintColorLight = '#0a7ea4'; -const tintColorDark = '#fff'; - -export const Colors = { - light: { - text: '#11181C', - background: '#fff', - tint: tintColorLight, - icon: '#687076', - tabIconDefault: '#687076', - tabIconSelected: tintColorLight, - }, - dark: { - text: '#ECEDEE', - background: '#151718', - tint: tintColorDark, - icon: '#9BA1A6', - tabIconDefault: '#9BA1A6', - tabIconSelected: tintColorDark, - }, -}; - -export const Fonts = Platform.select({ - ios: { - /** iOS `UIFontDescriptorSystemDesignDefault` */ - sans: 'system-ui', - /** iOS `UIFontDescriptorSystemDesignSerif` */ - serif: 'ui-serif', - /** iOS `UIFontDescriptorSystemDesignRounded` */ - rounded: 'ui-rounded', - /** iOS `UIFontDescriptorSystemDesignMonospaced` */ - mono: 'ui-monospace', - }, - default: { - sans: 'normal', - serif: 'serif', - rounded: 'normal', - mono: 'monospace', - }, - web: { - sans: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif", - serif: "Georgia, 'Times New Roman', serif", - rounded: "'SF Pro Rounded', 'Hiragino Maru Gothic ProN', Meiryo, 'MS PGothic', sans-serif", - mono: "SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace", - }, -}); diff --git a/env.js b/env.js index 782c392..5abd1e0 100644 --- a/env.js +++ b/env.js @@ -64,11 +64,9 @@ const ENV = { } }; const IS_ROME = Constants?.expoConfig?.extra?.appVariant === 'ROME'; -//console.log("*** ~ Constants?.expoConfig?.extra:", Constants?.expoConfig); function getEnvVars() { if (Updates.channel !== "production") return IS_ROME ? ENV.rometest : ENV.test; else return IS_ROME ? ENV.romeprod : ENV.prod; } -console.log('APP_VARIANT:', Constants?.expoConfig?.extra?.appVariant, 'IS_ROME:', IS_ROME, "ENV: ", getEnvVars()); export default getEnvVars(); diff --git a/graphql/client.js b/graphql/client.js index 1c31d3c..dc547b6 100644 --- a/graphql/client.js +++ b/graphql/client.js @@ -25,34 +25,14 @@ const errorLink = onError( } ); -const subscriptionMiddleware = { - applyMiddleware: async (options, next) => { - options.authToken = - auth.currentUser && (await auth.currentUser.getIdToken(true)); - next(); - }, -}; -//wsLink.subscriptionClient.use([subscriptionMiddleware]); - -// const link = split( -// // split based on operation type -// ({ query }) => { -// const definition = getMainDefinition(query); -// // console.log( -// // "##Intercepted GQL Transaction : " + -// // definition.operation + -// // "|" + -// // // definition.name.value + -// // "##" -// // ); -// return ( -// definition.kind === "OperationDefinition" && -// definition.operation === "subscription" -// ); +// const subscriptionMiddleware = { +// applyMiddleware: async (options, next) => { +// options.authToken = +// auth.currentUser && (await auth.currentUser.getIdToken(true)); +// next(); // }, -// wsLink, -// httpLink -// ); +// }; + const authLink = setContext((_, { headers }) => { return ( @@ -84,7 +64,7 @@ const retryLink = new RetryLink({ }, }); -const cache = new InMemoryCache({}); +const cache = new InMemoryCache(); export const client = new ApolloClient({ //link: ApolloLink.from(middlewares), diff --git a/package-lock.json b/package-lock.json index 2ade863..34ac00f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "imexmobile", "version": "1.0.0", "dependencies": { - "@apollo/client": "^3.12.11", + "@apollo/client": "^3.14.0", "@expo/vector-icons": "^15.0.2", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-vector-icons/material-design-icons": "^12.3.0", @@ -57,6 +57,7 @@ "react-native-image-viewing": "^0.2.2", "react-native-paper": "^5.14.5", "react-native-reanimated": "~4.1.3", + "react-native-reanimated-dnd": "^1.1.0", "react-native-safe-area-context": "~5.6.1", "react-native-screens": "~4.17.1", "react-native-tab-view": "4.1.3", @@ -2792,9 +2793,9 @@ "license": "MIT" }, "node_modules/@expo/vector-icons": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.2.tgz", - "integrity": "sha512-IiBjg7ZikueuHNf40wSGCf0zS73a3guJLdZzKnDUxsauB8VWPLMeWnRIupc+7cFhLUkqyvyo0jLNlcxG5xPOuQ==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz", + "integrity": "sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==", "license": "MIT", "peerDependencies": { "expo-font": ">=14.0.4", @@ -13285,6 +13286,18 @@ "react-native-worklets": ">=0.5.0" } }, + "node_modules/react-native-reanimated-dnd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-native-reanimated-dnd/-/react-native-reanimated-dnd-1.1.0.tgz", + "integrity": "sha512-9ZgdAFsw2rjB/0VE3wsR9+PnBOWIoO+1s6lEiyV51ptBcoz0NaUnUb8aqGocEztnXSbySSznpOh5vy6Ijo9A3Q==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-native": ">=0.60.0", + "react-native-gesture-handler": ">=2.0.0", + "react-native-reanimated": ">=3.0.0" + } + }, "node_modules/react-native-reanimated/node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", diff --git a/package.json b/package.json index 559d0a6..a2a5045 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "lint": "expo lint" }, "dependencies": { - "@apollo/client": "^3.12.11", + "@apollo/client": "^3.14.0", "@expo/vector-icons": "^15.0.2", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-vector-icons/material-design-icons": "^12.3.0", @@ -72,6 +72,7 @@ "react-native-image-viewing": "^0.2.2", "react-native-paper": "^5.14.5", "react-native-reanimated": "~4.1.3", + "react-native-reanimated-dnd": "^1.1.0", "react-native-safe-area-context": "~5.6.1", "react-native-screens": "~4.17.1", "react-native-tab-view": "4.1.3", diff --git a/redux/photos/photos.sagas.js b/redux/photos/photos.sagas.js index c199db5..b90e9ea 100644 --- a/redux/photos/photos.sagas.js +++ b/redux/photos/photos.sagas.js @@ -83,7 +83,7 @@ export function* openImagePickerAction({ payload: jobid }) { yield put(mediaUploadStart({ photos: result.assets, jobid })); } } catch (error) { - console.log("Saga Error: open Picker", error); + // console.log("Saga Error: open Picker", error); } } @@ -93,8 +93,6 @@ export function* onMediaUploadStart() { export function* mediaUploadStartAction({ payload: { photos, jobid } }) { try { - console.log("Starting upload for", photos.length, "photos"); - const bodyshop = yield select(selectBodyshop); if (bodyshop.uselocalmediaserver) { @@ -130,7 +128,7 @@ export function* mediaUploadStartAction({ payload: { photos, jobid } }) { yield delay(100); } } - console.log("All uploads completed. This shouldn't fire before the uploads are done."); + yield put(mediaUploadCompleted(photos)); } catch (error) {