feature/IO-3477-Set-Parts-Location: Done
This commit is contained in:
@@ -1,25 +1,23 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { Select, Space } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, Space, Tag } from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapDispatchToProps = () => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
const mapDispatchToProps = () => ({});
|
||||
|
||||
const CLEAR_VALUE = "__CLEAR_LOCATION__";
|
||||
|
||||
export function JobLineLocationPopup({ bodyshop, jobline, disabled }) {
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [location, setLocation] = useState(jobline.location);
|
||||
const [updateJob] = useMutation(UPDATE_JOB_LINE);
|
||||
const { t } = useTranslation();
|
||||
@@ -29,55 +27,78 @@ export function JobLineLocationPopup({ bodyshop, jobline, disabled }) {
|
||||
if (editing) setLocation(jobline.location);
|
||||
}, [editing, jobline.location]);
|
||||
|
||||
const handleChange = (e) => {
|
||||
setLocation(e);
|
||||
};
|
||||
const options = useMemo(() => {
|
||||
const locs = bodyshop?.md_parts_locations || [];
|
||||
return [
|
||||
{ label: t("general.labels.none", "No location"), value: CLEAR_VALUE },
|
||||
...locs.map((loc) => ({ label: loc, value: loc }))
|
||||
];
|
||||
}, [bodyshop?.md_parts_locations, t]);
|
||||
|
||||
const handleSave = async () => {
|
||||
setLoading(true);
|
||||
const result = await updateJob({
|
||||
variables: { lineId: jobline.id, line: { location: location || "" } }
|
||||
});
|
||||
const saveLocation = async (nextLocation) => {
|
||||
setSaving(true);
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({ message: t("joblines.successes.saved") });
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("joblines.errors.saving", {
|
||||
error: JSON.stringify(result.errors)
|
||||
})
|
||||
try {
|
||||
const result = await updateJob({
|
||||
variables: { lineId: jobline.id, line: { location: nextLocation || "" } }
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
notification["success"]({ message: t("joblines.successes.saved") });
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("joblines.errors.saving", {
|
||||
error: JSON.stringify(result.errors)
|
||||
})
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
notification["error"]({
|
||||
message: t("joblines.errors.saving", { error: error?.message || String(error) })
|
||||
});
|
||||
} finally {
|
||||
setSaving(false);
|
||||
setEditing(false);
|
||||
}
|
||||
setLoading(false);
|
||||
setEditing(false);
|
||||
};
|
||||
|
||||
if (editing)
|
||||
const handleChange = async (value) => {
|
||||
const next = value === CLEAR_VALUE ? null : value;
|
||||
setLocation(next);
|
||||
await saveLocation(next);
|
||||
};
|
||||
|
||||
if (editing) {
|
||||
return (
|
||||
<div>
|
||||
<LoadingSpinner loading={loading}>
|
||||
<Select
|
||||
autoFocus
|
||||
allowClear
|
||||
popupMatchSelectWidth={100}
|
||||
value={location}
|
||||
onClear={() => setLocation(null)}
|
||||
onSelect={handleChange}
|
||||
onBlur={handleSave}
|
||||
>
|
||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</LoadingSpinner>
|
||||
<div style={{ width: "100%", display: "flex", alignItems: "center" }}>
|
||||
<Select
|
||||
autoFocus
|
||||
size="small"
|
||||
value={location ?? undefined}
|
||||
loading={saving}
|
||||
disabled={saving}
|
||||
style={{ flex: 1, minWidth: 0 }}
|
||||
popupMatchSelectWidth={false}
|
||||
getPopupContainer={(triggerNode) => triggerNode.parentNode}
|
||||
onChange={handleChange}
|
||||
onBlur={() => !saving && setEditing(false)}
|
||||
options={options}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }} onClick={() => !disabled && setEditing(true)}>
|
||||
<div
|
||||
style={{ width: "100%", minHeight: "2rem", cursor: disabled ? "default" : "pointer" }}
|
||||
onClick={() => !disabled && setEditing(true)}
|
||||
>
|
||||
<Space wrap>
|
||||
{jobline.location}
|
||||
{jobline.location ? (
|
||||
<Tag>{jobline.location}</Tag>
|
||||
) : (
|
||||
<span style={{ opacity: 0.6 }}>{t("general.labels.none")}</span>
|
||||
)}
|
||||
{jobline.parts_dispatch_lines?.length > 0 && "-Disp"}
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user