Added shop settings form to update groups.

This commit is contained in:
Patrick Fic
2020-10-19 10:42:41 -07:00
parent 4d5d370ccf
commit 65165906d4
13 changed files with 363 additions and 4 deletions

View File

@@ -19,8 +19,6 @@ if (isDev) {
REACT_DEVELOPER_TOOLS = devTools.REACT_DEVELOPER_TOOLS;
}
console.log(`${__dirname}/preload.js`);
let mainWindow;
let tray = null;
function createWindow() {

View File

@@ -0,0 +1,21 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_update_permission
- args:
permission:
columns:
- targets
filter:
associations:
user:
authid:
_eq: X-Hasura-User-Id
set: {}
role: user
table:
name: bodyshops
schema: public
type: create_update_permission

View File

@@ -0,0 +1,23 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_update_permission
- args:
permission:
columns:
- accepted_ins_co
- shopname
- targets
filter:
associations:
user:
authid:
_eq: X-Hasura-User-Id
set: {}
role: user
table:
name: bodyshops
schema: public
type: create_update_permission

View File

@@ -57,6 +57,8 @@ tables:
- role: user
permission:
columns:
- accepted_ins_co
- shopname
- targets
filter:
associations:

View File

@@ -0,0 +1,22 @@
import React from "react";
import { UpOutlined, DownOutlined } from "@ant-design/icons";
export default function FormListMoveArrows({ move, index, total }) {
const upDisabled = index === 0;
const downDisabled = index === total - 1;
const handleUp = () => {
move(index, index - 1);
};
const handleDown = () => {
move(index, index - 1);
};
return (
<div>
<UpOutlined disabled={upDisabled} onClick={handleUp} />
<DownOutlined disabled={downDisabled} onClick={handleDown} />
</div>
);
}

View File

@@ -0,0 +1,60 @@
import React from "react";
import { Row, Col, Typography } from "antd";
import "./layout-form-row.styles.scss";
export default function LayoutFormRow({
header,
children,
grow = false,
...restProps
}) {
if (!!!children.length) {
//We have only one element. It's going to get the whole thing.
return (
<div className="imex-form-row">
{header ? (
<Typography.Title level={4}>{header}</Typography.Title>
) : null}
{children}
</div>
);
}
const rowGutter = { gutter: [16, 16] };
const colSpan = (spanOverride) => {
if (spanOverride) return { span: spanOverride };
return {
xs: {
span: !grow ? 24 : Math.max(12, 24 / children.length),
},
sm: {
span: !grow ? 12 : Math.max(12, 24 / children.length),
},
md: {
span: !grow ? 8 : Math.max(8, 24 / children.length),
},
lg: {
span: !grow ? 6 : Math.max(6, 24 / children.length),
},
xl: {
span: !grow ? 4 : Math.max(4, 24 / children.length),
},
};
};
return (
<div className="imex-form-row" {...restProps}>
{header ? <Typography.Title level={4}>{header}</Typography.Title> : null}
<Row {...rowGutter}>
{children.map(
(c, idx) =>
c && (
<Col key={idx} {...colSpan(c && c.props && c.props.span)}>
{c}
</Col>
)
)}
</Row>
</div>
);
}

View File

@@ -0,0 +1,20 @@
//Override Antd Row margin to save space on forms.
.imex-form-row {
.ant-row {
margin-bottom: 0rem;
.ant-form-item-label {
padding: 0rem;
}
label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
display: inline-block;
padding: 0rem;
margin: 0rem;
}
}
}

View File

