added timeticket redux
This commit is contained in:
@@ -1,34 +1,31 @@
|
|||||||
import { Formik } from "formik";
|
import { Formik } from "formik";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { StyleSheet, Text } from "react-native";
|
import { StyleSheet, Text,View, ScrollView } from "react-native";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { View, ScrollView } from "react-native";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { Button, Dialog, TextInput } from "react-native-paper";
|
import { Button, Dialog, TextInput } from "react-native-paper";
|
||||||
import { QUERY_EMPLOYEE_BY_ID } from "../../graphql/employees.queries";
|
|
||||||
//import SelectDropdown from 'react-native-select-dropdown';
|
|
||||||
import { SelectCostCenter } from "../Selects/select-cost-center";
|
import { SelectCostCenter } from "../Selects/select-cost-center";
|
||||||
|
import { JobSearchSelect } from "../Selects/select-job-name";
|
||||||
|
import DateTimePickerModal from "react-native-modal-datetime-picker";
|
||||||
import {
|
import {
|
||||||
selectCurrentEmployee,
|
selectCurrentEmployee,
|
||||||
selectRates,
|
selectRates,
|
||||||
} from "../../redux/employee/employee.selectors";
|
} from "../../redux/employee/employee.selectors";
|
||||||
import DateTimePickerModal from "react-native-modal-datetime-picker";
|
|
||||||
import { JobSearchSelect } from "../Selects/select-job-name";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
//TODO add props needed for call
|
//TODO add props needed for call
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentEmployee: selectCurrentEmployee,
|
currentEmployee: selectCurrentEmployee,
|
||||||
currentRatesNCostCenters: selectRates,
|
currentRatesNCostCenters: selectRates,
|
||||||
bodyshop: selectBodyshop,
|
currentBodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({});
|
// const mapDispatchToProps = (dispatch) => ({});
|
||||||
|
|
||||||
export function TimeTicketCreate({
|
export function TimeTicketCreate({
|
||||||
currentEmployee,
|
currentEmployee,
|
||||||
currentRatesNCostCenters,
|
currentRatesNCostCenters,
|
||||||
bodyshop
|
currentBodyshop
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -53,15 +50,17 @@ export function TimeTicketCreate({
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
var count = Object.keys(currentRatesNCostCenters).length;
|
if (typeof currentRatesNCostCenters !== 'undefined') {
|
||||||
let selectDataArray = [];
|
var count = Object.keys(currentRatesNCostCenters).length;
|
||||||
for (let i = 0; i < count; i++) {
|
let selectDataArray = [];
|
||||||
selectDataArray.push({
|
for (let i = 0; i < count; i++) {
|
||||||
value: currentRatesNCostCenters[i].cost_center,
|
selectDataArray.push({
|
||||||
label: currentRatesNCostCenters[i].cost_center,
|
value: currentRatesNCostCenters[i].cost_center,
|
||||||
});
|
label: currentRatesNCostCenters[i].cost_center,
|
||||||
}
|
});
|
||||||
setCostCenters(selectDataArray);
|
}
|
||||||
|
setCostCenters(selectDataArray);
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -81,8 +80,8 @@ export function TimeTicketCreate({
|
|||||||
{({ handleChange, handleBlur, handleSubmit, values }) => (
|
{({ handleChange, handleBlur, handleSubmit, values }) => (
|
||||||
<View style={localStyles.topTimeTicketContainer}>
|
<View style={localStyles.topTimeTicketContainer}>
|
||||||
{/* Below will be replaced with a copy of SelectCostCenter but for jobs*/}
|
{/* Below will be replaced with a copy of SelectCostCenter but for jobs*/}
|
||||||
<JobSearchSelect convertedOnly={!bodyshop.tt_allow_post_to_invoiced}
|
<JobSearchSelect convertedOnly={!currentBodyshop.tt_allow_post_to_invoiced}
|
||||||
notExported={!bodyshop.tt_allow_post_to_invoiced} />
|
notExported={!currentBodyshop.tt_allow_post_to_invoiced} />
|
||||||
|
|
||||||
{/* Below will be replaced with a Date Picker*/}
|
{/* Below will be replaced with a Date Picker*/}
|
||||||
{/* <TextInput style={localStyles.input} mode="flat" onChangeText={handleChange("ticketdate")} onBlur={handleBlur("ticketdate")} value={values.ticketdate} label={"Ticket Date"} /> */}
|
{/* <TextInput style={localStyles.input} mode="flat" onChangeText={handleChange("ticketdate")} onBlur={handleBlur("ticketdate")} value={values.ticketdate} label={"Ticket Date"} /> */}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
//TODO: find out if cdk_dealerid, pbs_serialnumber and md_responsibility_centers.defaults.costs need to be added to this
|
||||||
export const QUERY_BODYSHOP = gql`
|
export const QUERY_BODYSHOP = gql`
|
||||||
query QUERY_BODYSHOP {
|
query QUERY_BODYSHOP {
|
||||||
bodyshops(where: { associations: { active: { _eq: true } } }) {
|
bodyshops(where: { associations: { active: { _eq: true } } }) {
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ const INITIAL_STATE = {
|
|||||||
documentUploadInProgress: null,
|
documentUploadInProgress: null,
|
||||||
documentUploadError: null,
|
documentUploadError: null,
|
||||||
deleteAfterUpload: false,
|
deleteAfterUpload: false,
|
||||||
timeTicketJobId: null,
|
|
||||||
timeTicketJob: null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const appReducer = (state = INITIAL_STATE, action) => {
|
const appReducer = (state = INITIAL_STATE, action) => {
|
||||||
@@ -45,16 +43,6 @@ const appReducer = (state = INITIAL_STATE, action) => {
|
|||||||
...state,
|
...state,
|
||||||
deleteAfterUpload: !state.deleteAfterUpload,
|
deleteAfterUpload: !state.deleteAfterUpload,
|
||||||
};
|
};
|
||||||
case AppActionTypes.SET_TIME_TICKET_JOB_ID:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
timeTicketJobId: action.payload,
|
|
||||||
};
|
|
||||||
case AppActionTypes.SET_TIME_TICKET_JOB:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
timeTicketJob: action.payload,
|
|
||||||
};
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,5 @@ const AppActionTypes = {
|
|||||||
DOCUMENT_UPLOAD_SUCCESS: "DOCUMENT_UPLOAD_SUCCESS",
|
DOCUMENT_UPLOAD_SUCCESS: "DOCUMENT_UPLOAD_SUCCESS",
|
||||||
DOCUMENT_UPLOAD_FAILURE: "DOCUMENT_UPLOAD_FAILURE",
|
DOCUMENT_UPLOAD_FAILURE: "DOCUMENT_UPLOAD_FAILURE",
|
||||||
TOGGLE_DLETE_AFTER_UPLOAD: "TOGGLE_DLETE_AFTER_UPLOAD",
|
TOGGLE_DLETE_AFTER_UPLOAD: "TOGGLE_DLETE_AFTER_UPLOAD",
|
||||||
SET_TIME_TICKET_JOB: "SET_TIME_TICKET_JOB",
|
|
||||||
SET_TIME_TICKET_JOB_ID: "SET_TIME_TICKET_JOB_ID",
|
|
||||||
};
|
};
|
||||||
export default AppActionTypes;
|
export default AppActionTypes;
|
||||||
|
|||||||
@@ -31,15 +31,4 @@ export const employeeGetRatesFailure = (error) => ({
|
|||||||
type: EmployeeActionTypes.EMPLOYEE_GET_RATES_FAILURE,
|
type: EmployeeActionTypes.EMPLOYEE_GET_RATES_FAILURE,
|
||||||
payload: error,
|
payload: error,
|
||||||
});
|
});
|
||||||
export const timeTicketCreateStart = (timeTicket) => ({
|
|
||||||
type: EmployeeActionTypes.TIME_TICKET_CREATE_START,
|
|
||||||
payload: timeTicket,
|
|
||||||
});
|
|
||||||
export const timeTicketCreateSuccess = (insertTimeTickets) => ({
|
|
||||||
type: EmployeeActionTypes.TIME_TICKET_CREATE_SUCCESS,
|
|
||||||
payload: insertTimeTickets,
|
|
||||||
});
|
|
||||||
export const timeTicketCreateFailure = (error) => ({
|
|
||||||
type: EmployeeActionTypes.TIME_TICKET_CREATE_FAILURE,
|
|
||||||
payload: error,
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ const INITIAL_STATE = {
|
|||||||
currentEmployee: {
|
currentEmployee: {
|
||||||
authorized: null,
|
authorized: null,
|
||||||
technician: null,
|
technician: null,
|
||||||
rates:[],
|
|
||||||
},
|
},
|
||||||
signingIn: false,
|
signingIn: false,
|
||||||
gettingRates: false,
|
gettingRates: false,
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ const EmployeeActionTypes = {
|
|||||||
EMPLOYEE_AUTHORIZING_SUCCESS: "EMPLOYEE_AUTHORIZING_SUCCESS",
|
EMPLOYEE_AUTHORIZING_SUCCESS: "EMPLOYEE_AUTHORIZING_SUCCESS",
|
||||||
EMPLOYEE_AUTHORIZING_FAILURE: "EMPLOYEE_AUTHORIZING_FAILURE",
|
EMPLOYEE_AUTHORIZING_FAILURE: "EMPLOYEE_AUTHORIZING_FAILURE",
|
||||||
EMPLOYEE_SIGN_OUT: "EMPLOYEE_SIGN_OUT",
|
EMPLOYEE_SIGN_OUT: "EMPLOYEE_SIGN_OUT",
|
||||||
TIME_TICKET_CREATE_START: "TIME_TICKET_CREATE_START",
|
|
||||||
TIME_TICKET_CREATE_SUCCESS: "TIME_TICKET_CREATE_SUCCESS",
|
|
||||||
TIME_TICKET_CREATE_FAILURE: "TIME_TICKET_CREATE_FAILURE",
|
|
||||||
EMPLOYEE_GET_RATES_START: "EMPLOYEE_GET_RATES_START",
|
EMPLOYEE_GET_RATES_START: "EMPLOYEE_GET_RATES_START",
|
||||||
EMPLOYEE_GET_RATES_SUCCESS: "EMPLOYEE_GET_RATES_SUCCESS",
|
EMPLOYEE_GET_RATES_SUCCESS: "EMPLOYEE_GET_RATES_SUCCESS",
|
||||||
EMPLOYEE_GET_RATES_FAILURE: "EMPLOYEE_GET_RATES_FAILURE",
|
EMPLOYEE_GET_RATES_FAILURE: "EMPLOYEE_GET_RATES_FAILURE",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import appReducer from "./app/app.reducer";
|
|||||||
import photosReducer from "./photos/photos.reducer";
|
import photosReducer from "./photos/photos.reducer";
|
||||||
import userReducer from "./user/user.reducer";
|
import userReducer from "./user/user.reducer";
|
||||||
import employeeReducer from './employee/employee.reducer';
|
import employeeReducer from './employee/employee.reducer';
|
||||||
|
import timeTicketsReducer from './timetickets/timetickets.reducer';
|
||||||
|
|
||||||
const persistConfig = {
|
const persistConfig = {
|
||||||
key: "root",
|
key: "root",
|
||||||
@@ -18,6 +19,7 @@ const rootReducer = combineReducers({
|
|||||||
app: appReducer,
|
app: appReducer,
|
||||||
photos: photosReducer,
|
photos: photosReducer,
|
||||||
employee: employeeReducer,
|
employee: employeeReducer,
|
||||||
|
timeTickets: timeTicketsReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default persistReducer(persistConfig, rootReducer);
|
export default persistReducer(persistConfig, rootReducer);
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import { appSagas } from "./app/app.sagas";
|
|||||||
import { photosSagas } from "./photos/photos.sagas";
|
import { photosSagas } from "./photos/photos.sagas";
|
||||||
import { userSagas } from "./user/user.sagas";
|
import { userSagas } from "./user/user.sagas";
|
||||||
import { employeeSagas } from "./employee/employee.sagas";
|
import { employeeSagas } from "./employee/employee.sagas";
|
||||||
|
import { timeTicketsSagas } from "./timetickets/timetickets.sagas";
|
||||||
|
|
||||||
export default function* rootSaga() {
|
export default function* rootSaga() {
|
||||||
yield all([call(userSagas), call(appSagas), call(photosSagas), call(employeeSagas)]);
|
yield all([call(userSagas), call(appSagas), call(photosSagas), call(employeeSagas), call(timeTicketsSagas)]);
|
||||||
}
|
}
|
||||||
|
|||||||
25
redux/timetickets/timetickets.actions.js
Normal file
25
redux/timetickets/timetickets.actions.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import TimeTicketsActionTypes from "./timetickets.types";
|
||||||
|
export const setTimeTicket = (timeTicket) => ({
|
||||||
|
type: TimeTicketsActionTypes.SET_TIME_TICKET,
|
||||||
|
payload: timeTicket,
|
||||||
|
});
|
||||||
|
export const setTimeTicketJobId = (jobId) => ({
|
||||||
|
type: TimeTicketsActionTypes.SET_TIME_TICKET_JOB_ID,
|
||||||
|
payload: jobId,
|
||||||
|
});
|
||||||
|
export const setTimeTicketJob = (job) => ({
|
||||||
|
type: TimeTicketsActionTypes.SET_TIME_TICKET_JOB,
|
||||||
|
payload: job,
|
||||||
|
});
|
||||||
|
export const timeTicketCreateStart = (timeTicket) => ({
|
||||||
|
type: TimeTicketsActionTypes.TIME_TICKET_CREATE_START,
|
||||||
|
payload: timeTicket,
|
||||||
|
});
|
||||||
|
export const timeTicketCreateSuccess = (insertTimeTickets) => ({
|
||||||
|
type: TimeTicketsActionTypes.TIME_TICKET_CREATE_SUCCESS,
|
||||||
|
payload: insertTimeTickets,
|
||||||
|
});
|
||||||
|
export const timeTicketCreateFailure = (error) => ({
|
||||||
|
type: TimeTicketsActionTypes.TIME_TICKET_CREATE_FAILURE,
|
||||||
|
payload: error,
|
||||||
|
});
|
||||||
51
redux/timetickets/timetickets.reducer.js
Normal file
51
redux/timetickets/timetickets.reducer.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import TimeTicketsActionTypes from "./timetickets.types";
|
||||||
|
|
||||||
|
const INITIAL_STATE = {
|
||||||
|
timeTicket: null,
|
||||||
|
timeTickets: [],
|
||||||
|
timeTicketJobId: null,
|
||||||
|
timeTicketJob: null,
|
||||||
|
uploadTimeTicketInProgress: false,
|
||||||
|
uploadTimeTicketError: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeTicketsReducer = (state = INITIAL_STATE, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case TimeTicketsActionTypes.SET_TIME_TICKET:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
timeTicket: action.payload,
|
||||||
|
};
|
||||||
|
case TimeTicketsActionTypes.SET_TIME_TICKET_JOB_ID:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
timeTicketJobId: action.payload,
|
||||||
|
};
|
||||||
|
case TimeTicketsActionTypes.SET_TIME_TICKET_JOB:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
timeTicketJob: action.payload,
|
||||||
|
};
|
||||||
|
case TimeTicketsActionTypes.TIME_TICKET_CREATE_START:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
uploadTimeTicketInProgress: true,
|
||||||
|
};
|
||||||
|
case TimeTicketsActionTypes.TIME_TICKET_CREATE_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state, //TODO add logic here when successful
|
||||||
|
uploadTimeTicketInProgress: false,
|
||||||
|
uploadTimeTicketError: null,
|
||||||
|
};
|
||||||
|
case TimeTicketsActionTypes.TIME_TICKET_CREATE_FAILURE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
uploadTimeTicketInProgress: false,
|
||||||
|
uploadTimeTicketError: action.payload,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default timeTicketsReducer;
|
||||||
51
redux/timetickets/timetickets.sagas.js
Normal file
51
redux/timetickets/timetickets.sagas.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
timeTicketCreateFailure,
|
||||||
|
timeTicketCreateSuccess,
|
||||||
|
} from "./timetickets.actions";
|
||||||
|
import TimeTicketsActionTypes from "./timetickets.types";
|
||||||
|
import { client } from "../../graphql/client";
|
||||||
|
|
||||||
|
import { all, call, put, select, takeLatest } from "redux-saga/effects";
|
||||||
|
import { logImEXEvent } from "../../firebase/firebase.analytics";
|
||||||
|
import { selectCurrentTimeTicket } from "./timetickets.selectors";
|
||||||
|
import { INSERT_NEW_TIME_TICKET } from "../../graphql/timetickets.queries";
|
||||||
|
|
||||||
|
|
||||||
|
export function* onCreateTimeTicketStart() {
|
||||||
|
yield takeLatest(
|
||||||
|
TimeTicketsActionTypes.TIME_TICKET_CREATE_START,
|
||||||
|
insertNewTimeTicket
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export function* insertNewTimeTicket({ payload: { timeticketinsert } }) {
|
||||||
|
try {
|
||||||
|
logImEXEvent("redux_insertnewtimeticket_attempt");
|
||||||
|
//console.loging
|
||||||
|
// console.log("Saga", employeeId, pin, pin);
|
||||||
|
const timeTicket = yield select(selectCurrentTimeTicket);
|
||||||
|
// const response = yield call(axios.post, "/tech/login", {
|
||||||
|
// shopid: bodyshop.id,
|
||||||
|
// employeeid: employeeId,
|
||||||
|
// pin: pin,
|
||||||
|
// });
|
||||||
|
// const { valid, data, error } = response.data;
|
||||||
|
const result = yield client.query({
|
||||||
|
query: INSERT_NEW_TIME_TICKET,
|
||||||
|
variables: {
|
||||||
|
id: employeeId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { valid, data, error } = result.data;
|
||||||
|
if (valid) {
|
||||||
|
yield put(timeTicketCreateSuccess(data));
|
||||||
|
} else {
|
||||||
|
yield put(timeTicketCreateFailure(error));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
yield put(timeTicketCreateFailure(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* timeTicketsSagas() {
|
||||||
|
yield all([call(onCreateTimeTicketStart)]);
|
||||||
|
}
|
||||||
16
redux/timetickets/timetickets.selectors.js
Normal file
16
redux/timetickets/timetickets.selectors.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { createSelector } from "reselect";
|
||||||
|
|
||||||
|
const selectTimeTicketsState = (state) => state.TimeTickets;
|
||||||
|
|
||||||
|
export const selectCurrentTimeTicketJobId = createSelector(
|
||||||
|
[selectTimeTicketsState],
|
||||||
|
(TimeTickets) => TimeTickets.timeTicketJobId
|
||||||
|
);
|
||||||
|
export const selectCurrentTimeTicketJob = createSelector(
|
||||||
|
[selectTimeTicketsState],
|
||||||
|
(TimeTickets) => TimeTickets.timeTicketJob
|
||||||
|
);
|
||||||
|
export const selectCurrentTimeTicket = createSelector(
|
||||||
|
[selectTimeTicketsState],
|
||||||
|
(TimeTickets) => TimeTickets.timeTicket
|
||||||
|
);
|
||||||
9
redux/timetickets/timetickets.types.js
Normal file
9
redux/timetickets/timetickets.types.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const TimeTicketsActionTypes = {
|
||||||
|
SET_TIME_TICKET: "SET_TIME_TICKET",
|
||||||
|
SET_TIME_TICKET_JOB: "SET_TIME_TICKET_JOB",
|
||||||
|
SET_TIME_TICKET_JOB_ID: "SET_TIME_TICKET_JOB_ID",
|
||||||
|
TIME_TICKET_CREATE_START: "TIME_TICKET_CREATE_START",
|
||||||
|
TIME_TICKET_CREATE_SUCCESS: "TIME_TICKET_CREATE_SUCCESS",
|
||||||
|
TIME_TICKET_CREATE_FAILURE: "TIME_TICKET_CREATE_FAILURE",
|
||||||
|
};
|
||||||
|
export default TimeTicketsActionTypes;
|
||||||
Reference in New Issue
Block a user