import { useCallback, useEffect, useState } from "react"; import { Form, Modal } from "antd"; import axios from "axios"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { selectTimeTicketTasks } from "../../redux/modals/modals.selectors"; import { selectCurrentUser } from "../../redux/user/user.selectors"; import TimeTicketTaskModalComponent from "./time-ticket-task-modal.component"; import { useApolloClient } from "@apollo/client/react"; import { QUERY_COMPLETED_TASKS } from "../../graphql/jobs.queries"; import "./time-ticket-task-modal.styles.scss"; import { selectTechnician } from "../../redux/tech/tech.selectors"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; const mapStateToProps = createStructuredSelector({ timeTicketTasksModal: selectTimeTicketTasks, currentUser: selectCurrentUser, technician: selectTechnician }); const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("timeTicketTask")) }); export default connect(mapStateToProps, mapDispatchToProps)(TimeTickeTaskModalContainer); const toFiniteNumber = (value) => { const parsed = Number(value); return Number.isFinite(parsed) ? parsed : null; }; const getPreviewPayoutAmount = (ticket) => { const productiveHours = toFiniteNumber(ticket?.productivehrs); const rate = toFiniteNumber(ticket?.rate); if (productiveHours === null || rate === null) { return null; } return productiveHours * rate; }; export function TimeTickeTaskModalContainer({ currentUser, technician, timeTicketTasksModal, toggleModalVisible }) { const [form] = Form.useForm(); const { context, open, actions } = timeTicketTasksModal; const [completedTasks, setCompletedTasks] = useState([]); const [unassignedHours, setUnassignedHours] = useState(0); const { t } = useTranslation(); const [loading, setLoading] = useState(false); const client = useApolloClient(); const notification = useNotification(); async function handleFinish(values) { calculateTickets({ values, handleFinish: true }); } const getCompletedTasks = useCallback( async (jobid) => { setLoading(true); const { data } = await client.query({ query: QUERY_COMPLETED_TASKS, variables: { jobid } }); setCompletedTasks(data.jobs_by_pk.completed_tasks || []); setLoading(false); }, [client] ); useEffect(() => { if (open) { form.setFieldsValue({ ...context, task: null, timetickets: null }); if (context.jobid) { getCompletedTasks(context.jobid); } } }, [context.jobid, open, getCompletedTasks, form, context]); async function handleValueChange(changedValues, allValues) { if (changedValues.jobid) { getCompletedTasks(changedValues.jobid); } if (allValues.jobid && allValues.task) { calculateTickets({ values: allValues, handleFinish: false }); } } const calculateTickets = async ({ values, handleFinish }) => { setLoading(true); try { const { data, ...response } = await axios.post("/payroll/claimtask", { jobid: values.jobid, task: values.task, calculateOnly: !handleFinish, employee: technician ? { name: `${technician.first_name} ${technician.last_name}`.trim(), employeeid: technician.id } : { name: currentUser.displayName, email: currentUser.email } }); if (response.status === 200 && handleFinish) { //Close the modal if (actions?.refetch) actions.refetch(); toggleModalVisible(); } else if (handleFinish === false) { form.setFieldsValue({ timetickets: (data.ticketsToInsert || []).map((ticket) => ({ ...ticket, payoutamount: getPreviewPayoutAmount(ticket) })) }); setUnassignedHours(data.unassignedHours); } else { notification.error({ title: t("timetickets.errors.creating", { message: JSON.stringify(data) }) }); } } catch (error) { notification.error({ title: t("timetickets.errors.creating", { message: error.response?.data?.error || error.message }) }); } finally { setLoading(false); } }; return ( { toggleModalVisible(); form.resetFields(); }} width="80%" onOk={() => form.submit()} >
); }