Added file scanning module.
This commit is contained in:
23
src/components/atoms/last-scanned/last-scanned.atom.jsx
Normal file
23
src/components/atoms/last-scanned/last-scanned.atom.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Typography } from "antd";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectScanLastScanned } from "../../../redux/scan/scan.selectors";
|
||||
import TimeAgoFormatter from "../../atoms/time-ago-formatter/time-ago-formatter.atom";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
lastScanned: selectScanLastScanned,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
export function LastScannedAtom({ lastScanned }) {
|
||||
return (
|
||||
lastScanned && (
|
||||
<Typography.Title level={5}>
|
||||
<span>Last scanned </span>
|
||||
<TimeAgoFormatter>{lastScanned}</TimeAgoFormatter>
|
||||
</Typography.Title>
|
||||
)
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LastScannedAtom);
|
||||
22
src/components/atoms/scan-refresh/scan-refresh.atom.jsx
Normal file
22
src/components/atoms/scan-refresh/scan-refresh.atom.jsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Button } from "antd";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { scanStart } from "../../../redux/scan/scan.actions";
|
||||
import { selectScanLoading } from "../../../redux/scan/scan.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
scanLoading: selectScanLoading,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
scanStart: () => dispatch(scanStart()),
|
||||
});
|
||||
|
||||
export function ScanRefreshAtom({ scanLoading, scanStart }) {
|
||||
return (
|
||||
<Button onClick={() => scanStart()} loading={scanLoading}>
|
||||
Refresh
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ScanRefreshAtom);
|
||||
@@ -1,12 +1,19 @@
|
||||
import { Tooltip } from "antd";
|
||||
import moment from "moment";
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
export default function TimeAgoFormatter(props) {
|
||||
const [timestampString, setTimestampString] = useState("");
|
||||
const m = moment(props.children);
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => setTimestampString(m.fromNow()), 15000);
|
||||
setTimestampString(m.fromNow());
|
||||
return () => clearInterval(timer);
|
||||
}, [m]);
|
||||
|
||||
return props.children ? (
|
||||
<Tooltip placement="top" title={m.format("MM/DD/YYY hh:mm A")}>
|
||||
{m.fromNow()}
|
||||
{timestampString}
|
||||
</Tooltip>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Input, Table } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { setSelectedJobId } from "../../../redux/application/application.actions";
|
||||
import {
|
||||
selectReportData,
|
||||
selectReportLoading,
|
||||
} from "../../../redux/reporting/reporting.selectors";
|
||||
import { setSelectedJobId } from "../../../redux/application/application.actions";
|
||||
import { Link } from "react-router-dom";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
reportingLoading: selectReportLoading,
|
||||
reportData: selectReportData,
|
||||
@@ -108,9 +108,11 @@ export function ReportingJobsListMolecule({
|
||||
searchText !== ""
|
||||
? reportData.filter(
|
||||
(j) =>
|
||||
j.v_makedesc.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.v_model.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.ownr_fn.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.ownr_ln.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.ownr_clm_no.toLowerCase().includes(searchText.toLowerCase())
|
||||
j.clm_no.toLowerCase().includes(searchText.toLowerCase())
|
||||
)
|
||||
: reportData;
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import { Button, Input, Table } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import ipcTypes from "../../../ipc.types";
|
||||
import {
|
||||
selectScanEstimates,
|
||||
selectScanLoading,
|
||||
} from "../../../redux/scan/scan.selectors";
|
||||
import LastScannedAtom from "../../atoms/last-scanned/last-scanned.atom";
|
||||
import ScanRefreshAtom from "../../atoms/scan-refresh/scan-refresh.atom";
|
||||
|
||||
const { ipcRenderer } = window;
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
scanLoading: selectScanLoading,
|
||||
estimates: selectScanEstimates,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
export function ScanEstimateListMolecule({ scanLoading, estimates }) {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "Claim No.",
|
||||
dataIndex: "clm_no",
|
||||
key: "clm_no",
|
||||
},
|
||||
{
|
||||
title: "Ins Co.",
|
||||
dataIndex: "ins_co_nm",
|
||||
key: "ins_co_nm",
|
||||
},
|
||||
{
|
||||
title: "First Name",
|
||||
dataIndex: "ownr_fn",
|
||||
key: "ownr_fn",
|
||||
},
|
||||
{
|
||||
title: "Last Name",
|
||||
dataIndex: "ownr_ln",
|
||||
key: "ownr_ln",
|
||||
},
|
||||
{
|
||||
title: "Vehicle",
|
||||
dataIndex: "vehicle",
|
||||
key: "vehicle",
|
||||
render: (text, record) =>
|
||||
`${record.v_model_yr} ${record.v_makedesc} ${record.v_model} (${record.v_type})`,
|
||||
},
|
||||
{
|
||||
title: "Import",
|
||||
dataIndex: "import",
|
||||
key: "import",
|
||||
render: (text, record) => (
|
||||
<Button
|
||||
onClick={() =>
|
||||
ipcRenderer.send(
|
||||
ipcTypes.default.fileScan.toMain.importJob,
|
||||
record.filepath
|
||||
)
|
||||
}
|
||||
>
|
||||
Import
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const data =
|
||||
searchText !== ""
|
||||
? estimates.filter(
|
||||
(j) =>
|
||||
j.v_makedesc.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.v_model.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.ownr_fn.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.ownr_ln.toLowerCase().includes(searchText.toLowerCase()) ||
|
||||
j.clm_no.toLowerCase().includes(searchText.toLowerCase())
|
||||
)
|
||||
: estimates;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
title={() => (
|
||||
<div className="imex-table-header">
|
||||
<ScanRefreshAtom />
|
||||
<LastScannedAtom />
|
||||
<Input.Search
|
||||
className="imex-table-header__search"
|
||||
placeholder="Search"
|
||||
onSearch={(val) => {
|
||||
setSearchText(val);
|
||||
}}
|
||||
enterButton
|
||||
allowClear
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
columns={columns}
|
||||
rowKey="filepath"
|
||||
loading={scanLoading}
|
||||
size="small"
|
||||
pagination={false}
|
||||
dataSource={data}
|
||||
scroll={{
|
||||
x: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ScanEstimateListMolecule);
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
SettingFilled,
|
||||
CloseOutlined,
|
||||
BarChartOutlined,
|
||||
FileAddFilled,
|
||||
} from "@ant-design/icons";
|
||||
import { Menu } from "antd";
|
||||
import React from "react";
|
||||
@@ -20,6 +21,9 @@ export default function SiderMenuOrganism() {
|
||||
<Menu.Item key="/" icon={<PieChartOutlined />}>
|
||||
<Link to="/">Jobs</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="/scan" icon={<FileAddFilled />}>
|
||||
<Link to="/scan">File Scan</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="/reporting" icon={<BarChartOutlined />}>
|
||||
<Link to="/reporting">Reporting</Link>
|
||||
</Menu.Item>
|
||||
|
||||
@@ -8,6 +8,7 @@ import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
|
||||
import SiderMenuOrganism from "../../organisms/sider-menu/sider-menu.organism";
|
||||
import JobsPage from "../jobs/jobs.page";
|
||||
import ReportingPage from "../reporting/reporting.page";
|
||||
import ScanPage from "../scan/scan.page";
|
||||
import SettingsPage from "../settings/settings.page";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop });
|
||||
@@ -35,6 +36,7 @@ export function RoutesPage({ bodyshop }) {
|
||||
<Layout.Content style={{ margin: "1rem", height: "100%" }}>
|
||||
<Route exact path="/settings" component={SettingsPage} />
|
||||
<Route exact path="/reporting" component={ReportingPage} />
|
||||
<Route exact path="/scan" component={ScanPage} />
|
||||
<Route exact path="/" component={JobsPage} />
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
|
||||
10
src/components/pages/scan/scan.page.jsx
Normal file
10
src/components/pages/scan/scan.page.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from "react";
|
||||
import ScanEstimateListMolecule from "../../molecules/scan-estimate-list/scan-estimate-list.molecule";
|
||||
|
||||
export default function ScanPage() {
|
||||
return (
|
||||
<div>
|
||||
<ScanEstimateListMolecule />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user