IO-924 Rest of phonebook implementation

This commit is contained in:
Patrick Fic
2021-04-23 09:11:48 -07:00
parent 084c7d9c74
commit ddbb1df9d9
18 changed files with 1331 additions and 1 deletions

View File

@@ -153,6 +153,8 @@ const PartsQueue = lazy(() =>
const ExportLogs = lazy(() =>
import("../export-logs/export-logs.page.container")
);
const Phonebook = lazy(() => import("../phonebook/phonebook.page.container"));
const EmailTest = lazy(() =>
import("../../components/email-test/email-test-component")
);
@@ -348,6 +350,7 @@ export function Manage({ match, conflict, bodyshop }) {
component={ExportLogs}
/>
<Route exact path={`${match.path}/partsqueue`} component={PartsQueue} />
<Route exact path={`${match.path}/phonebook`} component={Phonebook} />
<Route exact path={`${match.path}/payments`} component={PaymentsAll} />
<Route exact path={`${match.path}/shiftclock`} component={ShiftClock} />

View File

@@ -0,0 +1,190 @@
import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client";
import { Button, Card, Input, Space, Table, Typography } from "antd";
import _ from "lodash";
import queryString from "query-string";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component";
import { QUERY_PHONEBOOK_PAGINATED } from "../../graphql/phonebook.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import ChatOpenButton from "../../components/chat-open-button/chat-open-button.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function PhonebookPageComponent({ bodyshop }) {
const searchParams = queryString.parse(useLocation().search);
const { page, sortcolumn, sortorder, search, phonebookentry } = searchParams;
const history = useHistory();
const { loading, error, data, refetch } = useQuery(
QUERY_PHONEBOOK_PAGINATED,
{
variables: {
search: search || "",
offset: page ? (page - 1) * 25 : 0,
limit: 25,
order: [
{
[sortcolumn || "lastname"]: sortorder
? sortorder === "descend"
? "desc"
: "asc"
: "desc",
},
],
},
}
);
const { t } = useTranslation();
if (error) return <AlertComponent message={error.message} type="error" />;
const handleTableChange = (pagination, filters, sorter) => {
searchParams.page = pagination.current;
searchParams.sortcolumn = sorter.columnKey;
searchParams.sortorder = sorter.order;
if (filters.status) {
searchParams.statusFilters = JSON.stringify(
_.flattenDeep(filters.status)
);
} else {
delete searchParams.statusFilters;
}
history.push({ search: queryString.stringify(searchParams) });
};
const columns = [
{
title: t("phonebook.fields.firstname"),
dataIndex: "firstname",
key: "firstname",
},
{
title: t("phonebook.fields.lastname"),
dataIndex: "lastname",
key: "lastname",
},
{
title: t("phonebook.fields.company"),
dataIndex: "company",
key: "company",
},
{
title: t("phonebook.fields.email"),
dataIndex: "email",
key: "email",
},
{
title: t("phonebook.fields.phone1"),
dataIndex: "phone1",
key: "phone1",
render: (text, record) => <ChatOpenButton phone={text} />,
},
{
title: t("phonebook.fields.phone2"),
dataIndex: "phone2",
key: "phone2",
render: (text, record) => <ChatOpenButton phone={text} />,
},
{
title: t("phonebook.fields.street1"),
dataIndex: "street1",
key: "street1",
},
{
title: t("phonebook.fields.city"),
dataIndex: "city",
key: "city",
},
];
const handleNewPhonebook = () => {
searchParams.phonebookentry = "new";
history.push({ search: queryString.stringify(searchParams) });
};
const handleOnRowClick = (record) => {
if (record) {
searchParams.phonebookentry = record.id;
history.push({ search: queryString.stringify(searchParams) });
} else {
delete searchParams.phonebookentry;
history.push({ search: queryString.stringify(searchParams) });
}
};
return (
<Card
extra={
<Space wrap>
{searchParams.search && (
<>
<Typography.Title level={4}>
{t("general.labels.searchresults", {
search: searchParams.search,
})}
</Typography.Title>
<Button
onClick={() => {
delete searchParams.search;
history.push({ search: queryString.stringify(searchParams) });
}}
>
{t("general.actions.clear")}
</Button>
</>
)}
<Button onClick={handleNewPhonebook}>
{t("phonebook.actions.new")}
</Button>
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Input.Search
placeholder={searchParams.search || t("general.labels.search")}
onSearch={(value) => {
searchParams.search = value;
history.push({ search: queryString.stringify(searchParams) });
}}
/>
</Space>
}
>
<Table
loading={loading}
pagination={{
position: "top",
pageSize: 25,
current: parseInt(page || 1),
total: data && data.search_phonebook_aggregate.aggregate.count,
}}
columns={columns}
rowKey="id"
dataSource={data && data.search_phonebook}
//scroll={{ x: true }}
onChange={handleTableChange}
rowSelection={{
onSelect: handleOnRowClick,
type: "radio",
selectedRowKeys: [phonebookentry],
}}
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
handleOnRowClick(record);
},
};
}}
/>
</Card>
);
}
export default connect(mapStateToProps, null)(PhonebookPageComponent);

View File

@@ -0,0 +1,68 @@
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import {
setBreadcrumbs,
setSelectedHeader,
} from "../../redux/application/application.actions";
import PhonebookPage from "./phonebook.page.component";
import { Drawer, Grid } from "antd";
import queryString from "query-string";
import { useHistory, useLocation } from "react-router-dom";
import PhonebookFormContainer from "../../components/phonebook-form/phonebook-form.container";
const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
});
export function PhonebookContainer({ setBreadcrumbs, setSelectedHeader }) {
const { t } = useTranslation();
useEffect(() => {
document.title = t("titles.phonebook");
setSelectedHeader("phonebook");
setBreadcrumbs([
{
link: "/manage/phonebook",
label: t("titles.bc.phonebook"),
},
]);
}, [setBreadcrumbs, t, setSelectedHeader]);
const search = queryString.parse(useLocation().search);
const { phonebookentry } = search;
const history = useHistory();
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1])
.slice(-1)[0];
const bpoints = {
xs: "100%",
sm: "100%",
md: "100%",
lg: "50%",
xl: "50%",
xxl: "45%",
};
const drawerPercentage = selectedBreakpoint
? bpoints[selectedBreakpoint[0]]
: "100%";
return (
<RbacWrapper action="phonebook:view">
<PhonebookPage />
<Drawer
width={drawerPercentage}
onClose={() => {
delete search.phonebookentry;
history.push({ search: queryString.stringify(search) });
}}
visible={phonebookentry}
>
<PhonebookFormContainer />
</Drawer>
</RbacWrapper>
);
}
export default connect(null, mapDispatchToProps)(PhonebookContainer);