Added formatting for jobs lists and jobs detail components

This commit is contained in:
Patrick Fic
2020-10-14 22:37:49 -07:00
parent 76f8a17b92
commit 0456543574
24 changed files with 616 additions and 30 deletions

View File

@@ -0,0 +1,48 @@
import { useQuery } from "@apollo/client";
import { Result } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_JOB_BY_PK } from "../../../graphql/jobs.queries";
import { selectSelectedJobId } from "../../../redux/application/application.selectors";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import JobsDetailDescriptionMolecule from "../../molecules/jobs-detail-description/jobs-detail-description.molecule";
import JobsLinesTableMolecule from "../../molecules/jobs-lines-table/jobs-lines-table.molecule";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
selectedJobId: selectSelectedJobId,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobsDetailOrganism({ selectedJobId }) {
const { loading, error, data } = useQuery(QUERY_JOB_BY_PK, {
variables: { jobId: selectedJobId },
skip: !selectedJobId,
});
if (!selectedJobId) return <Result title="No job selected." />;
if (error)
return (
<ErrorResultAtom
title="Error fetching Job details.."
errorMessage={JSON.stringify(error)}
/>
);
return (
<div>
<JobsDetailDescriptionMolecule
loading={loading}
job={data ? data.jobs_by_pk : null}
/>
<JobsLinesTableMolecule
loading={loading}
jobLines={data ? data.jobs_by_pk.joblines : []}
/>
{selectedJobId}
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailOrganism);

View File

@@ -0,0 +1,135 @@
import { useQuery } from "@apollo/client";
import { List, Space, Spin, Typography } from "antd";
import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroller";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_JOBS_PAGINATED } from "../../../graphql/jobs.queries";
import { setSelectedJobId } from "../../../redux/application/application.actions";
import { selectSelectedJobId } from "../../../redux/application/application.selectors";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import TimeAgoFormatter from "../../atoms/time-ago-formatter/time-ago-formatter.atom";
import "./jobs-table.organism.styles.scss";
const mapStateToProps = createStructuredSelector({
selectedJobId: selectSelectedJobId,
});
const mapDispatchToProps = (dispatch) => ({
setSelectedJobId: (jobId) => dispatch(setSelectedJobId(jobId)),
});
const limit = 20;
export function JobsTableOrganism({ selectedJobId, setSelectedJobId }) {
const [state, setState] = useState({ hasMore: true });
const { loading, error, data, fetchMore } = useQuery(
QUERY_ALL_JOBS_PAGINATED,
{
variables: {
offset: 0,
limit: limit,
order: [{ updated_at: "desc" }],
},
}
);
const handleInfiniteOnLoad = (page) => {
fetchMore({
variables: {
offset: limit * page,
},
updateQuery: (prev, { fetchMoreResult }) => {
if (!fetchMoreResult) {
console.log("No more results. Fetch More was empty.");
setState({ ...state, hasMore: false });
return prev;
}
const newCache = Object.assign({}, prev, {
jobs: [...prev.jobs, ...fetchMoreResult.jobs],
});
if (
newCache.jobs.length >= data &&
data.jobs_aggregate.aggregate.count
) {
console.log("No more results.");
setState({ ...state, hasMore: false });
}
return newCache;
},
});
};
const handleSelect = (jobId) => {
setSelectedJobId(jobId);
};
if (error)
return (
<ErrorResultAtom
title="Error fetching Jobs data."
errorMessage={JSON.stringify(error)}
/>
);
return (
<div>
<div className="jobs-list-infinite-container">
<InfiniteScroll
pageStart={0}
loadMore={handleInfiniteOnLoad}
hasMore={!loading && state.hasMore}
useWindow={false}
>
<List
dataSource={data ? data.jobs : []}
renderItem={(item) => (
<List.Item
className="jobs-list-item"
key={item.id}
onClick={() => handleSelect(item.id)}
>
<div
className={`jobs-list-item-content ${
item.id === selectedJobId
? "jobs-list-item-content-selected"
: ""
}`}
>
<div style={{ display: "flex" }}>
<Typography.Title level={4} style={{ flex: 1 }}>
{`${item.clm_no}${
item.ins_co_nm ? ` | ${item.ins_co_nm}` : ""
}`}
</Typography.Title>
<span className="job-list-last-updated-time">
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
</span>
</div>
<Space>
<span>{`${item.ownr_fn} ${item.ownr_ln}`}</span>
<span>
{`${item.v_model_yr} ${item.v_makedesc} ${item.v_model} ${item.v_vin}`}
</span>
</Space>
</div>
</List.Item>
)}
>
{loading && state.hasMore && (
<div>
<Spin />
</div>
)}
</List>
</InfiniteScroll>
</div>
{`${data ? data.jobs.length : 0} jobs loaded. ${
data ? data.jobs_aggregate.aggregate.count : 0
} total jobs.`}
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsTableOrganism);

View File

@@ -0,0 +1,26 @@
.jobs-list-infinite-container {
overflow-y: auto;
overflow-x: hidden;
height: 95vh;
}
.jobs-list-item {
padding: 0;
margin: 0;
.jobs-list-item-content {
&-selected {
border-left: 3px solid #1890ff;
}
display: inline;
margin: 0.5rem;
padding: 0.5rem;
width: 100%;
}
cursor: pointer;
&:hover {
background-color: #e6f7ff;
}
}