@@ -18,7 +18,7 @@ export function PriceDiffPcFormatterAtom({
v_age,
}) {
const metTarget = useMemo(() => {
const targetsForGroup = bodyshop.targets[group];
const targetsForGroup = bodyshop.targets.filter((t) => t.group === group);
if (!targetsForGroup) return 0;
const targetPc = targetsForGroup.filter(
(t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true)

View File

@@ -13,7 +13,7 @@ const mapDispatchToProps = (dispatch) => ({
export function PriceDiffPcFormatterAtom({ bodyshop, group, v_age }) {
const metTarget = useMemo(() => {
const targetsForGroup = bodyshop.targets[group];
const targetsForGroup = bodyshop.targets.filter((t) => t.group === group);
if (!targetsForGroup) return 0;
const targetPc = targetsForGroup.filter(
(t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true)

View File

@@ -0,0 +1,127 @@
import { Button, Input, Form, Select, InputNumber } from "antd";
import FormListMoveArrows from "../../atoms/form-list-move-arrows/form-list-move-arrows.atom";
import React from "react";
import LayoutFormRow from "../../atoms/layout-form-row/layout-form-row.atom";
import { DeleteFilled } from "@ant-design/icons";
export default function ShopSettingsFormMolecule({ form, saveLoading }) {
return (
<div>
<Button
type="primary"
loading={saveLoading}
onClick={() => form.submit()}
>
Save
</Button>
<Form.Item
label="Shop Name"
name="shopname"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="accepted_ins_co"
label="Accepted Insurance Company Names (must be exactly as in estimating system)"
rules={[
{
required: true,
type: "array",
},
]}
>
<Select mode="tags" />
</Form.Item>
<Form.List name={["targets"]}>
{(fields, { add, remove, move }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key} style={{ padding: 0, margin: 2 }}>
<LayoutFormRow>
<Form.Item
label="Group"
key={`${index}group`}
name={[field.name, "group"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Age >="
key={`${index}ageGte`}
name={[field.name, "ageGte"]}
rules={[
{
required: true,
},
]}
>
<InputNumber />
</Form.Item>
<Form.Item
label="Age <"
key={`${index}ageLt`}
name={[field.name, "ageLt"]}
>
<InputNumber />
</Form.Item>
<Form.Item
label="Target (as decimal)"
key={`${index}target`}
name={[field.name, "target"]}
rules={[
{
required: true,
},
]}
>
<InputNumber />
</Form.Item>
<div>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
</div>
</LayoutFormRow>
</Form.Item>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
Add
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</div>
);
}

View File

@@ -0,0 +1,72 @@
import { useMutation, useQuery } from "@apollo/client";
import { Form, notification, Skeleton } from "antd";
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_BODYSHOP, UPDATE_SHOP } from "../../../graphql/bodyshop.queries";
import { setBodyshop } from "../../../redux/user/user.actions";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import ShopSettingsFormMolecule from "../../molecules/shop-settings-form/shop-settings-form.molecule";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
setBodyshop: (shop) => dispatch(setBodyshop(shop)),
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(ShopSettingsOrganism);
export function ShopSettingsOrganism({ setBodyshop }) {
const { loading, error, data } = useQuery(QUERY_BODYSHOP);
const [form] = Form.useForm();
const [updateBodyshop] = useMutation(UPDATE_SHOP);
const [saveLoading, setSaveLoading] = useState(false);
useEffect(() => {
if (data) form.resetFields();
}, [form, data]);
const handleFinish = async (values) => {
setSaveLoading(true);
const result = await updateBodyshop({
variables: { id: data.bodyshops[0].id, shop: values },
});
if (!result.errors) {
notification["success"]({ message: "Settings saved successfully." });
// console.log("r", result.data.update_bodyshops.returning[0]);
setBodyshop(result.data.update_bodyshops.returning[0]);
form.resetFields();
} else {
notification["error"]({
message: "Error while saving settings " + error,
});
}
setSaveLoading(false);
};
return (
<div>
<Form
form={form}
layout="vertical"
autoComplete="new-password"
onFinish={handleFinish}
initialValues={data ? data.bodyshops[0] : null}
>
{loading && <Skeleton />}
{error && <ErrorResultAtom title="Error displaying job data." />}
<ShopSettingsFormMolecule
loading={loading}
form={form}
saveLoading={saveLoading}
/>
</Form>
</div>
);
}

View File

@@ -1,11 +1,13 @@
import React from "react";
import FilePathsListOrganism from "../../organisms/filepaths-list/filepaths-list.organism";
import ShopSettingsOrganism from "../../organisms/shop-settings/shop-settings.organism";
import WatcherManagerOrganism from "../../organisms/watcher-manager/watcher-manager.organism";
export default function SettingsPage() {
return (
<div>
<FilePathsListOrganism />
<WatcherManagerOrganism />
<ShopSettingsOrganism />
</div>
);
}

View File

@@ -9,3 +9,15 @@ export const QUERY_BODYSHOP = gql`
}
}
`;
export const UPDATE_SHOP = gql`
mutation UPDATE_SHOP($id: uuid, $shop: bodyshops_set_input!) {
update_bodyshops(where: { id: { _eq: $id } }, _set: $shop) {
returning {
id
shopname
targets
accepted_ins_co
}
}
}
`;