- Fix the page layout, the footer was in the content section causing it not to remain at the bottom and just reside 'at the bottom' of the content section. Also added a 100% on the outer container height (100vh) so the grey background fills the page

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-01-16 15:32:35 -05:00
9 changed files with 718 additions and 681 deletions

View File

@@ -1,22 +1,18 @@
import {
SyncOutlined,
ExclamationCircleFilled,
PauseCircleOutlined,
BranchesOutlined,
} from "@ant-design/icons";
import { useQuery } from "@apollo/client";
import { Button, Card, Grid, Input, Space, Table, Tooltip } from "antd";
import {BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, SyncOutlined,} from "@ant-design/icons";
import {useQuery} from "@apollo/client";
import {Button, Card, Grid, Input, Space, Table, Tooltip} from "antd";
import queryString from "query-string";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useNavigate, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { onlyUnique } from "../../utils/arrayHelper";
import React, {useState} from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {Link, useLocation, useNavigate} from "react-router-dom";
import {createStructuredSelector} from "reselect";
import {QUERY_ALL_ACTIVE_JOBS} from "../../graphql/jobs.queries";
import {selectBodyshop} from "../../redux/user/user.selectors";
import {onlyUnique} from "../../utils/arrayHelper";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { alphaSort } from "../../utils/sorters";
import {alphaSort, statusSort} from "../../utils/sorters";
import useLocalStorage from "../../utils/useLocalStorage";
import AlertComponent from "../alert/alert.component";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
@@ -25,13 +21,13 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsList({ bodyshop }) {
export function JobsList({bodyshop}) {
const searchParams = queryString.parse(useLocation().search);
const { selected } = searchParams;
const {selected} = searchParams;
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1])
.slice(-1)[0];
const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, {
const {loading, error, data, refetch} = useQuery(QUERY_ALL_ACTIVE_JOBS, {
variables: {
statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"],
},
@@ -39,16 +35,14 @@ export function JobsList({ bodyshop }) {
nextFetchPolicy: "network-only",
});
const [state, setState] = useState({
sortedInfo: {},
filteredInfo: { text: "" },
});
const [state, setState] = useState({sortedInfo: {}});
const [filter, setFilter] = useLocalStorage("filter_jobs_list", null);
const { t } = useTranslation();
const {t} = useTranslation();
const history = useNavigate();
const [searchText, setSearchText] = useState("");
if (error) return <AlertComponent message={error.message} type="error" />;
if (error) return <AlertComponent message={error.message} type="error"/>;
const jobs = data
? searchText === ""
@@ -91,7 +85,8 @@ export function JobsList({ bodyshop }) {
: [];
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
setState({...state, sortedInfo: sorter});
setFilter(filters);
};
const handleOnRowClick = (record) => {
@@ -126,14 +121,14 @@ export function JobsList({ bodyshop }) {
<Space>
{record.ro_number || t("general.labels.na")}
{record.production_vars && record.production_vars.alert ? (
<ExclamationCircleFilled className="production-alert" />
<ExclamationCircleFilled className="production-alert"/>
) : null}
{record.suspended && (
<PauseCircleOutlined style={{ color: "orangered" }} />
<PauseCircleOutlined style={{color: "orangered"}}/>
)}
{record.iouparent && (
<Tooltip title={t("jobs.labels.iou")}>
<BranchesOutlined style={{ color: "orangered" }} />
<BranchesOutlined style={{color: "orangered"}}/>
</Tooltip>
)}
</Space>
@@ -156,11 +151,11 @@ export function JobsList({ bodyshop }) {
to={"/manage/owners/" + record.ownerid}
onClick={(e) => e.stopPropagation()}
>
<OwnerNameDisplay ownerObject={record} />
<OwnerNameDisplay ownerObject={record}/>
</Link>
) : (
<span>
<OwnerNameDisplay ownerObject={record} />
<OwnerNameDisplay ownerObject={record}/>
</span>
);
},
@@ -172,7 +167,7 @@ export function JobsList({ bodyshop }) {
ellipsis: true,
responsive: ["md"],
render: (text, record) => (
<ChatOpenButton phone={record.ownr_ph1} jobid={record.id} />
<ChatOpenButton phone={record.ownr_ph1} jobid={record.id}/>
),
},
{
@@ -182,7 +177,7 @@ export function JobsList({ bodyshop }) {
ellipsis: true,
responsive: ["md"],
render: (text, record) => (
<ChatOpenButton phone={record.ownr_ph2} jobid={record.id} />
<ChatOpenButton phone={record.ownr_ph2} jobid={record.id}/>
),
},
@@ -195,6 +190,7 @@ export function JobsList({ bodyshop }) {
sorter: (a, b) => alphaSort(a.status, b.status),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
filteredValue: filter?.status || null,
filters:
(jobs &&
jobs
@@ -205,7 +201,14 @@ export function JobsList({ bodyshop }) {
text: s || "No Status*",
value: [s],
};
})) ||
})
.sort((a, b) =>
statusSort(
a.text,
b.text,
bodyshop.md_ro_statuses.active_statuses
)
)) ||
[],
onFilter: (value, record) => value.includes(record.status),
},
@@ -262,6 +265,7 @@ export function JobsList({ bodyshop }) {
dataIndex: "ins_co_nm",
key: "ins_co_nm",
ellipsis: true,
filteredValue: filter?.ins_co_nm || null,
filters:
(jobs &&
jobs
@@ -269,10 +273,11 @@ export function JobsList({ bodyshop }) {
.filter(onlyUnique)
.map((s) => {
return {
text: s,
text: s || "No Ins. Co.*",
value: [s],
};
})) ||
})
.sort((a, b) => alphaSort(a.text, b.text))) ||
[],
onFilter: (value, record) => value.includes(record.ins_co_nm),
responsive: ["md"],
@@ -298,6 +303,7 @@ export function JobsList({ bodyshop }) {
ellipsis: true,
responsive: ["xl"],
filterSearch: true,
filteredValue: filter?.estimator || null,
filters:
(jobs &&
jobs
@@ -305,10 +311,11 @@ export function JobsList({ bodyshop }) {
.filter(onlyUnique)
.map((s) => {
return {
text: s || "N/A",
text: s || "No Estimator*",
value: [s],
};
})) ||
})
.sort((a, b) => alphaSort(a.text, b.text))) ||
[],
onFilter: (value, record) =>
value.includes(
@@ -350,7 +357,7 @@ export function JobsList({ bodyshop }) {
extra={
<Space wrap>
<Button onClick={() => refetch()}>
<SyncOutlined />
<SyncOutlined/>
</Button>
<Input.Search
placeholder={t("general.labels.search")}
@@ -365,7 +372,7 @@ export function JobsList({ bodyshop }) {
>
<Table
loading={loading}
pagination={{ defaultPageSize: 50 }}
pagination={{defaultPageSize: 50}}
columns={columns}
rowKey="id"
dataSource={jobs}