Complete refactor of jobs detail screen.

This commit is contained in:
Patrick Fic
2020-01-27 16:20:33 -08:00
parent 9553062045
commit b5e9c65aee
38 changed files with 3409 additions and 401 deletions

View File

@@ -0,0 +1,9 @@
import React from 'react'
export default function JobsAvailablePageComponent() {
return (
<div>
JobsAvailablePageComponent
</div>
)
}

View File

@@ -0,0 +1,10 @@
import React from 'react'
import JobsAvailablePageComponent from './jobs-available.page.component'
export default function JobsAvailablePageContainer() {
return (
<div>
<JobsAvailablePageComponent />
</div>
)
}

View File

@@ -0,0 +1,181 @@
import { Form, Icon, Tabs } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { FaRegStickyNote } from "react-icons/fa";
import JobLinesContainer from "../../components/job-lines/job-lines.container.component";
import JobsDetailHeader from "../../components/jobs-detail-header/jobs-detail-header.component";
import JobsDocumentsContainer from "../../components/jobs-documents/jobs-documents.container";
import JobNotesContainer from "../../components/jobs-notes/jobs-notes.container";
import JobsRatesContainer from "../../components/jobs-rates/jobs-rates.container";
export default function JobsDetailPage({
job,
mutationUpdateJob,
mutationConvertJob,
handleSubmit,
handleChange,
getFieldDecorator,
refetch
}) {
const { t } = useTranslation();
const formItemLayout = {
labelCol: {
xs: { span: 12 },
sm: { span: 5 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 12 }
}
};
// const TEMP = (
// <div>
// {" "}
// <Form.Item label='Estimator Last Name'>
// {getFieldDecorator("est_ct_ln", {
// initialValue: jobContext.est_ct_ln
// })(<Input name='est_ct_ln' onChange={handleChange} />)}
// </Form.Item>
// <Form.Item label='Estimator First Name'>
// {getFieldDecorator("est_ct_fn", {
// initialValue: jobContext.est_ct_fn
// })(<Input name='est_ct_fn' onChange={handleChange} />)}
// </Form.Item>
// <Form.Item label='Estimator Phone #'>
// {getFieldDecorator("est_ph1", {
// initialValue: jobContext.est_ph1
// })(
// <FormItemPhone
// customInput={Input}
// name='est_ph1'
// onValueChange={handleChange}
// />
// )}
// </Form.Item>
// <Form.Item label='Estimator Email'>
// {getFieldDecorator("est_ea", {
// initialValue: jobContext.est_ea,
// rules: [
// {
// type: "email",
// message: "This is not a valid email address."
// }
// ]
// })(<Input name='est_ea' onChange={handleChange} />)}
// </Form.Item>
// </div>
// );
return (
<Form onSubmit={handleSubmit} {...formItemLayout}>
<JobsDetailHeader
job={job}
mutationConvertJob={mutationConvertJob}
refetch={refetch}
getFieldDecorator={getFieldDecorator}
/>
<Tabs defaultActiveKey='claimdetail'>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("menus.jobsdetail.claimdetail")}
</span>
}
key='claimdetail'>
Claim detail
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("menus.jobsdetail.insurance")}
</span>
}
key='insurance'>
Insurance
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("menus.jobsdetail.repairdata")}
</span>
}
key='repairdata'>
<JobLinesContainer jobId={job.id} />
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='dollar' />
{t("menus.jobsdetail.financials")}
</span>
}
key='financials'>
<JobsRatesContainer />
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("menus.jobsdetail.partssublet")}
</span>
}
key='partssublet'>
Partssublet
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("menus.jobsdetail.labor")}
</span>
}
key='labor'>
Labor
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("menus.jobsdetail.dates")}
</span>
}
key='dates'>
Dates
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='file-image' />
{t("jobs.labels.documents")}
</span>
}
key='#documents'>
<JobsDocumentsContainer jobId={job.id} />
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon component={FaRegStickyNote} />
{t("jobs.labels.notes")}
</span>
}
key='#notes'>
<JobNotesContainer jobId={job.id} />
</Tabs.TabPane>
</Tabs>
</Form>
);
}

View File

