From ab1e04f5643e08d6d868f35c245b3a59a8854997 Mon Sep 17 00:00:00 2001
From: Patrick Fic <>
Date: Mon, 9 Nov 2020 18:43:59 -0800
Subject: [PATCH] Added app reducer, fixed package issues, begun camera screen
updates
---
babel-translations.babel | 31 +++
components/job-list/job-list.component.jsx | 2 +-
components/job-notes/job-notes.component.jsx | 2 +-
.../screen-camera/screen-camera.component.jsx | 45 ++-
.../screen-main/screen-main.component.jsx | 23 +-
.../screen-media-cache.component.jsx | 257 +++++++++++++++++-
graphql/client.js | 6 +-
graphql/jobs.queries.js | 20 +-
package.json | 3 +
redux/app/app.actions.js | 21 ++
redux/app/app.reducer.js | 39 +++
redux/app/app.sagas.js | 158 +++++++++++
redux/app/app.selectors.js | 16 ++
redux/app/app.types.js | 7 +
redux/root.reducer.js | 17 +-
redux/root.saga.js | 16 +-
redux/store.js | 21 +-
redux/user/user.sagas.js | 2 +-
translations/en-US/common.json | 5 +
translations/es-MX/common.json | 5 +
translations/fr-CA/common.json | 5 +
yarn.lock | 20 +-
22 files changed, 653 insertions(+), 68 deletions(-)
create mode 100644 redux/app/app.actions.js
create mode 100644 redux/app/app.reducer.js
create mode 100644 redux/app/app.sagas.js
create mode 100644 redux/app/app.selectors.js
create mode 100644 redux/app/app.types.js
diff --git a/babel-translations.babel b/babel-translations.babel
index 8ea525b..ca5774d 100644
--- a/babel-translations.babel
+++ b/babel-translations.babel
@@ -47,6 +47,37 @@
+
+ camera
+
+
+ titles
+
+
+ cameratab
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
+
+
+
+
general
diff --git a/components/job-list/job-list.component.jsx b/components/job-list/job-list.component.jsx
index 81bcc63..580aabb 100644
--- a/components/job-list/job-list.component.jsx
+++ b/components/job-list/job-list.component.jsx
@@ -18,7 +18,7 @@ const mapStateToProps = createStructuredSelector({
export function JobListComponent({ bodyshop }) {
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
- statuses: bodyshop.md_ro_statuses.open_statuses || ["Open", "Open*"],
+ statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"],
},
skip: !bodyshop,
});
diff --git a/components/job-notes/job-notes.component.jsx b/components/job-notes/job-notes.component.jsx
index 57197c9..9c696ff 100644
--- a/components/job-notes/job-notes.component.jsx
+++ b/components/job-notes/job-notes.component.jsx
@@ -18,7 +18,7 @@ export default function JobNotes({ job, loading, refetch }) {
Job is not defined.
;
}
- console.log("job.notes :>> ", job.notes);
+
const onRefresh = async () => {
return refetch();
};
diff --git a/components/screen-camera/screen-camera.component.jsx b/components/screen-camera/screen-camera.component.jsx
index b2e2a6c..1f448ef 100644
--- a/components/screen-camera/screen-camera.component.jsx
+++ b/components/screen-camera/screen-camera.component.jsx
@@ -7,16 +7,36 @@ import {
MaterialCommunityIcons,
} from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
+import * as FileSystem from "expo-file-system";
+import * as Permissions from "expo-permissions";
+import * as MediaLibrary from "expo-media-library";
export default function ScreenCamera() {
const navigation = useNavigation();
const [hasPermission, setHasPermission] = useState(null);
+ const [rollPermision, setRollPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const cameraRef = useRef(null);
+
useEffect(() => {
(async () => {
+ //Ensure local photo direcotry exists.
+ console.log(
+ "ScreenCamera -> FileSystem.documentDirectory ",
+ FileSystem.documentDirectory
+ );
+
+ await FileSystem.makeDirectoryAsync(
+ FileSystem.documentDirectory + "photos"
+ ).catch((e) => {
+ console.log(e, "Directoryc already exists");
+ });
+
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === "granted");
+ // camera roll
+ const { cam_roll } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
+ setRollPermission(cam_roll === "granted");
})();
}, []);
@@ -31,8 +51,29 @@ export default function ScreenCamera() {
const handleTakePicture = async () => {
console.log("Taking the picture!");
if (cameraRef.current) {
- let photo = await cameraRef.current.takePictureAsync();
- console.log("The Photo", photo);
+ const options = {
+ //quality: 0.5,
+ //base64: true,
+ //skipProcessing: true,
+ };
+
+ let photo = await cameraRef.current.takePictureAsync(options);
+ console.log("ScreenCamera -> photo", photo);
+ const filename = new Date().getTime() + ".jpg";
+
+ await FileSystem.copyAsync({
+ from: photo.uri,
+ to: FileSystem.documentDirectory + "photos/" + filename,
+ });
+
+ console.log(
+ "List of Files",
+ await FileSystem.readDirectoryAsync(FileSystem.documentDirectory),
+ await FileSystem.readDirectoryAsync(
+ FileSystem.documentDirectory + "photos"
+ )
+ );
+ //const asset = await MediaLibrary.createAssetAsync(photo.uri);
}
};
diff --git a/components/screen-main/screen-main.component.jsx b/components/screen-main/screen-main.component.jsx
index 5395f1d..556231b 100644
--- a/components/screen-main/screen-main.component.jsx
+++ b/components/screen-main/screen-main.component.jsx
@@ -75,11 +75,25 @@ const JobStackNavigator = ({ navigation }) => (
i18n.t("joblist.labels.detail"),
})}
/>
-
+
);
+const CameraStackNavigator = ({ navigation }) => (
+
+
+
+
+);
const MessagingStackNavigator = ({ navigation }) => (
(
iconName = "ios-list";
} else if (route.name === "MessagingTab") {
iconName = "ios-chatboxes";
+ } else if (route.name === "CameraTab") {
+ iconName = "ios-camera";
}
return ;
},
@@ -116,6 +132,11 @@ const BottomTabsNavigator = () => (
options={{ title: i18n.t("joblist.titles.jobtab") }}
component={JobStackNavigator}
/>
+
{
+// console.log(p);
+// });
- FileSystem.readDirectoryAsync(FileSystem.documentDirectory).then((p) => {
- console.log(p);
- });
- return (
-
- This is the media cache screen.
-
- );
+// useEffect(() => {
+// (async () => {
+// if (Constants.platform.ios) {
+// const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
+// if (status !== "granted") {
+// alert("Sorry, we need camera roll permissions to make this work!");
+// }
+// }
+// })();
+// }, []);
+
+// return (
+//
+// This is the media cache screen.
+//
+// {image && (
+//
+// )}
+//
+// );
+// }
+
+import React, { Component } from "react";
+import {
+ ActivityIndicator,
+ Button,
+ Clipboard,
+ Image,
+ Share,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from "react-native";
+import { Constants } from "expo";
+import * as Permissions from "expo-permissions";
+import * as ImagePicker from "expo-image-picker";
+export default class App extends Component {
+ state = {
+ image: null,
+ uploading: false,
+ };
+
+ render() {
+ let { image } = this.state;
+
+ return (
+
+
+
+
+ Example: Upload ImagePicker result
+
+
+
+
+
+
+ {this._maybeRenderImage()}
+ {this._maybeRenderUploadingOverlay()}
+
+ );
+ }
+
+ _maybeRenderUploadingOverlay = () => {
+ if (this.state.uploading) {
+ return (
+
+
+
+ );
+ }
+ };
+
+ _maybeRenderImage = () => {
+ let { image } = this.state;
+
+ if (!image) {
+ return;
+ }
+
+ return (
+
+
+
+
+
+
+ {image}
+
+
+ );
+ };
+
+ _share = () => {
+ Share.share({
+ message: this.state.image,
+ title: "Check out this photo",
+ url: this.state.image,
+ });
+ };
+
+ _copyToClipboard = () => {
+ Clipboard.setString(this.state.image);
+ alert("Copied image URL to clipboard");
+ };
+
+ _takePhoto = async () => {
+ const { status: cameraPerm } = await Permissions.askAsync(
+ Permissions.CAMERA
+ );
+
+ const { status: cameraRollPerm } = await Permissions.askAsync(
+ Permissions.CAMERA_ROLL
+ );
+
+ // only if user allows permission to camera AND camera roll
+ if (cameraPerm === "granted" && cameraRollPerm === "granted") {
+ let pickerResult = await ImagePicker.launchCameraAsync({
+ allowsMultipleSelection: true,
+ quality: 0.8,
+ //allowsEditing: true,
+ aspect: [4, 3],
+ });
+
+ if (!pickerResult.cancelled) {
+ this.setState({ image: pickerResult.uri });
+ }
+
+ this.uploadImageAsync(pickerResult.uri);
+ }
+ };
+
+ _pickImage = async () => {
+ const { status: cameraRollPerm } = await Permissions.askAsync(
+ Permissions.CAMERA_ROLL
+ );
+
+ // only if user allows permission to camera roll
+ if (cameraRollPerm === "granted") {
+ let pickerResult = await ImagePicker.launchImageLibraryAsync({
+ allowsEditing: true,
+ base64: true,
+ aspect: [4, 3],
+ });
+
+ if (!pickerResult.cancelled) {
+ this.setState({ image: pickerResult.uri });
+ }
+
+ this.uploadImageAsync(pickerResult.uri);
+ }
+ };
+
+ uploadImageAsync(pictureuri) {
+ let apiUrl = "http://123.123.123.123/ABC";
+
+ var data = new FormData();
+ data.append("file", {
+ uri: pictureuri,
+ name: "file",
+ type: "image/jpg",
+ });
+
+ fetch(apiUrl, {
+ headers: {
+ Accept: "application/json",
+ "Content-Type": "multipart/form-data",
+ },
+ method: "POST",
+ body: data,
+ })
+ .then((response) => {
+ console.log("succ ");
+ console.log(response);
+ })
+ .catch((err) => {
+ console.log("err ");
+ console.log(err);
+ });
+ }
}
+
+const styles = StyleSheet.create({
+ container: {
+ alignItems: "center",
+ flex: 1,
+ justifyContent: "center",
+ },
+ exampleText: {
+ fontSize: 20,
+ marginBottom: 20,
+ marginHorizontal: 15,
+ textAlign: "center",
+ },
+ maybeRenderUploading: {
+ alignItems: "center",
+ backgroundColor: "rgba(0,0,0,0.4)",
+ justifyContent: "center",
+ },
+ maybeRenderContainer: {
+ borderRadius: 3,
+ elevation: 2,
+ marginTop: 30,
+ shadowColor: "rgba(0,0,0,1)",
+ shadowOpacity: 0.2,
+ shadowOffset: {
+ height: 4,
+ width: 4,
+ },
+ shadowRadius: 5,
+ width: 250,
+ },
+ maybeRenderImageContainer: {
+ borderTopLeftRadius: 3,
+ borderTopRightRadius: 3,
+ overflow: "hidden",
+ },
+ maybeRenderImage: {
+ height: 250,
+ width: 250,
+ },
+ maybeRenderImageText: {
+ paddingHorizontal: 10,
+ paddingVertical: 10,
+ },
+});
diff --git a/graphql/client.js b/graphql/client.js
index d9f89c8..455c820 100644
--- a/graphql/client.js
+++ b/graphql/client.js
@@ -42,15 +42,15 @@ const wsLink = new WebSocketLink({
const errorLink = onError(
({ graphQLErrors, networkError, operation, forward }) => {
- console.log(graphQLErrors);
+ console.error(graphQLErrors);
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
- console.log(
+ console.error(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError)
- console.log(`[Network error]: ${JSON.stringify(networkError)}`);
+ console.error(`[Network error]: ${JSON.stringify(networkError)}`);
console.log(operation.getContext());
}
);
diff --git a/graphql/jobs.queries.js b/graphql/jobs.queries.js
index f9f5be6..0e64858 100644
--- a/graphql/jobs.queries.js
+++ b/graphql/jobs.queries.js
@@ -126,7 +126,7 @@ export const QUERY_JOB_COSTING_DETAILS = gql`
ded_amt
ded_status
depreciation_taxes
- federal_tax_payable
+
other_amount_payable
towing_payable
storage_payable
@@ -143,7 +143,7 @@ export const QUERY_JOB_COSTING_DETAILS = gql`
parts_tax_rates
job_totals
labor_rate_desc
- rate_atp
+
rate_la1
rate_la2
rate_la3
@@ -289,7 +289,7 @@ export const GET_JOB_BY_PK = gql`
ded_amt
ded_status
depreciation_taxes
- federal_tax_payable
+
other_amount_payable
towing_payable
storage_payable
@@ -329,7 +329,7 @@ export const GET_JOB_BY_PK = gql`
ownr_ph1
}
labor_rate_desc
- rate_atp
+
rate_la1
rate_la2
rate_la3
@@ -716,7 +716,7 @@ export const QUERY_ALL_JOB_FIELDS = gql`
est_ph1
est_st
est_zip
- federal_tax_payable
+
federal_tax_rate
g_bett_amt
ins_addr1
@@ -791,7 +791,7 @@ export const QUERY_ALL_JOB_FIELDS = gql`
plate_st
po_number
policy_no
- rate_atp
+
rate_la1
rate_la2
rate_la3
@@ -981,7 +981,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
ded_amt
ded_status
depreciation_taxes
- federal_tax_payable
+
other_amount_payable
towing_payable
storage_payable
@@ -1007,7 +1007,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
ownr_zip
ownr_ctry
ownr_ph1
- rate_atp
+
rate_la1
rate_la2
rate_la3
@@ -1065,10 +1065,6 @@ export const generate_UPDATE_JOB_KANBAN = (
newChildId,
newChildParent
) => {
- // console.log("oldChildId", oldChildId, "oldChildNewParent", oldChildNewParent);
- // console.log("Moved", movedId, movedNewParent, movedNewStatus);
- // console.log("new", newChildId, newChildParent);
-
const oldChildQuery = `
updateOldChild: update_jobs(where: { id: { _eq: "${oldChildId}" } },
_set: {kanbanparent: ${
diff --git a/package.json b/package.json
index fae1aab..f438872 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,10 @@
"expo-camera": "~9.0.0",
"expo-file-system": "~9.2.0",
"expo-font": "~8.3.0",
+ "expo-image-picker": "~9.1.1",
"expo-localization": "~9.0.0",
+ "expo-media-library": "~9.2.1",
+ "expo-permissions": "~9.3.0",
"expo-status-bar": "~1.0.2",
"firebase": "7.9.0",
"formik": "^2.2.3",
diff --git a/redux/app/app.actions.js b/redux/app/app.actions.js
new file mode 100644
index 0000000..9e536c4
--- /dev/null
+++ b/redux/app/app.actions.js
@@ -0,0 +1,21 @@
+import AppActionTypes from "./app.types";
+
+export const setCameraJobId = (jobId) => ({
+ type: AppActionTypes.SET_CAMERA_JOB_ID,
+ payload: jobId,
+});
+
+export const documentUploadStart = (jobId) => ({
+ type: AppActionTypes.DOCUMENT_UPLOAD_START,
+ payload: jobId,
+});
+
+export const documentUploadSuccess = (jobId) => ({
+ type: AppActionTypes.DOCUMNET_UPLOAD_SUCCESS,
+ payload: jobId,
+});
+
+export const documentUploadFailure = (error) => ({
+ type: AppActionTypes.DOCUMENT_UPLOAD_FAILURE,
+ payload: error,
+});
diff --git a/redux/app/app.reducer.js b/redux/app/app.reducer.js
new file mode 100644
index 0000000..8799af8
--- /dev/null
+++ b/redux/app/app.reducer.js
@@ -0,0 +1,39 @@
+import AppActionTypes from "./app.types";
+
+const INITIAL_STATE = {
+ cameraJobId: null,
+ documentUploadInProgress: null,
+ documentUploadError: null,
+};
+
+const appReducer = (state = INITIAL_STATE, action) => {
+ switch (action.type) {
+ case AppActionTypes.SET_CAMERA_JOB_ID:
+ return {
+ ...state,
+ cameraJobId: action.payload,
+ };
+ case AppActionTypes.DOCUMENT_UPLOAD_START:
+ return {
+ ...state,
+ documentUploadError: null,
+ documentUploadInProgress: action.payload,
+ };
+ case AppActionTypes.DOCUMNET_UPLOAD_SUCCESS:
+ return {
+ ...state,
+ documentUploadError: null,
+ documentUploadInProgress: null,
+ };
+ case AppActionTypes.DOCUMENT_UPLOAD_FAILURE:
+ return {
+ ...state,
+ documentUploadError: action.payload,
+ documentUploadInProgress: null,
+ };
+ default:
+ return state;
+ }
+};
+
+export default appReducer;
diff --git a/redux/app/app.sagas.js b/redux/app/app.sagas.js
new file mode 100644
index 0000000..0d498e3
--- /dev/null
+++ b/redux/app/app.sagas.js
@@ -0,0 +1,158 @@
+import {
+ all,
+ //call, put, takeLatest
+} from "redux-saga/effects";
+// import {
+// auth,
+// getCurrentUser,
+// updateCurrentUser,
+// } from "../../firebase/firebase.utils";
+// import {
+// sendPasswordResetFailure,
+// sendPasswordResetSuccess,
+// signInFailure,
+// signInSuccess,
+// signOutFailure,
+// signOutSuccess,
+// unauthorizedUser,
+// updateUserDetailsSuccess,
+// validatePasswordResetFailure,
+// validatePasswordResetSuccess,
+// setBodyshop,
+// } from "./user.actions";
+// import UserActionTypes from "./user.types";
+// import { client } from "../../graphql/client";
+// import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
+
+// export function* onEmailSignInStart() {
+// yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
+// }
+// export function* signInWithEmail({ payload: { email, password } }) {
+// try {
+// //logImEXEvent("redux_sign_in_attempt", { user: email });
+// const { user } = yield auth.signInWithEmailAndPassword(email, password);
+// yield put(
+// signInSuccess({
+// uid: user.uid,
+// email: user.email,
+// displayName: user.displayName,
+// photoURL: user.photoURL,
+// authorized: true,
+// })
+// );
+// } catch (error) {
+// yield put(signInFailure(error));
+// //logImEXEvent("redux_sign_in_failure", { user: email, error });
+// }
+// }
+
+// export function* onCheckUserSession() {
+// yield takeLatest(UserActionTypes.CHECK_USER_SESSION, isUserAuthenticated);
+// }
+// export function* isUserAuthenticated() {
+// try {
+// //logImEXEvent("redux_auth_check");
+
+// const user = yield getCurrentUser();
+// if (!user) {
+// yield put(unauthorizedUser());
+// return;
+// }
+
+// yield put(
+// signInSuccess({
+// uid: user.uid,
+// email: user.email,
+// displayName: user.displayName,
+// photoURL: user.photoURL,
+// authorized: true,
+// })
+// );
+// } catch (error) {
+// yield put(signInFailure(error));
+// }
+// }
+// export function* onSignOutStart() {
+// yield takeLatest(UserActionTypes.SIGN_OUT_START, signOutStart);
+// }
+// export function* signOutStart() {
+// try {
+// //logImEXEvent("redux_sign_out");
+
+// yield auth.signOut();
+// yield put(signOutSuccess());
+// } catch (error) {
+// yield put(signOutFailure(error.message));
+// }
+// }
+
+// export function* onUpdateUserDetails() {
+// yield takeLatest(UserActionTypes.UPDATE_USER_DETAILS, updateUserDetails);
+// }
+// export function* updateUserDetails(userDetails) {
+// try {
+// yield updateCurrentUser(userDetails.payload);
+// yield put(updateUserDetailsSuccess(userDetails.payload));
+// } catch (error) {
+// //yield put(signOutFailure(error.message));
+// //TODO error handling
+// }
+// }
+
+// export function* onSignInSuccess() {
+// yield takeLatest(UserActionTypes.SIGN_IN_SUCCESS, signInSuccessSaga);
+// }
+
+// export function* signInSuccessSaga({ payload }) {
+// try {
+// const shop = yield client.query({ query: QUERY_BODYSHOP });
+
+// yield put(setBodyshop(shop.data.bodyshops[0]));
+// } catch (error) {
+// console.log("UH-OH. Couldn't get shop details.", error);
+// }
+// }
+
+// export function* onSendPasswordResetStart() {
+// yield takeLatest(
+// UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START,
+// sendPasswordResetEmail
+// );
+// }
+// export function* sendPasswordResetEmail({ payload }) {
+// try {
+// yield auth.sendPasswordResetEmail(payload, {
+// url: "https://imex.online/passwordreset",
+// });
+// yield put(sendPasswordResetSuccess());
+// } catch (error) {
+// yield put(sendPasswordResetFailure(error.message));
+// }
+// }
+
+// export function* onValidatePasswordResetStart() {
+// yield takeLatest(
+// UserActionTypes.VALIDATE_PASSWORD_RESET_START,
+// validatePasswordResetStart
+// );
+// }
+// export function* validatePasswordResetStart({ payload: { password, code } }) {
+// try {
+// yield auth.confirmPasswordReset(code, password);
+// yield put(validatePasswordResetSuccess());
+// } catch (error) {
+// yield put(validatePasswordResetFailure(error.message));
+// }
+// }
+
+export function* appSagas() {
+ yield all([
+ // call(onEmailSignInStart),
+ // call(onCheckUserSession),
+ // call(onSignOutStart),
+ // call(onUpdateUserDetails),
+ // call(onSignInSuccess),
+ // call(onSendPasswordResetStart),
+ // call(onValidatePasswordResetStart),
+ ]);
+}
diff --git a/redux/app/app.selectors.js b/redux/app/app.selectors.js
new file mode 100644
index 0000000..537c353
--- /dev/null
+++ b/redux/app/app.selectors.js
@@ -0,0 +1,16 @@
+import { createSelector } from "reselect";
+
+const selectApp = (state) => state.app;
+
+export const selectCurrentCameraJobId = createSelector(
+ [selectApp],
+ (user) => app.cameraJobId
+);
+export const selectDocumentUploadInProgress = createSelector(
+ [selectApp],
+ (user) => app.documentUploadInProgress
+);
+export const selectDocumentUploadError = createSelector(
+ [selectApp],
+ (user) => app.documentUploadError
+);
diff --git a/redux/app/app.types.js b/redux/app/app.types.js
new file mode 100644
index 0000000..b370bf7
--- /dev/null
+++ b/redux/app/app.types.js
@@ -0,0 +1,7 @@
+const AppActionTypes = {
+ SET_CAMERA_JOB_ID: "SET_CAMERA_JOB_ID",
+ DOCUMENT_UPLOAD_START: "DOCUMENT_UPLOAD_START",
+ DOCUMNET_UPLOAD_SUCCESS: "DOCUMNET_UPLOAD_SUCCESS",
+ DOCUMENT_UPLOAD_FAILURE: "DOCUMENT_UPLOAD_FAILURE",
+};
+export default AppActionTypes;
diff --git a/redux/root.reducer.js b/redux/root.reducer.js
index 38653fb..043e82e 100644
--- a/redux/root.reducer.js
+++ b/redux/root.reducer.js
@@ -1,30 +1,21 @@
+import AsyncStorage from "@react-native-community/async-storage";
import { combineReducers } from "redux";
import { persistReducer } from "redux-persist";
-import AsyncStorage from "@react-native-community/async-storage";
-
+import appReducer from "./app/app.reducer";
import userReducer from "./user/user.reducer";
-// import messagingReducer from "./messaging/messaging.reducer";
-// import emailReducer from "./email/email.reducer";
-// import modalsReducer from "./modals/modals.reducer";
-// import applicationReducer from "./application/application.reducer";
-// import techReducer from "./tech/tech.reducer";
const persistConfig = {
key: "root",
storage: AsyncStorage,
whitelist: [],
- blacklist: ["user"],
+ blacklist: ["user", "app"],
// whitelist: ["messaging", "tech", "application"],
// blacklist: ["user", "email", "modals"],
};
const rootReducer = combineReducers({
user: userReducer,
- // messaging: messagingReducer,
- // email: emailReducer,
- // modals: modalsReducer,
- // application: applicationReducer,
- // tech: techReducer,
+ app: appReducer,
});
export default persistReducer(persistConfig, rootReducer);
diff --git a/redux/root.saga.js b/redux/root.saga.js
index 82bb66b..921340c 100644
--- a/redux/root.saga.js
+++ b/redux/root.saga.js
@@ -1,19 +1,7 @@
import { all, call } from "redux-saga/effects";
-
+import { appSagas } from "./app/app.sagas";
import { userSagas } from "./user/user.sagas";
-// import { messagingSagas } from "./messaging/messaging.sagas";
-// import { emailSagas } from "./email/email.sagas";
-// import { modalsSagas } from "./modals/modals.sagas";
-// import { applicationSagas } from "./application/application.sagas";
-// import { techSagas } from "./tech/tech.sagas";
export default function* rootSaga() {
- yield all([
- call(userSagas),
- // call(messagingSagas),
- // call(emailSagas),
- // call(modalsSagas),
- // call(applicationSagas),
- // call(techSagas),
- ]);
+ yield all([call(userSagas), call(appSagas)]);
}
diff --git a/redux/store.js b/redux/store.js
index 67cf65e..a01700f 100644
--- a/redux/store.js
+++ b/redux/store.js
@@ -10,14 +10,23 @@ const sagaMiddleWare = createSagaMiddleware();
const middlewares = [sagaMiddleWare];
if (process.env.NODE_ENV === "development") {
- middlewares.push(
- createLogger({
- collapsed: true,
- })
- );
+ middlewares
+ .push
+ // createLogger({
+ // collapsed: true,
+ // })
+ ();
}
-const enhancer = compose(
+//Add in for React Native Debugger.
+const composeEnhancers =
+ typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
+ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
+ // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
+ })
+ : compose;
+
+const enhancer = composeEnhancers(
applyMiddleware(...middlewares)
// other store enhancers if any
);
diff --git a/redux/user/user.sagas.js b/redux/user/user.sagas.js
index 9561fad..2fd0e55 100644
--- a/redux/user/user.sagas.js
+++ b/redux/user/user.sagas.js
@@ -106,7 +106,7 @@ export function* signInSuccessSaga({ payload }) {
yield put(setBodyshop(shop.data.bodyshops[0]));
} catch (error) {
- console.log("UHOH. Couldn't get shop details.", error);
+ console.log("UH-OH. Couldn't get shop details.", error);
}
}
diff --git a/translations/en-US/common.json b/translations/en-US/common.json
index 1cbc39a..8a50e75 100644
--- a/translations/en-US/common.json
+++ b/translations/en-US/common.json
@@ -3,6 +3,11 @@
"app": {
"title": "ImEX Mobile"
},
+ "camera": {
+ "titles": {
+ "cameratab": "Camera"
+ }
+ },
"general": {
"actions": {
"signout": "Sign Out"
diff --git a/translations/es-MX/common.json b/translations/es-MX/common.json
index e23211b..bdea773 100644
--- a/translations/es-MX/common.json
+++ b/translations/es-MX/common.json
@@ -3,6 +3,11 @@
"app": {
"title": ""
},
+ "camera": {
+ "titles": {
+ "cameratab": ""
+ }
+ },
"general": {
"actions": {
"signout": ""
diff --git a/translations/fr-CA/common.json b/translations/fr-CA/common.json
index e23211b..bdea773 100644
--- a/translations/fr-CA/common.json
+++ b/translations/fr-CA/common.json
@@ -3,6 +3,11 @@
"app": {
"title": ""
},
+ "camera": {
+ "titles": {
+ "cameratab": ""
+ }
+ },
"general": {
"actions": {
"signout": ""
diff --git a/yarn.lock b/yarn.lock
index e3de005..29126ba 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3242,6 +3242,14 @@ expo-font@~8.3.0:
fbjs "1.0.0"
fontfaceobserver "^2.1.0"
+expo-image-picker@~9.1.1:
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-9.1.1.tgz#42abe9deb595fa9f9d8ac0d2ba8aad2cd6f69581"
+ integrity sha512-Etz2OQhRflfx+xFbSdma8QLZsnV/yq0M/yqYlsi3/RLiWAQYM/D/VmRfDDPiG10gm+KX3Xb5iKplNjPrWeTuQg==
+ dependencies:
+ expo-permissions "~9.3.0"
+ uuid "7.0.2"
+
expo-keep-awake@~8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-8.3.0.tgz#11bb8073dfe453259926855c81d9f35db03a79b9"
@@ -3273,6 +3281,11 @@ expo-location@~9.0.0:
resolved "https://registry.yarnpkg.com/expo-location/-/expo-location-9.0.1.tgz#adf93b8adf5e9dcf9570cba1d66c8e3831329156"
integrity sha512-yl4V2IelxrjG1h3nshkyILwghysNJvvEuR4Of0U7oYAsBrT0cq8NxFuaDemRvqt9Yb19wVFNMoVtYFNpthcqpQ==
+expo-media-library@~9.2.1:
+ version "9.2.1"
+ resolved "https://registry.yarnpkg.com/expo-media-library/-/expo-media-library-9.2.1.tgz#11583e40087d77cf16e70bb7db0048d2bd1938b5"
+ integrity sha512-A9AAGI1200P0oULoXA7U7wQ91zgPWl9GWo5H9EQvVDHp1ABX8tf2qTOad6Y0KotHYWVMIyfsVXzVYAbjJ9LxPQ==
+
expo-permissions@~9.3.0:
version "9.3.0"
resolved "https://registry.yarnpkg.com/expo-permissions/-/expo-permissions-9.3.0.tgz#b90c7e9e411d306c1c7ba2bae18d5c53c201affd"
@@ -3298,7 +3311,7 @@ expo-status-bar@~1.0.2:
resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-1.0.2.tgz#2441a77c56be31597898337b0d086981f2adefd8"
integrity sha512-5313u744GcLzCadxIPXyTkYw77++UXv1dXCuhYDxDbtsEf93iMra7WSvzyE8a7mRQLIIPRuGnBOdrL/V1C7EOQ==
-expo@^39.0.0:
+expo@^39.0.4:
version "39.0.4"
resolved "https://registry.yarnpkg.com/expo/-/expo-39.0.4.tgz#320b7453ac055fc37c64942d5ba442f4e2781993"
integrity sha512-lyd7VSg0DG+I2CwWtOHwhmMwgANoqggqU1ooWRdO4KdWPYA8hWMMsLC2vBBBemKv3PPwxhl9hhzFxtjJ/MaR7g==
@@ -6953,6 +6966,11 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+uuid@7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.2.tgz#7ff5c203467e91f5e0d85cfcbaaf7d2ebbca9be6"
+ integrity sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==
+
uuid@^3.3.2, uuid@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"