diff --git a/components/Buttons/tech-clock-out-button.component.jsx b/components/Buttons/tech-clock-out-button.component.jsx new file mode 100644 index 0000000..19fd1ae --- /dev/null +++ b/components/Buttons/tech-clock-out-button.component.jsx @@ -0,0 +1,28 @@ +import React from "react"; +import { Text } from "react-native"; +import { Button } from "react-native-paper"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { employeeSignOut } from "../../redux/employee/employee.actions"; +import { setTmTicketJobId } from "../../redux/app/app.actions"; + +const mapDispatchToProps = (dispatch) => ({ + signOut:(jobId) => dispatch(setTmTicketJobId()), +}); + +export function TechClockOffButton({ setTmTicketJobId, + jobId, + timeTicketId, }) { + const { t } = useTranslation(); + return ( + + ); +} +export default connect(null, mapDispatchToProps)(SignOutButton); diff --git a/components/job-list-item/job-list-item.component.jsx b/components/job-list-item/job-list-item.component.jsx index 9d823b3..a91856f 100644 --- a/components/job-list-item/job-list-item.component.jsx +++ b/components/job-list-item/job-list-item.component.jsx @@ -6,16 +6,16 @@ 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, setTmTicketJobId } from "../../redux/app/app.actions"; +import { setCameraJob, setCameraJobId } from "../../redux/app/app.actions"; const mapStateToProps = createStructuredSelector({}); const mapDispatchToProps = (dispatch) => ({ setCameraJobId: (id) => dispatch(setCameraJobId(id)), setCameraJob: (job) => dispatch(setCameraJob(job)), - setTmTicketJobId:(id) => dispatch(setTmTicketJobId(id)), + // setTmTicketJobId:(id) => dispatch(setTmTicketJobId(id)), }); -export function JobListItem({ setCameraJob, setCameraJobId,setTmTicketJobId, item }) { +export function JobListItem({ setCameraJob, setCameraJobId, item }) { const { t } = useTranslation(); const navigation = useNavigation(); // const _swipeableRow = useRef(null); @@ -72,7 +72,7 @@ export function JobListItem({ setCameraJob, setCameraJobId,setTmTicketJobId, ite onPress={() => { logImEXEvent("imexmobile_setcamerajobid_row"); setCameraJobId(item.id); - setTmTicketJobId(item.id); + // setTmTicketJobId(item.id); setCameraJob(item); navigation.navigate("MediaBrowserTab"); }} diff --git a/components/time-ticket-items/clockedin-list-item.component.jsx b/components/time-ticket-items/clockedin-list-item.component.jsx index f93a741..4d92c93 100644 --- a/components/time-ticket-items/clockedin-list-item.component.jsx +++ b/components/time-ticket-items/clockedin-list-item.component.jsx @@ -3,64 +3,84 @@ import { useNavigation } from "@react-navigation/native"; import React from "react"; import { useTranslation } from "react-i18next"; import { Button, Card, Text } from "react-native-paper"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; +import { connect, useSelector, useDispatch } from "react-redux"; +import { createSelector, createStructuredSelector } from "reselect"; import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; import { DateTimeFormatter } from "../../util/DateFormater"; // import { setTimeTicketJobId } from "../../redux/timetickets/timetickets.actions"; import { setTmTicketJobId } from "../../redux/app/app.actions"; import { logImEXEvent } from "../../firebase/firebase.analytics"; +import { employeeSignInStart } from "../../redux/employee/employee.actions"; +import { useRef } from "react"; + + +// const selectNumCompletedTodos = createSelector( +// (state) => state.timeTickets, +// (timeTickets) => timeTickets.timeTicketJobId +// ); +//const mapStateToProps = createStructuredSelector({}); + // // setTimeTicketJobId: (jobId) =>dispatch(setTimeTicketJobId({jobId})), + //employeeSignInStart:(idjob) => dispatch(employeeSignInStart(idjob)), -const mapStateToProps = createStructuredSelector({}); const mapDispatchToProps = (dispatch) => ({ - // setTimeTicketJobId: (jobId) =>dispatch(setTimeTicketJobId({jobId})), - setTmTicketJobId:(id) => dispatch(setTmTicketJobId(id)), + setTmTicketJobId:() => dispatch(setTmTicketJobId(jobId)), }); -export function ClockedinListItem({ setTmTicketJobId, ticket }) { +export function ClockedinListItem( props ) { + const { t } = useTranslation(); const navigation = useNavigation(); - - const onPress = (ticket, setCameraJobId) => { - console.log("ClockedinListItem, onPress called"); - console.log("ClockedinListItem, ticket", ticket); - setTimeTicketJobId(ticket.jobid); - // logImEXEvent("imexmobile_view_job_detail"); - navigation.push("TimeTicketClockOff", { - jobId: ticket.jobid, //item.id, - timeTicketId: ticket.id, - //completedCallback: refetch, - }); - // navigation.push("JobDetail", { - // jobId: item.id, - // timeTicketId: item.ro_number || t("general.labels.na"), - // job: item, - // }); - // () => {navigation.navigate("TimeTicketClockOff");} - }; + console.log("ClockedinListItem, ", props.ticket.job.id); + const jbId = props.ticket.job.id; + console.log("ClockedinListItem, jbId: ", jbId); + const te = useRef(jbId) + let makeNave = (jobId) => ( + console.log("ClockedinListItem ", setTmTicketJobId) + ,console.log("te", jobId) + ,setTmTicketJobId(jobId) + + // ,navigation.navigate("TimeTicketClockOff") + ); + // const onPress = (ticket, setCameraJobId) => { + // console.log("ClockedinListItem, onPress called"); + // console.log("ClockedinListItem, ticket", ticket); + // setTimeTicketJobId(ticket.jobid); + // // logImEXEvent("imexmobile_view_job_detail"); + // navigation.push("TimeTicketClockOff", { + // jobId: ticket.jobid, //item.id, + // timeTicketId: ticket.id, + // //completedCallback: refetch, + // }); + // // navigation.push("JobDetail", { + // // jobId: item.id, + // // timeTicketId: item.ro_number || t("general.labels.na"), + // // job: item, + // // }); + // // () => {navigation.navigate("TimeTicketClockOff");} + // }; return ( Vehicle : - {`${ticket.job.v_model_yr || ""} ${ticket.job.v_make_desc || ""} ${ - ticket.job.v_model_desc || "" + {`${props.ticket.job.v_model_yr || ""} ${props.ticket.job.v_make_desc || ""} ${ + props.ticket.job.v_model_desc || "" }`} - Clocked In : {ticket.clockon} + Clocked In : {props.ticket.clockon} Cost Center :{" "} - {ticket.cost_center === "timetickets.labels.shift" - ? t(ticket.cost_center) - : ticket.cost_center} + {props.ticket.cost_center === "timetickets.labels.shift" + ? t(props.ticket.cost_center) + : props.ticket.cost_center} @@ -70,21 +90,25 @@ export function ClockedinListItem({ setTmTicketJobId, ticket }) { completedCallback={refetch} /> */} @@ -121,4 +145,4 @@ export function ClockedinListItem({ setTmTicketJobId, ticket }) { ); } -export default connect(mapStateToProps, mapDispatchToProps)(ClockedinListItem); +export default connect(null, mapDispatchToProps)(ClockedinListItem); diff --git a/components/time-ticket-lists/employee-clockedin-list.component.jsx b/components/time-ticket-lists/employee-clockedin-list.component.jsx index f2ebd68..ec1b2cd 100644 --- a/components/time-ticket-lists/employee-clockedin-list.component.jsx +++ b/components/time-ticket-lists/employee-clockedin-list.component.jsx @@ -1,24 +1,32 @@ import { connect } from "react-redux"; -import { selectCurrentEmployee, selectTechnician } from "../../redux/employee/employee.selectors"; +import { + selectCurrentEmployee, + selectTechnician, +} from "../../redux/employee/employee.selectors"; import { QUERY_ACTIVE_TIME_TICKETS } from "../../graphql/timetickets.queries"; -import { ActivityIndicator,Button, List, Modal, Portal, Searchbar } from "react-native-paper"; +import { ActivityIndicator } from "react-native-paper"; import ErrorDisplay from "../error-display/error-display.component"; -import { View,Text,FlatList, RefreshControl, } from "react-native"; +import { View, Text, FlatList, RefreshControl } from "react-native"; import { useQuery } from "@apollo/client"; import { createStructuredSelector } from "reselect"; import { useTranslation } from "react-i18next"; import { ClockedinListItem } from "../time-ticket-items/clockedin-list-item.component"; +import { setTmTicketJobId } from "../../redux/app/app.actions"; const mapStateToProps = createStructuredSelector({ technician: selectTechnician, //currentEmployee: selectCurrentEmployee, }); -const mapDispatchToProps = (dispatch) => ({}); +const mapDispatchToProps = (dispatch) => ({ + setTmTicketJobId: (jobId) => dispatch(setTmTicketJobId(jobId)), +}); export function EmployeeClockedInList({ technician }) { - const { t } = useTranslation(); + const { t } = useTranslation(); - const { loading, error, data, refetch } = useQuery(QUERY_ACTIVE_TIME_TICKETS, { + const { loading, error, data, refetch } = useQuery( + QUERY_ACTIVE_TIME_TICKETS, + { variables: { employeeId: technician?.id, }, @@ -30,9 +38,9 @@ export function EmployeeClockedInList({ technician }) { if (loading) return ; if (error) return ; //if (error) return ; -console.log("QUERY_ACTIVE_TIME_TICKETS data",data) - -const onRefresh = async () => { + console.log("QUERY_ACTIVE_TIME_TICKETS data", data); +// if (data) () => {setTmTicketJobId(data)} + const onRefresh = async () => { return refetch(); }; return ( @@ -40,9 +48,13 @@ const onRefresh = async () => { {data.timetickets.length > 0 ? ( You are already clocked in to the following job(s): - } - renderItem={(object) => } /> + + } + renderItem={(object) => } + /> ) : null} @@ -105,4 +117,4 @@ const onRefresh = async () => { ); } -export default connect(mapStateToProps,null)(EmployeeClockedInList); +export default connect(mapStateToProps, mapDispatchToProps)(EmployeeClockedInList); diff --git a/components/time-ticket/screen-time-ticket-clockoff.component.jsx b/components/time-ticket/screen-time-ticket-clockoff.component.jsx index 01a99a8..b86fdc5 100644 --- a/components/time-ticket/screen-time-ticket-clockoff.component.jsx +++ b/components/time-ticket/screen-time-ticket-clockoff.component.jsx @@ -16,6 +16,7 @@ import { UPDATE_TIME_TICKET } from "../../graphql/timetickets.queries"; import { useMutation } from "@apollo/client"; import { selectCurrentTmTicketJobId } from "../../redux/app/app.selectors"; import ErrorDisplay from "../error-display/error-display.component"; +import { timeTicketClockOutStart } from "../../redux/timetickets/timetickets.actions"; // import { selectCurrentTimeTicketJobId } from "../../redux/timetickets/timetickets.selectors"; //TODO add props needed for call @@ -26,7 +27,9 @@ const mapStateToProps = createStructuredSelector({ currentTmTicketJobId: selectCurrentTmTicketJobId, // currentJobId: selectCurrentTimeTicketJobId }); -// const mapDispatchToProps = (dispatch) => ({}); + const mapDispatchToProps = (dispatch) => ({ + timeTicketClockOutStart + }); export function TimeTicketClockOff({ currentEmployee, diff --git a/redux/timetickets/timetickets.actions.js b/redux/timetickets/timetickets.actions.js index b1bcfd4..3de6263 100644 --- a/redux/timetickets/timetickets.actions.js +++ b/redux/timetickets/timetickets.actions.js @@ -24,3 +24,29 @@ export const timeTicketCreateFailure = (error) => ({ type: TimeTicketsActionTypes.TIME_TICKET_CREATE_FAILURE, payload: error, }); + +export const timeTicketClockInStart = (timeTicket) => ({ + type: TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_START, + payload: timeTicket, +}); +export const timeTicketClockInSuccess = (insertTimeTickets) => ({ + type: TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_SUCCESS, + payload: insertTimeTickets, +}); +export const timeTicketClockInFailure = (error) => ({ + type: TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_FAILURE, + payload: error, +}); + +export const timeTicketClockOutStart = (timeTicket) => ({ + type: TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_START, + payload: timeTicket, +}); +export const timeTicketClockOutSuccess = (insertTimeTickets) => ({ + type: TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_SUCCESS, + payload: insertTimeTickets, +}); +export const timeTicketClockOutFailure = (error) => ({ + type: TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_FAILURE, + payload: error, +}); diff --git a/redux/timetickets/timetickets.reducer.js b/redux/timetickets/timetickets.reducer.js index 075db46..377c355 100644 --- a/redux/timetickets/timetickets.reducer.js +++ b/redux/timetickets/timetickets.reducer.js @@ -6,6 +6,10 @@ const INITIAL_STATE = { timeTicketJob: null, uploadTimeTicketInProgress: false, uploadTimeTicketError: null, + clockingIn: false, + clockingInError: null, + clockingOut: false, + clockingOutError: null, }; const timeTicketsReducer = (state = INITIAL_STATE, action) => { @@ -23,22 +27,41 @@ const timeTicketsReducer = (state = INITIAL_STATE, action) => { timeTicketJob: action.payload }; case TimeTicketsActionTypes.TIME_TICKET_CREATE_START: - return { - ...state, - uploadTimeTicketInProgress: true - }; + return {...state,uploadTimeTicketInProgress: true}; case TimeTicketsActionTypes.TIME_TICKET_CREATE_SUCCESS: - return { - ...state, //TODO add logic here when successful + return {...state, uploadTimeTicketInProgress: false, uploadTimeTicketError: null, }; case TimeTicketsActionTypes.TIME_TICKET_CREATE_FAILURE: - return { - ...state, + return {...state, uploadTimeTicketInProgress: false, uploadTimeTicketError: action.payload, }; + case TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_START: + return {...state,clockingIn: true}; + case TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_SUCCESS: + return {...state, + clockingIn: false, + clockingInError: null, + }; + case TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_FAILURE: + return {...state, + clockingIn: false, + clockingInError: action.payload, + }; + case TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_START: + return {...state,clockingOut: true}; + case TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_SUCCESS: + return {...state, + clockingOut: false, + clockingOutError: null, + }; + case TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_FAILURE: + return {...state, + clockingOut: false, + clockingOutError: action.payload, + }; default: return state; } diff --git a/redux/timetickets/timetickets.sagas.js b/redux/timetickets/timetickets.sagas.js index 6ea8c7f..5c702b6 100644 --- a/redux/timetickets/timetickets.sagas.js +++ b/redux/timetickets/timetickets.sagas.js @@ -1,6 +1,10 @@ import { timeTicketCreateFailure, timeTicketCreateSuccess, + timeTicketClockInSuccess, + timeTicketClockInFailure, + timeTicketClockOutSuccess, + timeTicketClockOutFailure } from "./timetickets.actions"; import TimeTicketsActionTypes from "./timetickets.types"; import { client } from "../../graphql/client"; @@ -67,6 +71,69 @@ export function* insertNewTimeTicket({ payload: { timeTicketInput } }) { } } -export function* timeTicketsSagas() { - yield all([call(onCreateTimeTicketStart)]); +export function* onClockOutStart() { + yield takeLatest(TimeTicketsActionTypes.TIME_TICKET_CLOCKOUT_START,clockOutStart); +} +export function* clockOutStart({ payload: { timeTicketInput } }) { + try { + logImEXEvent("redux_clockOutStart_attempt"); + //console.loging + console.log("Saga, clockOutStart :", timeTicketInput); + // 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.mutate({ + // mutation: INSERT_NEW_TIME_TICKET, + // variables: { + // timeTicketInput: [ + // // { + // // bodyshopid: bodyshop.id, + // // employeeid: technician.id, + // // date: moment(theTime).format("YYYY-MM-DD"), + // // clockon: moment(theTime), + // // jobid: values.jobid, + // // cost_center: values.cost_center, + // // ciecacode: + // // bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber + // // ? values.cost_center + // // : Object.keys( + // // bodyshop.md_responsibility_centers.defaults.costs + // // ).find((key) => { + // // return ( + // // bodyshop.md_responsibility_centers.defaults.costs[key] === + // // values.cost_center + // // ); + // // }), + // // }, + // ], + // }, + // }); + // console.log(result); + // const { valid, data, error } = result.data; + // if (valid) { + // yield put(timeTicketCreateSuccess(data)); + // } else { + // yield put(timeTicketCreateFailure(error)); + // } + } catch (error) { + yield put(timeTicketClockOutFailure(error)); + } +} +export function* onClockInStart() { + yield takeLatest(TimeTicketsActionTypes.TIME_TICKET_CLOCKIN_START,clockInStart); +} +export function* clockInStart({ payload: { timeTicketInput } }) { + try { + logImEXEvent("redux_clockInStart_attempt"); + console.log("Saga, clockInStart :", timeTicketInput); + } catch (error) { + yield put(timeTicketClockInFailure(error)); + } +} +export function* timeTicketsSagas() { + yield all([call(onCreateTimeTicketStart),call(onClockOutStart),call(onClockInStart)]); } diff --git a/redux/timetickets/timetickets.types.js b/redux/timetickets/timetickets.types.js index 5737385..db91800 100644 --- a/redux/timetickets/timetickets.types.js +++ b/redux/timetickets/timetickets.types.js @@ -5,5 +5,11 @@ const TimeTicketsActionTypes = { TIME_TICKET_CREATE_START: "TIME_TICKET_CREATE_START", TIME_TICKET_CREATE_SUCCESS: "TIME_TICKET_CREATE_SUCCESS", TIME_TICKET_CREATE_FAILURE: "TIME_TICKET_CREATE_FAILURE", + TIME_TICKET_CLOCKIN_START: "TIME_TICKET_CLOCKIN_START", + TIME_TICKET_CLOCKIN_SUCCESS: "TIME_TICKET_CLOCKIN_SUCCESS", + TIME_TICKET_CLOCKIN_FAILURE: "TIME_TICKET_CLOCKIN_FAILURE", + TIME_TICKET_CLOCKOUT_START: "TIME_TICKET_CLOCKOUT_START", + TIME_TICKET_CLOCKOUT_SUCCESS: "TIME_TICKET_CLOCKOUT_SUCCESS", + TIME_TICKET_CLOCKOUT_FAILURE: "TIME_TICKET_CLOCKOUT_FAILURE", }; export default TimeTicketsActionTypes;