@@ -1,38 +1,79 @@
import { useQuery } from "@apollo/react-hooks";
import { Form, notification } from "antd";
import React, { useEffect } from "react";
import { useMutation, useQuery } from "react-apollo";
import { useTranslation } from "react-i18next";
import AlertComponent from "../../components/alert/alert.component";
import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries";
import JobsDetailPage from "./jobs-detail.page";
import {
GET_JOB_BY_PK,
UPDATE_JOB,
CONVERT_JOB_TO_RO
} from "../../graphql/jobs.queries";
import JobsDetailPage from "./jobs-detail.page.component";
function JobsDetailPageContainer({ match, location }) {
function JobsDetailPageContainer({ match, form }) {
const { jobId } = match.params;
const { hash } = location;
const { t } = useTranslation();
const { loading, error, data } = useQuery(GET_JOB_BY_PK, {
const { loading, error, data, refetch } = useQuery(GET_JOB_BY_PK, {
variables: { id: jobId },
fetchPolicy: "network-only"
});
const [mutationUpdateJob] = useMutation(UPDATE_JOB);
const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO);
useEffect(() => {
document.title = loading
? "..."
: t("titles.jobsdetail", {
ro_number: data.jobs_by_pk.ro_number
document.title =
loading && !error
? "..."
: t("titles.jobsdetail", {
ro_number: data.jobs_by_pk.ro_number
});
}, [loading, data, t, error]);
const handleSubmit = e => {
e.preventDefault();
form.validateFieldsAndScroll((err, values) => {
if (err) {
notification["error"]({
message: t("jobs.errors.validationtitle"),
description: t("jobs.errors.validation")
});
}, [loading, data, t]);
}
if (!err) {
mutationUpdateJob({
variables: { jobId: data.jobs_by_pk.id, job: values }
}).then(r =>
notification["success"]({
message: t("jobs.successes.savetitle")
})
);
}
});
};
const handleChange = event => {
//const { name, value } = event.target ? event.target : event;
//setJobContext({ ...jobContext, [name]: value });
};
if (loading) return <SpinComponent />;
if (error) return <AlertComponent message={error.message} type='error' />;
return (
return data.jobs_by_pk ? (
<JobsDetailPage
hash={hash ? hash.substring(1) : "#lines"}
data={data}
jobId={jobId}
match={match}
job={data.jobs_by_pk}
mutationUpdateJob={mutationUpdateJob}
mutationConvertJob={mutationConvertJob}
handleSubmit={handleSubmit}
handleChange={handleChange}
getFieldDecorator={form.getFieldDecorator}
refetch={refetch}
/>
) : (
<AlertComponent message={t("jobs.errors.noaccess")} type='error' />
);
}
export default JobsDetailPageContainer;
export default Form.create({ name: "JobsDetailPageContainer" })(
JobsDetailPageContainer
);

View File

@@ -1,80 +0,0 @@
import { Icon, Row, Tabs } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { FaRegStickyNote } from "react-icons/fa";
import { withRouter } from "react-router-dom";
import JobLinesContainer from "../../components/job-lines/job-lines.container.component";
import JobTombstone from "../../components/job-tombstone/job-tombstone.component";
import JobsDocumentsContainer from "../../components/jobs-documents/jobs-documents.container";
import JobNotesContainer from "../../components/jobs-notes/jobs-notes.container";
import JobsRatesContainer from "../../components/jobs-rates/jobs-rates.container";
function JobsDetailPage({ jobId, hash, data, match, history }) {
const { t } = useTranslation();
return (
<div>
<Row>
<JobTombstone job={data.jobs_by_pk} />
</Row>
<Row>
<Tabs
defaultActiveKey={`#${hash}`}
onChange={p => {
history.push(p);
}}>
<Tabs.TabPane
tab={
<span>
<Icon type='bars' />
{t("jobs.labels.lines")}
</span>
}
key='#lines'>
<JobLinesContainer match={match} />
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='dollar' />
{t("jobs.labels.rates")}
</span>
}
key='#rates'>
<JobsRatesContainer />
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='tool1' />
{t("jobs.labels.parts")}
</span>
}
key='#parts'>
Estimate Parts
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon type='file-image' />
{t("jobs.labels.documents")}
</span>
}
key='#documents'>
<JobsDocumentsContainer jobId={jobId} />
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<Icon component={FaRegStickyNote} />
{t("jobs.labels.notes")}
</span>
}
key='#notes'>
<JobNotesContainer jobId={jobId} />
</Tabs.TabPane>
</Tabs>
</Row>
</div>
);
}
export default withRouter(JobsDetailPage);

View File

@@ -20,6 +20,9 @@ const ProfilePage = lazy(() => import("../profile/profile.container.page"));
const JobsDocumentsPage = lazy(() =>
import("../../components/jobs-documents/jobs-documents.container")
);
const JobsAvailablePage = lazy(() =>
import("../jobs-available/jobs-available.page.container")
);
const { Header, Content, Footer } = Layout;
//This page will handle all routing for the entire application.
@@ -43,6 +46,7 @@ export default function Manage({ match }) {
<Route exact path={`${match.path}`} component={WhiteBoardPage} />
<Route exact path={`${match.path}/jobs`} component={JobsPage} />
<Route
exact
path={`${match.path}/jobs/:jobId`}
@@ -58,6 +62,12 @@ export default function Manage({ match }) {
path={`${match.path}/profile`}
component={ProfilePage}
/>
<Route
exact
path={`${match.path}/available`}
component={JobsAvailablePage}
/>
</Suspense>
</ErrorBoundary>
</Content>