From 7254622f52f153b868827f7ba520fa1b3c053c2b Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 2 Apr 2020 12:37:15 -0700 Subject: [PATCH] CLEANUP Schedule modal now using redux. Deleted manual schedule modal. To be incorporated into generic. --- .../jobs-detail-header.component.jsx | 28 ++-- .../schedule-appointment-modal.component.jsx | 67 ---------- .../schedule-appointment-modal.container.jsx | 74 ----------- .../schedule-calendar.component.jsx | 34 +++-- .../schedule-calendar.container.jsx | 13 +- .../schedule-job-modal.component.jsx | 103 +++++++-------- .../schedule-job-modal.container.jsx | 121 ++++++++++-------- .../jobs-available.page.container.jsx | 7 +- .../jobs-detail.page.component.jsx | 34 +---- .../jobs-detail.page.container.jsx | 10 +- client/src/redux/modals/modals.reducer.js | 3 +- client/src/redux/modals/modals.selectors.js | 5 + 12 files changed, 177 insertions(+), 322 deletions(-) delete mode 100644 client/src/components/schedule-appointment-modal/schedule-appointment-modal.component.jsx delete mode 100644 client/src/components/schedule-appointment-modal/schedule-appointment-modal.container.jsx diff --git a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx index 03269ccd5..d84de214a 100644 --- a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx +++ b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx @@ -24,24 +24,25 @@ import BarcodePopup from "../barcode-popup/barcode-popup.component"; import OwnerTagPopoverComponent from "../owner-tag-popover/owner-tag-popover.component"; import VehicleTagPopoverComponent from "../vehicle-tag-popover/vehicle-tag-popover.component"; import JobsDetailHeaderActions from "../jobs-detail-header-actions/jobs-detail-header-actions.component"; - +import { setModalContext } from "../../redux/modals/modals.actions"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop }); +const mapDispatchToProps = dispatch => ({ + setScheduleContext: context => + dispatch(setModalContext({ context: context, modal: "schedule" })) +}); -export default connect( - mapStateToProps, - null -)(function JobsDetailHeader({ +export function JobsDetailHeader({ job, mutationConvertJob, refetch, - scheduleModalState, + bodyshop, - updateJobStatus + updateJobStatus, + setScheduleContext }) { const { t } = useTranslation(); - const setscheduleModalVisible = scheduleModalState[1]; const tombstoneTitle = (
@@ -74,7 +75,12 @@ export default connect( - + ); } +export default connect(null, mapDispatchToProps)(ScheduleCalendarComponent); diff --git a/client/src/components/schedule-calendar/schedule-calendar.container.jsx b/client/src/components/schedule-calendar/schedule-calendar.container.jsx index b881d9cc6..8184eb686 100644 --- a/client/src/components/schedule-calendar/schedule-calendar.container.jsx +++ b/client/src/components/schedule-calendar/schedule-calendar.container.jsx @@ -1,18 +1,14 @@ -import React, { useState } from "react"; import { useQuery } from "@apollo/react-hooks"; -import ScheduleCalendarComponent from "./schedule-calendar.component"; +import React from "react"; import { QUERY_ALL_ACTIVE_APPOINTMENTS } from "../../graphql/appointments.queries"; -import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import AlertComponent from "../alert/alert.component"; +import LoadingSpinner from "../loading-spinner/loading-spinner.component"; +import ScheduleCalendarComponent from "./schedule-calendar.component"; export default function ScheduleCalendarContainer() { const { loading, error, data, refetch } = useQuery( - QUERY_ALL_ACTIVE_APPOINTMENTS, - { - fetchPolicy: "network-only" - } + QUERY_ALL_ACTIVE_APPOINTMENTS ); - const scheduleModalState = useState(false); if (loading) return ; if (error) return ; @@ -28,7 +24,6 @@ export default function ScheduleCalendarContainer() { return ( diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx index 7faf10e07..51c62a7af 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx @@ -1,74 +1,63 @@ -import { Checkbox, Col, DatePicker, Modal, Row, Tabs, TimePicker } from "antd"; +import { Checkbox, Col, DatePicker, Row, Tabs, TimePicker } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.container"; import ScheduleExistingAppointmentsList from "../schedule-existing-appointments-list/schedule-existing-appointments-list.component"; - - export default function ScheduleJobModalComponent({ existingAppointments, appData, setAppData, formData, - setFormData, - ...props + setFormData }) { const { t } = useTranslation(); //TODO Existing appointments list only refreshes sometimes after modal close. May have to do with the container class. return ( - - - - - - Automatic Job Selection. - - - - Manual Job Selection Scheduled Time - { - setAppData({ ...appData, start: e }); - }} - /> - { - setAppData({ ...appData, start: e }); - }} - /> - - - - - { - //TODO Build out notifications. + + + + + Automatic Job Selection. + + + + Manual Job Selection Scheduled Time + { + setAppData({ ...appData, start: e }); + }} + /> + { + setAppData({ ...appData, start: e }); + }} + /> + + + + + { + //TODO Build out notifications. + } + + setFormData({ ...formData, notifyCustomer: e.target.checked }) } - - setFormData({ ...formData, notifyCustomer: e.target.checked }) - } - > - {t("jobs.labels.appointmentconfirmation")} - - - - - - - + > + {t("jobs.labels.appointmentconfirmation")} + + + + + + ); } diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx index 808300ed4..3f5656f7c 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx @@ -6,28 +6,32 @@ import { QUERY_APPOINTMENTS_BY_JOBID } from "../../graphql/appointments.queries"; import moment from "moment"; -import { notification } from "antd"; +import { notification, Modal } from "antd"; import { useTranslation } from "react-i18next"; import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import { selectSchedule } from "../../redux/modals/modals.selectors"; +import { toggleModalVisible } from "../../redux/modals/modals.actions"; const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop + bodyshop: selectBodyshop, + scheduleModal: selectSchedule }); - -export default connect( - mapStateToProps, - null -)(function ScheduleJobModalContainer({ - scheduleModalState, - jobId, +const mapDispatchToProps = dispatch => ({ + toggleModalVisible: () => dispatch(toggleModalVisible("schedule")) +}); +export function ScheduleJobModalContainer({ + scheduleModal, bodyshop, - refetch + toggleModalVisible }) { - const [scheduleModalVisible, setscheduleModalVisible] = scheduleModalState; + const { visible, context, actions } = scheduleModal; + const { jobId } = context; + const { refetch } = actions; + const [appData, setAppData] = useState({ jobid: jobId, start: null, @@ -46,48 +50,61 @@ export default connect( const existingAppointments = useQuery(QUERY_APPOINTMENTS_BY_JOBID, { variables: { jobid: jobId }, fetchPolicy: "network-only", - skip: !scheduleModalVisible + skip: !visible }); - return ( - setscheduleModalVisible(false)} - onOk={() => { - //TODO Customize the amount of minutes it will add. - insertAppointment({ - variables: { - app: { ...appData, end: moment(appData.start).add(60, "minutes") } - } - }) - .then(r => { - updateJobStatus().then(r => { - notification["success"]({ - message: t("appointments.successes.created") - }); - - if (formData.notifyCustomer) { - //TODO Implement customer reminder on scheduling. - alert("Chosed to notify the customer somehow!"); - } - setscheduleModalVisible(false); - if (refetch) refetch(); - }); - }) - .catch(error => { - notification["error"]({ - message: t("appointments.errors.saving", { - message: error.message - }) - }); + //TODO Customize the amount of minutes it will add. + const handleOk = () => { + insertAppointment({ + variables: { + app: { ...appData, end: moment(appData.start).add(60, "minutes") } + } + }) + .then(r => { + updateJobStatus().then(r => { + notification["success"]({ + message: t("appointments.successes.created") }); - }} - /> + + if (formData.notifyCustomer) { + //TODO Implement customer reminder on scheduling. + alert("Chosed to notify the customer somehow!"); + } + toggleModalVisible(); + if (refetch) refetch(); + }); + }) + .catch(error => { + notification["error"]({ + message: t("appointments.errors.saving", { + message: error.message + }) + }); + }); + }; + + return ( + toggleModalVisible()} + onOk={handleOk} + width={"90%"} + maskClosable={false} + destroyOnClose + okButtonProps={{ disabled: appData.start ? false : true }} + > + + ); -}); +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ScheduleJobModalContainer); diff --git a/client/src/pages/jobs-available/jobs-available.page.container.jsx b/client/src/pages/jobs-available/jobs-available.page.container.jsx index 4014ea5bd..7955d331a 100644 --- a/client/src/pages/jobs-available/jobs-available.page.container.jsx +++ b/client/src/pages/jobs-available/jobs-available.page.container.jsx @@ -11,12 +11,7 @@ export default function JobsAvailablePageContainer() { const [deleteJob] = useMutation(DELETE_AVAILABLE_JOB); const { t } = useTranslation(); - const estDataLazyLoad = useLazyQuery( - QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK, - { - fetchPolicy: "network-only" - } - ); + const estDataLazyLoad = useLazyQuery(QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK); useEffect(() => { document.title = t("titles.jobsavailable"); diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index 638eacba2..ef4740c73 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -16,20 +16,9 @@ import { FaRegStickyNote, FaShieldAlt } from "react-icons/fa"; -import { useHistory } from "react-router-dom"; -//import JobsLinesContainer from "../../components/job-detail-lines/job-lines.container"; -//import JobsDetailClaims from "../../components/jobs-detail-claims/jobs-detail-claims.component"; -//import JobsDetailDatesComponent from "../../components/jobs-detail-dates/jobs-detail-dates.component"; -//import JobsDetailFinancials from "../../components/jobs-detail-financial/jobs-detail-financial.component"; -//import JobsDetailHeader from "../../components/jobs-detail-header/jobs-detail-header.component"; -//import JobsDetailInsurance from "../../components/jobs-detail-insurance/jobs-detail-insurance.component"; -//import JobsDocumentsContainer from "../../components/jobs-documents/jobs-documents.container"; -//import JobNotesContainer from "../../components/jobs-notes/jobs-notes.container"; -//import ScheduleJobModalContainer from "../../components/schedule-job-modal/schedule-job-modal.container"; -//import JobLineUpsertModalContainer from "../../components/job-lines-upsert-modal/job-lines-upsert-modal.container"; -//import EnterInvoiceModalContainer from "../../components/invoice-enter-modal/invoice-enter-modal.container"; +import { useHistory, useLocation } from "react-router-dom"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; - +import queryString from "query-string"; const JobsLinesContainer = lazy(() => import("../../components/job-detail-lines/job-lines.container") ); @@ -84,14 +73,13 @@ export default function JobsDetailPage({ mutationConvertJob, handleSubmit, refetch, - scheduleModalState, - updateJobStatus, - tab + updateJobStatus }) { const { t } = useTranslation(); const [form] = Form.useForm(); const history = useHistory(); + const search = queryString.parse(useLocation().search); const formItemLayout = { labelCol: { xs: { span: 12 }, @@ -118,12 +106,7 @@ export default function JobsDetailPage({ } > - - + @@ -168,14 +151,11 @@ export default function JobsDetailPage({ mutationConvertJob={mutationConvertJob} refetch={refetch} handleSubmit={handleSubmit} - scheduleModalState={scheduleModalState} updateJobStatus={updateJobStatus} /> - history.replace({ ...history.location, search: `?${key}` }) - } + defaultActiveKey={search.tab} + onChange={key => history.push({ search: `?tab=${key}` })} > ) : ( diff --git a/client/src/redux/modals/modals.reducer.js b/client/src/redux/modals/modals.reducer.js index 99a08090e..cab4d7437 100644 --- a/client/src/redux/modals/modals.reducer.js +++ b/client/src/redux/modals/modals.reducer.js @@ -12,7 +12,8 @@ const INITIAL_STATE = { jobLineEdit: { ...baseModal }, invoiceEnter: { ...baseModal }, courtesyCarReturn: { ...baseModal }, - noteUpsert: { ...baseModal } + noteUpsert: { ...baseModal }, + schedule: { ...baseModal } }; const modalsReducer = (state = INITIAL_STATE, action) => { diff --git a/client/src/redux/modals/modals.selectors.js b/client/src/redux/modals/modals.selectors.js index 2fdf870b2..92ee54a90 100644 --- a/client/src/redux/modals/modals.selectors.js +++ b/client/src/redux/modals/modals.selectors.js @@ -21,3 +21,8 @@ export const selectNoteUpsert = createSelector( [selectModals], modals => modals.noteUpsert ); + +export const selectSchedule = createSelector( + [selectModals], + modals => modals.schedule +);